IMU Preintegration Started.?33[0m" ); // 打印消息 ros::MultiThreadedSpinner spinner( 4 ); // 開四個線程 通過并發的方式使得速度得到提升 spinner.spin(); // 程序執行到這個地方 則等待 topic 回調函數執行 return 0 ;} main函數部分很簡潔,功能主要完成部分都在定義的兩個類中進行。 在main函數中進行 節點初始" />

精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

IMU預積分功能數據初始化代碼解讀

麥辣雞腿堡 ? 來源:古月居 ? 作者:月照銀海似蛟龍 ? 2023-11-22 15:18 ? 次閱讀

代碼解讀

int main(int argc, char** argv){    ros::init(argc, argv, "roboat_loam");    IMUPreintegration ImuP;//IMUPreintegration 類的實例    TransformFusion TF;//TransformFusion 類的實例    ROS_INFO("?33[1;32m---- > IMU Preintegration Started.?33[0m");//打印消息    ros::MultiThreadedSpinner spinner(4);//開四個線程 通過并發的方式使得速度得到提升    spinner.spin();//程序執行到這個地方 則等待 topic 回調函數執行    return 0;}

main函數部分很簡潔,功能主要完成部分都在定義的兩個類中進行。

在main函數中進行

  • 節點初始化
  • IMUPreintegration 類的實例
  • TransformFusion 類的實例
  • 打印消息
  • 開四個線程 通過并發的方式使得速度得到提升
  • 等待 topic 回調函數執行
  • 之后則看 IMUPreintegration 這個類,先看構造函數部分

在里面首先進行了 訂閱imu信息

subImu      = nh.subscribe< sensor_msgs::Imu >  (imuTopic,2000, &IMUPreintegration::imuHandler,this, ros::TransportHints().tcpNoDelay());

imuTopic 為 imu_correct, imu原始數據,這個imuTopic是從參數服務器讀取的,具體的配置在prams.yaml中

圖片

如果你的imu的topic和默認的不一致則需要修改

然后可以看其具體的回調函數 imuHandler

void imuHandler(const sensor_msgs::Imu::ConstPtr& imu_raw)    {        std::lock_guard< std::mutex > lock(mtx);        //首先把imu的狀態做一個簡單的轉換        sensor_msgs::Imu thisImu = imuConverter(*imu_raw);        // 注意這里有兩個imu隊列,作用不相同,一個用來執行預積分和位姿變換的優化,一個用來更新最新imu狀態          imuQueOpt.push_back(thisImu);        imuQueImu.push_back(thisImu);        // 如果沒有發生過優化 則 return        if (doneFirstOpt == false)            return;

回調函數先把imu的狀態做一個簡單的轉換,轉到lidar坐標系 下

將轉換后的imu數據存入兩個隊列中,注意這里有兩個imu隊列,作用不相同,一個用來執行預積分和位姿變換的優化,一個用來更新最新imu狀態

如果沒有發生過優化 則 retur,doneFirstOpt這個標志位,在接受到幀間里程計信息后,則至為true,imuConverter函數在utility.h文件中

sensor_msgs::Imu imuConverter(const sensor_msgs::Imu& imu_in)    {        sensor_msgs::Imu imu_out = imu_in;        // rotate acceleration  //進行加速度坐標旋轉        Eigen::Vector3d acc(imu_in.linear_acceleration.x, imu_in.linear_acceleration.y, imu_in.linear_acceleration.z);        acc = extRot * acc;        imu_out.linear_acceleration.x = acc.x();        imu_out.linear_acceleration.y = acc.y();        imu_out.linear_acceleration.z = acc.z();        // rotate gyroscope  // 進行陀螺儀坐標旋轉        Eigen::Vector3d gyr(imu_in.angular_velocity.x, imu_in.angular_velocity.y, imu_in.angular_velocity.z);        gyr = extRot * gyr;        imu_out.angular_velocity.x = gyr.x();        imu_out.angular_velocity.y = gyr.y();        imu_out.angular_velocity.z = gyr.z();        // rotate roll pitch yaw // 進行姿態角坐標旋轉        Eigen::Quaterniond q_from(imu_in.orientation.w, imu_in.orientation.x, imu_in.orientation.y, imu_in.orientation.z);        Eigen::Quaterniond q_final = q_from * extQRPY;        imu_out.orientation.x = q_final.x();        imu_out.orientation.y = q_final.y();        imu_out.orientation.z = q_final.z();        imu_out.orientation.w = q_final.w();        //檢測姿態數據是否正常        if (sqrt(q_final.x()*q_final.x() + q_final.y()*q_final.y() + q_final.z()*q_final.z() + q_final.w()*q_final.w()) &lt; 0.1)        {            ROS_ERROR("Invalid quaternion, please use a 9-axis IMU!");            ros::shutdown();        }        return imu_out;//返回變換后的imu數據    }};

進行加速度坐標旋轉、進行陀螺儀坐標旋轉、進行姿態角坐標旋轉、檢測姿態數據是否正常、返回變換后的imu數據

在進行加速度和陀螺儀變換的時候,使用的是extRot,該參數的根源來源于prams.yaml中

圖片

進行姿態角坐標旋轉,使用的是extQRPY,該參數的根源來源于prams.yaml中

圖片

所有終于明白為什么在配置文件中有兩個外參了!

imuHandler這個回調函數,先看到這部分,后面的之后再看,需要回到上面的IMUPreintegration的構造函數,看訂閱到幀間里程計信息做了哪些事情。

subOdometry = nh.subscribe< nav_msgs::Odometry >("lio_sam/mapping/odometry_incremental", 5,    &IMUPreintegration::odometryHandler, this, ros::TransportHints().tcpNoDelay());

訂閱雷達里程計信息,lio_sam/mapping/odometry_incremental 是mapOptmization發出的,odometryHandler回調函數,走起

double currentCorrectionTime = ROS_TIME(odomMsg);

通過ROS_TIME函數把消息中的時間戳取了出來

if (imuQueOpt.empty())            return;

保證imu隊列中有數據

float p_x = odomMsg- >pose.pose.position.x;        float p_y = odomMsg- >pose.pose.position.y;        float p_z = odomMsg- >pose.pose.position.z;        float r_x = odomMsg- >pose.pose.orientation.x;        float r_y = odomMsg- >pose.pose.orientation.y;        float r_z = odomMsg- >pose.pose.orientation.z;        float r_w = odomMsg- >pose.pose.orientation.w;

通過里程計話題獲得位置信息 四元數 獲得雷達里程計位姿

bool degenerate = (int)odomMsg- >pose.covariance[0] == 1 ? true : false;

該位姿是否出現退化 pose.covariance[0] 為1 則 雷達里程計有退化風險,該幀位姿精度有一定程序下降

gtsam::Pose3 lidarPose = gtsam::Pose3(gtsam::Rot3::Quaternion(r_w, r_x, r_y, r_z), gtsam::Point3(p_x, p_y, p_z));

把位姿轉成 gtsam的格式,進入系統的初始化,下面部分僅執行一次

resetOptimization();

在函數內部 初始化gtsam的一些量

while (!imuQueOpt.empty())            {                if (ROS_TIME(&imuQueOpt.front()) < currentCorrectionTime - delta_t)                {                    lastImuT_opt = ROS_TIME(&imuQueOpt.front());                    imuQueOpt.pop_front();                }                else                    break;            }

將這個雷達里程計之前的imu信息全部扔掉,整個LIO-SAM中作者對時間同步這塊的思想都是這樣的,保證imu與odometry消息時間同步 因為imu是高頻數據所以這是必要的

prevPose_ = lidarPose.compose(lidar2Imu);

將lidar的位姿移到imu坐標系下,lidar2Imu 是lidar到imu的外參,compose是gtsam的一個功能函數,VIO和LIO的框架都在在IMU坐標系下進行的

gtsam::PriorFactor< gtsam::Pose3 > priorPose(X(0), prevPose_, priorPoseNoise);            graphFactors.add(priorPose);

設置其初始位姿和置信度,約束加入到因子中

  • gtsam::PriorFactor 模塊涉及到的變量結點
  • gtsam::Pose3 表示六自由度位姿
  • gtsam::Vector3 表示三自由度速度
  • gtsam::imuBias::ConstantBias 表示IMU零偏

以上也是預積分模型中涉及到的三種狀態變量

gtsam::PriorFactor 為先驗因子,表示對某個狀態量T的一個先驗估計,約束某個狀態變量的狀態不會離該先驗值過遠。

其中的X(0)的,初始定義如下。事先的符號

圖片

priorPoseNoise 是先驗位姿的噪聲,該值為

priorPoseNoise  = gtsam::noiseModel::Diagonal::Sigmas((gtsam::Vector(6) < < 1e-2, 1e-2, 1e-2, 1e-2, 1e-2, 1e-2).finished()); // rad,rad,rad,m, m, m

初始 位姿 置信度 設置 比較高 后面構成協方差矩陣 值越小 表示 置信度越高

prevVel_ = gtsam::Vector3(0, 0, 0);            gtsam::PriorFactor< gtsam::Vector3 > priorVel(V(0), prevVel_, priorVelNoise);               graphFactors.add(priorVel);

和上面位姿基本一樣初始化速度,這里直接賦 0 了,將速度約束加到因子圖中,其中priorVelNoise 速度的噪聲是

priorVelNoise   = gtsam::noiseModel::Isotropic::Sigma(3, 1e4); // m/s

初始化速度 置信度 設置 差些 因為速度一開始設置的是0,不知道是多少

prevBias_ = gtsam::imuBias::ConstantBias();            gtsam::PriorFactor< gtsam::imuBias::ConstantBias > priorBias(B(0), prevBias_, priorBiasNoise);                  graphFactors.add(priorBias);

初始化IMU 零偏 ,將零偏約束加到因子圖中,gtsam::imuBias::ConstantBias()是gtsam做好的一個imu零偏,其中都是0,所以對應bias的噪聲置信度也要設置的高些

priorBiasNoise  = gtsam::noiseModel::Isotropic::Sigma(6, 1e-3); // 1e-2 ~ 1e-3 seems to be good

以上把約束加入完畢,下面就開始添加狀態量

graphValues.insert(X(0), prevPose_);            graphValues.insert(V(0), prevVel_);            graphValues.insert(B(0), prevBias_);

給各個狀態量賦成初始值

optimizer.update(graphFactors, graphValues);

約束和狀態量更新 進isam優化器

graphFactors.resize(0);            graphValues.clear();

進優化器之后 保存約束和狀態量的變量就清零

imuIntegratorImu_-&gt;resetIntegrationAndSetBias(prevBias_);            imuIntegratorOpt_-&gt;resetIntegrationAndSetBias(prevBias_);

預積分的接口,使用初始零偏進行初始化 之前imu有兩個隊列,每個隊列對應預積分處理器

key = 1;
            systemInitialized = true;//系統初始化完成
            return;

系統初始化完成

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 函數
    +關注

    關注

    3

    文章

    4307

    瀏覽量

    62433
  • 代碼
    +關注

    關注

    30

    文章

    4751

    瀏覽量

    68358
  • 激光雷達
    +關注

    關注

    967

    文章

    3940

    瀏覽量

    189602
  • IMU
    IMU
    +關注

    關注

    6

    文章

    298

    瀏覽量

    45678
  • 3D激光
    +關注

    關注

    0

    文章

    30

    瀏覽量

    7465
收藏 人收藏

    評論

    相關推薦

    LINUX系統引導和初始化-LINUX內核解讀

    Linux 的系統引導和初始化 ----------Linux2.4.22內核解讀之一 一、 系統引導和初始化概述 相關代碼(引導扇區的程序及其輔助程序,以 x86體系為例): \li
    發表于 11-03 22:31 ?53次下載

    RM68171配BOE3.97玻璃的初始化代碼

    RM68171配BOE3.97玻璃的初始化代碼,測試OK,確定沒問題!
    發表于 06-17 17:07 ?2次下載

    使用QCS生成DPAA初始化代碼

    本文檔指導用戶如何使用從qc DPAA生成的代碼,用戶應用程序的上下文中利用USDPAA司機。該文檔解釋了反射器應用程序,并演示了幫助用戶快速插入QCS的步驟,這些插件在應用程序中生成DPAA初始化代碼
    發表于 09-07 17:21 ?0次下載
    使用QCS生成DPAA<b class='flag-5'>初始化</b><b class='flag-5'>代碼</b>

    如何排除代碼編寫器Studio 2和2.10的初始化問題

    此應用程序報告使讀者熟悉XDSPo探測實用程序。這個實用程序可能是用于排除代碼編寫器Studio 2和2.10的初始化問題通常表現為指示目標DSP的錯誤消息。無法初始化。此問題可能是由于配置或硬件不正確造成的。
    發表于 04-25 09:59 ?4次下載
    如何排除<b class='flag-5'>代碼</b>編寫器Studio 2和2.10的<b class='flag-5'>初始化</b>問題

    8259a初始化的步驟及代碼介紹

    本文首先介紹了8259a工作初始化的步驟及程序,其次介紹了通過OCW對8259A進行操作方法,最后介紹了8259A初始化編程。
    的頭像 發表于 05-23 14:24 ?3w次閱讀
    8259a<b class='flag-5'>初始化</b>的步驟及<b class='flag-5'>代碼</b>介紹

    lcd NT35512的手冊及初始化代碼免費下載

    本文檔的主要內容詳細介紹的是lcd NT35512的手冊及初始化代碼免費下載
    發表于 06-29 08:00 ?95次下載
    lcd NT35512的手冊及<b class='flag-5'>初始化</b><b class='flag-5'>代碼</b>免費下載

    IIC總線初始化基本驅動參考程序應用代碼免費下載

    本文檔的主要內容詳細介紹的是IIC總線初始化基本驅動參考程序應用代碼免費下載。程序功能:為IIC總線的基本驅動程序(此程序沒有寫主函數,只是一些IIC必備的子函數)
    發表于 01-16 08:00 ?5次下載
    IIC總線<b class='flag-5'>初始化</b>基本驅動參考程序應用<b class='flag-5'>代碼</b>免費下載

    STM32執行代碼初始化卡住,或者上電卡住,或者復位卡住,導致代碼不執行

    STM32的板子上電或者復位,接有顯示屏或者LED指示燈的都會卡住解決:1、檢查自己的代碼是否有中斷,有中斷的話,其初始化放在其他硬件初始化之后 即:中斷的初始化放在進入while
    發表于 12-09 09:21 ?22次下載
    STM32執行<b class='flag-5'>代碼</b><b class='flag-5'>初始化</b>卡住,或者上電卡住,或者復位卡住,導致<b class='flag-5'>代碼</b>不執行

    BF533 AD73360初始化程序代碼

    BF533 AD73360初始化程序代碼源碼分享
    發表于 10-08 14:59 ?0次下載

    初始化的if和switch語句詳解

    在上面的代碼中,初始化語句是int s = check()。s的生命周期是整個if語句,這里也包含else語句。
    的頭像 發表于 10-14 10:50 ?1349次閱讀

    DB2163_STM32配置和初始化C代碼生成

    DB2163_STM32配置和初始化C代碼生成
    發表于 11-23 20:29 ?0次下載
    DB2163_STM32配置和<b class='flag-5'>初始化</b>C<b class='flag-5'>代碼</b>生成

    使用STM32CubeMX生成初始化代碼

    我使用STM32CubeMX生成初始化代碼,使用LL庫,這里只介紹跟i2c相關的部分,其他必要的初始化需要自己完成。芯片使用stm32f042。本文的代碼不能到手即用,只提供思路。
    的頭像 發表于 03-22 15:26 ?2871次閱讀

    CPU CACHE策略的初始化

    build_mem_type_table()函數的功能是獲取當前CPU的CACHE類型,據此初始化mem_type。
    的頭像 發表于 06-05 15:03 ?1365次閱讀
    CPU CACHE策略的<b class='flag-5'>初始化</b>

    rt-thread線程棧初始化參數分析

    RT-Thread 在線程初始化代碼內有一段初始化線程堆棧的代碼
    的頭像 發表于 08-14 16:50 ?1623次閱讀
    rt-thread線程棧<b class='flag-5'>初始化</b>參數分析

    MCU單片機GPIO初始化該按什么順序配置?為什么初始化時有電平跳變?

    GPIO初始化時有時鐘配置、模式配置、輸出配置、復用配置,那么在編寫初始化代碼時,到底該按什么順序執行呢?如果順序不當那初始化過程可能會出現短暫的電平跳變。
    的頭像 發表于 02-22 11:07 ?1430次閱讀
    MCU單片機GPIO<b class='flag-5'>初始化</b>該按什么順序配置?為什么<b class='flag-5'>初始化</b>時有電平跳變?