UGV Rover PI ROS2 4. 基于激光雷达的二维建图
| ||||||||||||||||||||||
|
4. 基于激光雷达的二维建图
4.1 基于 Gmapping 的二维建图
4.1.1 Gmapping 简介
Gmapping 是一种用于机器人导航和地图构建的同步定位与建图(SLAM)算法,它基于 RBpf 粒子滤波算法,来帮助机器人在未知环境中定位自身并构建地图,即将定位和建图过程分离,先进行定位再进行建图。粒子滤波算法是早期的一种建图算法,其基本原理为机器人不断地通过运动、观测的方式,获取周围环境信息,逐步降低自身位置的不确定度,最终得到准确的定位结果。用上一时刻的地图和运动模型预测当前时刻的位姿,然后计算权重,重采样,更新粒子的地图,如此往复。
Gmapping 优点:
- 可以实时构建室内地图,在构建小场景地图所需的计算量较小且精度较高;
- 通过粒子滤波技术处理噪声,具有较强的鲁棒性;
- 适用于具有平面环境的室内机器人导航。
Gmapping 缺点:
- 对大规模或高度动态的环境支持有限,在构建大地图时所需内存和计算量都会增加,不适合构建大场景地图;
- 没有回环检测,因此在回环闭合时可能会造成地图错位,虽然增加粒子数目可以使地图闭合但是以增加计算量和内存为代价的。
- Gmapping 是二维 SLAM,无法处理复杂的三维场景。
4.1.2 启动 Gmapping 建图节点
在启动建图节点前,默认您已根据第一章 UGV Rover PI ROS2 1. 准备工作里的内容已结束主程序且远程连接上 Docker 容器。
在一个新的 Docker 容器终端,点击左边侧栏中的“⭐”符号,双击打开 Docker 的远程终端,输入用户名:root,密码:ws。
在容器中,进入该产品 ROS 2 项目的工作空间:
cd /home/ws/ugv_ws
将小车放置在需要构建地图的室内中,启动建图节点:
ros2 launch ugv_slam gmapping.launch.py use_rviz:=true
此时,RViz 界面显示的地图上只会显示出激光雷达所扫描到的区域,若还有未扫描到的区域需要建图,则可以控制小车移动来扫描建图。
在一个新的 Docker 容器终端中,运行手柄控制或键盘控制节点任意一个:
#手柄控制(确保手柄接收器插入树莓派中) ros2 launch ugv_tools teleop_twist_joy.launch.py #键盘控制(保持运行键盘控制节点处于激活状态) ros2 run ugv_tools keyboard_ctrl
这样,你就能控制底盘移动,来实现对周边环境的建图了。
在控制底盘移动时,若小车需要脱离你的视线范围之外进行建图,则可以通过 OAK 摄像头查看画面来控制小车移动,防止脱离视线之外后小车运动碰撞。
在一个新的 Docker 容器终端中,开启 OAK 摄像头:
ros2 launch ugv_vision oak_d_lite.launch.py
如图所示,即代表 OAK 摄像头开启成功。
接着点击 RViz 界面左下角的“Add”,选择“By topic”,找到 /oak,选择“/oak/rgb/image_rect”的 Image,点击“OK”。这样,就可以看见 OAK 摄像头画面出现在 RViz 左下角的界面中了。
4.1.3 保存地图
建图完,保持建图节点的运行,在一个新的 Docker 容器终端进行地图保存。打开一个新的 Docker 容器终端,点击左边侧栏中的“⭐”符号,双击打开 Docker 的远程终端,输入用户名:root,密码:ws。
在容器中,进入该产品 ROS 2 项目的工作空间:
cd /home/ws/ugv_ws
给地图保存脚本增加可执行权限:
chmod +x ./save_2d_gmapping_map.sh
接着运行地图保存脚本,如下图即地图保存成功:
./save_2d_gmapping_map.sh
该脚本里的具体内容为:
cd /home/ws/ugv_ws/src/ugv_main/ugv_nav/maps ros2 run nav2_map_server map_saver_cli -f ./map
执行完上述脚本文件后,会保存一个命名为 map 的 2D 栅格地图,该地图是保存于 /home/ws/ugv_ws/src/ugv_main/ugv_nav/maps 目录下,可以在上述目录里看见有两个文件生成,一个是 map.pgm,一个是 map.yaml。
- map.pgm:这是地图的栅格图(通常是灰度图像文件);
- map.yaml:这是地图的配置文件。
接着 Gmapping 建图节点可以通过 Ctrl+C 关闭。
4.2 基于 Cartographer 的二维建图
4.2.1 Cartographer 简介
Cartographer 是 Google 推出的一套基于图优化的 SLAM 算法。该算法的主要目标是实现计算资源消耗,达到实时 SLAM 的目的。它能帮助机器人实时构建环境的二维或三维建图,同时追踪机器人的位姿。
Cartographer 优点:
- 高精度建图:Cartographer 在处理 2D 和 3D 地图时具有很高的精度,尤其是在复杂环境中。其精度主要得益于传感器融合和全局优化技术,如回环检测。
- 传感器融合能力强:可以同时处理来自多个传感器的数据,如激光雷达、IMU(惯性测量单元)、GPS 等。通过融合不同传感器的数据,能够提高定位和地图构建的准确性。
- 全局优化:通过回环检测和全局优化,有效地减少了长时间运行过程中积累的误差,确保地图的整体一致性和准确性。
- 实时性:能够在机器人运动的同时,实时生成地图和跟踪机器人位姿,适用于动态环境中的实时 SLAM 应用。
Cartographer 缺点:
- 计算资源消耗大:对计算资源要求较高,特别是在处理 3D SLAM 时。其多传感器融合和全局优化算法需要大量的 CPU 和内存资源,可能不适用于低计算资源的设备。
- 配置复杂:配置选项繁多,需要用户深入理解其各个参数的意义并进行精细调整,以确保在特定环境中达到最优性能。
4.2.2 启动 Cartographer 建图节点
在容器中,进入该产品 ROS 2 项目的工作空间:
cd /home/ws/ugv_ws
将小车放置在需要构建地图的室内中,启动建图节点:
ros2 launch ugv_slam cartographer.launch.py use_rviz:=true
此时,RViz 界面显示的地图上只会显示出激光雷达所扫描到的区域,若还有未扫描到的区域需要建图,则可以控制小车移动来扫描建图。
在一个新的 Docker 容器终端中,运行手柄控制或键盘控制节点任意一个:
#手柄控制(确保手柄接收器插入树莓派中) ros2 launch ugv_tools teleop_twist_joy.launch.py #键盘控制(保持运行键盘控制节点处于激活状态) ros2 run ugv_tools keyboard_ctrl
这样,你就能控制底盘移动,来实现对周边环境的建图了。
在控制底盘移动时,若小车需要脱离你的视线范围之外进行建图,则可以通过 OAK 摄像头查看画面来控制小车移动,防止脱离视线之外后小车运动碰撞。
在一个新的 Docker 容器终端中,开启 OAK 摄像头:
ros2 launch ugv_vision oak_d_lite.launch.py
如图所示,即代表 OAK 摄像头开启成功。
接着点击 RViz 界面左下角的“Add”,选择“By topic”,找到 /oak,选择“/oak/rgb/image_rect”的 Image,点击“OK”。这样,就可以看见 OAK 摄像头画面出现在 RViz 左下角的界面中了。
4.2.3 保存地图
建图完,保持建图节点的运行,在一个新的 Docker 容器终端进行地图保存。打开一个新的 Docker 容器终端,点击左边侧栏中的“⭐”符号,双击打开 Docker 的远程终端,输入用户名:root,密码:ws。
在容器中,进入该产品 ROS 2 项目的工作空间:
cd /home/ws/ugv_ws
给地图保存脚本增加可执行权限:
chmod +x ./save_2d_cartographer_map.sh
接着运行地图保存脚本,如下图即地图保存成功:
./save_2d_cartographer_map.sh
该脚本里的具体内容为:
cd /home/ws/ugv_ws/src/ugv_main/ugv_nav/maps ros2 run nav2_map_server map_saver_cli -f ./map && ros2 service call /write_state cartographer_ros_msgs/srv/WriteState "{filename:'/home/ws/ugv_ws/src/ugv_main/ugv_nav/maps/map.pbstream'}"
执行完上述脚本文件后,会保存一个命名为 map 的地图,该地图是保存于 /home/ws/ugv_ws/src/ugv_main/ugv_nav/maps。可以在该目录里看见有三个文件生成,分别是 map.pgm、map.yaml 和 map.pbstram。
注意:如果你前面已经使用 Gmapping 建过图了,那么这里建的 map 地图会覆盖前面建的。若要建不一样的地图,则可以更改所建地图的名称,将“save_2d_cartographer”脚本中 “./map” 中的 map 更改为你想要建的地图名称即可。 例如:你需要建一个名为“room”的地图,则将脚本里的第二行指令改为 “ros2 run nav2_map_server map_saver_cli -f ./room && ros2 service call /write_state cartographer_ros_msgs/srv/WriteState "{filename:'/home/ws/ugv_ws/src/ugv_main/ugv_nav/maps/room.pbstream'}"”