slam中的旋转表示

旋转表示

以下是角轴、四元数、旋转矩阵、欧拉角的表示及其相互转换。

角轴

对于两个坐标系 F 1 \mathcal{F}_1 F1 F 2 \mathcal{F}_2 F2,其坐标轴表示如下,两个坐标系之间的关系我们可以这样表述,坐标系 F 1 \mathcal{F}_1 F1沿着z轴旋转 θ \theta θ角得到 F 2 \mathcal{F}_2 F2系,这里的z轴,即为角轴中的旋转轴, θ \theta θ为角轴中的旋转角。

在这里插入图片描述

图 1

角轴=>旋转矩阵

一般的,我们定义旋转轴为 u = [ u 1 , u 2 , u 3 ] T \boldsymbol{u}=[u_1,u_2,u_3]^T u=[u1,u2,u3]T,绕着 u \boldsymbol{u} u旋转的角度为 θ \theta θ,根据罗德里格斯公式,可以将角轴转换为旋转矩阵,具体如下,设空间中一点在 F 1 \mathcal{F}_1 F1系中坐标为 v 1 \boldsymbol{v}^1 v1,在 F 2 \mathcal{F}_2 F2系中坐标为 v 2 \boldsymbol{v}^2 v2,有 v 1 = C 2 1 v 2 \boldsymbol{v}^1=\boldsymbol{C}_2^1 \boldsymbol{v}^2 v1=C21v2
C 2 1 = cos ⁡ θ I + ( 1 − cos ⁡ θ ) u u T + sin ⁡ θ u ∧ (1) \boldsymbol{C}_2^1 = \cos\theta \boldsymbol{I} + (1-\cos \theta)\boldsymbol{uu^T} + \sin \theta\boldsymbol{u^{\wedge}} \tag{1} C21=cosθI+(1cosθ)uuT+sinθu(1)
Eigen库中的角轴转换为旋转矩阵就是按照公式 ( 1 ) (1) (1)计算的,代码如下,

Eigen::Matrix3f testRz;
Eigen::Vector3f unitz(0, 0, 1); 
testRz = Eigen::AngleAxisf(M_PI/2, unitz);

计算结果如下,在这里插入图片描述

以上为角轴与旋转矩阵的转换关系。


角轴=>四元数

Eigen中的四元数定义如下,
q = cos ⁡ θ 2 + u sin ⁡ θ 2 (2) \boldsymbol{q} = \cos{\frac{\theta}{2}} + \boldsymbol{u}\sin{\frac{\theta}{2}} \tag{2} q=cos2θ+usin2θ(2)
其中的 u \boldsymbol u u θ \theta θ和角轴中的定义一样,公式 ( 2 ) (2) (2)定义的四元数描述的是“将坐标系 F 1 \mathcal{F}_1 F1沿 u \boldsymbol u u旋转 θ \theta θ变成坐标系 F 2 \mathcal{F}_2 F2”,其中 u \boldsymbol u u是定义在 F 1 \mathcal{F}_1 F1系的。设空间中一点在 F 1 \mathcal{F}_1 F1系中坐标为 v 1 \boldsymbol{v}^1 v1,在 F 2 \mathcal{F}_2 F2系中坐标为 v 2 \boldsymbol{v}^2 v2,有 v 1 = q v 2 q ∗ \boldsymbol{v}^1=\boldsymbol{q} \boldsymbol{v}^2 \boldsymbol{q^{\ast}} v1=qv2q,通常情况下, q \boldsymbol{q} q可记为 q 2 1 \boldsymbol{q}_2^1 q21,是一个单位四元数。利用角轴构造四元数代码如下,

Eigen::AngleAxisf utheta;
utheta = Eigen::AngleAxisf(M_PI/2, unitz);
Eigen::Quaternionf q(utheta);

q的各个分量打印如下,

在这里插入图片描述

利用同一角轴构造的旋转矩阵和四元数,表示的是同一个旋转。

四元数

Eigen中四元数还可以采用两个向量来构造,这两个向量可以求出轴和角,设这两个向量为 v 1 , v 2 v_1,v_2 v1,v2,那么角轴为 v 1 × v 2 v_1 \times v_2 v1×v2,示例代码如下,

Eigen::Vector3f v1(1, 0, 0);
Eigen::Vector3f v2(0, 1, 0);
qutheta = Eigen::Quaternionf::FromTwoVectors(v1, v2);

可以看出 v 1 , v 2 v_1,v_2 v1,v2构造出的旋转是按z轴以右手系正向旋转90°,其结果应该与由角轴构建的四元数相同,结果如下,
在这里插入图片描述

这个可以方便得求出当前坐标系与水平系的旋转,设水平系中,重力为 g = [ 0 , 0 , g ] \boldsymbol{g}=[0,0,g] g=[0,0,g],其中 g ≈ 9.8 g\approx 9.8 g9.8,这里没有假设g为负,是因为imu水平时,测得的重力为g,是正值,这是由imu测量原理决定的。由imu静止状态下测得的重力为 g ^ \hat{\boldsymbol{g}} g^ g ^ × g \hat{\boldsymbol{g}} \times \boldsymbol{g} g^×g得到的旋转就是水平系到测量系的旋转,带入代码中,即可得到 C 测量系 水平系 C_{测量系}^{水平系} C测量系水平系

四元数=>旋转矩阵

四元数转换为旋转矩阵,可以按四元数中定义的 u \boldsymbol u u θ \theta θ,按式 ( 1 ) (1) (1)计算,还可以按求导来计算,主要思想如下,
R p = q ⊗ p ⊗ q ∗ = ⌊ q ⌋ L ⌊ q ∗ ⌋ R p (3) Rp = q\otimes p \otimes q^{\ast} = {\lfloor{q}\rfloor}_L{\lfloor{q^{\ast}}\rfloor}_R p \tag{3} Rp=qpq=qLqRp(3)

