• 角速度变化时四元数和旋转矩阵微分方程的证明


    摘要: 本文证明了在角速度向量不是常数时,四元数和旋转矩阵微分方程依然成立,成立的条件和性质等,并指出了大部分资料里给出四元数微分方程时没有提到的一个关于角速度向量在哪个坐标系下表示的重要细节,最后给出仿真验证。

    四元数和旋转矩阵微分方程分别指下面两式
    Q ˙ ( t ) = 1 2 Q ( t ) ∘ W ( t ) R ˙ ( t ) = w ⃗ ( t ) × R ( t ) \dot Q(t)=\frac 12Q(t)\circ W(t) \\ \dot R(t)=\vec w(t)\times R(t) Q˙(t)=21Q(t)W(t)R˙(t)=w (t)×R(t)

    1. 四元数微分方程的证明

      首先列出一些需要用到的四元数公式(基本知识见参考链接[1]),其中 ∘ \circ 表示四元数乘法。
    Q 1 ∘ Q 2 = [ s 1 , v ⃗ 1 ] ∘ [ s 2 , v ⃗ 2 ] = [ s 1 s 2 − v ⃗ 1 ⋅ v ⃗ 2 , s 1 v ⃗ 2 + s 2 v ⃗ 1 + v ⃗ 1 × v ⃗ 2 ] Q = [ s , v ⃗ ] ,   Q − 1 = [ s , − v ⃗ ] ,   Q ∘ Q − 1 = [ 1 , 0 ] d Q d t ∘ Q − 1 + Q ∘ d ( Q − 1 ) d t = 0 Q_1\circ Q_2=[s_1,\vec v_1]\circ[s_2,\vec v_2] =[s_1s_2-\vec v_1\cdot\vec v_2,s_1\vec v_2+s_2\vec v_1+\vec v_1\times\vec v_2] \\ Q=[s,\vec v],\ Q^{-1}=[s,-\vec v],\ Q\circ Q^{-1}=[1,0] \\ \frac{\text dQ}{\text dt}\circ Q^{-1}+Q\circ \frac{\text d(Q^{-1})}{\text dt}=0 Q1Q2=[s1,v 1][s2,v 2]=[s1s2v 1v 2,s1v 2+s2v 1+v 1×v 2]Q=[s,v ], Q1=[s,v ], QQ1=[1,0]dtdQQ1+Qdtd(Q1)=0
    四元数微分方程有两个等价形式,本文主要推导更常见的第一种形式
    [ q ˙ 0 q ˙ 1 q ˙ 2 q ˙ 3 ] = 1 2 [ 0 − w x − w y − w z w x 0 − w z w y w y w z 0 − w x w z − w y w x 0 ] [ q 0 q 1 q 2 q 3 ]

    [q˙0q˙1q˙2q˙3]" role="presentation" style="position: relative;">[q˙0q˙1q˙2q˙3]
    =\frac{1}{2}
    [0wxwywzwx0wzwywywz0wxwzwywx0]" role="presentation" style="position: relative;">[0wxwywzwx0wzwywywz0wxwzwywx0]
    [q0q1q2q3]" role="presentation" style="position: relative;">[q0q1q2q3]
    q˙0q˙1q˙2q˙3 =21 0wxwywzwx0wzwywywz0wxwzwywx0 q0q1q2q3
    当把角速度向量写成四元数形式(即 W = [ 0 , w ⃗ ] W=[0,\vec w] W=[0,w ])时还可以写作
    Q ˙ ( t ) = 1 2 W ( t ) ∘ Q ( t ) \dot Q(t)=\frac 12W(t)\circ Q(t) Q˙(t)=21W(t)Q(t)
    或写成向量形式
    [ s ˙ v ⃗ ˙ ] = 1 2 [ 0 − w ⃗ T w ⃗ w ⃗ × ] [ s v ⃗ ]
    [s˙v˙]" role="presentation" style="position: relative;">[s˙v˙]
    =\frac{1}{2}
    [0wTww×]" role="presentation" style="position: relative;">[0wTww×]
    [sv]" role="presentation" style="position: relative;">[sv]
    [s˙v ˙]=21[0w w Tw ×][sv ]

    特别注意,当角速度在世界系下表示时,这里的 w ⃗ × \vec w^\times w × 前面的符号为正,大部分资料里给出的都是角速度在本体系下的表示,此时符号为负,后面会详细解释。

    1.1 四元数旋转公式

      对任意单位四元数
    Q = [ cos ⁡ θ 2 , n ⃗ sin ⁡ θ 2 ] Q=\left[\cos\frac\theta 2,\vec n\sin\frac\theta 2\right] Q=[cos2θ,n sin2θ]
    和任意向量 v ⃗ ∈ R 3 \vec v\in\mathbb R^3 v R3,下面的公式(或算子)
    L q ( v ⃗ ) = Q ∘ V ∘ Q − 1 L_q(\vec v)=Q\circ V\circ Q^{-1} Lq(v )=QVQ1
    等价于将向量 v ⃗ \vec v v 沿旋转轴 n ⃗ \vec n n 旋转了 θ \theta θ 角度,其中 V = [ 0 , v ⃗ ] V=[0,\vec v] V=[0,v ] 表示向量 v ⃗ \vec v v 的四元数形式。
    证明: (见参考链接[2],有空继续补充)

    1.2 正式推导

      这个推导来自参考链接[3],与参考链接[4]相比我认为更简单,没有复杂的坐标系变换,只用了基本的求导,证明过程非常精彩。推导中为了方便起见省略了四元数乘法符号 ∘ \circ
      根据四元数旋转公式
    R ( t ) = Q ( t ) R 0 Q − 1 ( t ) R(t) = Q(t)R_0Q^{-1}(t) R(t)=Q(t)R0Q1(t)
    其中 R ( t ) R(t) R(t) 表示向量 R ⃗ \vec R R 的四元数形式,于是
    R ˙ ( t ) = Q ˙ ( t ) R 0 Q − 1 ( t ) + Q ( t ) R 0 d d t ( Q − 1 ( t ) ) = Q ˙ Q − 1 R Q Q − 1 + Q Q − 1 R Q d d t ( Q − 1 ) = Q ˙ Q − 1 R + R Q d d t ( Q − 1 ) = Q ˙ Q − 1 R − R Q ˙ Q − 1

    R˙(t)=Q˙(t)R0Q1(t)+Q(t)R0ddt(Q1(t))=Q˙Q1RQQ1+QQ1RQddt(Q1)=Q˙Q1R+RQddt(Q1)=Q˙Q1RRQ˙Q1" role="presentation" style="position: relative;">R˙(t)=Q˙(t)R0Q1(t)+Q(t)R0ddt(Q1(t))=Q˙Q1RQQ1+QQ1RQddt(Q1)=Q˙Q1R+RQddt(Q1)=Q˙Q1RRQ˙Q1
    R˙(t)====Q˙(t)R0Q1(t)+Q(t)R0dtd(Q1(t))Q˙Q1RQQ1+QQ1RQdtd(Q1)Q˙Q1R+RQdtd(Q1)Q˙Q1RRQ˙Q1
    其中第1行到第2行是因为 R 0 = Q − 1 ( t ) R ( t ) Q ( t ) R_0=Q^{-1}(t)R(t)Q(t) R0=Q1(t)R(t)Q(t)。因为单位四元数模长为1,等式两边对 t t t 求导
    q 0 2 ( t ) + q 1 2 ( t ) + q 2 2 ( t ) + q 3 2 ( t ) = 1 2 q 0 q ˙ 0 + 2 q 1 q ˙ 1 + 2 q 2 q ˙ 2 + 2 q 3 q ˙ 3 = 0
    q02(t)+q12(t)+q22(t)+q32(t)=12q0q˙0+2q1q˙1+2q2q˙2+2q3q˙3=0" role="presentation" style="position: relative;">q02(t)+q12(t)+q22(t)+q32(t)=12q0q˙0+2q1q˙1+2q2q˙2+2q3q˙3=0
    q02(t)+q12(t)+q22(t)+q32(t)=12q0q˙0+2q1q˙1+2q2q˙2+2q3q˙3=0

    所以
    Q ˙ Q − 1 = [ q ˙ s , q ⃗ v ˙ ] [ q s , − q ⃗ v ] = [ q ˙ s q s + q ⃗ v ˙ ⋅ q ⃗ v , q s q ⃗ v ˙ − q ˙ s q ⃗ v − q ⃗ ˙ v × q ⃗ v ] = [ 0 , q s q ⃗ v ˙ − q ˙ s q ⃗ v − q ⃗ ˙ v × q ⃗ v ]
    Q˙Q1=[q˙s,qv˙][qs,qv]=[q˙sqs+qv˙qv,qsqv˙q˙sqvq˙v×qv]=[0,qsqv˙q˙sqvq˙v×qv]" role="presentation" style="position: relative;">Q˙Q1=[q˙s,qv˙][qs,qv]=[q˙sqs+qv˙qv,qsqv˙q˙sqvq˙v×qv]=[0,qsqv˙q˙sqvq˙v×qv]
    Q˙Q1===[q˙s,q v˙][qs,q v][q˙sqs+q v˙q v,qsq v˙q˙sq vq ˙v×q v][0,qsq v˙q˙sq vq ˙v×q v]

    Q ˙ Q − 1 \dot QQ^{-1} Q˙Q1 的向量部分简记作 v ⃗ 1 = q s q ⃗ v ˙ − q ˙ s q ⃗ v − q ⃗ ˙ v × q ⃗ v \vec v_1=q_s\dot{\vec q_v}-\dot q_s\vec q_v-\dot{\vec q}_v\times\vec q_v v 1=qsq v˙q˙sq vq ˙v×q v(后面也不会再拆开了),继续推导
    R ˙ ( t ) = [ 0 , v ⃗ 1 ] [ 0 , r ⃗ ] − [ 0 , r ⃗ ] [ 0 , v ⃗ 1 ] = [ 0 , 2 v ⃗ 1 × r ⃗ ]
    R˙(t)=[0,v1][0,r][0,r][0,v1]=[0,2v1×r]" role="presentation" style="position: relative;">R˙(t)=[0,v1][0,r][0,r][0,v1]=[0,2v1×r]
    R˙(t)==[0,v 1][0,r ][0,r ][0,v 1][0,2v 1×r ]

    根据角速度公式得到
    r ⃗ ˙ = w ⃗ × r ⃗ = 2 v ⃗ 1 × r ⃗ \dot{\vec r}=\vec w\times\vec r=2\vec v_1\times\vec r r ˙=w ×r =2v 1×r
    因为该式对刚体上的任意向量 r ⃗ \vec r r 都成立,所以必然有 w ⃗ = 2 v ⃗ 1 \vec w=2\vec v_1 w =2v 1,写成四元数形式为
    W = 2 Q ˙ Q − 1 ,   Q ˙ = 1 2 W Q W=2\dot QQ^{-1},\ \dot Q=\frac 12WQ W=2Q˙Q1, Q˙=21WQ
    式中的 W W W Q Q Q 都是四元数,与矩阵形式等价。

    1.3 角速度不变的特殊情况

      角速度不变时,角速度向量与四元数的虚部方向相同
    Q ( t ) = [ cos ⁡ θ ( t ) 2 i sin ⁡ θ ( t ) 2 j sin ⁡ θ ( t ) 2 k sin ⁡ θ ( t ) 2 ] = [ cos ⁡ w t 2 w x w sin ⁡ w t 2 w y w sin ⁡ w t 2 w z w sin ⁡ w t 2 ] = [ cos ⁡ w t 2 ( 1 w sin ⁡ w t 2 ) w ⃗ ] Q(t)=

    [cosθ(t)2isinθ(t)2jsinθ(t)2ksinθ(t)2]" role="presentation" style="position: relative;">[cosθ(t)2isinθ(t)2jsinθ(t)2ksinθ(t)2]
    =
    [coswt2wxwsinwt2wywsinwt2wzwsinwt2]" role="presentation" style="position: relative;">[coswt2wxwsinwt2wywsinwt2wzwsinwt2]
    =
    [coswt2(1wsinwt2)w]" role="presentation" style="position: relative;">[coswt2(1wsinwt2)w]
    Q(t)= cos2θ(t)isin2θ(t)jsin2θ(t)ksin2θ(t) = cos2wtwwxsin2wtwwysin2wtwwzsin2wt =[cos2wt(w1sin2wt)w ]
    其中 w = w x 2 + w y 2 + w z 2 w=\sqrt{w_x^2+w_y^2+w_z^2} w=wx2+wy2+wz2 是角速度大小。
    W Q ( t ) = [ 0 − w ⃗ T w ⃗ w ⃗ × ] [ cos ⁡ w t 2 ( 1 w sin ⁡ w t 2 ) w ⃗ ] = [ − ( 1 w sin ⁡ w t 2 ) w ⃗ T w ⃗ w ⃗ cos ⁡ w t 2 + ( 1 w sin ⁡ w t 2 ) w ⃗ × w ⃗ ] = [ − w sin ⁡ w t 2 w ⃗ cos ⁡ w t 2 ] = 2 Q ˙ ( t )
    WQ(t)=[0wTww×][coswt2(1wsinwt2)w]=[(1wsinwt2)wTwwcoswt2+(1wsinwt2)w×w]=[wsinwt2wcoswt2]=2Q˙(t)" role="presentation" style="position: relative;">WQ(t)=[0wTww×][coswt2(1wsinwt2)w]=[(1wsinwt2)wTwwcoswt2+(1wsinwt2)w×w]=[wsinwt2wcoswt2]=2Q˙(t)
    WQ(t)===[0w w Tw ×][cos2wt(w1sin2wt)w ][(w1sin2wt)w Tw w cos2wt+(w1sin2wt)w ×w ][wsin2wtw cos2wt]=2Q˙(t)

    但是当角速度变化时,也就是 θ ( t ) ≠ w t \theta(t)\neq wt θ(t)=wt 时,这种关系不成立,角速度向量与四元数的虚部不再同向。这两者之间的关系有待进一步研究。
      进一步研究发现,不需要严格满足角速度是常数,只需要保持角速度的方向不变,四元数的虚部就与角速度方向相同。这一点也可以直观理解,四元数可以近似看作角速度积分后的结果,如果角速度一直在变的话,四元数虚部的方向就可以看作是,从0时刻开始到当前时刻的过程中一直在变化的方向的"平均方向",而角速度是当前时刻的瞬时方向,所以当且仅当角速度方向不变时,四元数虚部与角速度方向相同。

    1.4 叉乘项的符号问题

      前面推出当角速度在世界系下表示时的四元数微分方程为
    Q ˙ = 1 2 W Q \dot Q=\frac 12WQ Q˙=21WQ
    现在用四元数将角速度从世界系转换到本体系就可以得到主流的公式。旋转矩阵的一个含义是,将一个向量在本体系下的坐标左乘旋转矩阵就可以得到该向量在世界系下的表示,同理四元数的含义是将一个向量在本体系下的坐标进行四元数旋转操作就可以得到该向量在世界系下的表示,即
    W I = Q W b Q − 1 W_I=QW_bQ^{-1} WI=QWbQ1
    代入四元数微分方程得到
    Q ˙ = 1 2 W I Q = 1 2 Q W b Q − 1 Q = 1 2 Q W b = 1 2 [ s , v ⃗ ] [ 0 , w ⃗ ] = [ − v ⃗ T w ⃗ , s w ⃗ − w ⃗ × v ⃗ ] = 1 2 [ 0 − w ⃗ T w ⃗ − w ⃗ × ] [ s v ⃗ ] = 1 2 W Q

    Q˙=12WIQ=12QWbQ1Q=12QWb=12[s,v][0,w]=[vTw,sww×v]=12[0wTww×][sv]=12WQ" role="presentation" style="position: relative;">Q˙=12WIQ=12QWbQ1Q=12QWb=12[s,v][0,w]=[vTw,sww×v]=12[0wTww×][sv]=12WQ
    Q˙====21WIQ=21QWbQ1Q=21QWb21[s,v ][0,w ]=[v Tw ,sw w ×v ]21[0w w Tw ×][sv ]21WQ
    也就是说,叉乘项 w ⃗ × \vec w^\times w × 的符号取决于角速度在哪个坐标系下描述惯性系下为正,本体系下为负。旋转矩阵微分方程也有类似的性质,后面细说。

    2. 旋转矩阵微分方程的证明

    旋转矩阵 R ( t ) R(t) R(t) 满足
    R ˙ ( t ) = w ⃗ ( t ) × R ( t ) \dot R(t)=\vec w(t)\times R(t) R˙(t)=w (t)×R(t)
    其中 w ⃗ \vec w w 为世界系下描述的角速度。

    2.1 角速度不变的推导

      这个推导来自参考文献[5]。书中是在假设角速度不变的前提下推导的,而且也没有说明角速度向量的实际含义。
      旋转矩阵 R ( t ) R(t) R(t) 是正交矩阵,满足
    R R T = I RR^\text T=I RRT=I
    等式两边同时对时间 t t t 求导得到
    R ˙ R T + R R ˙ T = R ˙ R T + ( R ˙ R T ) T = 0 \dot RR^\text T+R\dot R^\text T=\dot RR^\text T+(\dot RR^\text T)^\text T =0 R˙RT+RR˙T=R˙RT+(R˙RT)T=0
    可以看出 R ˙ ( t ) R T ( t ) \dot R(t)R^\text T(t) R˙(t)RT(t) 是个反对称矩阵,用 M ( t ) M(t) M(t) 表示。等式两边同时右乘 R ( t ) R(t) R(t) 得到
    R ˙ ( t ) R T ( t ) = M ( t ) R ˙ ( t ) = M ( t ) R ( t ) \dot R(t)R^\text T(t)=M(t) \\ \dot R(t)=M(t)R(t) \\ R˙(t)RT(t)=M(t)R˙(t)=M(t)R(t)
    式中的 M ( t ) M(t) M(t) 实际上就是角速度对应的反对称矩阵 w × w^\times w×,当角速度不变时, M ( t ) M(t) M(t) 为常数,旋转矩阵的解为
    R ˙ ( t ) = w × R ( t ) R ( t ) = e w × t R 0 \dot R(t)=w^\times R(t) \\ R(t)=\text e^{w^\times t}R_0 R˙(t)=w×R(t)R(t)=ew×tR0

    例如,绕z轴的旋转矩阵为
    R = [ cos ⁡ t − sin ⁡ t 0 sin ⁡ t cos ⁡ t 0 0 0 1 ] R=

    [costsint0sintcost0001]" role="presentation" style="position: relative;">[costsint0sintcost0001]
    R= costsint0sintcost0001

    w × R ( t ) = [ 0 − 1 0 1 0 0 0 0 0 ] [ cos ⁡ t − sin ⁡ t 0 sin ⁡ t cos ⁡ t 0 0 0 1 ] = [ − sin ⁡ t − cos ⁡ t 0 cos ⁡ t − sin ⁡ t 0 0 0 1 ] = R ˙ ( t ) w^\times R(t)=
    [010100000]" role="presentation" style="position: relative;">[010100000]
    [costsint0sintcost0001]" role="presentation" style="position: relative;">[costsint0sintcost0001]
    =
    [sintcost0costsint0001]" role="presentation" style="position: relative;">[sintcost0costsint0001]
    =\dot R(t)
    w×R(t)= 010100000 costsint0sintcost0001 = sintcost0costsint0001 =R˙(t)

    2.2 角速度变化的推导

      当角速度变化时,旋转矩阵微分方程仍然成立。我想到的不严谨的证明方法是只需要证明角速度公式
    r ⃗ ˙ ( t ) = ω ⃗ ( t ) × r ⃗ ( t ) \dot{\vec r}(t)=\vec\omega(t)\times\vec r(t) r ˙(t)=ω (t)×r (t)
    成立即可(证明见参考链接[6]),然后旋转矩阵等价于矩阵中的3个正交坐标轴向量在世界系下的坐标,因此当3个坐标轴成立时旋转矩阵就成立
    [ e ⃗ x ˙ e ⃗ y ˙ e ⃗ z ˙ ] = ω ⃗ ( t ) × [ e ⃗ x e ⃗ y e ⃗ z ]

    [ex˙ey˙ez˙]" role="presentation" style="position: relative;">[ex˙ey˙ez˙]
    =\vec\omega(t)\times
    [exeyez]" role="presentation" style="position: relative;">[exeyez]
    [e x˙e y˙e z˙]=ω (t)×[e xe ye z]
    不知道有没有严谨证明。

    2.3 角速度的符号问题

      与四元数类似,当角速度在本体系下描述时且旋转矩阵表示成世界系到本体系时,角速度取负号,于是有了3种等价的旋转矩阵微分方程表示方法
    R ˙ T = − w ⃗ × R T R ˙ = R w ⃗ × R ˙ = ( R w ⃗ ) × R

    R˙T=w×RTR˙=Rw×R˙=(Rw)×R" role="presentation" style="position: relative;">R˙T=w×RTR˙=Rw×R˙=(Rw)×R
    R˙T=R˙=R˙=w ×RTRw ×(Rw )×R
    其中 w ⃗ \vec w w 为本体系下描述的角速度,与前面不同。其中第一种是主流教材中的表示,第二种是一种较为简洁的形式,第三种的意思是先把角速度从本体系转换到世界系。下面证明这3种表示方法等价。
    R ˙ = − ( w ⃗ × R T ) T = − R ( w ⃗ × ) T = R w ⃗ × R ˙ = ( R w ⃗ ) × R = R ( w ⃗ × I ) = R w ⃗ ×
    R˙=(w×RT)T=R(w×)T=Rw×R˙=(Rw)×R=R(w×I)=Rw×" role="presentation" style="position: relative;">R˙=(w×RT)T=R(w×)T=Rw×R˙=(Rw)×R=R(w×I)=Rw×
    R˙=R˙=(w ×RT)T=R(w ×)T=Rw ×(Rw )×R=R(w ×I)=Rw ×

    其中第二行用到了向量叉乘的乘法分配律,见 刚体姿态动力学推导与进动现象仿真 的附录。

    3. 参考

    1. Understanding Quaternions -3D Game Engine Programming
    2. Quaternions and Rotations
    3. Quaternion differentiation -euclideanspace
    4. 四元数微分方程的推导和解算实现 -知乎
    5. 高博. 视觉SLAM十四讲[M]. 电子工业出版社.
    6. How to derive the formula for angular velocity? -stackexchange
    7. 汤锡生. 载人飞船轨道确定和返回控制. 国防工业出版社.
    8. 屠善澄. 卫星姿态动力学与控制[M]. 宇航出版社.

    4. 仿真验证

      下面的验证程序的思路是,同时对四元数和旋转矩阵两个微分方程
    R ˙ ( t ) = w × ( t ) R ( t ) Q ˙ ( t ) = 1 2 W ( t ) Q ( t )

    R˙(t)=w×(t)R(t)Q˙(t)=12W(t)Q(t)" role="presentation" style="position: relative;">R˙(t)=w×(t)R(t)Q˙(t)=12W(t)Q(t)
    R˙(t)=w×(t)R(t)Q˙(t)=21W(t)Q(t)
    输入变化的角速度(可以自己另外设置)
    w ⃗ ( t ) = [ 1 ln ⁡ ( t + 1 ) cos ⁡ ( t ) ] \vec w(t)=
    [1ln(t+1)cos(t)]" role="presentation" style="position: relative;">[1ln(t+1)cos(t)]
    w (t)= 1ln(t+1)cos(t)

    t = 1 t=1 t=1 10 10 10 的10个时刻时,将输出的四元数 Q ( t ) Q(t) Q(t) 转换成旋转矩阵 R q ( t ) R_q(t) Rq(t) 与输出的旋转矩阵 R ( t ) R(t) R(t) 比较,可以验证两者相等,并且旋转矩阵微分方程的三种表示方法等价。
      同时可以进一步验证,当角速度的方向不固定时,四元数的虚部与角速度向量不同向。方法是把这两个向量叉乘看是否为0即可。
      simucpp 代码如下

    /**************************************************************
    // 验证四元数和旋转矩阵微分方程
    simucpp版本:2.1.14
    **************************************************************/
    #include 
    #include 
    #include "simucpp.hpp"
    using namespace simucpp;
    using namespace zhnmat;
    using namespace std;
    
    double Matrix_Error(Mat materr) {
        double sumerr = 0;  // 误差平方和
        for (uint32_t i = 0; i < 3; i++)
            for (uint32_t j = 0; j < 3; j++)
                sumerr += materr.at(i, j)*materr.at(i, j);
        return sumerr;
    }
    
    int main() {
        Simulator sim1;
        auto intR = new MStateSpace(&sim1, BusSize(3, 3), true, "intR");  // 旋转矩阵R
        auto intQ = new MStateSpace(&sim1, BusSize(4, 1), true, "intQ");  // 姿态四元数Q
        auto misoR = new MFcnMISO(&sim1, BusSize(3, 3), "misoR");  // 旋转矩阵导数R'
        auto misoQ = new MFcnMISO(&sim1, BusSize(4, 1), "misoQ");  // 四元数导数Q'
        auto muxw = new Mux(&sim1, BusSize(3, 1), "muxw");  // 本体系下的角速度向量w
        UInput **inws = new UInput*[3];  // 三轴角速度
        for (uint32_t i = 0; i < 3; i++) {
            inws[i] = new UInput(&sim1, "inw"+to_string(i));
            sim1.connectU(inws[i], muxw, BusSize(i, 0));
        }
        sim1.connectM(muxw, misoR);
        sim1.connectM(intR, misoR);
        sim1.connectM(misoR, intR);
        sim1.connectM(muxw, misoQ);
        sim1.connectM(intQ, misoQ);
        sim1.connectM(misoQ, intQ);
        inws[0]->Set_Function([](double t){ return 1; });  // 设置三轴角速度函数
        inws[1]->Set_Function([](double t){ return log(t+1); });
        inws[2]->Set_Function([](double t){ return cos(t); });
        intR->Set_InitialValue(eye(3));
        intQ->Set_InitialValue(Mat(vecdble{1, 0, 0, 0}));
        misoR->Set_Function([](Mat *u){  // u[0]为本体系下的角速度向量,u[1]为旋转矩阵
            // 下面给出了三种方法
            Mat ans = Antisymmetric(u[1]*u[0])*u[1];
            // Mat ans = (Mat(3, 3)-Antisymmetric(u[0]))*u[1].T(); ans = ans.T();
            // Mat ans = u[1]*Antisymmetric(u[0]);
            return ans;
        });
        misoQ->Set_Function([](Mat *u){  // u[0]为本体系下的角速度向量,u[1]为四元数
            Mat W(4, 4, vecdble{  // 角速度向量对应的四元数乘法左矩阵
                0, -u[0].at(0, 0), -u[0].at(1, 0), -u[0].at(2, 0),
                u[0].at(0, 0), 0, u[0].at(2, 0), -u[0].at(1, 0),
                u[0].at(1, 0), -u[0].at(2, 0), 0, u[0].at(0, 0),
                u[0].at(2, 0), u[0].at(1, 0), -u[0].at(0, 0), 0,
            });
            return 0.5*W*u[1];
        });
        sim1.Set_SimStep(0.01);  // 步长0.01
        sim1.Initialize();
        Vector3d vecw, vecrefw;
        for (uint32_t i = 0; i < 2; i++) {
            for (uint32_t j = 0; j < 99; j++)  // 仿真100步为1秒
                sim1.Simulate_OneStep();
            sim1.Simulate_OneStep();
            Mat matr = intR->Get_OutValue();  // 旋转矩阵
            Mat matq = intQ->Get_OutValue();  // 四元数
            vecw = Vector3d(muxw->Get_OutValue());  //本体系下的角速度向量
            double q0 = matq.at(0, 0);
            double q1 = matq.at(1, 0);
            double q2 = matq.at(2, 0);
            double q3 = matq.at(3, 0);
            Mat matqr = Mat(3, 3, vecdble{  // 四元数转旋转矩阵
                q0*q0+q1*q1-q2*q2-q3*q3, 2*q1*q2-2*q0*q3, 2*q1*q3+2*q0*q2,
                2*q1*q2+2*q0*q3, q0*q0-q1*q1+q2*q2-q3*q3, 2*q2*q3-2*q0*q1,
                2*q1*q3-2*q0*q2, 2*q2*q3+2*q0*q1, q0*q0-q1*q1-q2*q2+q3*q3,
            });
            cout << "err:" << Matrix_Error(matr - matqr) << endl;  // 两个旋转矩阵的误差矩阵
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
  • 相关阅读:
    ClickHouse表引擎
    SpringCloudGateway网关整合swagger3+Knife4j3,basePath丢失请求404问题
    用低代码搭建千人食品制造企业高效管理系统案例分析
    mysql双主互从通过KeepAlived虚拟IP实现高可用
    Clickhouse分布式表式对本地表的对比
    基于DEM的坡度坡向分析
    8.26 Day44---项目部署
    C# Onnx Yolov8 Cls 分类
    JVM高频知识点总结【3】
    Java注解(3):一个真实的Elasticsearch案例
  • 原文地址:https://blog.csdn.net/qq_34288751/article/details/124217941