我整个上午一直在努力解决这个问题,最终不得不诉诸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中的矩阵示例或有用的库也会很棒!
答案 0 :(得分:2)
编辑:我的原始答案完全避免了俯仰,翻滚和偏航。基于对问题的澄清,似乎此代码可能正在使用要求使用俯仰,滚动和偏航的数据结构和/或API,因此我现在将尝试解决此要求。
有几种方法可以在三维笛卡尔坐标系中指定旋转:
偏航,俯仰和滚动是欧拉角 (至少根据我对这三个术语的任何适用定义)。 但是transformations.py 说有24种可能的方法来解释三个欧拉角的序列, 这些解释中的每一个都有不同的结果 每个其他的至少一些角度序列。 如何翻译“偏航,投球和翻滚”并不明显。其中一个 24种可能的"轴序列"在transformations.py中。 实际上,除非您完全了解 您现有的数据/软件 连接应用偏航,俯仰和滚动到对象 旋转,我不认为你真的能说出什么" yaw,pitch,roll"意味着在这个应用程序中,您不太可能猜测正确的轴序列"在transformations.py中使用。 我怀疑这可能是你无法获得的主要原因 transformations.py为你工作。
除了这些含糊之处之外,我还不清楚参数是什么
axisx
,axisy
和axisz
代表
rotate(self, axisx, axisy, axisz, rotx, roty, rotz)
。
通常,偏航,俯仰和滚转是指围绕三个轴的旋转
旋转的身体,通常应该定义一个
这些轴是什么以及旋转的顺序
在进行任何轮换之前,永远不要更改这些定义。
因此,每次必须指定轴时没有任何意义
再做一次轮换;该软件应该已经确切地知道哪个
要使用的轴,即使它们是体轴而不是世界轴。
(我现在假设每个参数axisx
,axisy
和axisz
是一个轴本身,这三个参数不是以某种方式
用于指定我在初始答案中假设的单轴。)
增加混乱,通常应用俯仰,滚转和偏航 对于体轴,你应该旋转整个物体集合, 这似乎意味着你应该围绕世界轴而不是 个体轴。
实际上,一旦你弄清楚了什么是偏航,俯仰和翻滚
在您的应用程序中真正意味着,以及您的参数是什么
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)
但这是一个你可以独立制作的设计选择 你最终选择做什么数学轮换。