R = ( q 0 2 − ∥ q v ∥ 2 ) I 3 × 3 + 2 q v q v T + 2 q 0 q v ∧ (4) R=(q_0^2 - {\|{q_v}\|}^2)\boldsymbol{I}_{3\times3} + 2q_v q_v^T + 2q_0 q_v^{\wedge} \tag{4} R=(q02qv2)I3×3+2qvqvT+2q0qv(4)

旋转矩阵 R R R ⌊ q ⌋ L ⌊ q ∗ ⌋ R {\lfloor{q}\rfloor}_L{\lfloor{q^{\ast}}\rfloor}_R qLqR的右下角 3 × 3 3\times3 3×3子块,Eigen库中就是按照公式 ( 4 ) (4) (4)来计算的,以下为Eigen中 q q q转为 R R R的代码,计算方法与公式 ( 4 ) (4) (4)是一样的。

template<class Derived>
inline typename QuaternionBase<Derived>::Matrix3
QuaternionBase<Derived>::toRotationMatrix(void) const
{
  // NOTE if inlined, then gcc 4.2 and 4.4 get rid of the temporary (not gcc 4.3 !!)
  // if not inlined then the cost of the return by value is huge ~ +35%,
  // however, not inlining this function is an order of magnitude slower, so
  // it has to be inlined, and so the return by value is not an issue
  Matrix3 res;

  const Scalar tx  = Scalar(2)*this->x();
  const Scalar ty  = Scalar(2)*this->y();
  const Scalar tz  = Scalar(2)*this->z();
  const Scalar twx = tx*this->w();
  const Scalar twy = ty*this->w();
  const Scalar twz = tz*this->w();
  const Scalar txx = tx*this->x();
  const Scalar txy = ty*this->x();
  const Scalar txz = tz*this->x();
  const Scalar tyy = ty*this->y();
  const Scalar tyz = tz*this->y();
  const Scalar tzz = tz*this->z();

  res.coeffRef(0,0) = Scalar(1)-(tyy+tzz);
  res.coeffRef(0,1) = txy-twz;
  res.coeffRef(0,2) = txz+twy;
  res.coeffRef(1,0) = txy+twz;
  res.coeffRef(1,1) = Scalar(1)-(txx+tzz);
  res.coeffRef(1,2) = tyz-twx;
  res.coeffRef(2,0) = txz-twy;
  res.coeffRef(2,1) = tyz+twx;
  res.coeffRef(2,2) = Scalar(1)-(txx+tyy);

  return res;
}

欧拉角

目前常用的是yaw->pitch->roll的约定,即 F 1 \mathcal{F}_1 F1系先按z轴以右手系旋转yaw角得到 T \mathcal{T} T系,以 T \mathcal{T} T系为基础,按 T \mathcal{T} T系的y轴以右手系旋转pitch角得到 I \mathcal{I} I系,以 I \mathcal{I} I系为基础,按 I \mathcal{I} I系的x轴以右手系旋转roll角,得到 F 2 \mathcal{F}_2 F2系,这里yaw pitch roll即为欧拉角。根据约定的不同,欧拉角有多种形式,但是目前仅使用过上述形式。

欧拉角=>旋转矩阵

在Eigen中可以根据角轴得到旋转矩阵,
C 2 1 = C T 1 C I T C 2 I (5) \boldsymbol{C}_2^1 = \boldsymbol{C}_{\mathcal{T}}^1 \boldsymbol{C}_{\mathcal{I}}^{\mathcal{T}} \boldsymbol{C}_2^{\mathcal{I}} \tag{5} C21=CT1CITC2I(5)
( 5 ) (5) (5)中的3个分量均可根据式 ( 1 ) (1) (1)计算得到,以下为代码

Eigen::Matrix3f Rypr;
Eigen::Vector3f Unitz(0, 0, 1);
Eigen::Vector3f Unity(0, 1, 0);
Eigen::Vector3f Unitx(1, 0, 0);
float yaw = M_PI/4, pitch = M_PI/4, roll = M_PI/4;
// 以下得到的就是公式(5)中的C12
Rypr = Eigen::AngleAxisf(yaw, Unitz)
    * Eigen::AngleAxisf(pitch, Unity)
    * Eigen::AngleAxisf(roll, Unitx);

关于欧拉角更详细的内容见此处

旋转矩阵

旋转矩阵=>欧拉角

根据公式 ( 5 ) (5) (5)可以找到旋转矩阵与欧拉角的关系,在Eigen中根据旋转矩阵 C 2 1 \boldsymbol{C}_2^1 C21,按以下代码可以得到按yaw-pitch-roll的欧拉角,需要注意的是,得到的结果顺序为[yaw, pitch, roll]。代码中的2,1,0代表的是按哪个轴旋转,2代表z,1代表y,0代表x,即 R = R z R y R x R=R_zR_yR_x R=RzRyRx

//Rypr为C12
Eigen::Vector3f ypr = Rypr.eulerAngles(2, 1, 0);

结果为,

在这里插入图片描述

罗德里格斯公式

可以参考这里,利用性质 a ∧ a ∧ = a a T − I a^{\wedge}a^{\wedge}=aa^T-\boldsymbol{I} aa=aaTI,其中 a a a是单位向量,可以得到罗德里格斯公式两种形式,将式 ( 1 ) (1) (1)中的 u u T uu^T uuT换成 u ∧ u ∧ + I u^{\wedge}u^{\wedge}+\boldsymbol{I} uu+I即可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值