矩阵在Python

时间:2015-05-28 11:35:33

标签: python matrix rotational-matrices

我整个上午一直在努力解决这个问题,最终不得不诉诸SO。

我正在尝试旋转一组具有3D位置和旋转的“对象”(它实际上是另一个程序,但我正在编写一个快速的Python工具来解析数据,旋转它我想要的方式并将其吐回来出)。

在我的课程中有两个课程:

class Object:

    def __init__(self, mod, px, py, pz, rx, ry, rz):
        self.mod = mod
        self.pos = [px, py, pz]
        self.rot = [rx, ry, rz]


    def rotate(self, axisx, axisy, axisz, rotx, roty, rotz):
        """rotates object around axis"""

        ?

这是我的'对象'课程(好吧,我现在意识到它的名字有多么糟糕!)。忽略'mod',它非常简单,只存在于具有位置和旋转(度)的空间中。

我不知道写入旋转部分的内容。我有点得到矩阵,但只有数学形式,我从来没有真正为它们编写代码,并想知道是否有任何库可以提供帮助。

我的另一个类是这些对象的简单组。唯一的另一个属性是平均位置,实际上是我想要旋转每个对象的轴:

class ObjectMap:

    def __init__(self, objs):
        self.objs = objs

        tpx = 0.0
        tpy = 0.0
        tpz = 0.0

        for obj in objs:
            tpx += obj.pos[0]
            tpy += obj.pos[1]
            tpz += obj.pos[2]

        # calculate average position for this object map
        # somewhere in the middle of all the objects
        self.apx = tpx / len(objs)
        self.apy = tpy / len(objs)
        self.apz = tpz / len(objs)



    def rotate(self, rotx, roty, rotz):
        """rotate the entire object map around the averaged position in the centre"""

        for o in self.objs:
            o.rotate(self.apx, self.apy, self.apz, rotx, roty, rotz)

正如你所看到的,这个类有一个旋转函数,它只是遍历其中包含的所有对象,并围绕“平均位置”轴旋转它们,该轴应位于中间的某个位置,因为它是一个平均值。

我制作了一个快速动画,以便更好地解释我在此之后的情况:

http://puu.sh/i3DxU/adfe44a99d.gif http://puu.sh/i3DxU/adfe44a99d.gif 球体形状是我的“物体”,中间的形状是它们旋转的轴(ObjectMap类的apx,apy,apz坐标)。

我试图让this library工作,但它没有工作,所以我放弃了这个想法。我正在使用Python 3,安装了numpy,因为我认为它会有所帮助。我也尝试过互联网上的大量代码,但事情根本就没有用(或者它们适用于旧的python版本,或者只是安装失败)。

如果有人能指出我正确的方向让这些轮换工作,我会很高兴。即使只是链接到Python中的矩阵示例或有用的库也会很棒!

1 个答案:

答案 0 :(得分:2)

编辑:我的原始答案完全避免了俯仰,翻滚和偏航。基于对问题的澄清,似乎此代码可能正在使用要求使用俯仰,滚动和偏航的数据结构和/或API,因此我现在将尝试解决此要求。

有几种方法可以在三维笛卡尔坐标系中指定旋转:

  • 欧拉角(3个数字参数)
  • 轴和角度(4个数字参数)
  • 旋转矩阵(9个数字参数)
  • 四元数(4个数字参数)

偏航,俯仰和滚动是欧拉角 (至少根据我对这三个术语的任何适用定义)。 但是transformations.py 说有24种可能的方法来解释三个欧拉角的序列, 这些解释中的每一个都有不同的结果 每个其他的至少一些角度序列。 如何翻译“偏航,投球和翻滚”并不明显。其中一个 24种可能的"轴序列"在transformations.py中。 实际上,除非您完全了解 您现有的数据/软件 连接应用偏航,俯仰和滚动到对象 旋转,我不认为你真的能说出什么" yaw,pitch,roll"意味着在这个应用程序中,您不太可能猜测正确的轴序列"在transformations.py中使用。 我怀疑这可能是你无法获得的主要原因 transformations.py为你工作。

除了这些含糊之处之外,我还不清楚参数是什么 axisxaxisyaxisz代表 rotate(self, axisx, axisy, axisz, rotx, roty, rotz)。 通常,偏航,俯仰和滚转是指围绕三个轴的旋转 旋转的身体,通常应该定义一个 这些轴是什么以及旋转的顺序 在进行任何轮换之前,永远不要更改这些定义。 因此,每次必须指定轴时没有任何意义 再做一次轮换;该软件应该已经确切地知道哪个 要使用的轴,即使它们是体轴而不是世界轴。 (我现在假设每个参数axisxaxisyaxisz 是一个轴本身,这三个参数不是以某种方式 用于指定我在初始答案中假设的单轴。)

增加混乱,通常应用俯仰,滚转和偏航 对于体轴,你应该旋转整个物体集合, 这似乎意味着你应该围绕世界轴而不是 个体轴。

