多物理场仿真 Chrono(1.6) 坐标变换

为方便查阅,此文是原网站文档翻译,如有侵权,请与本人联系。

坐标变换

此文档组件介绍了整个Chrono API中用于管理坐标、点、转换和旋转的重要概念。

向量

表示空间中三维点的矢量是通过chrono::ChVector类定义的。在数学符号中:
P = { p x , p y , p z } \mathbf{P}=\{p_x,p_y,p_z\} P={px,py,pz}
ChVector<>类已模板化。可以有单精度的向量,如ChVector<float>,双精度的向量如ChVector<double>等。默认数据类型为double;即ChVector<>默认为ChVector<double>
比如,创建一个向量:

ChVector<> mvect1(2,3,4);

使用+、-、*运算符对矢量进行加法、减法、乘法运算。

ChVector<double> mvect1(2,3,4);  // Create a vector with given the 2,3,4 ‘double’ components
 
ChVector<float> mvect2(4,1,2);  // Create a vector with given the 4,1,2 ‘float’ components
 
ChVector<> mvect3();    // Create a 0,0,0, vector. The <> defaults to ‘double’
 
ChVector<> mvect4(mvect1 + mvect2);  // Create a vector by copying another (a result from +)
 
mvect3 = mvect1 + mvect2;   // Vector operators: +, - 
 
mvect3 += mvect1;       // In-place operators
 
mvect3 = mvect2 * 0.003;    // Vector product by scalar
 
mvect3.Normalize();     // One of many member functions, normalizes a vector
 
mvect3 = mvect1 % mvect2;   // Operator for cross product: A%B means vector cross-product AxB
 
double val = mvect1 ^ mvect2;   // Operator for inner product (scalar product)

Chrono还提供了一组有用的常量(双精度类型)向量-VNULLVECT_XVECT.YVECT_W,它们分别表示零和坐标轴上的单位向量。

四元数

四元数提供了一个扩展复数的数字系统,它被Chrono用来表示三维空间中的旋转。Chrono实现四元数的封装在Chrono::ChQuaternion类中。在数学符号中,四元数表示为四个实数的集合:
q = { q 0 , q 1 , q 2 , q 3 } \mathbf{q}=\{q_0,q_1,q_2,q_3\} q={q0,q1,q2,q3}
四元数代数性质:

  • 实单位四元数 q = { 1 , 0 , 0 , 0 } \mathbf{q}=\{1,0,0,0\} q={1,0,0,0}表示没有旋转
  • 给定关于一般单位向量 u \mathbf{u} u的旋转 θ u \theta_{u} θu,相应的四元数为

q = { cos ⁡ ( α u / 2 ) u x sin ⁡ ( θ u / 2 ) u y sin ⁡ ( θ u / 2 ) u z sin ⁡ ( θ u / 2 ) } \mathbf{q}=\left\{ \begin{array}{c} \cos(\alpha_u / 2)\\ {u}_x \sin(\theta_u / 2)\\ {u}_y \sin(\theta_u / 2)\\ {u}_z \sin(\theta_u / 2) \end{array} \right\} q= cos(αu/2)uxsin(θu/2)uysin(θu/2)uzsin(θu/2)

在这里插入图片描述
只有具有单位范数的四元数表示有效的旋转。四元数可以用不同的方式构建。
构建表示没有旋转的等效四元数的示例:

ChQuaternion<> qA(1,0,0,0);
ChQuaternion<> qB(QUNIT);
ChQuaternion<> qC = QUNIT;

四元数可以作为关于单位向量 u \mathbf{u} u旋转 θ u \theta{u} θu的函数,用以下公式构建:

ChQuaternion<> qA = Q_from_AngAxis(theta, u);

通过使用四元数的.Rotate()成员函数,可以很容易地通过四元数旋转点。下面的示例显示了如何将点绕y轴旋转20度:

ChVector vA(1,2,3);
ChVector vB();
ChQuaternion qA = Q_from_AngAxis(20 * CH_C_DEG_TO_RAD, VECT_Y);
vB = qA.Rotate(vA);

*运算符用于执行四元数乘积。从运动学角度来看,这表示旋转的串联。

旋转矩阵

在Chrono中使用旋转矩阵 A \mathbf{A} A来表征参考系相对于不同参考系的3D定向。与旋转矩阵概念相关的大多数实现支持都封装在chrono::ChMatrix33中。以下是给出四元数的Chrono函数,可生成3x3方向矩阵 q ↦ A \mathbf{q} \mapsto \mathbf{A} qA,反之亦然 A ↦ q \mathbf{A} \mapsto \mathbf{q} Aq,注意,旋转矩阵是正交矩阵, A ∈ S O ( 3 ) \mathbf{A} \in \mathsf{SO}(3) ASO(3),因此 A − 1 = A t \mathbf{A}^{-1} = \mathbf{A}^{t} A1=At.
创建一个旋转矩阵

ChMatrix33<> mB(1);  // Unit matrix, this is a rotation matrix, meaning no rotation
ChMatrix33<> mC(quat); // Build a rotation matrix from a given quaternion

