VINS-Mono初始化过程中的坐标转换关系

前言

在学习VINS-Mono过程中,对初始化代码中的坐标转换关系做出了一些推导,特意写了博客记录一下,主要记录大体的变量转换关系。

相机和IMU的外参

若需要VINS标定旋转外参,则进入以下代码:

    if (initial_ex_rotation.CalibrationExRotation(corres, pre_integrations[frame_count]->delta_q, calib_ric))
    {
        ROS_WARN("initial extrinsic rotation calib success");
        ROS_WARN_STREAM("initial extrinsic rotation: " << endl << calib_ric);
        ric[0] = calib_ric;
        RIC[0] = calib_ric;
        ESTIMATE_EXTRINSIC = 1;
    }

旋转外参 r i c [ 0 ] ric\left[0\right] ric[0] 是 camera 坐标系到 body 坐标系的转换关系,记为 R b , c R_{b,c} Rb,c,平移外参在未后期优化前,默认为 0 0 0,记为 t b , c t_{b,c} tb,c

全局sfm

首先选定一个 camera 参考坐标系 c l c_l cl

    int l;
    if (!relativePose(relative_R, relative_T, l))
    {
        ROS_INFO("Not enough features or parallax; Move device around");
        return false;
    }

设 WZ为滑动窗口大小。 c l c_l cl 为滑窗中第 l l l 帧到第 WZ 帧满足一定视差(三角化时相对更准确)并可以解出两帧之间位姿 relative_R、relative_T 的图像帧(一般就是 c 0 c_0 c0 帧)。relative_R、relative_T 表示的是第 WZ帧到第 l l l 帧的变化。

    GlobalSFM sfm;
    if(!sfm.construct(frame_count + 1, Q, T, l,
              relative_R, relative_T,
              sfm_f, sfm_tracked_points))
    {
        ROS_DEBUG("global SFM failed!");
        marginalization_flag = MARGIN_OLD;
        return false;
    }

在 initial_sfm.cpp 中,三角化求的路标点便以 c l c_l cl 帧为参考系。经过一次 ceres 优化后得到滑窗中图像帧的位姿为 q [ i ] q\left[i\right] q[i] T [ i ] T\left[i\right] T[i]

	for (int i = 0; i < frame_num; i++)
	{
		q[i].w() = c_rotation[i][0]; 
		q[i].x() = c_rotation[i][1]; 
		q[i].y() = c_rotation[i][2]; 
		q[i].z() = c_rotation[i][3]; 
		q[i] = q[i].inverse();
	}
	for (int i = 0; i < frame_num; i++)
	{
		T[i] = -1 * (q[i] * Vector3d(c_translation[i][0], c_translation[i][1], c_translation[i][2]));
	}

这些位姿具体表示的转换关系为:
R c l , c 0 R_{c_{l},c_{0}} Rcl,c0 R c l , c 1 R_{c_{l},c_{1}} Rcl,c1、… 、 R c l , c W Z − 1 R_{c_{l},c_{WZ-1}} Rcl,cWZ1 R c l , c W Z R_{c_{l},c_{WZ}} Rcl,cWZ ;
P c l , c 0 P_{c_{l},c_{0}} Pcl,c0 P c l , c 1 P_{c_{l},c_{1}} Pcl,c1、… 、 P c l , c W Z − 1 P_{c_{l},c_{WZ-1}} Pcl,cWZ1 P c l , c W Z P_{c_{l},c_{WZ}} Pcl,cWZ

用恢复出的三角点 pnp 求解出 all_image_frame 所有帧的位姿:

    for (int i = 0; frame_it != all_image_frame.end( ); frame_it++)
    {
       //省略
       ...
       frame_it->second.R = R_pnp * RIC[0].transpose();
       frame_it->second.T = T_pnp; 
    }

