【自动驾驶中的SLAM技术】第2讲:基础数学知识回顾

第二讲:基础数学回顾

文章目录

  • 第二讲:基础数学回顾
  • 1 几何学
    • 1.1 坐标系
    • 1.2 坐标变换
      • ① 空间向量
      • ② 基变换
      • ③ 坐标变换
      • ④ 总结
    • 1.3 四元数与旋转向量
  • 2 运动学
    • 2.1 李群视角
    • 2.2 四元数视角
    • 2.3 四元数的李代数与旋转向量间的转换
    • 2.4 SO(3)+t 上的运动学
    • 2.5 线速度与加速度
    • 2.6 扰动模型
    • 2.7 关于左扰动和右扰动的选择
      • 2.7.1 第一种形式
      • 2.7.2 第二种形式
    • 2.8 运动学示例:圆周运动
  • 3 滤波器与最优化理论
    • 3.1 状态估计问题与最小二乘
    • 3.2 卡尔曼滤波器
    • 3.3 非线性系统的处理方法-EKF
    • 2.4 最优化方法与图优化
  • 4 关于环境编译
  • 5 习题
    • 5.1 计算
    • 5.2 计算
    • 5.3 设计程序
    • 5.4 GN和LM在处理非线性迭代时的差异

1 几何学

1.1 坐标系

  车辆上会装有各式各样的传感器,下面得顺序都是XYZ车辆本体一般使用前左上(XYZ)或者右前上的顺序来定义它的坐标系,相机坐标系则普遍取右下前的顺序,激光雷达和GNSS通常采用前左上(XYZ)得顺序。

在这里插入图片描述

1.2 坐标变换

  这里定义的是坐标之间的变换关系。 R w b R_{wb} Rwb t w b t_{wb} twb 都用于处理向量之间的坐标变换。而有些资料处理的是坐标轴(或者坐标基底)之间的变换关系,把旋转和平移解释成某个坐标轴从一处变换到了另一处。那样的定义方式是与这里相反
p w = R w b p b + t w b p_w=R_{wb}p_b+t_{wb} pw=Rwbpb+twb
  这里相反得本质就是,基变换
坐标变换
得关系(矩阵论第一讲)

① 空间向量

  对于一个向量来讲,它不会随空间基向量变化而变化,变化的只是其在不同基下的空间坐标!向量 c c c在两组空间基 ( α 1 , α 2 , … , α n ) (\alpha_1,\alpha_2,\ldots,\alpha_n) (α1,α2,,αn) ( β 1 , β 2 , … , β n ) (\beta_1,\beta_2,\ldots,\beta_n) (β1,β2,,βn)下的坐标分别为 [ a 1 a 2 . . . a n ] \begin{bmatrix}a_1\\a_2\\.\\.\\.\\a_n\end{bmatrix} a1a2...an [ b 1 b 2 . . . b n ] \begin{bmatrix}b_1\\b_2\\.\\.\\.\\b_n\end{bmatrix} b1b2...bn 。通过下面这一关系,我们可以得到基变换和坐标变换公式!

c = ( α 1 , α 2 , … , α n ) [ a 1 a 2 . . . a n ] = ( β 1 , β 2 , … , β n ) [ b 1 b 2 . . . b n ] ( 1 ) c=(\alpha_1,\alpha_2,\ldots,\alpha_n)\begin{bmatrix}a_1\\a_2\\.\\.\\.\\a_n\end{bmatrix}=(\beta_1,\beta_2,\ldots,\beta_n)\begin{bmatrix}b_1\\b_2\\.\\.\\.\\b_n\end{bmatrix}\quad(1) c=(α1,α2,,αn) a1a2...an =(β1,β2,,βn) b1b2...bn (1)

② 基变换

  以三维空间为例,两组空间基存在以下的变换
( β 1 β 2 β 3 ) 1 × 3 = ( α 1 α 2 α 3 ) 1 × 3 ⋅ A 3 × 3 ( 2 ) (\beta_{1}\quad\beta_{2}\quad\beta_{3})_{1\times3}=(\alpha_{1}\quad\alpha_{2}\quad\alpha_{3})_{1\times3}\cdot A_{3\times3} \quad(2) (β1β2β3)1×3=(α1α2α3)1×3A3×3(2)

③ 坐标变换

  把基变换公式(2)带入公式(1),即可得到坐标变换公式
[ a 1 a 2 a 3 ] = A 3 × 3 [ b 1 b 2 b 3 ] ( 3 ) \begin{bmatrix}a_1\\a_2\\a_3\end{bmatrix} = A_{3\times3}\begin{bmatrix}b_1\\b_2\\b_3\end{bmatrix} \quad(3) a1a2a3 =A3×3 b1b2b3 (3)

[ b 1 b 2 b 3 ] = A 3 × 3 − 1 [ a 1 a 2 a 3 ] ( 4 ) \begin{bmatrix}b_1\\b_2\\b_3\end{bmatrix}=A_{3\times3}^{-1}\begin{bmatrix}a_1\\a_2\\a_3\end{bmatrix} \quad(4) b1b2b3 =A3×31 a1a2a3 (4)

④ 总结

  从公式(2)和公式(4)可以看出坐标变换和基变换的关系,互为逆矩阵!

坐标变换:左乘
p w = R w b p b + t w b p_w=R_{wb}p_b+t_{wb} pw=Rwbpb+twb
基(坐标轴)变换:右乘转置(逆)
P w = P b R w b T + t w b P_w=P_bR_{wb}^T+t_{wb} Pw=PbRwbT+twb
旋转不影响平移,平移都是以原点来看的(不论是坐标变换,还是基变换)。

1.3 四元数与旋转向量

  利用单位四元数 q = q 0 + q 1 i + q 2 j + q 3 k \boldsymbol{q}=q_0+q_1 \mathrm{i}+\mathrm{q}_2 \mathrm{j}+\mathrm{q}_3 \mathrm{k} q=q0+q1i+q2j+q3k表示旋转,实部表示了旋转角,虚部表示了旋转轴。下面公式可知,实部为0时,虚部刚好为转轴。,

q = [ cos ⁡ θ 2 , n sin ⁡ θ 2 ] T . {\mathbf{q}}=[\cos\frac{\theta}{2},n\sin\frac{\theta}{2}]^\mathrm{T}. q=[cos2θ,nsin2θ]T.