*运算符可以将两个旋转矩阵相乘,例如,旋转mA之后旋转mB变为:

ChMatrix33<> mC = mB * mA;

*运算符可以乘以ChVector<>,这对应于旋转矢量:

ChVector<> vB = m * vA;

逆旋转是矩阵的逆,也是转置。

坐标

chrono::ChCoordsys表示三维空间中的坐标系。它嵌入向量(坐标平移 d \mathbf{d} d)和四元数(坐标旋转 q \mathbf{q} q):
c = { d , q } \mathbf{c}=\{\mathbf{d},\mathbf{q}\} c={d,q}
ChCoordys是ChFrame的轻量级版本,下面将对此进行讨论。

ChFrame 坐标架

chrono::ChFrame表示三维空间中的坐标系,如ChCoordsys,但包含更高级的功能。
在这里插入图片描述
如上图所示,ChFrame对象表示坐标系 b \mathbf{b} b相对于另一坐标系 a \mathbf{a} a的“旋转”和“移位”程度。很多时候 a \mathbf{a} a是绝对参考系。
d a , b ( c ) \mathbf{d}_{a,b(c)} da,b(c)
用于定义,以基 c \mathbf{c} c表示从点 b \mathbf{b} b开始,到点 a \mathbf{a} a结束的矢量 d \mathbf{d} d(沿坐标系 c \mathbf{c} c的x、y、z轴测量),如果省略 b \mathbf{b} b,则假定它是绝对参考系的原点。作为ChCoordsys,ChFrame对象具有用于平移的矢量和用于旋转的四元数
c = { d , q } \mathbf{c}=\{\mathbf{d},\mathbf{q}\} c={d,q}
作为四元数的替代,ChFrame对象还存储辅助3x3旋转矩阵,该矩阵可用于在四元数效率较低的情况下加快计算速度。
ChCoordsys可以被视为ChFrame的轻量级版本。
为了节省内存或如果不需要高级功能,ChCoordsys<>可以是更好的选择。
有几种方法可以构建ChFrame。例如:

ChFrame<> Xa;          // build default frame: zero translation, no rotation
ChFrame<> Xb(va, qa);  // build from given translation va and rotation quaternion qa
ChFrame<> Xc(csys);    // build from a given ChCoordys<>
ChFrame<> Xd(va, tetha, u); // build from translation va and rotation theta about axis u

ChFrame对象最重要的特征之一是能够变换点和其他ChFrame对象。
示例:将点从局部坐标系 b \mathbf{b} b转换为绝对坐标系 a \mathbf{a} a
在这里插入图片描述
通常一个仿射变换 使用涉及矩阵a旋转和平移的:
这可以在Chrono中完成,如下所示:

ChVector<> d_Paa, d_baa, d_Pbb;
ChMatrix33<> A_ba;
...
d_Paa = d_baa + A_ba * d_Pbb;

然而,ChFrame<>类使其更简单:

ChVector<> d_Paa, d_Pbb;
ChFrame<> X_ba;
...
d_Paa = X_ba * d_Pbb;

同样的概念可以用于链坐标变换。例如如果从坐标架 c \mathbf{c} c b \mathbf{b} b和从 b \mathbf{b} b a \mathbf{a} a的变换是已知的,则可以找到总的框架旋转和位移。
在这里插入图片描述

ChFrame<> X_ba, X_cb, X_ca;
...
X_ca = X_ba * X_cb;

这意味着使用不那么复杂的表示。符号被循环使用,以强调后一种形式在使用位移和四元数时具有相同的含义:
在这里插入图片描述
上面的转换可以用替换运算符>>表示,其操作数相对于*运算符交换:

ChFrame<> X_ba, X_cb, X_ca;
...
X_ca = X_cb >> X_ba;     // equivalent to   X_ca = X_ba * X_cb;

在Chrono中,ChCorrdsys<>与ChFrame和ChFrameMoving(定义如下)之间的大部分转换可以用两种等效的方式表示:
…使用*运算符从右到左转换,如:X_ca = X_ba * X_cb
…使用>>运算符从左到右转换,如:``X_ca = X_cb >> X_ba

后者有一些优点:
它更“直观”(参见下标cb-ba如何遵循“链”),
第一个操作数是矢量,如vnew = v >> X_dc >> X_cb >> X_ba,编译器的默认行为是从左侧执行操作,从而生成一系列返回临时向量的矩阵乘ChFrame操作。否则,*运算符将创建多个ChFrame<>临时对象,这会比较慢。

还可以对其他对象使用*或>>运算符,例如在ChFrame Xa和ChVector vb之间使用>>。此操作的结果是一个新的ChFrame对象,该对象通过矢量vb转换旧对象而获得:

ChVector<> vb;
ChFrame<> Xa, Xt; ...
Xt = Xa >> vb;    // also  Xt = vb * Xa;

对于可以用于平移或旋转ChFrame的在位运算符*=或>>=,或者完全转换,这取决于它的使用方式:使用ChVector或ChQuaternion或另一个ChFrame。例如,要通过矢量vb转换Xa,可以写下:

