移动机器人地图管理实战:从SLAM建图到多楼层动态更新的完整方案 前两天调试一台移动机器人遇到一个特别典型的场景小车在实验室里跑得好好的一断电重启地图就没了。现场观众盯着屏幕上空的栅格图我只好让小车重新绕一圈建图五分钟过去演示节奏全被打乱。那会儿我突然明白导航算法再强地图模块要是没做好一切都是白搭。lingbot-map这个模块就是在这个背景下真正成型的——它不是一个单纯的建图算法而是一整套围绕“环境地图”的构建、保存、加载、切换和动态更新机制解决的是机器人从“能画图”到“能长期稳定地用图”之间那段没人写进论文里的事。这篇文章适合正在做移动机器人导航、SLAM落地的工程师也适合那些在GitHub上看到各种建图方案、但不知道如何组织地图数据流的同学。我会把lingbot-map的设计思路、核心管线、实操步骤、调参与踩坑经历完整梳理一遍内容偏工程向尽量说人话保证每一步都能照着做。1. 从“机器人不知道自己在哪”说起lingbot-map要解决什么1.1 最原始的问题地图只能活在内存里很多新手做机器人导航第一步就是用现成的SLAM方案跑起来确实能出一张漂亮的栅格地图。但接着问题就来了这张地图存在哪里机器人重启之后还能不能找回换一个楼层怎么办环境里多了几把椅子要不要整张图重新建我第一次处理这类问题是在一台差速底盘的小车上。当时的流程很原始SLAM节点启动后地图一直存在内存里机器人一断电图就丢。为了演示机器人能在某个区域自主导航我不得不提前把地图保存在本地启动后再用map_server发出来。听起来没问题可实验室区域经常有人搬设备、推椅子静态地图和现实环境一旦对不上路径规划就会穿墙或者绕远路。地图不是“建完就结束”的东西它有自己的生命周期构建、持久化、加载、局部更新、多版本管理、动态感知。这一整串需求才是lingbot-map真正想做的事。1.2 lingbot-map的定位地图应用框架而不是又一个SLAM我一开始也考虑过直接魔改某个开源SLAM算法把地图保存功能硬塞进去。后来发现这条路走不通SLAM前端关心的是帧间匹配和位姿优化而工程上真正要关心的是“地图怎么被导航栈使用”“换场景怎么切换”“局部更新怎么不破坏全局图”。这两类目标不一样混在一起会让算法和业务互相拖累。lingbot-map的定位是夹在SLAM算法和导航决策之间的一层地图应用框架底层可以接不同的建图算法上层对外提供统一的地图模型和接口。它要处理的不是“怎么把点云拼起来”而是“拼好的地图如何长期、可靠、多场景地服务于机器人”。这样做的好处是底层算法想换就换不影响上层导航逻辑反过来业务层加需求也无需动算法代码。除了技术分层lingbot-map还做了一个关键决策地图模型采用“栅格地图 拓扑图层”的双层结构。栅格地图负责精细的障碍物表示是导航栈直接消费的数据拓扑图层负责房间、走廊、电梯口、充电桩这些语义节点是任务调度层用于决策的抽象地图。二维栅格负责“能不能走”拓扑节点负责“要去哪”两者互补正好覆盖了自主导航的完整链路。1.3 三个设计目标可管理、可切换、可更新从实际项目痛点出发lingbot-map确定了对外的三个核心目标后面所有代码和参数都围绕它们展开。第一是可管理地图必须能命名保存、版本归档、随时加载。连演示都撑不过去的地图模块没法谈落地。第二是可切换一栋楼有多层一个园区有多块区域机器人在运行途中需要能主动或被动地切换到对应地图并且切换后还能快速重新定位。第三是可更新静态地图不能是一潭死水局部环境变化后要能只修一块区域而不是推翻整张图重来。这个“局部更新”能力后来帮我们省了大量重复建图的工作量。2. 地图模块的骨架从传感器数据到可导航地图的管线2.1 分四层看lingbot-map的架构整个lingbot-map按照数据流的方向拆成了四层每层职责单一依赖关系清晰。传感器接入层负责激光雷达、里程计、IMU消息的时间同步和坐标变换预处理。这一层不关心具体算法只负责把数据整理成“干净、有序、带正确时间戳”的输入。建图引擎层运行核心SLAM算法包括前端扫描匹配、后端图优化、回环检测。lingbot-map把算法层做成可插拔的接口只要能传入雷达帧和里程计初值、输出位姿更新都可以接入。地图管理层维护全局占据栅格、拓扑图层、地图版本索引处理地图保存/加载、局部更新、同名冲突等业务逻辑。这一层是lingbot-map工作量的主体也是和普通SLAM实现最大的差异所在。服务接口层以ROS 2的话题、服务、动作形式对外暴露能力导航栈可以通过标准接口读取地图调度系统可以下发建图、保存、切换指令。分层设计不只是为了好看而是实际踩坑踩出来的结论。早期的地图模块把SLAM和管理逻辑揉在一起换传感器型号要改算法代码加一层地图切换需求又动到底层位姿改了三天才理清楚。拆层之后传感器接入层只要改配置地图管理层只处理地图本身导航栈完全不用关心底层算法换没换。2.2 数据管线的一次完整流转为了说清楚整个流程我按一次典型的建图过程描述一下数据是怎么走的。第一步激光雷达发出/scan消息里程计发出/odom消息IMU发出/imu消息三者在传感器接入层做时间同步。这里特别强调时间戳因为在实际机器人上不同传感器的消息到达顺序是乱的如果直接用本地接收时间来建图位姿对不上地图必歪。第二步建图引擎层拿到同步后的数据先做前端扫描匹配把当前激光帧和局部地图对齐估算出机器人在odom坐标系下的最新位姿。然后判断当前位姿是否靠近历史轨迹如果接近就触发回环检测找到最优闭环边放入后端图优化器。第三步后端图优化器周期性地优化整个位姿图把累积漂移分摊到整条轨迹上。优化后的位姿被用来更新全局栅格地图对每一束激光按命中点和自由空间做射线更新命中点占据射线经过区域标记为自由。第四步地图管理层把更新后的栅格块写入内存缓存并通过/map话题周期性发布全局地图快照导航栈在收到地图后转成costmap用于规划。如果收到/save_map服务请求地图管理层会把当前栅格图、拓扑节点、雷达参数、分辨率等打包成标准文件落盘。这四个步骤循环往复就是整个地图模块最核心的运转逻辑。2.3 接口设计外界怎么跟地图模块打交道接口设计直接影响后续所有业务能否顺利接入。lingbot-map对外提供了三类通信接口话题Topic持续流式的数据比如/map、/map_updates。导航栈订阅/map获得全局栅格订阅/map_updates获得增量变化块。服务Service一次性请求应答比如save_map保存地图、load_map加载地图、switch_map切换当前地图、relocalize触发重新定位。这类操作不适合用话题因为需要明确的反馈结果。动作Action长耗时任务比如“建图并保存”“遍历多个目标点后回充”。动作可以随时反馈进度、被取消适合和调度系统集成。在设计这些接口时我坚持了一个原则所有外部接口尽量避免暴露底层算法细节。调用方只需要关心“保存这张图”“切到三楼地图”“重新定位”不需要知道底层用的是哪种扫描匹配方法、后端优化器是什么。这为后续替换算法留足了空间。3. 建图实操从启动节点到第一张可用的栅格地图3.1 环境准备与编译在动手之前先把硬件和软件条件列清楚。lingbot-map基于ROS 2开发需要一台能输出里程计的移动机器人底盘、一束激光雷达或RGB-D深度相机、IMU可选但强烈建议。软件方面需要安装好ROS 2环境并确保colcon构建工具可用。编译过程不复杂但有个容易出问题的地方先确认所有依赖包都install完整再来编译lingbot-map。如果只编译这单个包系统里缺少依赖会报find_package失败。cd ~/lingbot_ws colcon build --packages-select lingbot_map source install/setup.bash编译通过后先简单跑一下单元测试确认基本的数据结构没有问题。地图模块这种底层组件最好在仿真环境里先跑通一遍再上真机。我习惯用仿真器先放几个虚拟障碍物验证建图接口正常再让小车真跑省去很多在真机上排查基础错误的成本。3.2 核心参数配置文件解析lingbot-map的建图参数集中在config/mapping.yaml里下面是一份典型的配置我顺手把每一项的作用都标出来。lingbot_map: ros__parameters: lidar_topic: /scan odom_topic: /odom imu_topic: /imu map_frame: map base_frame: base_footprint lidar_frame: laser resolution: 0.05 publish_rate: 1.0 max_laser_range: 30.0 treat_unknown_as_occupied: false enable_loop_closure: true loop_search_distance: 15.0 backend_optimize_interval: 1.0先说坐标变换相关参数。map_frame是全局地图坐标系base_frame是机器人本体坐标系lidar_frame是雷达坐标系。这三者的关系必须和机器人实际装配一致否则建出来的地图就像把两张照片硬拼在一起边缘全是重影。特别是lidar_frame和base_frame之间的静态变换装雷达时量错几厘米地图上就会稳定地出现几厘米的墙线偏移。再说地图参数。resolution表示每个栅格对应的物理尺寸0.05米就是5厘米一格室内场景够用如果覆盖范围特别大可以改成0.1米来降低内存占用。publish_rate是全局地图的发布频率导航用1Hz足够了频繁发布只会增加CPU和带宽开销。max_laser_range要和雷达实际量程匹配否则大量无效数据会拖慢射线更新。还有三个容易忽略的开关treat_unknown_as_occupied如果设成true导航栈会把地图中的未知区域当成障碍物机器人在建图不完整的地方会表现得特别胆小路径规划经常绕远路enable_loop_closure是回环检测开关大场景一定要开backend_optimize_interval控制后端图优化的频率一般1秒一次CPU紧张时可以降到0.5Hz。3.3 启动建图流程配置改好后启动建图命令ros2 launch lingbot_map mapping.launch.py启动后可以在可视化工具里看到激光点云和实时栅格地图。这时别急着让机器人到处乱跑先手动控制机器人原地转动一圈让雷达充分扫描当前环境确认地图原点周围的基本轮廓正确。然后再开始低速巡检环境重点覆盖走廊转角、房间门洞、柱子周围这些容易产生遮挡盲区的位置。整个巡检过程有几条经验值得记下来尽量走“闭合回路”让机器人回到起点附近触发回环检测把累积漂移拉回来。如果全程只走直线不绕圈长走廊末端的地图很容易歪。遇到玻璃墙、落地窗这类低反射物体雷达点会穿透或丢失地图上会出现空洞。这时候只能靠后期手动修正或者融合其他传感器纯激光建图没法完美处理。巡检速度不宜过快太快会导致扫描帧间距过大帧间匹配容易跟丢。我一般控制底盘线速度不超过0.3m/s。3.4 保存地图与加载地图巡检完成后确认地图整体轮廓没有明显重影就可以保存了。保存接口是标准的ROS 2服务调用ros2 service call /lingbot_map/save_map lingbot_map/srv/SaveMap {map_name: lab_2024}执行成功后地图会保存到指定目录生成三种文件PGM图片文件栅格图、YAML配置文件分辨率、原点、frame等元信息、扩展JSON文件拓扑节点、语义标注、建图时间。这里特别说明PGMYAML是机器人社区里最常见的地图格式几乎所有导航栈都能直接读取所以lingbot-map选择用它作为标准输出。扩展JSON则用来保存拓扑图层这部分是lingbot-map自己的数据结构导航栈不需要读但调度系统会用到。下次启动时直接加载地图ros2 launch lingbot_map map_server.launch.py map:lab_2024加载后建议手动运行一次relocalize服务让机器人在已知地图上重新估计位姿避免直接使用上次断电前的旧位姿导致定位发散。3.5 为什么主地图用栅格而不是点云这是很多人会问的问题。既然手上已经有激光雷达为什么不直接保存点云地图看起来更直观定位精度似乎也更高我的回答是栅格地图在“导航决策”这个环节的效率优势太明显了。点云地图动辄几百MB栅格地图可以把每格压缩成1个字节的占用状态200米乘200米、5厘米分辨率的区域单层栅格只要16MB左右。导航栈做路径规划时在栅格上做膨胀和A星搜索非常直接点云地图则要先做最近邻查询、地面分割计算量完全不在一个量级。lingbot-map并不是完全丢弃点云而是在建图过程中保留一份降采样后的点云帧作为可视化参考和后期回环验证。但作为导航主地图栅格表示是经过权衡后更稳的选择。这个取舍在工程落地中经常要做不必追求算法上的“最先进”关键是合适。4. 多楼层与动态环境map版本与更新机制4.1 地图分组与版本管理单张地图在多楼层场景里完全不够用。lingbot-map把地图组织成一个索引文件每张地图带独立标签、坐标原点和版本信息。实际运行时我们会给地图文件按区域命名比如floor_01、floor_02、storage_area并额外维护一份map_index.json描述每张图的适用范围、最近更新时间、创建时的传感器配置。这样做的直接好处是机器人到了新环境调度系统下发一条“切换地图”指令地图模块就能从索引里找出对应文件并加载不用关心总共有多少张图。版本管理同样重要。每次重新建图或局部修正地图模块都会生成新版本号旧版本并不会被覆盖。为什么要保留旧版本因为修正操作有风险万一某次手动改错了区域还能快速回滚到上一个可用版本。实际项目中我就遇到过一次同事用地图编辑器把一排柱子误删了导致机器人规划路径直接穿过柱子区域还好版本回滚救了场。4.2 地图热切换与重新定位多楼层场景里最棘手的不是“加载地图”而是“切换后怎么重新定位”。如果机器人带着上一楼层的地图直接切到新楼层位姿大概率是错的因为两层楼的几何结构完全不同。lingbot-map的解决思路是“分层触发式重定位”。切换地图后地图模块自动暂停全局定位输出启动重定位流程先在栅格地图上撒大量候选粒子用当前激光扫描和地图匹配筛选出得分最高的位姿作为初始估计。如果全局匹配失败则在拓扑图层里寻找最近的语义节点如电梯口、楼梯口把机器人的位置约束在某个已知节点附近再局部搜索位姿。这个过程在实际项目中经历过一次很典型的验证机器人在某栋实验楼的电梯里从一层到三层电梯内激光扫描到的封闭空间和楼层地图完全不同出电梯后荷移已经积累了一大截。通过楼层触发指令切换地图再配合电梯口的拓扑节点约束大约两三秒就能完成重新定位整个导航流程不需要人工介入。4.3 动态障碍物到底该放哪层环境是动态的人会在走廊里走动椅子会被搬动纸箱会临时堆在通道旁边。如果把动态障碍物写进静态地图全局路径规划会越来越僵硬最后哪条路都走不了。lingbot-map对这类问题的处理是分层的静态全局地图只保存“长期稳定的障碍物”比如墙体、柱子、固定设备动态障碍物由局部代价地图来实时感知以机器人当前位置为中心膨胀处理和超时清理都是由导航栈完成。lingbot-map要确保的是静态地图不能因为一次有个人站在走廊里就把那一整块区域永久标成障碍。实现上最关键是栅格更新策略的约束只有“多次观测都稳定占据”的栅格才会被提升为静态占据瞬时出现的激光点只进入局部观测层不进全局图。这个逻辑看起来简单但会让地图质量差距巨大。不加约束的话建图过程中只要有活物在附近走动地图上就会残留一圈圈“鬼影”非常影响后续导航。4.4 局部更新只修一块不要推翻整张图环境里某个区域变了最常见的要求是“只更新那一块地方”。lingbot-map支持局部重绘把机器人开到变化区域启动局部更新模式雷达重新扫描周围几十米范围地图模块只替换被覆盖的那部分栅格块其他区域完全不动。要支持这个能力地图在内存里不能是完整的一块大数组而是切成固定大小的块比如每块100乘100格。更新时只读写落在更新窗口内的块保存时也支持增量保存只把变化的块写回文件。这个设计初期看起来是过度设计但后来碰到真实场景才意识到价值某个区域要改造成临时展台开放了五天又恢复我们用旧版本的局部快照一次性回滚省了重新全图建图的时间。5. 调参与压测让地图在真实场景中能跑起来5.1 核心参数调优思路参数调优这件事最忌讳的是凭感觉乱调。lingbot-map里每一个影响较大的参数都可以用“任务需求 - 数值推导 - 实测验证”的方式来确定。分辨率是第一个要定的参数。室内导航0.05米是够用的车体宽0.6米的话膨胀半径设为0.3米以上栅格精度对路径安全性的影响不大。室外或大面积仓库可以放宽到0.1米内存和CPU都会明显下降。第二个要配合的是最大雷达量程它决定了单帧能更新多远的栅格量程越大地图更新越快但射线遍历的计算量也越大。建议max_laser_range设成地图期望覆盖范围的1.5倍左右不要盲目用满雷达的极限量程。回环检测参数同样关键。loop_search_distance表示在多大范围内搜索历史关键帧设太小回环检测不到设太大搜索耗时暴涨。我的经验是参考建图场景的物理尺寸单层不超过30米时设20米回环搜索距离比较合适更长的大厅或厂房再适当调大。我用一张表汇总最关键的一组默认参数和调优建议方便对照参数名含义推荐值调优建议resolution栅格分辨率0.05m大面积场景改0.1m精细工位可改0.02mpublish_rate全局地图发布频率1Hz导航够用即可上限2Hzmax_laser_range激光最大使用距离30m室内10-20m更好减少无效更新treat_unknown_as_occupied未知区域是否当障碍false地图未完善区域设为falseenable_loop_closure回环检测开关true必须与后端优化配合loop_search_distance回环搜索半径15-20m大场景按物理尺寸放大backend_optimize_interval后端优化周期1sCPU紧张可设0.5Hzmap_block_size地图块边长100格大场景可增至200格5.2 一次压测后的优化记录我印象很深的一次压测是在一条100米长、30米宽的模拟走廊里连续运行了30分钟建图。初始配置下机器人端的工控机CPU占用跑到85%左右地图发布延时偶尔跳到500毫秒明显会影响后续导航。排查发现瓶颈不在扫描匹配而在全局栅格的持续更新雷达量程设得太长每帧都要更新大量远离机器人的栅格而绝大多数更新对导航毫无意义。优化分成两步。第一步把max_laser_range从30米降到15米CPU直接降了20个百分点。第二步启用点云降采样让每0.1米网格内只保留一个代表性激光点参与射线更新的点数量大幅减少而地图质量肉眼几乎看不出变化。最终CPU占用稳定在40%左右地图发布延时控制在100毫秒内。这次压测给我的核心感受是地图模块的性能瓶颈往往是“持续更新 超大全局地图”带来的I/O开销而不是SLAM算法本身。把更新范围限制在机器人周围的有效区域比盲目提升算法优化频率更有效。这也解释了为什么地图块和局部更新机制不是可选项而是长期运行的必要条件。5.3 长期运行的资源控制在导航机器人上地图模块大概率是7乘24小时运行的资源控制必须要单独考虑。lingbot-map的内存开销主要集中在全局栅格块、点云帧缓冲和后端图结构三个方面。点云帧缓冲最容易失控。如果每帧雷达数据都存下来用于回环检测长时间运行后内存会线性增长。lingbot-map里对关键帧做了“距离时间”双重阈值只有移动距离超过0.5米或旋转角度超过30度时才插入关键帧并且限制关键帧总数超出后自动丢弃最旧的帧。全局地图块同样需要上限控制。地图块只增不减的话在一个超大园区里跑来跑去内存迟早爆掉。我们后来加了块缓存淘汰机制距离机器人超过一定范围且长时间没有被访问的地图块优先从内存换出只保留索引信息需要时再按需加载。这个机制上线后连续运行三天内存占用始终稳定在350MB左右彻底解决了之前越跑越卡的问题。6. 踩坑实录坐标变换错位、地图黑边、内存上涨的完整排查6.1 地图重影先查时间戳再查TF树有一阵子建图效果特别差地图上的墙线总是出现双层轮廓转角的贴合处明显错开像是两张没对齐的照片叠在一起。一开始怀疑是雷达安装位置产生了偏差我反复量了支架尺寸确认没有物理错位。接着我用工具查看TF树和位姿轨迹发现一个规律重影主要出现在机器人快速转动的时候直线匀速行驶时反而轻微。这个现象指向一个方向激光帧对应的位姿和实际位姿不同步。再细查代码发现雷达消息的时间戳使用的是传感器驱动里的时间而坐标变换缓冲在查询时却用了本地接收时间。雷达数据到达时已经有几十毫秒延迟机器人一转几十毫秒的位姿误差就会造成明显的扫描错位。修复方案是把时间戳统一改成传感器时间所有坐标变换都基于同一个时间源查询。重新建图后双层墙线彻底消失。这个坑提醒我处理地图相关问题第一嫌疑永远是时间同步第二才是坐标关系。顺序错了会浪费大量排查时间。6.2 地图边缘黑边未知区域被误判成障碍物另一个很典型的问题是地图边缘出现大片黑色区域尤其是机器人紧贴墙壁扫描时墙体外侧总有一大片被标记成“障碍”的黑色块。地图上看墙体像是被一层厚厚的墨迹包围导航路径规划遇到这种区域会绕很大的圈子。排查时先看栅格更新逻辑。激光命中点会被标记为占据这是对的但雷达到达最大量程之前的射线区域需要区分“确实扫描过且空闲”和“没有数据”两种情况。原来的实现为了效率把未知区域直接当成了占据区域导致建图范围边缘和墙后区域全部变黑。修法很简单把treat_unknown_as_occupied改为false并修正射线更新逻辑超出量程的区域一律标记为未知只有激光实际穿过的区域才标记为自由。修复后的地图在边缘处变成了灰色未知区域导航栈不再把未知区域当障碍物处理机器人规划路径时明显更合理不会再为了躲开那片“黑边”绕一大圈。这个问题的教训是栅格地图里“未知”“自由”“占据”三个状态必须严格区分不能为了节省计算量就牺牲语义准确性。6.3 内存持续上涨地图块只增不删长期运行的机器人最怕内存悄悄涨。有一版lingbot-map在模拟环境里连续运行两个小时后内存从300MB持续涨到1.5GB机器人速度明显变慢了。第一时间怀疑是哪个节点在漏消息反复检查后发现所有话题订阅数量正常回调函数也没有明显泄漏。最后用性能工具分析内存分配情况发现大量的内存都指向地图块缓存。原因出现了地图块在初始化后会被缓存起来等待后续更新但代码里只写了“放入缓存”的逻辑没有写“按需淘汰”的逻辑。机器人走到哪里地图块就缓存到哪里永远不会释放跑得越久内存涨得越高。修复方案就是前面提到的块缓存淘汰机制限制缓存块总数超过阈值后优先淘汰离机器人最远的块。同时给每个块记录最近访问时间LRU策略淘汰。修复后再跑72小时内存一直稳定在350MB左右。这件事让我深刻理解了“地图模块是常驻服务不是一次性工具”这句话的含义所有资源管理都要按服务标准来设计。7. 在实战中沉淀下来的设计体会与扩展方向7.1 地图模块需要的是“可干预”而不是全自动做地图模块久了会发现完全自动化的建图流程只存在于理想环境。真实现场里总有一些特殊情况玻璃反光打出的假墙、临时堆放的物料、门洞下面雷达扫不到的悬空障碍。全自动算法很难把这些情况处理得完美所以lingbot-map从一开始就保留了“人工干预”的接口。我们在系统里内置了一个地图编辑器支持手动擦除局部障碍、添加禁行区、标注房间名和通道语义节点。刚开始我觉得让操作员手工改地图是种倒退后来发现恰恰相反一个可靠的地图编辑器能让现场部署效率大幅提升。操作员发现某块区域地图不对直接在编辑器里圈选修正比反复重新建图快得多也比让算法自动猜测环境语义更可控。7.2 值得扩展的三个方向这套地图模块跑通之后我陆续在思考它的扩展空间第一个是语义地图增强。现在栅格地图只区分占据和自由如果能给每个区域打上“房间”“走廊”“电梯”“充电桩”的标签调度系统就能直接利用语义信息做任务分配和路径约束比如“只送餐到房间门口的取餐点不进入房间”。第二个是动态物体滤除。结合时序点云把行人、其他机器人的运动点从建图数据里分离出去静态地图会更干净定位的鲁棒性也会更高。这个方向对工厂和商场场景特别有价值。第三个是云端地图同步。单台机器人的地图数据上传到云端车队之间共享地图新来的机器人可以直接下载最近版本的地图省去每台车重新建图的时间。版本管理和增量同步就需要用到前文提到的地图块机制这也是我设计时坚持分块的一个重要原因。7.3 最后分享一个小技巧写到最后分享一个最实用的经验无论地图模块结构怎么设计一定要留一个主动强制重定位的接口。我在实际运行中发现机器人长期使用后即使地图完全正确偶尔也会因为光照变化、雷达局部遮挡等原因丢定位。如果没有一个可随时触发的relocalize接口现场人员只能重启系统重启后又得人工确认位姿过程相当狼狈。给调度系统开放了这个接口之后机器人每次自动离开充电桩、进出电梯前都会主动执行一次重定位作为“复位动作”后续导航的可靠性明显提升。从“地图只是SLAM的副产物”到“地图是整个导航系统的基础设施”这是我在lingbot-map上最大的体会。地图模块的技术含量未必体现在算法论文里但它在工程现场的价值是任何花哨算法都替代不了的。