0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一个利用GT-SAM的紧耦合激光雷达惯导里程计的框架

3D视觉工坊 来源:古月居 作者:月照银海似蛟龙 2022-10-31 09:25 次阅读

前言

LIO-SAM的全称是:Tightly-coupled Lidar Inertial Odometry via Smoothing and Mapping,从全称上可以看出,该算法是一个紧耦合的雷达惯导里程计(Tightly-coupled Lidar Inertial Odometry),借助的手段就是利用GT-SAM库中的方法。

LIO-SAM 提出了一个利用GT-SAM的紧耦合激光雷达惯导里程计的框架。实现了高精度、实时的移动机器人的轨迹估计和建图。在之前的博客讲解了imu如何进行预积分,最终以imu的频率发布了imu的预测位姿里程计。

fbb2dc46-58aa-11ed-a3b6-dac502259ad0.png

本篇博客主要讲解,最终是如何进行位姿融合输出的

fbcbbef0-58aa-11ed-a3b6-dac502259ad0.png

Eigen::Affine3f

其中功能的核心在于 位姿间的变换,所以要了解 Eigen::Affine3f 部分的内容,Affine3f 是eighen库的仿射变换矩阵

实际上就是:平移向量+旋转变换组合而成,可以同时实现旋转,缩放,平移等空间变换。

Eigen库中,仿射变换矩阵的大致用法为:

创建Eigen::Affine3f 对象a。

创建类型为Eigen::Translation3f 对象b,用来存储平移向量;

创建类型为Eigen::Quaternionf 四元数对象c,用来存储旋转变换;

最后通过以下方式生成最终Affine3f变换矩阵:a=b*c.toRotationMatrix();

一个向量通过仿射变换时的方法是result_vector=test_affine*test_vector;

仿射变换包括:平移、旋转、放缩、剪切、反射

平移(translation)和旋转(rotation)顾名思义,两者的组合称之为欧式变换(Euclidean transformation)或刚体变换(rigid transformation);

放缩(scaling)可进一步分为uniform scaling和non-uniform scaling,前者每个坐标轴放缩系数相同(各向同性),后者不同;

如果放缩系数为负,则会叠加上反射(reflection)——reflection可以看成是特殊的scaling;

刚体变换+uniform scaling 称之为,相似变换(similarity transformation),即平移+旋转+各向同性的放缩;

位姿融合输出

在imu预积分的节点中,在main函数里面 还有一个类的实例对象,那就是

TransformFusion TF

其主要功能是做位姿融合输出,最终输出imu的预测结果,与上节中的imu预测结果的区别就是:

该对象的融合输出是基于全局位姿的基础上再进行imu的预测输出。全局位姿就是 经过回环检测后的lidar位姿。

fbe75688-58aa-11ed-a3b6-dac502259ad0.png

建图优化会输出两种激光雷达的位姿:

lidar 增量位姿

lidar 全局位姿

其中lidar 增量位姿就是 通过 lidar的匹配功能,优化出的帧间的相对位姿,通过相对位姿的累积,形成世界坐标系下的位姿

lidar全局位姿 则是在 帧间位姿的基础上,通过 回环检测,再次进行优化的 世界坐标系下的位姿,所以对于增量位姿,全局位姿更加精准

