给定任意凸2D多边形,如何计算其转动惯量?

10

我已经花了几个小时研究这个问题,但不知何故,我找不到解决方案。

给定一个凸多边形,该多边形以顺时针顺序围绕多边形的质心定义为点数组,如何计算多边形的惯性矩?

我已经能够找到各种形状的公式,例如矩形或圆形,但没有针对任意凸多边形的公式。

例如,质量为m,高度为h,宽度为w的矩形绕其质心旋转的惯性矩可计算为:

Moment of Inertia for a Rectangle

我正在寻找一个类似的公式/算法,但适用于凸多边形。


1
找到一个将凸多边形细分为三角形的算法(图形学需要经常这样做)。计算每个三角形的矩。将它们全部加起来。 - Andy Newman
只是为了澄清,您需要用于动力学的“质量惯性矩”,而不是用于梁挠曲中使用的“截面面积第二矩”吗? - John Alexiou
这个回答解决了你的问题吗?在2D中计算惯性张量 - John Alexiou
2个回答

9

我认为使用矢量代数分析2D多边形的方法比依赖三角学的方法更容易在程序中实现。

每个向量量都有两个分量.x.y,以及用于点积和叉积的矢量代数向量方法。

add(a,b) = [a.x+b.x, a.y+b.y]    // a+b = add(a,b)
scale(f,x) = [f*a.x, f*a.y]      // 2*a = scale(2,a), a/3 = scale(1/3,a)
dot(a,b) = a.x*b.x + a.y*b.y     // a·b = dot(a,b)
cross(a,b) = a.x*b.y - a.y*b.x   // a×b = cross(a,b)

以下方法遍历多边形的所有边,计算每个由边和原点定义的三角形的面积、中心和质量矩。最终的求和考虑了添加或减去靠近或远离原点的面积,以得到准确的结果。
最后,将质量矩从原点转移到质心。
polygon(Vector[] points, double depth, double density)
{
    // Accumulate the following values
    double area = 0.0;
    double mass = 0.0;
    Vector center = [0.0, 0.0];
    double mmoi = 0.0;

    // Take each vertex pair starting from the last-first vertex
    // in order to consider all sides.
    int count = points.Length;
    int prev = count - 1;
    for(int index=0; index<count; index++)
    {
        Vector a = points[prev];
        Vector b = points[index];

        double area_step = TriangleArea(a,b);
        double mass_step = density * area_step * depth;
        Vector center_step = TriangleCenter(a,b);
        double mmoi_step = TriangleMmoi(a,b, mass_step);

        area += area_step;
        center = (mass*center + mass_step*center_step)/(mass+mass_step);
        mass += mass_step;
        mmoi += mmoi_step;

        prev = index;
    }

    // Transfer mass moment of inertia from the origin to the center of mass
    mmoi -= mass*dot(center,center);

    // use area, mass, center and mmoi
}

double TriangleArea(Vector a, Vector b)
{
    return cross(a,b)/2;
}
double TriangleCenter(Vector a, Vector b)
{
    return (a+b)/3;
{
double TriangleMmoi(Vector a, Vector b, double triangleMass)
{
    return triangleMass/6*(dot(a,a)+dot(b.b)+dot(a.b));
}

以上是一个类似于此答案中概述的过程。链接的答案中包含更多细节。
以下是上述过程的实现,但指定了质量而不是密度和厚度。
public static RigidBody2 FromShape(double mass, params Vector2[] polygon)
{
    double area = 0;
    Vector2 center = Vector2.Zero;
    double mmoi = 0;

    int prev = polygon.Length-1;
    for (int index = 0; index < polygon.Length; index++)
    {
        var a = polygon[prev];
        var b = polygon[index];

        var area_step = Vector2.Cross(a, b)/2;
        var center_step = (a+b)/3;
        var mmoi_step = area_step*(Vector2.Dot(a, a)+Vector2.Dot(b, b)+Vector2.Dot(a, b))/6;

        center = (center*area + center_step * area_step)/(area + area_step);
        area += area_step;
        mmoi += mmoi_step;

        prev = index;
    }

    double density = mass/area;
    mmoi *= density;
    mmoi -= mass * Vector2.Dot(center, center);

    return new RigidBody2(mass, mmoi, center);
}

在测试中,我使用了以下形状:

shape

并且当 center = [1.0, 0.75]mmoi = 687.5 时,结果与CAD软件分析的结果相匹配。

CAD

这里是针对CAD数据进行检查的单元测试:

[TestMethod, TestCategory("Linear Algebra, Planar")]
public void Geom_PlanarPolygonMass()
{
    Vector2[] points = new Vector2[] {
        Vector2.Cartesian(0.75, 0),
        Vector2.Cartesian(2, 0),
        Vector2.Cartesian(2, 0.5),
        Vector2.Cartesian(1.25, 0.5),
        Vector2.Cartesian(1.25, 1.5),
        Vector2.Cartesian(0, 1.5),
        Vector2.Cartesian(0, 1.0),
        Vector2.Cartesian(0.75, 1),
    };

    var rg = RigidBody2.FromShape(1500, points);

    Assert.AreEqual(1500, rg.Mass);
    CollectionAssert.AreEqual(Vector2.Cartesian(1.0, 0.75), rg.LocalCg, AbsComparer(TinyNumber));
    Assert.AreEqual(687.5, rg.LocalMmoi, DoubleEx.TinyNumber);
}

1
我无法仅编辑一个字符,但 MMOI 应为 687.5 而非 787.5 - 答案中有一个打字错误。 - John Aaron
1
@JohnAaron - 很好的发现,谢谢你。 - John Alexiou
我知道这很老,但是如果您在C#实现中的点测试中使用Vector2(0, 0),似乎会出现一个错误。然后您会得到center(NaN, NaN)(除以0)。 - Cobse
1
@Cobse - 检查 step_area 是否为零。如果是,则继续下一次迭代。否则,如果零面积元素是要考虑的第一个元素(且 area=0),则会除以零。 - John Alexiou

0

惯性矩的公式相当简单,您可以在此处找到解释:https://en.wikipedia.org/wiki/Moment_of_inertia

例如,它被用于推导您引用的方程式。

正如安迪·纽曼提到的那样,凸多边形可以被认为是由三角形组成。 但是将它们各自的惯性累加起来并不是一个解决方案——它不会产生考虑旋转轴的有效方程式。

所以基本上你需要做的就是针对你想要绕其旋转的旋转轴得出多边形的方程式。

根据您所考虑的形状类型,您可能会发现以下定理之一有用:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接