不妨记为:
R c l , 0 R_{c_{l},0} Rcl,0 R c l , 1 R_{c_{l},1} Rcl,1、… 、 R c l , b 0 R_{c_{l},b_{0}} Rcl,b0 R c l , 9 R_{c_{l},9} Rcl,9、… 、 R c l , b 1 R_{c_{l},b_{1}} Rcl,b1、… 、 R c l , b W Z − 1 R_{c_{l},b_{WZ-1}} Rcl,bWZ1、… 、 R c l , 98 R_{c_{l},98} Rcl,98 R c l , b W Z R_{c_{l},b_{WZ}} Rcl,bWZ ;
P c l , 0 P_{c_{l},0} Pcl,0 P c l , 1 P_{c_{l},1} Pcl,1、… 、 P c l , c 0 P_{c_{l},c_{0}} Pcl,c0 P c l , 9 P_{c_{l},9} Pcl,9、… 、 P c l , c 1 P_{c_{l},c_{1}} Pcl,c1、… 、 P c l , c W Z − 1 P_{c_{l},c_{WZ-1}} Pcl,cWZ1、… 、 P c l , 98 P_{c_{l},98} Pcl,98 P c l , c W Z P_{c_{l},c_{WZ}} Pcl,cWZ

速度、重力和尺度因子

在 initial_alignment.cpp 中,使用 all_image_frame 所有帧间的关系求出陀螺仪 bias、所有帧在body下的速度、 c l c_l cl 帧下的重力因子以及尺度因子:
v 0 v_{0} v0 v 1 v_{1} v1、… 、 v b 0 v_{b_{0}} vb0 v 9 v_{9} v9、… 、 v b 1 v_{b_{1}} vb1、… 、 v b W Z − 1 v_{b_{WZ-1}} vbWZ1、… 、 v 98 v_{98} v98 v b W Z v_{b_{WZ}} vbWZ g c l g_{c_{l}} gcl s s s
此后第 0 帧到第 WZ 帧的 R s Rs Rs P s Ps Ps 被赋值:

    for (int i = 0; i <= frame_count; i++)
    {
        Matrix3d Ri = all_image_frame[Headers[i].stamp.toSec()].R;
        Vector3d Pi = all_image_frame[Headers[i].stamp.toSec()].T;
        Ps[i] = Pi;
        Rs[i] = Ri;
        all_image_frame[Headers[i].stamp.toSec()].is_key_frame = true;
    }

这些位姿此时表示为:
R c l , b 0 R_{c_{l},b_{0}} Rcl,b0 R c l , b 1 R_{c_{l},b_{1}} Rcl,b1、… 、 R c l , b W Z − 1 R_{c_{l},b_{WZ-1}} Rcl,bWZ1 R c l , b W Z R_{c_{l},b_{WZ}} Rcl,bWZ ;
P c l , c 0 P_{c_{l},c_{0}} Pcl,c0 P c l , c 1 P_{c_{l},c_{1}} Pcl,c1、… 、 P c l , c W Z − 1 P_{c_{l},c_{WZ-1}} Pcl,cWZ1 P c l , c W Z P_{c_{l},c_{WZ}} Pcl,cWZ

特征点的深度

在 void triangulate(Vector3d Ps[ ],Vector3d tic[ ],Matrix3d ric[ ]) 函数中三角化求出特征点的深度。若特征点的深度值 estimated_depth小于0,则进行三角化求解。
一般来说,三角化的过程如下,已知多个视角匹配的归一化平面上的特征点 { u , u , , . . . } \{u,u^,,...\} {u,u,,...}以及对应的多个视觉的投影矩阵 { P , P ’ , … } \{P,P^’,…\} {P,P,};

