3D激光SLAM:ALOAM---后端lasermapping 里程计到地图位姿更新维护

简介: 在上一篇[博客](https://www.guyuehome.com/38662)(ALOAM:后端lasermapping通过Ceres进行帧到地图的位姿优化)中,通过Ceres优化得到了 **当前帧到地图的最优位姿**下面要做的是更新地图模块中维护的一个位姿,这个位姿就是**odom到map之间的位姿变换**。**为什么要更新这个位姿呢?**因为在前面[这篇](https://www.guyuehome.com/38611)博客中(ALOAM:后端laserMapping代码结构与数据处理分析),在收到前端里程计数据后,会以前端里程计的频率,向外发布一个高频率当前帧到地图坐标系下

前言

在上一篇博客(ALOAM:后端lasermapping通过Ceres进行帧到地图的位姿优化)中,通过Ceres优化得到了 当前帧到地图的最优位姿

下面要做的是更新地图模块中维护的一个位姿,这个位姿就是odom到map之间的位姿变换

为什么要更新这个位姿呢?
因为在前面这篇博客中(ALOAM:后端laserMapping代码结构与数据处理分析),在收到前端里程计数据后,会以前端里程计的频率,向外发布一个高频率当前帧到地图坐标系下的位姿。
在这里插入图片描述
这这里用到了T_map_odom,就是在后端通过Ceres得到当前帧到map的位姿后,再计算odom到map的位姿,所以要更新这个位姿,为下一帧做准备。

并且在进行栅格地图位置更新处理的时候,也通过上一帧维护的T_map_odom,得到当前帧的一个初值估计。所以得到当前帧到map的位姿后,需要更新odom到map的位姿,为下一帧的处理做准备。相关内容在这篇博客(ALOAM:后端lasermapping地图栅格化处理与提取)的这个地方:
在这里插入图片描述

odom到map之间的位姿更新原理

通过Ceres的优化 得到了,当前帧到map的位姿变换
在这里插入图片描述
前端里程计向后端发布的是,当前帧到odom的位姿变换
在这里插入图片描述
那么计算odom到map的位姿变换的公式为:
在这里插入图片描述
写成旋转+平移的齐次矩阵的形式,上面的公式则变为:
在这里插入图片描述
那么 odom到map之间旋转和平移则为
在这里插入图片描述

下面来看ALOAM中代码是如何实现的

代码解析

在前面通过ceres的优化得到了 当前帧到地图的位姿变换。该位姿变换存在 parameters 变量中。

这个parameters是一个double 的7维数组
在这里插入图片描述
前4位是旋转四元数,后三位是平移向量

然后程序则调用了

            //更新odom到map之间的位姿变换
            transformUpdate();

这个就是更新odom到map之间的位姿变换的函数。

里面的内容是:

//更新odom到map之间的位姿变换
void transformUpdate()
{
   
    q_wmap_wodom = q_w_curr * q_wodom_curr.inverse();
    t_wmap_wodom = t_w_curr - q_wmap_wodom * t_wodom_curr;
}

其中

  • q_wmap_wodom 就是 odom到map 的旋转 四元数
  • t_wmap_wodom 就是 odom到map 的平移

q_wodom_curr 是前端里程计发来的 curr到odom的 旋转四元数
t_wodom_curr 是前端里程计发来的 curr到odom的 平移

  • q_w_curr 是Ceres优化的 curr到map的旋转四元数
  • t_w_curr 是Ceres优化的 curr到map的平移

在整个程序中并没有发现q_w_curr 和 t_w_curr 被赋值的地方,尤其是ceres计算完后并没给这两个变量赋值。

那么这两个变量是如何被赋值的呢?
在它俩声明的地方:
在这里插入图片描述
是通过eigen的map声明的
当ceres 更新 parameters之后 会通过 eigen的map 实时更新q_w_curr和t_w_curr 不需要自己再去转换

这里简单介绍下 Eigen 的Map 类:
Eigen中定义了一系列的vector和matrix,相比copy数据,更一般的方式是复用数据的内存,将它们转变为Eigen类型。Map类很好地实现了这个功能。

简单理解Map就是将原始“连续内存存储”的数据,以矩阵形式重新组织。在使用Map时就需要原始数据,Map后的数据的维度形式,Map时使用的Stride设定。所谓Stride,既指矩阵中沿着矩阵列或行方向移动一个位置,内存中需要移动的位置数。这个需要移动的内存位置数与矩阵采用的存储方式有关(列或行主导)。

Eigen::Map原型

template<typename PlainObjectType, int MapOptions, typename StrideType> 
class Map: public MapBase<Map<PlainObjectType, MapOptions, StrideType> >
  • PlainObjectType :映射数据的等价矩阵类型
  • MapOptions:指定指针对齐方式,默认是未对齐的
  • StrideType:指定步长

这个类的作用就是让非Eigen数据结构变成Eigenj矩阵或者向量时,减少在复制过程中的开销,Eigen官网描述这样使用没有开销。

构造函数有以下

Map (PointerArgType dataPtr, const StrideType &stride=StrideType())
Map (PointerArgType dataPtr, Index size, const StrideType &stride=StrideType())
Map (PointerArgType dataPtr, Index rows, Index cols, const StrideType &stride=StrideType())

举个最简单的例子

    int array[9];
    for (int i = 0; i < 9; ++i)
        array[i] = i;
    std::cout << Eigen::Map<Eigen::Matrix3i>(array) << std::endl;

输出为:
0 3 6
1 4 7
2 5 8
再举一个和ALOAM使用情况一样的例子,将一个数组元素转换成Eigen数据结构

int data[] = {
   1,2,3,4,5,6,7,8,9};
Map<RowVectorXi> v(data,4);
cout << "The mapped vector v is: " << v << "\n";
new (&v) Map<RowVectorXi>(data+4,5);
cout << "Now v is: " << v << "\n

输出为:
The mapped vector v is: 1 2 3 4
Now v is: 5 6 7 8 9

看了这几个例子,就明白,在Ceres优化完成后,这两个变量(q_w_curr ,t_w_curr )就被更新值了。

  • q_w_curr 是Ceres优化的 curr到map的旋转四元数
  • t_w_curr 是Ceres优化的 curr到map的平移

transformUpdate() 函数中计算的公式就是上面推导的:

    q_wmap_wodom = q_w_curr * q_wodom_curr.inverse();
    t_wmap_wodom = t_w_curr - q_wmap_wodom * t_wodom_curr;

在这里插入图片描述

在后面后端会把 q_w_curr,t_w_curr做为里程计更新发布出来

            nav_msgs::Odometry odomAftMapped;
            odomAftMapped.header.frame_id = "/camera_init";
            odomAftMapped.child_frame_id = "/aft_mapped";
            odomAftMapped.header.stamp = ros::Time().fromSec(timeLaserOdometry);
            odomAftMapped.pose.pose.orientation.x = q_w_curr.x();
            odomAftMapped.pose.pose.orientation.y = q_w_curr.y();
            odomAftMapped.pose.pose.orientation.z = q_w_curr.z();
            odomAftMapped.pose.pose.orientation.w = q_w_curr.w();
            odomAftMapped.pose.pose.position.x = t_w_curr.x();
            odomAftMapped.pose.pose.position.y = t_w_curr.y();
            odomAftMapped.pose.pose.position.z = t_w_curr.z();
            pubOdomAftMapped.publish(odomAftMapped);

在这里插入图片描述
可以在rviz中添加一个odometry的选项,选择topic为/aft_mapped_to_init来显示。

相关文章
|
前端开发 定位技术 索引
3D激光SLAM:ALOAM---后端 lasermapping构建角点约束与面点约束
后端的构建约束问题和前端不一样。原因就是前端从上一帧上去找,而后端是在局部地图上找,点要多很多,并且没有了线束信息,所以原理上不一样了。 **线特征的提取** 通过kdtree在局部地图中找到5个最近的线特征,为了判断他们是否符合线特征的特性,需要对5个点构成的协方差矩阵进行特征值分解,当上述5个点在一条直线上时,他们只有一个主方向,也就是特征值是一个大特征值,以及两个小特征值,大特征值对应的特征向量就是对应直线的方向向量。 **面特征的提取** 通过kdtree在地图中找到最近的面特征也是5个, 理论上也可以通过特种值分解的方式,最小的特征值对应的特征向量就是平面的法向量, 不过代码里选
3D激光SLAM:ALOAM---后端 lasermapping构建角点约束与面点约束
|
前端开发 数据可视化 定位技术
3D激光slam:ALOAM---后端lasermapping最终篇地图更新及消息发布
本篇为ALOAM后端的最终篇,地图更新及消息发布。 **地图更新原因:** - 当地图调整之后,栅格有些空着的,需要进行填充 - 保障地图的实时更新 - 当前帧的点云加到地图中去,下帧会有更多的匹配点
3D激光slam:ALOAM---后端lasermapping最终篇地图更新及消息发布
|
前端开发 算法 数据处理
激光SLAM:ALOAM---后端lasermapping数据处理低延时性保障操作
ALOAM方法实现了低的漂移,并且计算的复杂度低,实时性很好.并且不需要高精度的lidar和惯导 这个方法的核心思想就是把SLAM问题进行了拆分,通过两个算法来进行.一个是执行高频率的前端里程计但是低精度的运动估计(定位),另一个算法在比定位低一个数量级的频率执行后端建图(建图和校正里程计).
激光SLAM:ALOAM---后端lasermapping数据处理低延时性保障操作
|
编解码 算法 前端开发
激光SLAM:ALOAM---后端laserMapping代码结构与数据处理分析
ALOAM方法实现了低的漂移,并且计算的复杂度低,实时性很好.并且不需要高精度的lidar和惯导 这个方法的核心思想就是把SLAM问题进行了拆分,通过两个算法来进行.一个是执行高频率的**前端里程计**但是低精度的运动估计(定位),另一个算法在比定位低一个数量级的频率执行**后端建图**(建图和校正里程计). 这个两个算法都需要提特征点,就是经典的角点和面点,然后进行配准.在前端的那个算法中也就是里程计算法,特征点的提取会用到快速计算的方法.在建图的后端算法中,相互关联的特征点是通过特征值和特征向量来获得的.
激光SLAM:ALOAM---后端laserMapping代码结构与数据处理分析
|
5月前
|
存储 消息中间件 前端开发
PHP后端与uni-app前端协同的校园圈子系统:校园社交场景的跨端开发实践
校园圈子系统校园论坛小程序采用uni-app前端框架,支持多端运行,结合PHP后端(如ThinkPHP/Laravel),实现用户认证、社交关系管理、动态发布与实时聊天功能。前端通过组件化开发和uni.request与后端交互,后端提供RESTful API处理业务逻辑并存储数据于MySQL。同时引入Redis缓存热点数据,RabbitMQ处理异步任务,优化系统性能。核心功能包括JWT身份验证、好友系统、WebSocket实时聊天及活动管理,确保高效稳定的用户体验。
301 4
PHP后端与uni-app前端协同的校园圈子系统:校园社交场景的跨端开发实践
|
7月前
|
JSON 自然语言处理 前端开发
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
312 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
|
10月前
|
存储 缓存 负载均衡
后端开发中的性能优化策略
本文将探讨几种常见的后端性能优化策略,包括代码层面的优化、数据库查询优化、缓存机制的应用以及负载均衡的实现。通过这些方法,开发者可以显著提升系统的响应速度和处理能力,从而提供更好的用户体验。
317 6
|
6月前
|
前端开发 JavaScript 关系型数据库
2025 年前端与后端开发方向的抉择与展望-优雅草卓伊凡
2025 年前端与后端开发方向的抉择与展望-优雅草卓伊凡
276 5
2025 年前端与后端开发方向的抉择与展望-优雅草卓伊凡
|
6月前
|
监控 前端开发 小程序
陪练,代练,护航,代打小程序源码/前端UNIAPP-VUE2.0开发 后端Thinkphp6管理/具备家政服务的综合型平台
这款APP通过技术创新,将代练、家政、娱乐社交等场景融合,打造“全能型生活服务生态圈”。以代练为切入点,提供模块化代码支持快速搭建平台,结合智能匹配与技能审核机制,拓展家政服务和商业管理功能。技术架构具备高安全性和扩展性,支持多业务复用,如押金冻结、录屏监控等功能跨领域应用。商业模式多元,包括交易抽成、增值服务及广告联名,同时设计跨领域积分体系提升用户粘性,实现生态共生与B端赋能。
499 12
|
6月前
|
人工智能 小程序 NoSQL
【一步步开发AI运动小程序】二十一、如何将AI运动项目配置持久化到后端?
本文介绍基于云智「Ai运动识别引擎」的运动配置持久化方案,旨在优化小程序或Uni APP中AI运动识别能力。通过将运动检测参数(如`Key`、`Name`、`TickMode`、`rules`或`samples`)持久化到后端,可避免因频繁调整运动参数而重新发布应用,提升用户体验。持久化数据结构支持规则和姿态样本存储,适用于关系数据库、文件或文档数据库(如MongoDB)。此外,云智还提供运动自动适配工具及「AI乐运动」产品,助力快速实现AI体育、全民健身等场景。

热门文章

最新文章