Xa >>= vb;    

请注意,虽然运算符 * 和>>创建临时对象,但*=或>>=并非如此,这会提高效率。在这种情况下,经验法则是避免:

  • 操作符*和>>
  • 使用低级函数,如TransformLocalToParent、TransformParentToLocal等。

*和>>操作都支持逆变换。示例:在关系式X_ca=X_cb>>X_ba中;假设X_ca和X_cb是已知的,并且人们对计算X_ba感兴趣。将方程两边乘以X_cb的倒数,得到

X_ba = X_cb.GetInverse() >> X_ca;    

注意,GetInverse操作可能比可读性较差的低级方法(在本例中为TransformParentToLocal())效率低,即:

X_ba = X_cb.TransformParentToLocal(X_ca);    

有关API详细信息,请参阅chrono::ChFrame

ChFrameMoving

chrono::ChFrameMoving对象表示三维空间中的坐标系,像ChFrame一样,但它也存储有关帧的速度和加速度的信息:
c = { p , q , p ˙ , q ˙ , p ¨ , q ¨ } \mathbf{c}=\{\mathbf{p},\mathbf{q},\dot{\mathbf{p}}, \dot{\mathbf{q}}, \ddot{\mathbf{p}}, \ddot{\mathbf{q}} \} c={p,q,p˙,q˙,p¨,q¨}
注意,使用四元数导数来表示角速度和角加速度可能很麻烦。因此,该类还可以设置和获取角速度 ω \mathbf{\omega} ω和角加速度 α \mathbf{\alpha} α方面的数据:
c = { p , q , p ˙ , ω , p ¨ , α } \mathbf{c}=\{\mathbf{p},\mathbf{q},\dot{\mathbf{p}}, \mathbf{\omega}, \ddot{\mathbf{p}}, \mathbf{\alpha}\} c={p,q,p˙,ω,p¨,α}
这可以通过下图直观地显示出来:
在这里插入图片描述
注意,“角”速度和加速度可以在移动z坐标架或绝对坐标架的基础上设置或者获得。
示例:创建ChFrameMoving,并为其指定非零角速度和线速度,同时还指定了线加速度和角加速度。

ChFrameMoving<> X_ba;
X_ba.SetPos(ChVector<>(2,3,5));
X_ba.SetRot(myquaternion);
 
// set velocity 
X_ba.SetPos_dt(ChVector<>(100,20,53)); 
X_ba.SetWvel_loc(ChVector<>(0,40,0)); // W in local frame, or..
X_ba.SetWvel_par(ChVector<>(0,40,0)); // W in parent frame
 
// set acceleration
X_ba.SetPos_dtdt(ChVector<>(13,16,22)); 
X_ba.SetWacc_loc(ChVector<>(80,50,0)); // a in local frame, or..
X_ba.SetWacc_par(ChVector<>(80,50,0)); // a in parent frame

ChFrameMoving可用于变换ChVector(空间中的点)、ChFrame或ChFrameMoving 对象。速度也可以被计算和转换。
示例:如果已知从 b \mathbf{b} b a \mathbf{a} a和从 c \mathbf{c} c b \mathbf{b} b的变换,则可以计算 c \mathbf{c} c相对于 a \mathbf{a} a的绝对速度和角速度:
在这里插入图片描述
使用两种替代形式(基于>>运算符的从左到右,或基于*运算符的从右到左),上述情况可转换为以下等效表达式:

X_ca = X_cb >> X_ba;
X_ca = X_ba * X_cb;

这与ChFrame和ChCoordsys中使用的代数完全相同,只是这一次速度和加速度也进行了转换。
注意,转换自动考虑了复杂项的贡献,如向心加速度、相对加速度、科里奥利加速度等。
以下是另一个较长的转换串联示例:
在这里插入图片描述
注意,还可以使用GetInverse()使用坐标架的逆变换,如ChFrame所示。
示例:计算移动目标8相对于夹具6的位置、速度和加速度,以框架6为基础表示。
在这里插入图片描述
在已知其他所有变换时如何计算X_86?从X_80的两个等价表达式开始:

X_86>>X_65>>X_54>>X_43>>X_32>>X_21>>X_10 = X_87>>X_70; 

或者

X_86>>(X_65>>X_54>>X_43>>X_32>>X_21>>X_10) = X_87>>X_70;

将两边乘以(…)的倒数,记住一般情况下

  • X >> X.GetInverse() = I
  • X.GetInverse() >> X = I,
    其中I是可以移除的身份转换,最终得到:
X_86 = X_87 >> X_70 >> (X_65 >> X_54 >> X_43 >> X_32 >> X_21 >> X_10).GetInverse();

基于同一图的示例:计算夹具相对于移动目标8的速度和加速度,以参考系8为基础表示。

X_68 = X_12 >> X_23 >> X_34 >> X_45 >> X_56 >> (X_87 >> X_70).GetInverse();

返回首页目录,交流学习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值