[ u x u y 1 ] = λ [ R t ] [ x y z 1 ] = λ [ p 1 p 2 p 3 p 4 p 5 p 6 p 7 p 8 p 9 p 10 p 11 p 12 ] [ x y z 1 ] = λ [ P 0 T P 1 T P 2 T ] X \quad\quad\quad\quad\quad\quad\left[\begin{matrix}u_x\\u_y\\1\end{matrix}\right]=\lambda[R\quad t]\left[\begin{matrix}x\\y\\z\\1\end{matrix}\right]=\lambda\left[\begin{matrix}p_1\quad p_2\quad p_3\quad p_4 \\p_5\quad p_6\quad p_7\quad p_8\\p_9\quad p_{10}\quad p_{11}\quad p_{12}\end{matrix}\right]\left[\begin{matrix}x\\y\\z\\1\end{matrix}\right]=\lambda\left[\begin{matrix}P^T_0\\P^T_1\\P^T_2\end{matrix}\right]X uxuy1=λ[Rt]xyz1=λp1p2p3p4p5p6p7p8p9p10p11p12xyz1=λP0TP1TP2TX
{ u x = λ P 0 T X u y = λ P 1 T X 1   =   λ P 2 T X ⇒ [ P 0 T − u x P 2 T P 1 T − u y P 2 T ] X = 0 \left\{\begin{matrix}u_x=\lambda P^T_0X\\u_y=\lambda P^T_1X\\1\ =\ \lambda P^T_2X\end{matrix}\right.\Rightarrow\left[\begin{matrix}P^T_0-u_xP^T_2\\P^T_1-u_yP^T_2\end{matrix}\right]X=0 ux=λP0TXuy=λP1TX1 = λP2TX[P0TuxP2TP1TuyP2T]X=0

那么 n 个匹配的特征点可构建 2n*4 大小的矩阵,SVD 求解得到 3D 点。
在VINS这个三角化的代码中,分成两种情况分析。

  1. 初始化没完成,此时 P b 0 , c 0 = 0 P_{b_0,c_0}=0 Pb0,c0=0,对 feature 中每个特征点:
    若特征点的 start_frame 为0,
    t 0 = P s [ 0 ] c l , c 0 + R s [ 0 ] c l , b 0 ∗ P b 0 , c 0 = P c l , c 0 t0=Ps[0]_{c_l,c_0}+Rs[0]_{c_l,b_0}*P_{b_0,c_0}=P_{c_l,c_0} t0=Ps[0]cl,c0+Rs[0]cl,b0Pb0,c0=Pcl,c0;
    R 0 = R s [ 0 ] c l , b 0 ∗ R b 0 , c 0 = R c l , c 0 R0=Rs[0]_{c_l,b_0}*R_{b_0,c_0}=R_{c_l,c_0} R0=Rs[0]cl,b0Rb0,c0=Rcl,c0;
    对 feature_per_frame 的特征点的不同坐标:
    第 0 帧: t 1 = t 0   ; R 1 = R 0   ;   t = 0 t1=t0\ ; R1=R0\ ;\ t=0 t1=t0 ;R1=R0 ; t=0 P c 0 , c 0 ; P_{c_0,c_0}; Pc0,c0; R = I R=I R=I R c 0 , c 0 ; R_{c_0,c_0}; Rc0,c0;
    第 1 帧: t 1 = P s [ 1 ] c l , c 1 + R s [ 1 ] c l , b 1 ∗ P b 1 , c 1 = P c l , c 1   ; t1=Ps[1]_{c_l,c_1}+Rs[1]_{c_l,b_1}*P_{b_1,c_1}=P_{c_l,c_1}\ ; t1=Ps[1]cl,c1+Rs[1]cl,b1Pb1,c1=Pcl,c1 ;
    R 1 = R s [ 1 ] c l , b 1 ∗ R b 1 , c 1 = R c l , c 1   ; \qquad\quad R1=Rs[1]_{c_l,b_1}*R_{b_1,c_1}=R_{c_l,c_1}\ ; R1=Rs[1]cl,b1Rb1,c1=Rcl,c1 ;
      t = R c l , c 0 − 1 ( P c l , c 1 − P c l , c 0 ) = P c 0 , c 1 ; \qquad\quad\ t=R^{-1}_{c_l,c_0}(P_{c_l,c_1}-P_{c_l,c_0})=P_{c_0,c_1};  t=Rcl,c01(Pcl,c1Pcl,c0)=Pc0,c1;
    R = R c l , c 0 − 1 ∗ R c l , c 1 = R c 0 , c 1 ; \qquad\quad R=R^{-1}_{c_l,c_0}*R_{c_l,c_1}=R_{c_0,c_1} ; R=Rcl,c01Rcl,c1=Rc0,c1;
    代码中的投影矩阵 P是 c 0 c_0 c0 c 1 c_1 c1 的位姿变换;
    第 2 帧: t = P c 0 , c 2 ; t=P_{c_0,c_2}; t=Pc0,c2; R = R c 0 , c 2 ; R=R_{c_0,c_2} ; R=Rc0,c2;
    投影矩阵 P是 c 0 c_0 c0 c 2 c_2 c2 的位姿变换;

    若特征点的 start_frame 为 1,2…,依次类推。
    可以推出 SVD 求解得到的是每个特征点在其 start_frame 帧下的深度z。
  2. 初始化完成了,此时 P b 0 , c 0 P_{b_0,c_0} Pb0,c0不为 0,P、V、Q皆转换到世界坐标系下,为 body 坐标系到世界坐标系的变换关系。
    对 feature中每个特征点:
    若特征点的 start_frame 为 0,
    t 0 = P s [ 0 ] w , b 0 + R s [ 0 ] w , b 0 ∗ P b 0 , c 0 = P w , c 0 t0=Ps[0]_{w,b_0}+Rs[0]_{w,b_0}*P_{b_0,c_0}=P_{w,c_0} t0=Ps[0]w,b0+Rs[0]w,b0Pb0,c0=Pw,c0;
    R 0 = R s [ 0 ] w , b 0 ∗ R b 0 , c 0 = R w , c 0 R0=Rs[0]_{w,b_0}*R_{b_0,c_0}=R_{w,c_0} R0=Rs[0]w,b0Rb0,c0=Rw,c0;
    第 0 帧: t 1 = t 0   ; R 1 = R 0   ;   t = 0 t1=t0\ ; R1=R0\ ;\ t=0 t1=t0 ;R1=R0 ; t=0 P c 0 , c 0 ; P_{c_0,c_0}; Pc0,c0; R = I R=I R=I R c 0 , c 0 ; R_{c_0,c_0}; Rc0,c0;
    第 1 帧: t 1 = P s [ 1 ] c l , c 1 + R s [ 1 ] c l , b 1 ∗ P b 1 , c 1 = P c l , c 1   ; t1=Ps[1]_{c_l,c_1}+Rs[1]_{c_l,b_1}*P_{b_1,c_1}=P_{c_l,c_1}\ ; t1=Ps[1]cl,c1+Rs[1]cl,b1Pb1,c1=Pcl,c1 ;
    R 1 = R s [ 1 ] c l , b 1 ∗ R b 1 , c 1 = R c l , c 1   ; \qquad\quad R1=Rs[1]_{c_l,b_1}*R_{b_1,c_1}=R_{c_l,c_1}\ ; R1=Rs[1]cl,b1Rb1,c1=Rcl,c1 ;
      t = R c l , c 0 − 1 ( P c l , c 1 − P c l , c 0 ) = P c 0 , c 1 ; \qquad\quad\ t=R^{-1}_{c_l,c_0}(P_{c_l,c_1}-P_{c_l,c_0})=P_{c_0,c_1};  t=Rcl,c01(Pcl,c1Pcl,c0)=Pc0,c1;
    R = R c l , c 0 − 1 ∗ R c l , c 1 = R c 0 , c 1 ; \qquad\quad R=R^{-1}_{c_l,c_0}*R_{c_l,c_1}=R_{c_0,c_1} ; R=Rcl,c01Rcl,c1=Rc0,c1;
    代码中的投影矩阵 P c 0 c_0 c0 c 1 c_1 c1 的位姿变换;
    第 2 帧: t = P c 0 , c 2 ; t=P_{c_0,c_2}; t=Pc0,c2; R = R c 0 , c 2 ; R=R_{c_0,c_2} ; R=Rc0,c2;
    投影矩阵 P 是 c 0 c_0 c0 c 2 c_2 c2 的位姿变换;
    若特征点的 start_frame 为 1,2…,依次类推。
    同样可以推出 SVD 求解得到的是每个特征点在其 start_frame 帧下的深度z。

真实尺度下的R、P、V和特征点深度

此时在滑窗中:
1. R R R表示的仍是各body坐标系到 c l c_l cl的转换关系:
\quad R s [ 0 ] : R s [ 0 ] c l , b 0 Rs[0]:Rs[0]_{c_{l},b_{0}} Rs[0]:Rs[0]cl,b0;
\quad R s [ 1 ] : R s [ 1 ] c l , b 1 Rs[1]:Rs[1]_{c_{l},b_{1}} Rs[1]:Rs[1]cl,b1;
\quad
\quad R s [ W Z ] : R s [ W Z ] c l , b W Z Rs[WZ]:Rs[WZ]_{c_{l},b_{WZ}} Rs[WZ]:Rs[WZ]cl,bWZ ;
2. P P P通过转换,表示body坐标系到 c l c_l cl的转换关系:

    for (int i = frame_count; i >= 0; i--)
    {
        Ps[i] = s * Ps[i] - Rs[i] * TIC[0] - (s * Ps[0] - Rs[0] * TIC[0]);
    }

\quad P s [ 0 ] : s ∗ P s [ 0 ] c l , c 0 − R s [ 0 ] c l , b 0 ∗ P s [ 0 ] b 0 , c 0 − ( s ∗ P s [ 0 ] c l , c 0 − R s [ 0 ] c l , b 0 ∗ P s [ 0 ] b 0 , c 0 ) = 0 即 s ∗ P s [ 0 ] c l , b 0 Ps[0]:s*Ps[0]_{{c_l},{c_0}}-Rs[0]_{{c_l},{b_0}}*Ps[0]_{{b_0},{c_0}}-(s*Ps[0]_{{c_l},{c_0}}-Rs[0]_{{c_l},{b_0}}*Ps[0]_{{b_0},{c_0}})=0即s*Ps[0]_{{c_l},{b_0}} Ps[0]:sPs[0]cl,c0Rs[0]cl,b0Ps[0]b0,c0(sPs[0]cl,c0Rs[0]cl,b0Ps[0]b0,c0)=0sPs[0]cl,b0;
\quad P s [ 1 ] : s ∗ P s [ 1 ] c l , c 1 − R s [ 1 ] c l , b 1 ∗ P s [ 1 ] b 1 , c 1 − ( s ∗ P s [ 0 ] c l , c 0 − R s [ 0 ] c l , b 0 ∗ P s [ 0 ] b 0 , c 0 ) 即 s ∗ P s [ 1 ] c l , b 1 Ps[1]:s*Ps[1]_{{c_l},{c_1}}-Rs[1]_{{c_l},{b_1}}*Ps[1]_{{b_1},{c_1}}-(s*Ps[0]_{{c_l},{c_0}}-Rs[0]_{{c_l},{b_0}}*Ps[0]_{{b_0},{c_0}})即s*Ps[1]_{{c_l},{b_1}} Ps[1]:sPs[1]cl,c1Rs[1]cl,b1Ps[1]b1,c1(sPs[0]cl,c0Rs[0]cl,b0Ps[0]b0,c0)sPs[1]cl,b1;
\quad
\quad P s [ W Z ] : 即 s ∗ P s [ W Z ] c l , b W Z Ps[WZ]:即s*Ps[WZ]_{{c_l},{b_{WZ}}} Ps[WZ]:sPs[WZ]cl,bWZ;
3. V V V被转换以 c l c_l cl为参考坐标系:

    for (frame_i = all_image_frame.begin(); frame_i != all_image_frame.end(); frame_i++)
    {
        if(frame_i->second.is_key_frame)
        {
            kv++;
            Vs[kv] = frame_i->second.R * x.segment<3>(kv * 3);
        }
    }

\quad V s [ 0 ] : R s [ 0 ] c l , b 0 ∗ v b 0 Vs[0]:Rs[0]_{c_{l},b_{0}}*v_{b_0} Vs[0]:Rs[0]cl,b0vb0;
\quad V s [ 1 ] : R s [ 1 ] c l , b 1 ∗ v b 1 Vs[1]:Rs[1]_{c_{l},b_{1}}*v_{b_1} Vs[1]:Rs[1]cl,b1vb1;
\quad
\quad V s [ W Z ] : R s [ W Z ] c l , b W Z ∗ v b W Z Vs[WZ]:Rs[WZ]_{c_{l},b_{WZ}}*v_{b_{WZ}} Vs[WZ]:Rs[WZ]cl,bWZvbWZ ;
4.feature中的每个特征点深度estimated_depth都乘以s,得到在实际尺度下的特征点深度。

    for (auto &it_per_id : f_manager.feature)
    {
        it_per_id.used_num = it_per_id.feature_per_frame.size();
        if (!(it_per_id.used_num >= 2 && it_per_id.start_frame < WINDOW_SIZE - 2))
            continue;
        it_per_id.estimated_depth *= s;
    }

当知道真实的米制平移时,投影矩阵 { P , P ’ , … } \{P,P^’,…\} {P,P,}的平移带有尺度;
[ u x u y 1 ] = λ ′ [ R t ] [ x y z ′ 1 ] = λ ′ [ p 1 p 2 p 3 s p 4 p 5 p 6 p 7 s p 8 p 9 p 10 p 11 s p 12 ] [ x y z ′ 1 ] = λ ′ [ p 1 p 2 p 3 p 4 p 5 p 6 p 7 p 8 p 9 p 10 p 11 p 12 ] [ x y z ′ s ] = λ ′ s [ p 1 p 2 p 3 p 4 p 5 p 6 p 7 p 8 p 9 p 10 p 11 p 12 ] [ x / s y / s z ′ s 1 ] = λ [ p 1 p 2 p 3 p 4 p 5 p 6 p 7 p 8 p 9 p 10 p 11 p 12 ] [ x / s y / s z ′ / s 1 ] \left[\begin{matrix}u_x\\u_y\\1\end{matrix}\right]=\lambda^{'} [R\quad t]\left[\begin{matrix}x\\y\\z^{'}\\1\end{matrix}\right]=\lambda^{'} \left[\begin{matrix}p_1\quad p_2\quad p_3\quad sp_4 \\p_5\quad p_6\quad p_7\quad sp_8\\p_9\quad p_{10}\quad p_{11}\quad sp_{12}\end{matrix}\right]\left[\begin{matrix}x\\y\\z^{'}\\1\end{matrix}\right]=\lambda^{'} \left[\begin{matrix}p_1\quad p_2\quad p_3\quad p_4 \\p_5\quad p_6\quad p_7\quad p_8\\p_9\quad p_{10}\quad p_{11}\quad p_{12}\end{matrix}\right]\left[\begin{matrix}x\\y\\z^{'}\\s\end{matrix}\right]=\lambda^{'} s\left[\begin{matrix}p_1\quad p_2\quad p_3\quad p_4 \\p_5\quad p_6\quad p_7\quad p_8\\p_9\quad p_{10}\quad p_{11}\quad p_{12}\end{matrix}\right]\left[\begin{matrix}x/s\\y/s\\z^{'}s\\1\end{matrix}\right]=\lambda\left[\begin{matrix}p_1\quad p_2\quad p_3\quad p_4 \\p_5\quad p_6\quad p_7\quad p_8\\p_9\quad p_{10}\quad p_{11}\quad p_{12}\end{matrix}\right]\left[\begin{matrix}x/s\\y/s\\z^{'}/s\\1\end{matrix}\right] uxuy1=λ[Rt]xyz1=λp1p2p3sp4p5p6p7sp8p9p10p11sp12xyz1=λp1p2p3p4p5p6p7p8p9p10p11p12xyzs=λsp1p2p3p4p5p6p7p8p9p10p11p12x/sy/szs1=λp1p2p3p4p5p6p7p8p9p10p11p12x/sy/sz/s1
此时求解的estimator_depth = z ′ = z ∗ s = z^{'}= z*s =z=zs

R、P、V转换到世界坐标系


    Matrix3d R0 = Utility::g2R(g);
    double yaw = Utility::R2ypr(R0 * Rs[0]).x();
    R0 = Utility::ypr2R(Eigen::Vector3d{-yaw, 0, 0}) * R0;

    g = R0 * g;
    Matrix3d rot_diff = R0;

    for (int i = 0; i <= frame_count; i++)
    {
        Ps[i] = rot_diff * Ps[i];
        Rs[i] = rot_diff * Rs[i];
        Vs[i] = rot_diff * Vs[i];
    }

1.首先求得将归一化的 g c l g_{c_l} gcl转换到世界坐标系 ( 0   0   1 ) T (0\ 0\ 1)^T (0 0 1)T的旋转矩阵 R w , c l R_{w,{c_l}} Rw,cl,使用XYZ顺序欧拉角来表示的话不妨记为 R w , c l = { R z w , c l ∗ R y w , c l ∗ R x w , c l } R_{w,{c_l}}=\{Rz_{w,{c_l}}*Ry_{w,{c_l}}*Rx_{w,{c_l}}\} Rw,cl={Rzw,clRyw,clRxw,cl}。用{…}表示由欧拉角表示的旋转矩阵。
2.令 R 0 = { R y w , c l ∗ R x w , c l } R0=\{Ry_{w,{c_l}}*Rx_{w,{c_l}}\} R0={Ryw,clRxw,cl}, R 0 R0 R0是yaw角为0的 R w , c l R_{w,{c_l}} Rw,cl,yaw角的变化不影响 R 0 R0 R0有和 R w , c l R_{w,{c_l}} Rw,cl一样的转换重力向量参考系的功能,因为 ( 0   0   1 ) T (0\ 0\ 1)^T (0 0 1)T没有xy平面的值(除了0),可以参考《如何通俗地解释欧拉角?之后为何要引入四元数?》直观感受一下欧拉角。
3.求得 R 0 ∗ R s [ 0 ] c l , b 0 R0*Rs[0]_{c_l,b_0} R0Rs[0]cl,b0的yaw角,并用XYZ顺序欧拉角{-yaw,0,0}形成旋转矩阵,记作 R z w , b 0 − 1 Rz^{-1}_{w,b_0} Rzw,b01;最终的rot_diff为 { R z w , b 0 − 1 ∗ R y w , c l ∗ R x w , c l } \{Rz^{-1}_{w,b_0}*Ry_{w,{c_l}}*Rx_{w,{c_l}}\} {Rzw,b01Ryw,clRxw,cl}
4.用rot_diff转换第0帧到第WZ帧的RsPsVs
P s [ 0 ] w , b 0 = { R z w , b 0 − 1 ∗ R y w , c l ∗ R x w , c l } ∗ s ∗ P s [ 0 ] c l , b 0 Ps[0]_{w,b_0}=\{Rz^{-1}_{w,b_0}*Ry_{w,{c_l}}*Rx_{w,{c_l}}\}*s*Ps[0]_{c_l,b_0} Ps[0]w,b0={Rzw,b01Ryw,clRxw,cl}sPs[0]cl,b0
R s [ 0 ] w , b 0 = { R z w , b 0 − 1 ∗ R y w , c l ∗ R x w , c l } ∗ R s [ 0 ] c l , b 0 Rs[0]_{w,b_0}=\{Rz^{-1}_{w,b_0}*Ry_{w,{c_l}}*Rx_{w,{c_l}}\}*Rs[0]_{c_l,b_0} Rs[0]w,b0={Rzw,b01Ryw,clRxw,cl}Rs[0]cl,b0
P s [ 0 ] w , b 0 = { R z w , b 0 − 1 ∗ R y w , c l ∗ R x w , c l } ∗ R s [ 0 ] c l , b 0 ∗ v b 0 Ps[0]_{w,b_0}=\{Rz^{-1}_{w,b_0}*Ry_{w,{c_l}}*Rx_{w,{c_l}}\}*Rs[0]_{c_l,b_0}*v_{b_0} Ps[0]w,b0={Rzw,b01Ryw,clRxw,cl}Rs[0]cl,b0vb0

依次类推得到其它帧的变换。
可见rot_diff将第0帧到WZ c l c_l cl帧坐标系下的Rs、Ps、Vs的水平方向即roll和pitch和变得世界坐标系的roll和pitch一致(yaw不可观),同时让初始帧 R s [ 0 ] w , b 0 Rs[0]_{w,b_0} Rs[0]w,b0的yaw角为0。后期优化时还会将滑窗中帧的yaw角调整到优化前的大小,防止优化值乱漂,这些留着下篇博客在讨论吧。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值