实际上,一旦你弄清楚了什么是偏航,俯仰和翻滚 在您的应用程序中真正意味着,以及您的参数是什么 rotate函数应该意味着,我会做的第一件事 任何旋转都是将其转换为 not 的表示 任何一种欧拉角。旋转矩阵看起来是个不错的选择。 如果您知道正确的"轴序列"代表你的定义 offormations,euler_matrix承诺中的偏航,俯仰和滚转 为你计算那个矩阵。

您可以通过对矩阵进行矩阵乘法来进一步旋转对象 新的旋转矩阵和现有旋转的矩阵; 结果是第三个矩阵。 如果它是世界坐标中的旋转,则新矩阵在乘法的左侧,如果它是在身体坐标中的旋转,则在右侧。

使用新的旋转矩阵重新定向对象后, 如果你真的需要将对象的结果方向存储为 某处欧拉角(滚动,俯仰和偏航)的序列, transformations.py中的euler_from_matrix承诺告诉你那些是什么 角度是(但再一次,你必须知道你的"滚动,俯仰和偏航" 定义了transformations.py如何将该定义表示为轴序列。

这一行下面的内容来自我原来的回答(也就是说,如果一个人没有被迫使用欧拉角,可以做一些事情。)

我的建议:

对于Object,旋转函数签名应该等同于:

    def rotate(self, axisx, axisy, axisz, angle)

对于ObjectMap,签名应该等同于

    def rotate(self, angle)

这个想法是,一旦你选择了一个轴(通过输入变量到函数或隐式已经按照ObjectMap计算),任何两个旋转之间的唯一区别是围绕该轴的旋转角度,描述通过单个标量参数angle。 (我建议angle的单位为弧度。)

要将其与您的GIF相关联,在GIF中每个彩色弧都有 自己的轴垂直于弧的平面。弧的半径 并不重要;唯一控制如何的东西 球体移动(当你围绕那个轴旋转时)是指针的距离 沿着弧线来回移动。动作来回是一种东西 由单个标量参数描述,在这种情况下是旋转角度。

对于Object的内容,它需要一组坐标 指定对象的位置"位置" (实际上可能 作为您选择对象的任何参考点;但是 如果有一个明显的中心,中心通常是一个很好的选择:

    def __init__(self, mod, px, py, pz):
        self.mod = mod
        self.position = [px, py, pz]

如果您还想表示对象的方向 (例如,以便GIF中的球体围绕它们旋转 它们绕着ObjectMap的轴旋转时自己的轴, 为Object添加足够的积分(除了"位置") 这样你就可以在旋转后的任何地方画出它。 最低限度是两个额外点; 例如,要像GIF中的一个那样绘制一个球体,它就是 足以知道北极的位置和一个的位置 指向赤道。 (实际上可以知道球体的确切方向 只有三个标量坐标,而不是参与的六个 这两点,但除非你愿意,否则我不会推荐它 认真学习所涉及的数学。)

这导致了这样的事情:

    def __init__(self, mod, px, py, pz, vector1x, vector1y, vector1z, vector2x, vector2y, vector2z):
        self.mod = mod
        self.position = [px, py, pz]
        self.feature1 = [px + vector1x, py + vector1y, pz + vector1z]
        self.feature2 = [px + vector2x, py + vector2y, pz + vector2z]

px + vector1x等的基本原理是您可能会找到它 方便用矢量描述对象的特征 从物体的中心到每个特征;但对于绘图和 您可能更喜欢所有点的物体旋转 用它们的全局坐标来描述。 (但我应该注意,它不是必要的 完全用全局坐标描述对象。)

然后Object的旋转变成类似伪代码:

    def rotate(self, axisx, axisy, axisz, angle):
        rotate self.position around [axisx, axisy, axisz] by angle radians
        rotate self.feature1 around [axisx, axisy, axisz] by angle radians
        rotate self.feature2 around [axisx, axisy, axisz] by angle radians

如果您的所有坐标都是全局坐标,则会移动所有坐标 围绕全局轴,导致对象的移动和旋转 由这些点组成。如果您确定只有Object的中心 有一个全局坐标,并描述了它的所有其他部分 相对于那一点,使用向量,你仍然可以使用相同的 rotate功能;结果将与您简单旋转的结果相同 每个点的全局坐标。

如何在3D空间中旋转点的实际细节 给定角度的给定轴被写在各个地方 例如Python - Rotation of 3D vector(包括 至少一个numpy实现)。 您可能会发现创建"旋转"宾语 (可能是一个矩阵,但你可以让图书馆照顾 设置其值的详细信息) 通过像

这样的东西
    rotation = define_rotation(axisx, axisy, axisz, angle)

这样您就可以重复使用同一个对象来计算旋转 每个Object内每个点的位置。这往往会产生 比你必须计算每个点的每个旋转更快的执行 从原始轴坐标和角度值。

如果这是我的代码,我宁愿定义一个Point类 和/或Vector类(或使用现有库中的类) 由单个点或向量的x,y和z坐标组成, 所以我不必继续以三个为一组传递参数 并在我的代码中写出向量加法公式。 例如,而不是

    self.feature1 = [px + vector1x, py + vector1y, pz + vector1z]

我可能有

    self.feature1 = p.add(vector1)

但这是一个你可以独立制作的设计选择 你最终选择做什么数学轮换。