当前位置: 首页 > news >正文

gmapping算法源码实现分析(一)

gmapping算法源码实现分析一—— slam-gmapping功能包主干流程分析1.slam_gmapping.cpp初始化流程:SlamGmapping() 构造函数 ├─ init() - 创建 GridSlamProcessor 实例读取参数 └─ startLiveSlam() - 设置订阅和回调 ├─ 创建 LaserScan 订阅 (通过 MessageFilter) ├─ 注册 laserCallback 回调 └─ 启动 publishLoop 线程 (定期发布 map-odom 变换)激光雷达数据处理流程:laserCallback(scan) ├─ 节流控制 (throttle_scans_) ├─ 首次扫描: initMapper(scan) │ ├─ 计算激光坐标系姿态 │ ├─ 创建 RangeSensor 和 OdometrySensor │ ├─ 设置 GMapping 参数 │ └─ 调用 gsp_-init() 初始化粒子滤波器 │ └─ addScan(scan, odom_pose) ├─ 获取里程计姿态 getOdomPose() ├─ 准备激光数据 (处理角度反转) ├─ 创建 RangeReading └─ 调用 gsp_-processScan(reading) ← 核心算法入口 如果 processScan 成功: ├─ 获取最佳粒子的位姿 ├─ 计算 map_to_odom_ 变换 ├─ 更新地图 updateMap(scan) (按时间间隔) └─ 发布地图和元数据2.核心算法层 - openslam_gmapping功能包(gridslamprocessor.cpp)processScan 的实际执行流程:boolGridSlamProcessor::processScan(constRangeReadingreading,intadaptParticles){// 步骤1: 获取相对位姿并初始化OrientedPoint relPosereading.getPose();if(!m_count){m_lastPartPosem_odoPoserelPose;// 第一次扫描初始化}// 步骤2: 运动模型更新 - 为每个粒子绘制新位姿for(ParticleVector::iterator itm_particles.begin();it!m_particles.end();it){OrientedPointpose(it-pose);// 根据运动模型从上一帧位姿采样新位姿posem_motionModel.drawFromMotion(it-pose,relPose,m_odoPose);}// 步骤3: 累积位移并检查是否达到更新阈值OrientedPoint moverelPose-m_odoPose;m_linearDistancesqrt(move*move);m_angularDistancefabs(move.theta);m_odoPoserelPose;boolprocessedfalse;// 步骤4: 判断是否需要处理 (距离/角度/时间阈值)if(!m_count||m_linearDistancem_linearThresholdDistance||m_angularDistancem_angularThresholdDistance||(period_0.0(reading.getTime()-last_update_time_)period_)){last_update_time_reading.getTime();double*plainReadingnewdouble[m_beams];// 复制激光数据到数组RangeReading*reading_copynewRangeReading(...);if(m_count0){// 步骤5a: 非首帧 - 执行 scan matching 重采样scanMatch(plainReading);// ← 对每个粒子进行扫描匹配优化onScanmatchUpdate();updateTreeWeights(false);// 更新轨迹树权重resample(plainReading,adaptParticles,reading_copy);// ← 重采样}else{// 步骤5b: 首帧 - 仅注册扫描到地图for(ParticleVector::iterator itm_particles.begin();it!m_particles.end();it){m_matcher.invalidateActiveArea();m_matcher.computeActiveArea(it-map,it-pose,plainReading);m_matcher.registerScan(it-map,it-pose,plainReading);// 创建轨迹树节点TNode*nodenewTNode(it-pose,0.,it-node,0);node-readingreading_copy;it-nodenode;}}updateTreeWeights(false);delete[]plainReading;// 步骤6: 重置状态供下一帧使用m_lastPartPosem_odoPose;m_linearDistance0;m_angularDistance0;m_count;processedtrue;// 更新粒子的 previousPosefor(ParticleVector::iterator itm_particles.begin();it!m_particles.end();it){it-previousPoseit-pose;}}m_readingCount;returnprocessed;}3.地图更新流程 - updateMap (slam_gmapping.cpp)voidSlamGmapping::updateMap(constsensor_msgs::msg::LaserScan::ConstSharedPtr scan){// 创建临时的 ScanMatcherMapScanMatcherMapsmap(center,xmin_,ymin_,xmax_,ymax_,delta_);// 遍历最佳粒子的轨迹树重建地图for(TNode*nbest.node;n;nn-parent){matcher.invalidateActiveArea();matcher.computeActiveArea(smap,n-pose,((*n-reading)[0]));matcher.registerScan(smap,n-pose,((*n-reading)[0]));}// 调整 ROS 地图消息大小if(map size changed){重新分配 map_.data}// 将栅格概率转换为 OccupancyGrid 格式for(x,y){doubleoccsmap.cell(p);if(occ0)→-1(未知)elseif(occocc_thresh_)→100(障碍)else→0(空闲)}// 发布地图sst_-publish(map_);sstm_-publish(map_.info);}4.坐标变换发布 - publishTransformvoidSlamGmapping::publishTransform(){// 定期发布 map - odom 的静态变换// map_to_odom_ 在 laserCallback 中计算:// map_to_odom_ (odom_to_laser * laser_to_map).inverse()transform.transformtf2::toMsg(map_to_odom_);tfB_-sendTransform(transform);}总结主要流程是:ROS2 Wrapper 层: 接收 LaserScan → 转换格式 → 调用底层算法GridSlamProcessor 层:运动模型预测粒子位姿扫描匹配优化位姿粒子重采样维护轨迹树地图生成层: 从最佳粒子轨迹重建 OccupancyGrid 并发布
http://www.rkmt.cn/news/1374947.html

相关文章:

  • 2026年口碑好的贵州家政培训哪家好 - 行业平台推荐
  • 模型流体:基于连续特征空间的蒸馏过程夹带剂智能筛选方法
  • Python 类型注解:从入门到日常实用
  • 【数据集】中国已签署双边投资协定(BIT)数据(2000-2025年)
  • 个人免费AI编程软件推荐:2026最新8款工具,独立开发者必看
  • 避开Hyper-V大坑!用物理机搭建Windows驱动HLK测试环境的保姆级指南
  • CentOS 7.9下Lustre 2.12.9集群部署避坑指南:从yum源配置到客户端挂载全流程
  • 从VirtualBox版本兼容性聊起:如何为你的Windows 10/11系统挑选合适的eNSP安装包组合
  • VMware VMX进程异常退出深度排查指南
  • 别再只用SSH了!给CentOS 7.9服务器装上图形桌面,用VNC远程操作真香
  • Windows 11热键冲突别抓狂!用OpenArk一键揪出‘元凶’并释放你的Ctrl+C
  • 用Linux内核模块复现AMDGPU的dma-fence:一个可运行的Ring Buffer同步模型Demo
  • 如何解决虚拟机无法和本机互相拖拽复制文件的问题
  • CentOS7 搭建 Kubernetes 集群
  • ARMv9 SME指令集:FDOT浮点点积操作深度解析
  • 3D激光SLAM入门:点云曲率计算与LOAM边缘/平面特征提取(附代码)
  • 告别卡顿!用Sunshine在Linux上搭建远程开发环境(保姆级教程,含显卡欺骗器选购)
  • VS2022调试Godot 4 C#项目避坑指南:断点失效与中文乱码根因修复
  • 【配色系列】粉色系 | 9类 x 2组 x 5色 | 色值 + 文字笔记示例
  • 量子极限学习机:利用横向伊辛模型实现噪声鲁棒的纠缠参数估计
  • PhysNet神经网络势能面评估:DNA碱基对振动频率预测精度与调优指南
  • 2026年比较好的丽水本地获客渠道实力公司推荐 - 品牌宣传支持者
  • 南宁口碑好的旧改企业哪家靠谱
  • 异常断电导致存储崩溃:Linux IO栈级数据恢复实战
  • Comba架构:基于状态空间模型的长序列高效处理方案
  • 机器学习预测冷等离子体处理种子萌发效果:Extra Trees模型构建与优化
  • MacOS下用ipmitool驯服联想RD450X服务器风扇噪音:从满速轰鸣到静音运行的保姆级教程
  • ZS315Q Type-C转DP1.4带PD100w方案,边投屏边充电,告别接口焦虑
  • python如何卸载安装包与清理内存
  • Product Hunt 每日热榜 | 2026-05-23