1. 程式人生 > >VINS詳解之IMU預積分(一)

VINS詳解之IMU預積分(一)

看VINS很久了,但一直處於似懂非懂的狀態,因此想借著寫部落格的機會結合論文對程式碼進行詳細的梳理。第一篇就從IMU預積分開始吧。

一 、首先是接收IMU的message

 1 void imu_callback(const sensor_msgs::ImuConstPtr &imu_msg)
 2 {
 3     ***
 4     imu_buf.push(imu_msg);
 5 
 6     ***
 7     predict(imu_msg);
 8 
 9     ***
10     pubLatestOdometry(tmp_P, tmp_Q, tmp_V, header);
11 12 }

主要是做三個操作

1、將imu_msg push到隊列當中

2、呼叫predict函式對當前imu的位置、朝向、速度進行計算

3、傳送imu的里程計資訊

1、3的操作很直觀,下面主要了解一下predict函式

 

二、predict函式解析

1、首先是從messgae讀入線性加速度和角速度

    Eigen::Vector3d linear_acceleration{dx, dy, dz};
    Eigen::Vector3d angular_velocity{rx, ry, rz};

這裡的線性加速度、加速度是在當前的IMU座標系下的,包含感測器的漂移和重力加速度

參見論文的公式(1)

其中帶有 尖冒子 a和ω是原始的線性加速度和角速度 , 而不帶尖帽子的a和ω是移除了漂移和重力加速度的。他們都是相對於當前的IMU座標系的。

 

2、位置計算

Eigen::Vector3d un_acc_0 = tmp_Q * (acc_0 - tmp_Ba) - estimator.g;
Eigen::Vector3d un_acc_1 = tmp_Q * (linear_acceleration - tmp_Ba) - estimator.g; 

上面兩行程式碼具有相同的形式,目的是獲得在世界座標系下的,移除了加速度計漂移和重力加速度的,線性加速度。

當前imu message的時間戳是t, 上一個imu message的接收時間是latest_time。

因此 alatest_time  =  un_acc_0

                     a=  un_acc_1

下面三行程式碼根據平均加速度計算位移和速度

Eigen::Vector3d un_acc = 0.5 * (un_acc_0 + un_acc_1);

tmp_P = tmp_P + dt * tmp_V + 0.5 * dt * dt * un_acc;

tmp_V = tmp_V + dt * un_acc;

 

3、朝向計算

 //latest_time 與 t之間的平均角速度
 Eigen::Vector3d un_gyr = 0.5 * (gyr_0 + angular_velocity) - tmp_Bg;
 //根據旋轉角度 得到當前朝向
 tmp_Q = tmp_Q * Utility::deltaQ(un_gyr * dt);

上面兩行程式碼就是根據角速度計算旋轉角度,繼而得到當前IMU在世界座標系的朝向

Utility::deltaQ函式的作用是將旋轉角度轉換成四元數

 1 static Eigen::Quaternion<typename Derived::Scalar> deltaQ(const Eigen::MatrixBase<Derived> &theta)
 2     {
 3         typedef typename Derived::Scalar Scalar_t;
 4 
 5         Eigen::Quaternion<Scalar_t> dq;
 6         Eigen::Matrix<Scalar_t, 3, 1> half_theta = theta;
 7         half_theta /= static_cast<Scalar_t>(2.0);
 8         dq.w() = static_cast<Scalar_t>(1.0);
 9         dq.x() = half_theta.x();
10         dq.y() = half_theta.y();
11         dq.z() = half_theta.z();
12         return dq;
13     }

它的邏輯是這樣的:

假設某個旋轉是繞單位向量n=[nx,ny,nz]T進行了角度為θ的旋轉,那麼這個旋轉的四元數為:

q=[cos(θ/2), nxsin(θ/2),nysin(θ/2),nzsin(θ/2)] T

根據等價無窮小sinx~x,則sin(θ/2)~θ/2, 以及當x->0s時,cosx->1

則當θ接近於0時,q=[1, nx(θ/2), ny(θ/2), nz(θ/2)] T

根據程式碼的對應關係,作者貌似是認為旋轉軸為[1,1,1]T(這裡我也是猜測,希望有了解的朋友可以解釋一下)