{ θ = 2 arccos ⁡ q 0 [ n x , n y , n z ] T = [ q 1 , q 2 , q 3 ] T / sin ⁡ θ 2 . \left\{\begin{array}{l} \theta=2 \arccos q_0 \\ {\left[n_x, n_y, n_z\right]^{\mathrm{T}}=\left[q_1, q_2, q_3\right]^{\mathrm{T}} / \sin \frac{\theta}{2}} \end{array} .\right. {θ=2arccosq0[nx,ny,nz]T=[q1,q2,q3]T/sin2θ.

  不是是旋转向量,还是四元数,它们只能旋转向量,不可以改变向量的尺度!所以,对于四元数,只可使用单位四元数,对尺度无影响;对于旋转向量,转轴是单位向量,长度只能是转角!

2 运动学

  用 ω 来表达角速度,用 ϕ 来表达旋转向量

2.1 李群视角

  当时间连续变化时,旋转和平移就成为了随时间变化的函数 $R(t) 和 和 t(t)$。平移变量本质就是一个在不断变化的量,这里忽略。
R ⊤ R = I R^\top R=I RR=I
  上式对时间的求导:
d d t ( R ⊤ R ) = R ˙ ⊤ R + R ⊤ R ˙ = 0 \frac{\mathrm{d}}{\mathrm{d}t}\left(R^\top R\right)=\dot{R}^\top R+R^\top\dot{R}=0 dtd(RR)=R˙R+RR˙=0

R ⊤ R ˙ = − ( R ⊤ R ˙ ) ⊤ R^\top\dot{R}=-(R^\top\dot{R})^\top RR˙=(RR˙)

  然后,注意到反对称矩阵经过转置运算后再取负保持不变,即 − ( R ⊤ R ˙ ) ⊤ = R ⊤ R ˙ -(R^\top\dot{R})^\top = R^\top\dot{R} (RR˙)=RR˙,为了简化表达形式,令 ω ∧ ∈ R 3 × 3 = R ⊤ R ˙ \omega^{\wedge}\in\mathbb{R}^{3\times3}=R^{\top}\dot{R} ωR3×3=RR˙,则得泊松方程:
R ˙ = − R ( R ⊤ R ˙ ) ⊤ = R ω ∧ \dot{R}=-R(R^\top\dot{R})^\top\\ =R\omega^{\wedge} R˙=R(RR˙)=Rω
  求导后是一种特殊的微分方程,这种方程都有类似得通解,比如 y ′ = a e a x , y ( 0 ) = 1 y'=ae^{ax},y(0)=1 y=aeax,y(0)=1,则 y = e a x y =e^{ax} y=eax

  考虑瞬时变化,那么在固定得时刻 t t t ω \omega ω就是一个确定的数,即角速度。微分方程初解: t 0 t_0 t0 时刻旋转矩阵为 R ( t 0 ) R(t_0 ) R(t0)。类比可以得到旋转矩阵微分方程得通解:
R ( t ) = R ( t 0 ) exp ⁡ ( ω ∧ ( t − t 0 ) ) \boldsymbol{R}(t)=\boldsymbol{R}(t_0)\exp(\boldsymbol{\omega}^\wedge(t-t_0)) R(t)=R(t0)exp(ω(tt0))
  计 Δ t = t − t 0 \Delta t=t-t_0 Δt=tt0,则:
R ( t ) = R ( t 0 ) E x p ( ω Δ t ) \boldsymbol{R}(t)=\boldsymbol{R}(t_0)\mathrm{Exp}(\boldsymbol{\omega}\Delta t) R(t)=R(t0)Exp(ωΔt)
  在 t = t 0 t = t_0 t=t0处进行泰勒展开:
R ( t 0 + Δ t ) ≈ R ( t 0 ) + R ˙ ( t 0 ) Δ t = R ( t 0 ) + R ( t 0 ) ω ∧ Δ t = R ( t 0 ) ( I + ω ∧ Δ t ) . \begin{aligned} \boldsymbol{R}(t_{0}+\Delta t)& \approx\boldsymbol{R}(t_{0})+\dot{\boldsymbol{R}}(t_{0})\Delta t \\ &=\boldsymbol{R}(t_{0})+\boldsymbol{R}(t_{0})\boldsymbol{\omega}^{\wedge}\Delta t \\ &=\boldsymbol{R}(t_{0})(\boldsymbol{I}+\boldsymbol{\omega}^{\wedge}\Delta t). \end{aligned} R(t0+Δt)R(t0)+R˙(t0)Δt=R(t0)+R(t0)ωΔt=R(t0)(I+ωΔt).
  侧面反映了指数映射形式,注意这里时大写的Exp,所以没有加反对称符号
Exp ⁡ ( ω Δ t ) = I + ω ∧ Δ t + 1 2 ( ω ∧ Δ t ) 2 + . . . \operatorname{Exp}(\boldsymbol{\omega}\Delta t)=\boldsymbol{I}+\boldsymbol{\omega}^{\wedge}\Delta t+\frac{1}{2}(\boldsymbol{\omega}^{\wedge}\Delta t)^2+... Exp(ωΔt)=I+ωΔt+21(ωΔt)2+...

关于这里微分方程求解的补充,可以用定积分求解的方法直接求解这个微分方程的通解,这个解在IMU的运动学方程之离散旋转矩阵中也会用到。

在这里插入图片描述

2.2 四元数视角

  在旋转矩阵R的求导中,利用 R ⊤ R = I R^\top R=I RR=I这一性质。只能使用单位四元数表示旋转, q q ∗ = q ∗ q = 1 qq^*=q^*q=1 qq=qq=1 q q ∗ qq^* qq是两个四元数的模长乘积,仍然是1。非常类似旋转矩阵形式。

  对时间求导:
q ∗ q ˙ + q ∗ q ˙ = 0 \dot{q^*q}+q^*\dot{q}=0 qq˙+qq˙=0

q ∗ q ˙ = − q ∗ q ˙ = − ( q ∗ q ˙ ) ∗ q^*\dot{q}=-\dot{q^*q}=-(\boldsymbol{q^*}\dot{\boldsymbol{q}})^* qq˙=qq˙=(qq˙)

  从上面这个式子中可以得到一个信息, q ∗ q ˙ q^*\dot{q} qq˙是一个纯虚四元数(实部为0)!这是因为负号的存在,共轭只是虚部不一样,但实部一致,那么就只有0满足条件了。

  记一个纯虚四元数 ϖ = [ 0 , ω 1 , ω 2 , ω 3 ⏟ ω ] ⊤ ∈ Q \varpi=[0,\underbrace{\omega_{1},\omega_{2},\omega_{3}}_{\omega}]^{\top}\in\mathcal{Q} ϖ=[0,ω ω1,ω2,ω3]Q,然后令:
q ∗ q ˙ = ϖ q^*\dot{q}=\varpi qq˙=ϖ
  通过下面推导,得到四元数关于时间的导数:
q q ∗ q ˙ = q ϖ s t : q q ∗ = q ∗ q = 1 q ˙ = q ϖ \begin{aligned}qq^*\dot{q}&=q\varpi\quad st:qq^*=q^*q=1\\\dot{q}&=q\varpi\end{aligned} qqq˙q˙=qϖst:qq=qq=1=qϖ
  类比于 SO(3) 的情况,我们也可以讨论在 t 时刻附近的瞬时角速度、李代数、指数映射。在考虑瞬时变化时,可以认为 ϖ ϖ ϖ 为固定值,于是上述微分方程给出解为:
q ( t ) = q ( t 0 ) exp ⁡ ( ϖ Δ t ) \boldsymbol{q}(t)=\boldsymbol{q}(t_0)\exp(\varpi\Delta t) q(t)=q(t0)exp(ϖΔt)
  指数映射
exp ⁡ ( ϖ ) = ∑ k = 0 ∞ 1 k ! ϖ k \exp\left(\varpi\right)=\sum_{k=0}^{\infty}\frac{1}{k!}\varpi^{k} exp(ϖ)=k=0k!1ϖk
  四元数可以表示为角轴,即方向与长度 ϖ = u θ \varpi=\boldsymbol{u}\theta ϖ=uθ θ \theta θ是长度, u u u是纯虚单位四元数。纯虚四元数有以下性质:
u 2 = − 1 , u 3 = − u u^2=-1,\quad u^3=-u u2=1,u3=u
  代入指数映射(会得到一个非常类似于欧拉公式的式子):
exp ⁡ ( u θ ) = 1 + u θ − 1 2 ! θ 2 − 1 3 ! θ 3 u + 1 4 ! θ 4 + … = ( 1 − 1 2 ! θ 2 + 1 4 ! θ 4 − … ) ⏟ cos ⁡ θ + ( θ − 1 3 ! θ 3 + 1 5 ! θ 5 − … ) ⏟ sin ⁡ θ u = cos ⁡ θ + u sin ⁡ θ . \begin{aligned} \exp\left(\boldsymbol{u}\theta\right)& =1+\boldsymbol{u}\theta-\frac1{2!}\theta^{2}-\frac1{3!}\theta^{3}\boldsymbol{u}+\frac1{4!}\theta^{4}+\ldots \\ &=\underbrace{\left(1-\frac{1}{2!}\theta^2+\frac{1}{4!}\theta^4-\ldots\right)}_{\cos\theta}+\underbrace{\left(\theta-\frac{1}{3!}\theta^3+\frac{1}{5!}\theta^5-\ldots\right)}_{\sin\theta}\boldsymbol{u} \\ &=\cos\theta+u\sin\theta. \end{aligned} exp(uθ)=1+uθ2!1θ23!1θ3u+4!1θ4+=cosθ (12!1θ2+4!1θ4)+sinθ (θ3!1θ3+5!1θ5)u=cosθ+usinθ.
  即
exp ⁡ ( ϖ ) = [ cos ⁡ θ , u sin ⁡ θ ] ⊤ \exp(\varpi)=[\cos\theta,u\sin\theta]^\top exp(ϖ)=[cosθ,usinθ]
  求模长后发现,纯虚四元数指数映射结果是一个单位四元数,反过来想,一个单位四元数的李代数就是一个纯虚四元数
∥ exp ⁡ ( ϖ ) ∥ = cos ⁡ 2 θ + sin ⁡ 2 θ ∥ u ∥ 2 = 1 \|\exp(\varpi)\|=\cos^2\theta+\sin^2\theta\|\boldsymbol{u}\|^2=1 exp(ϖ)=cos2θ+sin2θu2=1

2.3 四元数的李代数与旋转向量间的转换

  首先,一个单位四元数 q q q对于的李代数为一个纯虚四元数 ϖ = u θ \varpi=\boldsymbol{u}\theta ϖ=uθ,李代数通过指数映射得到的四元数为:
q = exp ⁡ ( ϖ ) = [ cos ⁡ θ , u sin ⁡ θ ] ⊤ ( 5 ) q = \exp(\varpi)=[\cos\theta,u\sin\theta]^\top \quad(5) q=exp(ϖ)=[cosθ,usinθ](5)
  其次,寻找一个旋转矩阵R对应的单位四元数李代数
R = E x p ( ϕ ) = E x p ( θ ′ n ) R=\mathrm{Exp}(\phi)=\mathrm{Exp}(\theta\boldsymbol{'n}) R=Exp(ϕ)=Exp(θn)
  这时候旋转向量 ϕ \phi ϕ对应的四元数为:
q = [ cos ⁡ θ ′ 2 , n sin ⁡ θ ′ 2 ] ( 6 ) q=[\cos\frac{\theta'}{2},n\sin\frac{\theta'}{2}]\quad(6) q=[cos2θ,nsin2θ](6)

  注意公式5和6中纯虚四元数 ϖ [ 0 , ω 1 , ω 2 , ω 3 ⏟ ω ] ⊤ = u θ \varpi[0,\underbrace{\omega_{1},\omega_{2},\omega_{3}}_{\omega}]^{\top} =\boldsymbol{u}\theta ϖ[0,ω ω1,ω2,ω3]=uθ ϕ = θ ′ n \phi = \theta'n ϕ=θn中的角度差了一倍!旋转矩阵中的角度是纯虚四元数的2倍,即 θ ′ 2 = θ \frac{\theta'}{2} = \theta 2θ=θ!因为旋转矩阵一半角度和其全部角度等价!

  也就是说,可得:
ϖ = [ 0 , 1 2 ϕ ] ⊤ , 或 ω = 1 2 ϕ . \varpi=[0,\frac{1}{2}\phi]^\top,\quad\text{或}\omega=\frac{1}{2}\phi. ϖ=[0,21ϕ],ω=21ϕ.
  四元数表达的角速度正好是 SO(3) 李代数的一半!这与四元数在旋转一个矢量时,要乘两遍相对应。

  • 总结

  对于一个三维瞬时角速度(或者优化函数的目标更新量) ω ∈ R 3 \omega\in\mathbb{R}^3 ωR3, 定义在SO(3)上的运动形式为:
R ˙ = R ω ∧ \dot{R}=R\omega^{\wedge} R˙=Rω

R = E x p ( ω ) = exp ⁡ ( ω ∧ ) R= Exp(\omega)=\exp(\omega^{\wedge}) R=Exp(ω)=exp(ω)
  如果这个量作为纯虚四元数的更新量(通常由优化函数求解得到),那么对应的四元数应该只更新它的一半
q ˙ = 1 2 q [ 0 , ω ] ⊤ \dot{q}=\frac{1}{2}q[0,\omega]^{\top} q˙=21q[0,ω]
  上面 ω \omega ω是三维,消除括号后已经变成了一个四元数:
q ˙ = 1 2 q ω \dot{q}=\frac12q\omega q˙=21qω
  四元数指数映射也可以类似也写作
q = exp ⁡ ( 1 2 [ 0 , ω ] ⊤ ) = Δ exp ⁡ ( ω ) q=\exp(\frac{1}{2}[0,\omega]^{\top})\stackrel{\Delta}{=}\exp(\omega) q=exp(21[0,ω])=Δexp(ω)
  若 ω \omega ω是一个较小量, cos ⁡ ( θ 2 ) ≈ 1 , n sin ⁡ θ 2 ≈ n θ 2 \cos(\frac\theta2)\approx1,n\sin\frac\theta2\approx n\frac\theta2 cos(2θ)1,nsin2θn2θ,简化
Exp ⁡ ( ω ) ≈ [ 1 , 1 2 ω ] \operatorname{Exp}(\omega)\approx[1,\frac{1}{2}\omega] Exp(ω)[1,21ω]
  四元数更新公式:
q E x p ( ω ) ≈ q [ 1 , 1 2 ω ] q\mathrm{Exp}(\omega)\approx\boldsymbol{q}[1,\frac12\omega] qExp(ω)q[1,21ω]

2.4 SO(3)+t 上的运动学

  用 ω 来表达角速度,t是平移量,v表示线速度
R ˙ = R ω ∧ , t ˙ = v \dot{R}=R\omega^{\wedge},\quad \dot{t}=v R˙=Rω,t˙=v

2.5 线速度与加速度

  考虑线速度和加速度在不同坐标系之间的变换关系。这里考虑只带旋转关系的两个坐标系之间的线速度和加速度的变换关系

  考虑坐标系1和2,某个向量p在两个系下坐标为 p 1 , p 2 p_{1},p_{2} p1,p2 ,它们满足关系 p 1 = R 12 p 2 p_{1}=R_{12}p_{2} p1=R12p2

对上述关系进行求导:
p ˙ 1 = R ˙ 12 p 2 + R 12 p ˙ 2 = R 12 ω ∧ p 2 + R 12 p ˙ 2 = R 12 ( ω ∧ p 2 + p ˙ 2 ) . \begin{aligned} \dot{p}_{1}& =\dot{R}_{12}\boldsymbol{p}_2+\boldsymbol{R}_{12}\dot{\boldsymbol{p}}_2 \\ &=R_{12}\omega^{\wedge}p_{2}+R_{12}\dot{p}_{2} \\ &=\boldsymbol{R}_{12}(\boldsymbol{\omega}^\wedge\boldsymbol{p}_2+\dot{\boldsymbol{p}}_2). \end{aligned} p˙1=R˙12p2+R12p˙2=R12ωp2+R12p˙2=R12(ωp2+p˙2).
  我们发现, p p p 在两个系下的速度矢量是不同的,不是同一个矢量在不同坐标系中的表达

  一般来讲,位置的导数是速度,即 p ˙ 1 = v 1 , p ˙ 2 = v 2 \dot{p}_{1}=\boldsymbol{v}_{1},\dot{p}_{2}=\boldsymbol{v}_{2} p˙1=v1,p˙2=v2,代入上式:
v 1 = R 12 ( ω ∧ p 2 + v 2 ) v_1=R_{12}(\omega^{\wedge}p_2+v_2) v1=R12(ωp2+v2)
  速度信息对时间求导:
v ˙ 1 = R ˙ 12 ( ω ∧ p 2 + v 2 ) + R 12 ( ω ˙ ∧ p 2 + ω ∧ p ˙ 2 + v ˙ 2 ) = R 12 ( ω ∧ ω ∧ p 2 + ω ∧ v 2 + ω ˙ ∧ p 2 + ω ∧ p ˙ 2 + v ˙ 2 ) = R 12 ( v ˙ 2 + 2 ω ∧ v 2 + ω ˙ ∧ p 2 + ω ∧ ω ∧ p 2 ) \begin{gathered} \dot{v}_{1} =\dot{R}_{12}\left(\boldsymbol{\omega}^{\wedge}\boldsymbol{p}_{2}+\boldsymbol{v}_{2}\right)+\boldsymbol{R}_{12}\left(\dot{\boldsymbol{\omega}}^{\wedge}\boldsymbol{p}_{2}+\boldsymbol{\omega}^{\wedge}\dot{\boldsymbol{p}}_{2}+\dot{\boldsymbol{v}}_{2}\right) \\ =R_{12}\left(\omega^{\wedge}\omega^{\wedge}p_{2}+\omega^{\wedge}v_{2}+\dot{\omega}^{\wedge}p_{2}+\omega^{\wedge}\dot{p}_{2}+\dot{v}_{2}\right) \\ =\boldsymbol{R}_{12}\left(\dot{\boldsymbol{v}}_{2}+2\boldsymbol{\omega}^{\wedge}\boldsymbol{v}_{2}+\dot{\boldsymbol{\omega}}^{\wedge}\boldsymbol{p}_{2}+\boldsymbol{\omega}^{\wedge}\boldsymbol{\omega}^{\wedge}\boldsymbol{p}_{2}\right) \end{gathered} v˙1=R˙12(ωp2+v2)+R12(ω˙p2+ωp˙2+v˙2)=R12(ωωp2+ωv2+ω˙p2+ωp˙2+v˙2)=R12(v˙2+2ωv2+ω˙p2+ωωp2)
  定义加速度 a 1 = v ˙ 1 , a 2 = v ˙ 2 a_{1}=\dot{v}_{1},a_{2}=\dot{v}_{2} a1=v˙1,a2=v˙2,则得到
a 1 = R 12 ( a 2 ⏟ 加速度 + 2 ω ∧ v 2 ⏟ 科氏加速度 + ω ˙ ∧ p 2 ⏟ 角加速度 + ω ∧ ω ∧ p 2 ⏟ 向心加速度 ) a_1=\boldsymbol{R}_{12}(\underbrace{a_2}_\text{加速度}+\underbrace{2\boldsymbol{\omega}^{\wedge}\boldsymbol{v}_2}_\text{科氏加速度}+\underbrace{\dot{\boldsymbol{\omega}}^{\wedge}\boldsymbol{p}_2}_\text{角加速度}+\underbrace{\boldsymbol{\omega}^{\wedge}\boldsymbol{\omega}^{\wedge}\boldsymbol{p}_2}_\text{向心加速度}) a1=R12(加速度 a2+科氏加速度 2ωv2+角加速度 ω˙p2+向心加速度 ωωp2)
  在精度不高的应用场景中,通常会选择忽略后面三项,只保留最简单的转换关系

  车辆本身的速度,也就是车体坐标系原点在世界系下的速度车体原点在车辆系下速度一直是零,没有实际意义)。这个速度是定义在世界系中的,记为 v w v_w vw 。如果左乘 R b w R_{bw} Rbw ,也可以将这个矢量转换到车辆坐标系下,记作 v b v_b vb,称其为车体系速度

2.6 扰动模型

  • R 1 R_1 R1进行右扰动求导

∂ L o g ( R 1 R 2 ) ∂ R 1 = lim ⁡ ϕ → 0 Log ⁡ ( R 1 E x p ( ϕ ) R 2 ) − Log ⁡ ( R 1 R 2 ) ϕ = lim ⁡ ϕ → 0 L o g ( R 1 R 2 E x p ( R 2 ⊤ ϕ ) ) − L o g ( R 1 R 2 ) ϕ = J r − 1 ( Log ⁡ ( R 1 R 2 ) ) R 2 ⊤ . \begin{aligned} \frac{\partial\mathrm{Log}\left(\boldsymbol{R}_1\boldsymbol{R}_2\right)}{\partial\boldsymbol{R}_1}& =\lim_{\phi\to0}\frac{\operatorname{Log}\left(\boldsymbol{R}_1\mathrm{Exp}\left(\phi\right)\boldsymbol{R}_2\right)-\operatorname{Log}\left(\boldsymbol{R}_1\boldsymbol{R}_2\right)}\phi \\ &=\lim_{\phi\to0}\frac{\mathrm{Log}\left(\boldsymbol{R}_1\boldsymbol{R}_2\mathrm{Exp}\left(\boldsymbol{R}_2^\top\boldsymbol{\phi}\right)\right)-\mathrm{Log}\left(\boldsymbol{R}_1\boldsymbol{R}_2\right)}\phi \\ &=\boldsymbol{J}_r^{-1}(\operatorname{Log}(\boldsymbol{R}_1\boldsymbol{R}_2))\boldsymbol{R}_2^\top. \end{aligned} R1Log(R1R2)=ϕ0limϕLog(R1Exp(ϕ)R2)Log(R1R2)=ϕ0limϕLog(R1R2Exp(R2ϕ))Log(R1R2)=Jr1(Log(R1R2))R2.

其中第二行的转换使用到 S O ( 3 ) SO(3) SO(3)的伴随性质:
R ⊤ E x p ( ϕ ) R = E x p ( R ⊤ ϕ ) R^\top\mathrm{Exp}(\phi)R=\mathrm{Exp}(\boldsymbol{R}^\top\phi) RExp(ϕ)R=Exp(Rϕ)
第三行使用了BCH近似公式:
L o g ( R 1 R 2 E x p ( R 2 ⊤ ϕ ) ) = L o g ( R 1 R 2 ) + J r − 1 ( R 1 R 2 ) L o g ( E x p ( R 2 ⊤ ϕ ) ) \mathrm{Log}\left(R_1R_2\mathrm{Exp}\left(R_2^\top\phi\right)\right)=\mathrm{Log}(R_1R_2)+J_r^{-1}(R_1R_2)\mathrm{Log}(\mathrm{Exp}(R_2^\top\phi)) Log(R1R2Exp(R2ϕ))=Log(R1R2)+Jr1(R1R2)Log(Exp(R2ϕ))

  • R 2 R_2 R2进行右扰动求导

∂ L o g ( R 1 R 2 ) ∂ R 2 = lim ⁡ ϕ → 0 L o g ( R 1 R 2 E x p ( ϕ ) ) − L o g ( R 1 R 2 ) ϕ = J r − 1 ( L o g ( R 1 R 2 ) ) \frac{\partial\mathrm{Log}\left(R_1R_2\right)}{\partial R_2}=\lim_{\phi\to0}\frac{\mathrm{Log}\left(R_1R_2\mathrm{Exp}\left(\phi\right)\right)-\mathrm{Log}\left(R_1R_2\right)}{\phi}=J_r^{-1}(\mathrm{Log}(R_1R_2)) R2Log(R1R2)=ϕ0limϕLog(R1R2Exp(ϕ))Log(R1R2)=Jr1(Log(R1R2))

  • 不能直接说 R 1 R 2 R 1 R 2 R1R2 R 1 R 1 R1 R 2 R 2 R2 的导数,那样就变成矩阵对向量求导,无法使用矩阵来描述了。在不引入张量的前提下,我们最多只能求向量到向量的导数。因此分子部分必须加上 Log 符号,取为矢量

2.7 关于左扰动和右扰动的选择

左右扰动由状态定义和误差状态定义形式确定

2.7.1 第一种形式

  1. 定义状态:定义系统旋转状态为Globally形式: R L G R_L^{G} RLG ,即pose表达在Global坐标系(平移量在Global坐标系下)

  2. 定义误差状态:旋转的误差状态为: θ L ′ L \theta_{L^{\prime}}^L θLL

  3. 确认状态的叠加方式:根据旋转的链式法则,叠加了扰动的旋转为:

R L ′ G = R L G R L ′ L = R L G ( I + [ θ L ′ L ] × ) R_{L^{\prime}}^G=R_L^GR_{L^{\prime}}^L=R_L^G(I+[\theta_{L^{\prime}}^L]^\times) RLG=RLGRLL=RLG(I+[θLL]×)

  扰动的叠加是右扰动形式

2.7.2 第二种形式

  1. 定义状态:定义系统旋转状态为Locally形式: R G L R_{G}^L RGL ,即pose表达在Local坐标系(平移量在local坐标系下)
  2. 定义误差状态:旋转的误差状态为: θ L ′ L {\theta^L_{L^{\prime}}} θLL
  3. 确认状态的叠加方式:根据旋转的链式法则,叠加了扰动的旋转为:

R G L ′ = R L L ′ R G L = ( I + [ θ L L ′ ] × ) R G L = ( I − [ θ L ′ L ] × ) R G L R_G^{L^{\prime}}=R_L^{L^{\prime}}R_G^{L}=(I+[\theta_L^{L^{\prime}}]^{\times})R_G^{L}=(I-[\theta_{L^{\prime}}^{L}]^{\times})R_G^{L} RGL=RLLRGL=(I+[θLL]×)RGL=(I[θLL]×)RGL

​ 扰动的叠加是左扰动形式,注意上面括号里面+-号,转换为四元数的话,+表示了常见的Hamilton四元数,-表示了JPL四元数。两个微小四元数表示的旋转是相反的。

2.8 运动学示例:圆周运动

bin/motion −−use_quaternion=true −−angular_velocity=15   #  

搞清楚body系与世界系
1 body系:有恒定的线速度和恒定的角速度,那么就一定可以表示为圆周运动
2 世界系:body系下速度不发生变化,但旋转到世界系就会变化。我们求的位移是世界系的位移,所以要转换速度
3 pose.so3()就相当于 R w b R_{wb} Rwb,角速度omega就不需要转换到世界系,这里位姿的变换是右扰动(全局坐标系)。 R w b ′ = R w b R b b ′ R_{wb'} =R_{wb}R_{bb'} Rwb=RwbRbb

#include <gflags/gflags.h>
#include <glog/logging.h>

#include "common/eigen_types.h"
#include "common/math_utils.h"
#include "tools/ui/pangolin_window.h"

/// 本节程序演示一个正在作圆周运动的1车辆
/// 车辆的角速度与线速度可以在flags中设置

DEFINE_double(angular_velocity, 10.0, "角速度(角度)制");		// 这里都是宏变量
DEFINE_double(linear_velocity, 5.0, "车辆前进线速度 m/s");
DEFINE_bool(use_quaternion, false, "是否使用四元数计算");

int main(int argc, char** argv) {
    google::InitGoogleLogging(argv[0]);// 这行代码用于初始化Google日志系统。它将日志输出到标准错误输出(stderr)
    FLAGS_stderrthreshold = google::INFO;	// 这行代码设置了在stderr中显示的日志级别。在这里,将日志级别设置为INFO,这意味着只有INFO级别及以上的日志会被输出到stderr
    FLAGS_colorlogtostderr = true;	// 在stderr中显示彩色日志输出
    google::ParseCommandLineFlags(&argc, &argv, true);	// 解析命令行参数。它会检查命令行中的标志参数(例如--flag_name=value)并根据相应的定义来设置相应的标志值
		
    /// 可视化
    sad::ui::PangolinWindow ui;
    if (ui.Init() == false) {
        return -1;
    }

    double angular_velocity_rad = FLAGS_angular_velocity * sad::math::kDEG2RAD;  // 弧度制角速度
    SE3 pose;                                                                    // TWB表示的位姿
    Vec3d omega(0, 0, angular_velocity_rad);    // 角速度矢量   00z  如果z=1是角轴,这样是旋转向量,值代表角度
    Vec3d v_body(FLAGS_linear_velocity, 0, 0);  // 本体系速度  所以只有x方向有值
    const double dt = 0.05;                                                      // 每次更新的时间

    while (ui.ShouldQuit() == false) {
        // 更新自身位置
        Vec3d v_world = pose.so3() * v_body;
        pose.translation() += v_world * dt;

        // 更新自身旋转
        if (FLAGS_use_quaternion) {
            Quatd q = pose.unit_quaternion() * Quatd(1, 0.5 * omega[0] * dt, 0.5 * omega[1] * dt, 0.5 * omega[2] * dt);
            q.normalize();
            pose.so3() = SO3(q);
        } else {
            pose.so3() = pose.so3() * SO3::exp(omega * dt);
        }

        LOG(INFO) << "pose: " << pose.translation().transpose();
        ui.UpdateNavState(sad::NavStated(0, pose, v_world));

        usleep(dt * 1e6);
    }

    ui.Quit();
    return 0;
}

3 滤波器与最优化理论

3.1 状态估计问题与最小二乘

  首先要知道状态是什么?在多个传感器中,状态可以是旋转、平移、速度等等。

​  状态估计,就是我们要通过什么样的方式去估计状态量,得到的值是否正确,是否值得信赖。

  典型的离散时间状态估计由运动方程(如IMU/Wheel)和观测方程(cam/lidar/GNSS)组成
{ x k = f ( x k − 1 , u k ) + w k , k = 1 , … , N z k = h ( x k ) + v k , \left.\left\{\begin{array}{l}x_k=f\left(x_{k-1},u_k\right)+\boldsymbol{w}_k,\quad k=1,\ldots,N\\z_k=\boldsymbol{h}\left(x_k\right)+\boldsymbol{v}_k,\end{array}\right.\right. {xk=f(xk1,uk)+wk,k=1,,Nzk=h(xk)+vk,

  上面是非线性函数,将其线性化,就可以得到线性高斯系统得状态估计问题。线性系统的无偏最优估计由KF给出。

{ x k = A k x k − 1 + u k + w k z k = C k x k + v k \left.\left\{\begin{array}{l}x_k=A_k\boldsymbol{x}_{k-1}+\boldsymbol{u}_k+\boldsymbol{w}_k\\\boldsymbol{z}_k=C_k\boldsymbol{x}_k+\boldsymbol{v}_k\end{array}\right.\right. {xk=Akxk1+uk+wkzk=Ckxk+vk

3.2 卡尔曼滤波器

预测
x k , pred = A k x k − 1 + u k , P k , pred = A k P k − 1 A k ⊤ + R k x_{k,\text{pred}} = A _ k x _ { k - 1 }+u_k,\quad P_{k,\text{pred}} = A _ k P _ { k - 1 }A_k^\top+R_k xk,pred=Akxk1+uk,Pk,pred=AkPk1Ak+Rk
更新
K k = P k , pred C k ⊤ ( C k P k , pred C k ⊤ + Q k ) − 1 K_k=P_{k,\text{pred}} C _ k ^ { \top }\left(C_kP_{k,\text{pred}} C _ k ^ { \top }+Q_k\right)^{-1} Kk=Pk,predCk(CkPk,predCk+Qk)1
计算后验概率的分布
x k = x k , p r e d + K k ( z k − C k x k , p r e d ) , P k = ( I − K k C k ) P k , p r e d . \begin{aligned}&\boldsymbol{x}_k=\boldsymbol{x}_{k,\mathrm{pred}}+\boldsymbol{K}_k\left(\boldsymbol{z}_k-\boldsymbol{C}_k\boldsymbol{x}_{k,\mathrm{pred}}\right),\\&\boldsymbol{P}_k=\left(\boldsymbol{I}-\boldsymbol{K}_k\boldsymbol{C}_k\right)\boldsymbol{P}_{k,\mathrm{pred}}.\end{aligned} xk=xk,pred+Kk(zkCkxk,pred),Pk=(IKkCk)Pk,pred.

补充:关于最后那个协方差矩阵的更新,有三种形式

1 P = ( I − K H ) P \begin{aligned}P=(I-KH)P\end{aligned} P=(IKH)P 最常见的卡尔曼滤波的形式,数值稳定性较差,计算的协方差不能保证对称正定。

2 P = P − K ( H P H T + R ) K T P = P-K(HPH^T+R)K^T P=PK(HPHT+R)KT: 对称形式,计算的协方差仍是对称阵。

3 P ← ( I − K H ) P ( I − K H ) T + K R K T P\leftarrow(I-KH)P(I-KH)^T+KRK^T P(IKH)P(IKH)T+KRKT:对称正定形式,计算出的协方差是仍是对称正定阵

K = P H T ( H P H T + R ) − 1 ⇒ K ( H P H T + R ) = P H T P − K ( H P H T + R ) K T = P − P H T K T = P T − K H P T = ( I − K H ) P ( I − K H ) P ( I − K H ) T + K R K T = ( I − K H ) P − ( I − K H ) P H T K T + K R K T = ( I − K H ) P − P H T K T + K ( H P H T + R ) K T = ( I − K H ) P − P H T K T + P H T K T \begin{aligned} K=PH^{T}(HPH^{T}+R)^{-1}& \Rightarrow K(HPH^T+R)=PH^T \\ P-K(HPH^{T}+R)K^{T}& =P-PH^{T}K^{T} \\ &=P^{T}-KHP^{T} \\ &=(I-KH)P \\ (I-KH)P(I-KH)^T+KRK^T& =(I-KH)P-(I-KH)PH^TK^T+KRK^T \\ &=(I-KH)P-PH^TK^T+K(HPH^T+R)K^T \\ &=(I-KH)P-PH^TK^T+PH^TK^T \end{aligned} K=PHT(HPHT+R)1PK(HPHT+R)KT(IKH)P(IKH)T+KRKTK(HPHT+R)=PHT=PPHTKT=PTKHPT=(IKH)P=(IKH)P(IKH)PHTKT+KRKT=(IKH)PPHTKT+K(HPHT+R)KT=(IKH)PPHTKT+PHTKT

3.3 非线性系统的处理方法-EKF

  假设一个高斯分布状态变量经过非线性函数后仍为高斯分布

x k , p r e d = f ( x k − 1 , u k ) , P k , p r e d = F k P k − 1 F k ⊤ + R k . x_{k,\mathrm{pred}}=f(x_{k-1},u_{k}),\quad P_{k,\mathrm{pred}}=F_{k}P_{k-1}F_{k}^{\top}+R_{k}. xk,pred=f(xk1,uk),Pk,pred=FkPk1Fk+Rk.

K k = P k , p r e d H k ⊤ ( H k P k , p r e d H k ⊤ + Q k ) − 1 , x k = x k , pred + K k ( z k − H k x k , pred ) , P k = ( I − K k C k ) P k , p r e d . \begin{aligned} &K_{k} =P_{k,\mathrm{pred}}H_{k}^{\top}(H_{k}P_{k,\mathrm{pred}}H_{k}^{\top}+Q_{k})^{-1}, \\ &x_{k} =x_{k,\text{pred}} + K _ k ( z _ k - H _ k x _ { k ,\text{pred}} ) , \\ &P_{k} =(\boldsymbol{I}-\boldsymbol{K}_{k}\boldsymbol{C}_{k})\boldsymbol{P}_{k,\mathrm{pred}}. \end{aligned} Kk=Pk,predHk(HkPk,predHk+Qk)1,xk=xk,pred+Kk(zkHkxk,pred),Pk=(IKkCk)Pk,pred.

2.4 最优化方法与图优化

  运动学方程和观测方程都可以看成一个状态变量 x 与运动学输入、观测值之间的残差,这是一种批量最小二乘

e motion = x k − f ( x k − 1 , u ) ∼ N ( 0 , R k ) , e obs = z k − h ( x k ) ∼ N ( 0 , Q k ) . \begin{aligned}e_{\text{motion}}&=x_k-f(x_{k-1},u)\sim\mathcal{N}(0,R_k),\\e_{\text{obs}}&=z_k-h(x_k)\sim\mathcal{N}(0,Q_k).\end{aligned} emotioneobs=xkf(xk1,u)N(0,Rk),=zkh(xk)N(0,Qk).

  对于上面提及的滤波器这种处理方法,其中的最优状态估计可以看成关于各种误差项的最小二乘问题(比较计算了协方差和预测,那么后验估计就非常类似这里的批量最小二乘)

x ∗ = arg ⁡ min ⁡ x ∑ k ( e k ⊤ Ω k − 1 e k ) x^*=\arg\min_x\sum_k\left(e_k^\top\Omega_k^{-1}e_k\right) x=argxmink(ekΩk1ek)

  如果是迭代最小二乘,处理方法按下面步骤。

在这里插入图片描述

关于滤波器与最优化的区别与联系,

  它们在线性系统中会得到同样的结果 ,但在非线性系统中通常不然。主要原因有以下几个

  1. 最优化方法有迭代过程,而 EKF 则没有。

  2. 迭代过程会不断在新的线性化点 x i x_i xi上求取雅可比矩阵,而EKF的雅可比矩阵只在预测位置上求取一次。

  3. EKF还会区分 x k , p r e d x_{k,pred} xk,pred ,分开处理预测过程与观测过程。而最优化方法则没有 x k , p r e d x_{k,pred} xk,pred统一处理各处的状态变量

​ 如果忽略上面差异,把卡尔曼滤波当作一种优化,那么它的优化变量和误差函数是什么(图优化里面最关键的地方)

2个优化变量: x k − 1 x_{k-1} xk1 x k x_{k} xk,即上一个时刻与当前时刻状态。(图优化里面如滑动窗口,是一段时间内的状态;如果是全局优化,那么就是全部的状态)

3个误差函数:先验误差、运动误差、观测误差。(图优化:在纯视觉里面就是观测误差)

在这里插入图片描述

注意:普通的优化器没有计算协方差矩阵,需要边缘化Marginalization

在这里插入图片描述

4 关于环境编译

基础环境:Ubuntu20.04

ROS环境:Noetic

​ 然后根据GitHub安装相应依赖

sudo apt install -y ros-noetic-pcl-ros ros-noetic-velodyne-msgs libopencv-dev libgoogle-glog-dev libeigen3-dev libsuitesparse-dev libpcl-dev libyaml-cpp-dev libbtbb-dev libgmock-dev

​ 额外安装Pangolin、g2o库,Sophus库作者把相应的文件提取出来了,无需安装。

mkdir build		# 进入到thirdparty/xxx  进行相应的编译安装
cd build
cmake ..
make -j8

​ 这本书的程序就是一个大的工程项目,所以直接编译

mkdir build
cd build
cmake ..
make -j8

​ 因为每一次编译都很费劲,所以可以先编译使用的章节,注释其它章节

add_subdirectory(common)
add_subdirectory(ch2)
add_subdirectory(ch3)
# add_subdirectory(ch4)
# add_subdirectory(ch5)
# add_subdirectory(ch6)
# add_subdirectory(ch7)
# add_subdirectory(ch8)
# add_subdirectory(ch9)
# add_subdirectory(ch10)

add_subdirectory(tools)

5 习题

5.1 计算

∂ R − 1 p ∂ R . \frac{\partial R^{-1}p}{\partial R}. RR1p.

右扰动

∂ ( R − 1 p ) ∂ φ = lim ⁡ φ → 0 ( R exp ⁡ ( φ ∧ ) ) − 1 p − R − 1 p φ = lim ⁡ φ → 0 ( I − φ ∧ ) R − 1 p − R − 1 p φ = lim ⁡ φ → 0 ( R − 1 p ) ∧ φ φ = ( R − 1 p ) ∧ \begin{aligned} \begin{aligned}\frac{\partial\left(\mathbf{R^{-1}p}\right)}{\partial\varphi}\end{aligned}& \begin{aligned}=\lim_{\boldsymbol{\varphi}\to\boldsymbol{0}}\frac{(\mathbf{R}\exp\left(\boldsymbol{\varphi}^{\wedge})\right)^{-1}\mathbf{p}-\mathbf{R^{-1}}\mathbf{p}}{\varphi}\end{aligned} \\ &=\lim_{\boldsymbol{\varphi}\to\mathbf{0}}\frac{\left(\mathbf{I}-\boldsymbol{\varphi}^{\wedge}\right)\mathbf{R}^{-1}\mathbf{p}-\mathbf{R^{-1}}\mathbf{p}}{\varphi} \\ &=\lim_{\varphi\to0}\frac{(\mathbf{R}^{-1}\mathbf{p})^{\wedge}\boldsymbol{\varphi}}\varphi=(\mathbf{R}^{-1}\mathbf{p})^\wedge \end{aligned} φ(R1p)=φ0limφ(Rexp(φ))1pR1p=φ0limφ(Iφ)R1pR1p=φ0limφ(R1p)φ=(R1p)

左扰动:和右扰动推导一致,最后结果应该是 − R − 1 p ∧ -\mathbf{R}^{-1} \mathbf{p}^\wedge R1p

5.2 计算

∂ R 1 R 2 − 1 ∂ R 2 . \frac{\partial R_1R_2^{-1}}{\partial R_2}. R2R1R21.

右扰动

  以右扰动为例,第一行到第二行求 exp ⁡ ( ϕ ∧ ) − 1 = exp ⁡ ( − ϕ ∧ ) ≈ I − ϕ ∧ \exp(\phi^\wedge)^{-1}=\exp(-\phi^\wedge)\approx\mathbf{I}-\phi^\wedge exp(ϕ)1=exp(ϕ)Iϕ,第三行到第四行利用SO(3)的伴随性质,第四行到第五行是对数形式的BCH近似公式。
d ln ⁡ ( R 1 R 2 − 1 ) ∨ d R 2 = lim ⁡ ψ → 0 ln ⁡ ( R 1 ( R 2 exp ⁡ ( ψ ∧ ) ) − 1 ) ∨ − ln ⁡ ( R 1 R 2 − 1 ) ∨ ψ = lim ⁡ ψ → 0 ln ⁡ ( R 1 exp ⁡ ( − ψ ∧ ) R 2 − 1 ) ∨ − ln ⁡ ( R 1 R 2 − 1 ) ∨ ψ = lim ⁡ ψ → 0 ln ⁡ ( R 1 R 2 − 1 R 2 exp ⁡ ( − ψ ∧ ) R 2 − 1 ) ∨ − ln ⁡ ( R 1 R 2 − 1 ) ∨ ψ = lim ⁡ ψ → 0 ln ⁡ ( R 1 R 2 − 1 exp ⁡ ( − R 2 ψ ∧ ) ) ∨ − ln ⁡ ( R 1 R 2 − 1 ) ∨ ψ = lim ⁡ ψ → 0 ln ⁡ ( R 1 R 2 − 1 ) ∨ − J r − 1 R 2 ψ − ln ⁡ ( R 1 R 2 − 1 ) ∨ ψ = lim ⁡ ψ → 0 − J r − 1 R 2 ψ ψ = − J r − 1 ( ln ⁡ ( R 1 R 2 − 1 ) ∨ ) ⋅ R 2 = − J l − 1 ( ln ⁡ ( R 1 R 2 − 1 ) ∨ ) ⋅ R 1 \begin{aligned} \frac{d\ln(\mathbf{R}_1\mathbf{R}_2^{-1})^\vee}{d\mathbf{R}_2}& =\lim_{\psi\to0}\frac{\ln(\mathbf{R}_1(\mathbf{R}_2\exp(\psi^\wedge))^{-1})^\vee-\ln(\mathbf{R}_1\mathbf{R}_2^{-1})^\vee}\psi \\ &=\lim_{\psi\to0}\frac{\ln(\mathbf{R}_1\exp(-\psi^\wedge)\mathbf{R}_2^{-1})^\vee-\ln(\mathbf{R}_1\mathbf{R}_2^{-1})^\vee}\psi \\ &=\lim_{\psi\to0}\frac{\ln(\mathbf{R}_1\mathbf{R}_2^{-1}\mathbf{R}_2\exp(-\psi^{\wedge})\mathbf{R}_2^{-1})^\vee-\ln(\mathbf{R}_1\mathbf{R}_2^{-1})^\vee}\psi \\ &=\lim_{\psi\to0}\frac{\ln(\mathbf{R}_1\mathbf{R}_2^{-1}\exp(-\mathbf{R}_2\psi^{\wedge}))^{\vee}-\ln(\mathbf{R}_1\mathbf{R}_2^{-1})^{\vee}}\psi \\ &=\lim_{\psi\to0}\frac{\ln(\mathbf{R}_1\mathbf{R}_2^{-1})^\vee-\mathbf{J}_r^{-1}\mathbf{R}_2\psi-\ln(\mathbf{R}_1\mathbf{R}_2^{-1})^\vee}\psi \\ &=\lim_{\psi\to0}\frac{-\mathbf{J}_r^{-1}\mathbf{R}_2\psi}\psi \\ &=-\mathbf{J}_r^{-1}(\ln(\mathbf{R}_1\mathbf{R}_2^{-1})^\vee)\cdot\mathbf{R}_2 \\ &=-\mathbf{J}_l^{-1}(\ln(\mathbf{R}_1\mathbf{R}_2^{-1})^\vee)\cdot\mathbf{R}_1 \end{aligned} dR2dln(R1R21)=ψ0limψln(R1(R2exp(ψ))1)ln(R1R21)=ψ0limψln(R1exp(ψ)R21)ln(R1R21)=ψ0limψln(R1R21R2exp(ψ)R21)ln(R1R21)=ψ0limψln(R1R21exp(R2ψ))ln(R1R21)=ψ0limψln(R1R21)Jr1R2ψln(R1R21)=ψ0limψJr1R2ψ=Jr1(ln(R1R21))R2=Jl1(ln(R1R21))R1

左扰动:这个推导很简单,直接就类似于右扰动第4行,最后结果应该是 − J r − 1 ( l n ( R 1 R 2 − 1 ) ) -\boldsymbol{J}_r^{-1}(\mathrm{ln}(\boldsymbol{R}_1\boldsymbol{R}_2^{-1})) Jr1(ln(R1R21))

5.3 设计程序

  将2.3节的实验修改成带旋转的抛物线运动。物体一方面沿 Z 轴自转,一方面存在水平的初始线速度,又受到 −Z 方向的重力加速度影响。请设计程序并完成动画演示。

注意几点

1 绕z轴自转,和原来程序一致----所以旋转不发生变化

2 水平初始线速度,设置为x方向,假设保持不变

3 重力加速度–自由落体,v(z)=-gt, x(z)=vt+0.5gt^2

4 注意坐标系转换,搞清楚那个是body系,那个是世界系。比如位移是指世界系下位移,不能用body系下速度来更新;常见-9.8的重力加速度是世界系下量,如果要更新body系下速度,需要转换对应的加速度!


DEFINE_double(angular_velocity, 10.0, "角速度(角度)制");
DEFINE_double(linear_velocity, 5.0, "车辆前进线速度 m/s");
DEFINE_double(gravity, -9.8, "加速度 m/s2");
DEFINE_bool(use_quaternion, false, "是否使用四元数计算");

int main(int argc, char** argv) {

	....
	
    double angular_velocity_rad = FLAGS_angular_velocity * sad::math::kDEG2RAD;  // 弧度制角速度
    SE3 pose;                                                                    // TWB表示的位姿
    Vec3d omega(0, 0, angular_velocity_rad);                                     // 角速度矢量
    Vec3d v_body(FLAGS_linear_velocity, 0, 0);                                   // 本体系速度
    const double dt = 0.05;                                                      // 每次更新的时间
    const Vec3d a_w(0, 0, FLAGS_gravity);

    while (ui.ShouldQuit() == false) {
        // 1 v_w = R_wb * v_b;
        Vec3d v_world = pose.so3() * v_body;

        // 2 x_w = v_w * dt + 0.5 * a_w * dt * dt;
        pose.translation() += v_world * dt + 0.5 * a_w * dt * dt;

        // 3 a_b = (R_wb)^T * a_w
        Vec3d a_b = pose.so3().inverse() * a_w;

        // 4 v_b += a_b * dt
        v_body += a_b * dt; 

        // 更新自身旋转
        if (FLAGS_use_quaternion) {
            Quatd q = pose.unit_quaternion() * Quatd(1, 0.5 * omega[0] * dt, 0.5 * omega[1] * dt, 0.5 * omega[2] * dt);
            q.normalize();
            pose.so3() = SO3(q);
        } else {
            pose.so3() = pose.so3() * SO3::exp(omega * dt);
        }

        LOG(INFO) << "pose: " << pose.translation().transpose();
        ui.UpdateNavState(sad::NavStated(0, pose, v_world));

        usleep(dt * 1e6);
    }

    ui.Quit();
    return 0;
}

有了重力加速度,使得其不能在一个平面。右下角分别显示了世界系下的速度分量和body系(baselink)下的速度分量。body系下x分量不发生变换,z方向线性递减;世界系下两个速度像是随正弦函数变化。
在这里插入图片描述

5.4 GN和LM在处理非线性迭代时的差异

后续补充吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/286621.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

六、HTML 段落

HTML 可以将文档分割为若干段落。 一、HTML 段落 段落是通过 <p> 标签定义的。 <p>这是一个段落 </p> <p>这是另一个段落</p> 注意&#xff1a;浏览器会自动地在段落的前后添加空行。&#xff08;</p> 是块级元素&#xff09; 二、不…

算法巡练day03Leetcode203移除链表元素707设计链表206反转链表

今日学习的文章视频链接 https://www.bilibili.com/video/BV1nB4y1i7eL/?vd_source8272bd48fee17396a4a1746c256ab0ae https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE 链表理论基础 见我的博…

Linux 命令echo

命令作用 输出一行字符串在shell中&#xff0c;可以打印变量的值输出结果写入到文件在显示器上显示一段文字&#xff0c;起到提示的作用 语法 echo [选项] [字符串] 参数 字符含义-n不自动换行-e解释转义字符-E不解释转义字符 如果-e有效&#xff0c;则识别以下序列&…

2024,这将是量子计算的真正挑战

2023年&#xff0c;一项项量子计算纪录被打破。 谷歌量子AI团队证明了将多个量子比特分组合成为一个逻辑量子比特的纠错方法可以提供更低的容错率。以往的纠错研究随着比特数的增加&#xff0c;错误率会提高&#xff0c;都是“越纠越错”&#xff0c;而这次谷歌首次实现了“越纠…

K8S本地开发环境-minikube安装部署及实践

引言 在上一篇介绍了k8s的入门和实战&#xff0c;本章就来介绍一下在windows环境如何使用minikube搭建K8s集群&#xff0c;好了废话不多说&#xff0c;下面就和我一起了解Minikube吧。 什么是Minikube&#xff1f; Minikube 是一种轻量级的 Kubernetes 实现&#xff0c;可在本…

1688商品详情API:实现商品详情自动化的关键步骤

一、准备工作 在使用1688商品详情API之前&#xff0c;我们需要进行一些准备工作。 注册与登录&#xff1a;首先&#xff0c;你需要在1688的开放平台上注册一个账号并创建一个应用。这样你就可以获得一个API密钥&#xff0c;这是调用API的凭证。阅读API文档&#xff1a;详细阅…

web开发-springboot-web

报错&#xff1a; Failure to find org.springframework.boot:spring-boot-starter-parent:pom:3.2.1.RELEASE in https://maven.aliyun.com/nexus/content/groups/public was cached in the local repository, resolution will not be reattempted until the update interval …

定制自己的GPTs,及使用ChatGPT/GPT4写程序的注意事项

如何能高效地处理文本、文献查阅、PPT编辑、编程、绘图和论文写作已经成为您成功的关键。而 ChatGPT&#xff0c;作为一种强大的自然语言处理模型&#xff0c;具备显著优势&#xff0c;能够帮助您在各个领域取得突破。 ChatGPT 在论文写作与编程方面也具备强大的能力。无论是进…

安卓在SOA中的运用

安卓在运用SOA研发的过程中&#xff0c;会针对实际情况对研发的架构和流程进行优化&#xff0c;通过优化过的架构和实施方案&#xff0c;不仅可以大大提升了整车开发的效率和灵活行以及功能落地的稳定性&#xff0c;同时也增加了系统的向上兼容性。 目前基于车载SOA系统的研发…

记一个CSS样式实现思路(鼠标聚焦时完整内容,失焦时只显示部分)

效果图 默认状态 鼠标悬浮时 缓慢展示完整内容 实现方法 方法一 使用max-width,当鼠标悬浮时&#xff0c;设置max-width为一个足够大的数值 <div class"flex justify-center align-center mt-20px"><div v-for"(item, key) in ssoList" :key&q…

HTML----JavaScript操作对象BOM对象

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 本章要求 了解BOM模型掌握BOM模型实际应用 一.BOM模型概述 BOM&#xff08;浏览器对象模型&#xff09;是JavaScript中的一个重要概念&#xff0c;它提供了一组用于控制浏览器窗口和页面内容的…

基于 ESP32-C3 开启 Flash 加密和安全启动并进行 OTA 测试

软件&#xff1a; esp-idf v5.1.2 硬件&#xff1a; ESP32-C3 board 1. 首先&#xff0c;准备一个明文固件 hello-world.bin 基于 esp-idf-v5.1.2\examples\get-started\hello_world 例程&#xff0c;使用如下指令&#xff0c;直接编译&#xff0c;获取明文固件 hello-worl…

大数据时代快速获取数据方法,爬虫技术理论剖析与实战演练

一、教程描述 人工智能和机器学习&#xff0c;都离不开数据&#xff0c;若是没有数据&#xff0c;再好的算法&#xff0c;再好的模型&#xff0c;都没有用武之地。数据不仅是指现成的数据库&#xff0c;更加是指每天增加的海量互联网数据。本套教程将通过多个实战项目&#xf…

2024上海国际智慧城市,物联网,大数据博览会(上海智博会)

随着科技的飞速发展&#xff0c;智慧城市、物联网与大数据已经成为当今社会发展的重要驱动力。作为国内最具影响力的科技展会之一&#xff0c;2024上海国际智慧城市,物联网,大数据博览会&#xff08;简称:世亚智博会&#xff09;汇聚了全球顶尖的智慧城市、物联网与大数据技术&…

JMeter之测试WebService接口

JMeter之测试WebService接口 1 背景2 目的3 介绍4 具体操作4.1 soapUI调用4.2 JMeter工具调用4.3 操作步骤流程4.3 重点 1 背景 WebService应用的范围是非常广&#xff0c;任何需要跨平台、跨系统进行数据交换和功能调用的场景都可以用此来实现&#xff0c;在实际的工作中也常常…

k8s-yaml格式

三种常见的项目发布方式&#xff1a; 蓝绿发布&#xff1a; 金丝雀发布&#xff08;灰度发布&#xff09;&#xff1a; 滚动发布&#xff1a; 应用程序升级&#xff0c;面临的最大的问题&#xff0c;就是新旧业务的更换&#xff0c;立项--定稿--需求发布--开发--测试--发布&…

有效边表填充算法

有效边表填充算法 如何填充示例三角形 按照扫描线从上往下的顺序&#xff0c;依次处理和多边形相交的扫描线&#xff0c;对于当前处理的扫描线找到和它相交的所有边的交点&#xff0c;按照交点横坐标从小到大的顺序&#xff0c;两个两个配对&#xff0c;配对之后填充每对交点之…

踩了Vue2运行机制的坑-响应式原理

最近遇到一个很奇怪的bug&#xff1a; 前置&#xff1a;后端接口返回的数据是这样的&#xff1a; ①首先在store中取出后端返回的数据Ares.data&#xff0c;在这里打印输出是正常的 ②然后在vue页面上再取出A.data也就是res.data.data&#xff0c;以及其它几个字段即res.data.X…

Spring技术内幕笔记之IOC的实现

IOC容器的实现 依赖反转&#xff1a; 依赖对象的获得被反转了&#xff0c;于是依赖反转更名为&#xff1a;依赖注入。许多应用都是由两个或者多个类通过彼此的合作来实现业务逻辑的&#xff0c;这使得每个对象都需要与其合作的对象的引用&#xff0c;如果这个获取过程需要自身…

解决报错:找不到显卡

今天做实验碰到一个问题&#xff1a;torch找不到显卡&#xff1a; 打开任务管理器&#xff0c;独显直接没了&#xff0c;一度以为是要去修电脑了&#xff0c;突然想到上次做实验爆显存&#xff0c;屏蔽了gpu用cpu训练&#xff1a; import os os.environ["CUDA_DEVICE_OR…