在前面提到的发布的imu的预测位姿是在lidar的增量位姿上基础上预测的,那么为了更加准确,本部分功能就预测结果,计算到基于全局位姿的基础上面。首先看构造函数

  TransformFusion()  {    if(lidarFrame != baselinkFrame)    {      try      {          tfListener.waitForTransform(lidarFrame, baselinkFrame, ros::Time(0), ros::Duration(3.0));        tfListener.lookupTransform(lidarFrame, baselinkFrame, ros::Time(0), lidar2Baselink);      }      catch (tf::TransformException ex)      {        ROS_ERROR("%s",ex.what());      }    }

判断lidar帧和baselink帧是不是同一个坐标系,通常baselink指车体系,如果不是,查询 一下 lidar 和baselink 之间的 tf变换 ros::Time(0) 表示最新的,等待两个坐标系有了变换,更新两个的变换 lidar2Baselink

    subLaserOdometry = nh.subscribe("lio_sam/mapping/odometry", 5, &TransformFusion::lidarOdometryHandler, this, ros::TransportHints().tcpNoDelay());    subImuOdometry  = nh.subscribe(odomTopic+"_incremental",  2000, &TransformFusion::imuOdometryHandler,  this, ros::TransportHints().tcpNoDelay());

订阅地图优化的节点的全局位姿 和预积分节点的 增量位姿

    pubImuOdometry  = nh.advertise(odomTopic, 2000);    pubImuPath    = nh.advertise  ("lio_sam/imu/path", 1);

发布两个信息 odomTopic ImuPath,然后看第一个回调函数lidarOdometryHandler

  void lidarOdometryHandler(const nav_msgs::ConstPtr& odomMsg)  {    std::lock_guard lock(mtx);    lidarOdomAffine = odom2affine(*odomMsg);    lidarOdomTime = odomMsg->header.stamp.toSec();  }

将全局位姿保存下来,将ros的odom格式转换成 Eigen::Affine3f 的形式,将最新帧的时间保存下来,第二个回调函数是imuOdometryHandler,imu预积分之后所发布的imu频率的预测位姿

  void imuOdometryHandler(const nav_msgs::ConstPtr& odomMsg)  {

    static tf::TransformBroadcaster tfMap2Odom;    static tf::Transform map_to_odom = tf::createQuaternionFromRPY(0, 0, 0), tf::Vector3(0, 0, 0));

建图的话 可以认为 map坐标系和odom坐标系 是重合的(初始化时刻)

tfMap2Odom.sendTransform(tf::StampedTransform(map_to_odom, odomMsg->header.stamp, mapFrame, odometryFrame));

发布静态tf,odom系和map系 他们是重合的

imuOdomQueue.push_back(*odomMsg);

imu得到的里程计结果送入到这个队列中

    if (lidarOdomTime == -1)      return;

如果没有收到lidar位姿 就returen

    while (!imuOdomQueue.empty())    {      if (imuOdomQueue.front().header.stamp.toSec() <= lidarOdomTime)        imuOdomQueue.pop_front();      else        break;    }

弹出时间戳 小于 最新 lidar位姿时刻之前的imu里程计数据

    Eigen::Affine3f imuOdomAffineFront = odom2affine(imuOdomQueue.front());    Eigen::Affine3f imuOdomAffineBack = odom2affine(imuOdomQueue.back());    Eigen::Affine3f imuOdomAffineIncre = imuOdomAffineFront.inverse() * imuOdomAffineBack;

计算最新队列里imu里程计的增量

Eigen::Affine3f imuOdomAffineLast = lidarOdomAffine * imuOdomAffineIncre;

增量补偿到lidar的位姿上去,就得到了最新的预测的位姿

    float x, y, z, roll, pitch, yaw;    pcl::getTranslationAndEulerAngles(imuOdomAffineLast, x, y, z, roll, pitch, yaw);

分解成平移 + 欧拉角的形式

    nav_msgs::Odometry laserOdometry = imuOdomQueue.back();    laserOdometry.pose.pose.position.x = x;    laserOdometry.pose.pose.position.y = y;    laserOdometry.pose.pose.position.z = z;    laserOdometry.pose.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(roll, pitch, yaw);    pubImuOdometry.publish(laserOdometry);

发送全局一致位姿的 最新位姿

    static tf::TransformBroadcaster tfOdom2BaseLink;    tf::Transform tCur;    tf::poseMsgToTF(laserOdometry.pose.pose, tCur);    if(lidarFrame != baselinkFrame)      tCur = tCur * lidar2Baselink;

更新tf

    tf::StampedTransform odom_2_baselink = tf::StampedTransform(tCur, odomMsg->header.stamp, odometryFrame, baselinkFrame);    tfOdom2BaseLink.sendTransform(odom_2_baselink);

更新odom到baselink的tf

    static nav_msgs::Path imuPath;    static double last_path_time = -1;    double imuTime = imuOdomQueue.back().header.stamp.toSec();    // 控制一下更新频率,不超过10hz    if (imuTime - last_path_time > 0.1)    {      last_path_time = imuTime;      geometry_msgs::PoseStamped pose_stamped;      pose_stamped.header.stamp = imuOdomQueue.back().header.stamp;      pose_stamped.header.frame_id = odometryFrame;      pose_stamped.pose = laserOdometry.pose.pose;      // 将最新的位姿送入轨迹中      imuPath.poses.push_back(pose_stamped);      // 把lidar时间戳之前的轨迹全部擦除      while(!imuPath.poses.empty() && imuPath.poses.front().header.stamp.toSec() < lidarOdomTime - 1.0)        imuPath.poses.erase(imuPath.poses.begin());      // 发布轨迹,这个轨迹实践上是可视化imu预积分节点输出的预测值      if (pubImuPath.getNumSubscribers() != 0)      {        imuPath.header.stamp = imuOdomQueue.back().header.stamp;        imuPath.header.frame_id = odometryFrame;        pubImuPath.publish(imuPath);      }    }  }

发布imu里程计的轨迹,控制一下更新频率,不超过10hz,将最新的位姿送入轨迹中,把lidar时间戳之前的轨迹全部擦除,发布轨迹,这个轨迹实践上是可视化imu预积分节点输出的预测值

result

fbfb02c8-58aa-11ed-a3b6-dac502259ad0.png

其中粉色的部分就是imu的位姿融合输出path。







审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 移动机器人
    +关注

    关注

    2

    文章

    718

    浏览量

    33322
  • SLAM
    +关注

    关注

    22

    文章

    391

    浏览量

    31595
  • 激光雷达
    +关注

    关注

    961

    文章

    3665

    浏览量

    186855
  • 回调函数
    +关注

    关注

    0

    文章

    87

    浏览量

    11460

原文标题:3d激光SLAM:LIO-SAM框架-位姿融合输出

文章出处:【微信号:3D视觉工坊,微信公众号:3D视觉工坊】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    #硬声创作季 LIO-SAM耦合激光雷达-惯性里程计

    激光SAM计算机视觉
    Mr_haohao
    发布于 :2022年10月12日 15:21:47

    激光雷达分类以及应用

    激光雷达实际上是种工作在光学波段(特殊波段)的雷达,它的优点非常明显:1、具有极高的分辨率:激光雷达工作于光学波段,频率比微波高2~3
    发表于 09-19 15:51

    常见激光雷达种类

    单线激光雷达特点:结构简单、扫描速度快、分辨率高、可靠性高、成本低。单线激光雷达实际上就是高同频激光脉冲扫描仪,加上
    发表于 09-25 11:30

    消费级激光雷达的起航

    降低。激光雷达通过扫描从物体上反射回来的激光来确定物体的距离,可以形成精度高达厘米级的3D环境地图,因此它在ADAS(先进驾驶辅助系统)及无人驾驶系统中起重要作用。从当前车载
    发表于 12-07 14:47

    固态设计激光雷达

    ``一年一度的国际消费类电子产品展览会(CES)已经完满收官,短短的几天时间里,我们见识了Intel无人飞机灯光秀、百度无人车、移动行李箱等众多“黑科技”。而北醒不仅展示了性能卓越的固态激光雷达,在
    发表于 01-25 09:41

    激光雷达

    想了解行业国内做固态激光雷达的厂家,激光雷达里面是怎么样的啊
    发表于 01-17 15:29

    由iphone12说说激光雷达 FMCW激光雷达 精选资料分享

    。另一个就是比较火的AR(增强现实 ),通过LIDAR能够测出这个现实中物体的大小尺寸,进而能够很好的3D建模,当然待开发的应用还有很多很多,毕竟相当于赋予了手机双人的眼睛。主要说下这个
    发表于 07-22 09:12

    FMCW激光雷达与dTOF激光雷达的区别在哪?

    FMCW激光雷达与dTOF激光雷达的区别在哪?
    发表于 07-23 13:22

    如何理解SLAM用到的传感器轮式里程计IMU、雷达、相机的工作原理与使用场景?精选资料分享

    视觉惯性里程计 综述 VIO Visual Inertial Odometry msckf ROVIO ssf msf okvis ORB-VINS VINS-Mono gtsam目录里程计
    发表于 07-27 07:21

    请问如何理解SLAM用到的传感器轮式里程计IMU、雷达、相机的工作原理?

    请问如何理解SLAM用到的传感器轮式里程计IMU、雷达、相机的工作原理?
    发表于 10-09 08:52

    Cortex-A53嵌入式处理器平台上实现激光雷达SLAM的方法

    移动底座和激光雷达与Cortex-A53平台都是通过串口来通信的。在基于Cortex-A53处理器的平台上处理激光雷达的扫描数据以及底座中采集的里程计数据,结合激光雷达的数据和
    的头像 发表于 03-13 09:15 9114次阅读
    Cortex-A53嵌入式处理器平台上实现<b class='flag-5'>激光雷达</b>SLAM的方法

    一个利用GT-SAM的紧耦合激光雷达惯导里程计框架

    从全称上可以看出,该算法是一个紧耦合雷达惯导里程计(Tightly-coupled Lidar Inertial Odometry),借助的手段就是利用
    的头像 发表于 09-14 10:11 1472次阅读

    基于相机和激光雷达的视觉里程计和建图系统

    提出一种新型的视觉-LiDAR里程计和建图系统SDV-LOAM,能够综合利用相机和激光雷达的信息,实现高效、高精度的姿态估计和实时建图,且性能优于现有的相机和激光雷达系统。
    发表于 05-15 16:17 463次阅读
    基于相机和<b class='flag-5'>激光雷达</b>的视觉<b class='flag-5'>里程计</b>和建图系统

    3d激光SLAMLIO-SAM框架介绍

    惯导里程计(Tightly-coupled Lidar Inertial Odometry),借助的手段就是利用GT-SAM库中的方法。 LIO-SAM 提出了一个
    的头像 发表于 11-22 15:04 376次阅读
    3d<b class='flag-5'>激光</b>SLAMLIO-<b class='flag-5'>SAM</b><b class='flag-5'>框架</b>介绍

    LIO-SAM框架是什么

    惯导里程计(Tightly-coupled Lidar Inertial Odometry),借助的手段就是利用GT-SAM库中的方法。 LIO-SAM提出了一个
    的头像 发表于 11-24 17:08 386次阅读
    LIO-<b class='flag-5'>SAM</b><b class='flag-5'>框架</b>是什么