ROS2 使用

1. 准备工作

由于产品开机默认会自动运行上位机主程序,主程序会占用串口和摄像头资源,这种情况下是不能使用 ROS 2 的,需要结束主程序或禁止主程序自动运行。ROS 2 功能包都是在 Jetson Orin Nano 系统中的 Docker 容器中运行的,因此关闭 Jetson Orin Nano 主程序的运行后,还需要启动 Docker 远程服务,才能远程登录 Docker 容器执行 ROS 2 功能包。


1.1 结束主程序

在终端中实时显示系统中正在运行的任务和进程信息:

top

等待几秒后,可以看见 COMMAND 为 python 的 PID。



按 Ctrl+C 退出查看,接着输入结束该进程的指令:

kill -9 python进程PID

如上图,则输入:kill -9 1662。这样,就结束该产品主程序的运行。注意:结束该主程序的运行后,上位机 “IP 地址:5000” 这个网页是访问不成功的,但是产品重启再开机后仍然还是会自动运行主程序,若要让产品再开机后不会自动运行主程序,则可以根据下一小节【1.2 禁止主程序自动运行】中的内容进行操作。


1.2 禁止主程序自动运行

产品每一次重启再开机都会默认自动运行主程序的,若您需要直接禁止产品主程序开机自动运行的话,需要取消由 crontab 配置开机自动运行的主程序。在终端中输入以下命令:

crontab -e

如果询问希望使用什么编辑器,输入 1 后按回车,选择使用 nano。

打开 crontab 的配置文件后,你可以看到一行内容:

@reboot sleep 3 && whoami && pulseaudio --start && sleep 2 && XDG_RUNTIME_DIR=/run/user/1000 ~/ugv_jetson/ugv-env/bin/python ~/ugv_jetson/app.py >> ~/ugv.log 2>&1

在这行的最前面添加一个 “#” 号来注释掉这行,如下:

#@reboot sleep 3 && whoami && pulseaudio --start && sleep 2 && XDG_RUNTIME_DIR=/run/user/1000 ~/ugv_jetson/ugv-env/bin/python ~/ugv_jetson/app.py >> ~/ugv.log 2>&1

在终端页面,按 Ctrl + X 退出,它会询问你 Save modified buffer? 输入“Y”,按回车,保存变更。

输入重启命令进行设备重启:

sudo reboot

当机器人重新开机后,你仍然可以正常使用 jupyter Lab (JupyterLab 与 机器人主程序 app.py 是互相独立运行的)。

这里需要注意一点,由于下位机持续通过串口与上位机通信,上位机在重启过程中有可能会由于串口电平的连续变化不能正常开机,拿上位机为树莓派的情况举例,重启时树莓派关机后不会再开机,红灯常亮绿灯不亮,此时可以关闭机器人电源开关,再打开,机器人就能够正常重启了。


1.3 启动 Docker 远程服务

在 Jetson Orin 中进入 ugv_ws 项目目录,给 ros2_humble.sh 和 remotessh.sh 两个文件添加可执行权限:

cd /home/jetson/ugv_ws
sudo chmod +x ros2_humble.sh remotessh.sh

执行启动 Docker 远程服务的脚本文件 ros2_humble.sh :

./ros2_humble.sh

输入 1 进入 Docker 容器启动 SSH 服务。


1.4 远程登录 Docker 容器

Docker 容器成功启动 SSH 服务后,使用 MobaXterm 远程登录 Docker 容器。

点击“Session”→“SSH”,宿主机 IP 即为 Docker 容器 IP,在 Remote host 中输入 Jetson Orin Nano 的 IP 地址,Port 为已分配好的 23 端口,最后点击“OK”。

连接建立好后,输入用户名:root,密码:jetson。注意:输入密码时屏幕上没有变化属于正常现象,密码输入完成后按回车键即可访问 Docker 容器。自此 SSH 远程连接 Docker 容器成功。



2. Rviz 查看产品模型

默认您已根据第一章 UGV Beast Jetson Orin ROS2 1. 准备工作里的内容已结束主程序且远程连接上 Docker 容器。


2.1 查看模型关节

在容器中,进入该产品 ROS 2 项目的工作空间:

cd /home/ws/ugv_ws

启动 Rviz2 模型界面:

ros2 launch ugv_description display.launch.py use_rviz:=true

此时,仅可以查看该产品 Rviz2 模型界面,但不能通过控制面板划动滑块来控制小车运动。成功启动小车 Rviz2 模型的终端界面,该界面不要关闭,接着运行 ROS2 小车驱动节点。


2.2 运行 ROS2 小车驱动节点

我们需要打开一个新的 Docker 容器终端,点击左边侧栏中的“⭐”符号,双击打开 Docker 的远程终端,输入用户名:root,密码:jetson。


在容器中,进入该产品 ROS 2 项目的工作空间:

cd /home/ws/ugv_ws

运行驱动小车节点,该节点运行完后不会有任何信息反馈:

ros2 run ugv_bringup ugv_driver

接着通过滑动下图控制面板的滑块可以控制云台转动,此时模型和产品都会跟随您的滑动一起转动。

  • pt_base_link_to_pt_link1:控制云台水平舵机转动。
  • pt_link1_to_pt_link2:控制云台倾斜舵机转动。
  • Center:点击该键云台会回归中位。


2.3 控制小车灯光

UGV 系列产品,驱动板上集成了两路 12V 开关控制接口(实际最高电压会随着电池电压而改变),分别为由 ESP32 的 IO4 和 IO5 引脚通过 MOS 管来控制,每路对应有两个接口,一共 4 个 12V 开关控制接口,按照默认的组装方式,IO4 控制底盘大灯(OKA 相机旁的灯),IO5 控制头灯(USB 摄像头云台上的灯),你可以通过向下位机发送相应的指令来控制这两路接口的开关以及控制电压高低(但由于 MOS 管控制本身存在一定的延时所以 ESP32 的 IO 输出的 PWM 与实际接口输出的电压不成线性关系)。

对于没有配有 LED 灯的产品,你可以自行在这两路 12V 开关控制接口上扩展耐压 12.6V 的LED灯(一般情况下耐压 12V 的也可以,因为为了安全和保护电池,产品的 UPS 不会将电池电量充到 12V 以上),你也可以在剩余的开关控制接口上扩展其它外设——例如耐压 12V 的水弹枪波箱,直接连接在 IO5 控制的接口上,即可实现自动瞄准和射击的功能。

每运行一个控制节点,都需要打开一个新的 Docker 容器终端,点击左边侧栏中的“⭐”符号,双击打开 Docker 的远程终端,输入用户名:root,密码:jetson。

在容器中,进入该产品 ROS 2 项目的工作空间:

cd /home/ws/ugv_ws

运行灯光控制节点,此时可以看见小车上的三个 LED 灯都已亮起:

ros2 topic pub /ugv/led_ctrl std_msgs/msg/Float32MultiArray "{data: [255, 255]}" -1

data: [0, 0]——第一个 0 为控制 IO4 接口(底盘大灯)的开关;第二个 0 为控制 IO5 接口(头灯)的开关。

参数变量范围为 0-255,当此变量值为 0 时,IO4 和 IO5 控制的接口开关关闭;当此变量为 255 时,IO4 和 IO5 控制的接口开关输出的电压接近 UPS 的 BAT 电压(当前 UPS 内三节锂电池串联的电压)。

再次运行关闭 LED 灯的指令,可以看见三个 LED 灯都关闭:

ros2 topic pub /ugv/led_ctrl std_msgs/msg/Float32MultiArray "{data: [0, 0]}" -1



3. 使用手柄或键盘控制

本章节介绍如何使用手柄或键盘按键来控制产品运动,该产品出厂时有附带一个 Xbox 蓝牙手柄。默认您已根据第一章 UGV Beast Jetson Orin ROS2 1. 准备工作里的内容已结束主程序且远程连接上 Docker 容器。


3.1 底盘驱动

在运行手柄控制和键盘控制例程之前,必须要先运行底盘驱动节点。上一章节中我们有介绍一种 ROS2 小车驱动节点的运行,这里我们介绍另一种底盘驱动节点的运行。

在容器中,进入该产品 ROS 2 项目的工作空间:

cd /home/ws/ugv_ws

启动小车驱动节点:

ros2 launch ugv_bringup bringup_lidar.launch.py use_rviz:=true

此时,机器人云台会转至中位,摄像头面向前方,可以查看到该产品 Rviz2 模型界面,原地旋转小车可以看见模型中也会跟着一起旋转。


注意:如果模型界面中显示的不是 UGV Beast 履带型的底盘,则需要先按 Ctrl+C 关闭运行小车驱动节点。接着将 ROS 2 项目中的 UGV 模型切换为 UGV Beast 的,输入以下命令切换完模型后再启动小车驱动节点。

export UGV_MODEL=ugv_beast
source ~/.bashrc

3.2 手柄控制

启动小车驱动节点后,将手柄接收器接入到 Jetson Orin Nano 中。

插入后,需要先在一个新的 Docker 容器终端运行手柄控制节点。打开一个新的 Docker 容器终端,点击左边侧栏中的“⭐”符号,双击打开 Docker 的远程终端,输入用户名:root,密码:jetson。


在容器中,先运行如下命令查看是否识别到游戏手柄,运行后如图所示:

ls /dev/input

ROS2 xboxls.png

其中,js0 代表游戏手柄。

在容器中,进入该产品 ROS 2 项目的工作空间:

cd /home/ws/ugv_ws

运行手柄控制节点:

ros2 launch ugv_tools teleop_twist_joy.launch.py

接着打开手柄背后的开关,看见手柄上亮红灯之后可以控制小车运动。【标注手柄三个功能键手柄:R下面的那个键锁定or解锁,手柄的摇杆,左摇杆——前进,后退;右摇杆——左转,右转】

通过按 Ctrl+C 可以关闭手柄控制节点。


3.2 键盘控制

关闭手柄控制节点,可以接着再运行手柄控制节点的终端窗口中来运行键盘控制节点:

ros2 run ugv_tools keyboard_ctrl

保持这个窗口为激活状态(即确保操作按键时位于该终端窗口界面),通过以下按键来控制小车运动:

键盘按键操作描述键盘按键操作描述键盘按键操作描述
字母 U左前进字母 I直前进字母 O右前进
字母 J左转字母 K停止运动字母 L右转
字母 M左后退符号 ,直后退符号 .右后退

通过按 Ctrl+C 可以关闭键盘控制节点。



4. 基于激光雷达的二维建图

4.1 基于 Gmapping 的二维建图

4.1.1 Gmapping 简介

Gmapping 是一种用于机器人导航和地图构建的同步定位与建图(SLAM)算法,它基于 RBpf 粒子滤波算法,来帮助机器人在未知环境中定位自身并构建地图,即将定位和建图过程分离,先进行定位再进行建图。粒子滤波算法是早期的一种建图算法,其基本原理为机器人不断地通过运动、观测的方式,获取周围环境信息,逐步降低自身位置的不确定度,最终得到准确的定位结果。用上一时刻的地图和运动模型预测当前时刻的位姿,然后计算权重,重采样,更新粒子的地图,如此往复。

Gmapping 优点:

  • 可以实时构建室内地图,在构建小场景地图所需的计算量较小且精度较高;
  • 通过粒子滤波技术处理噪声,具有较强的鲁棒性;
  • 适用于具有平面环境的室内机器人导航。

Gmapping 缺点:

  • 对大规模或高度动态的环境支持有限,在构建大地图时所需内存和计算量都会增加,不适合构建大场景地图;
  • 没有回环检测,因此在回环闭合时可能会造成地图错位,虽然增加粒子数目可以使地图闭合但是以增加计算量和内存为代价的。
  • Gmapping 是二维 SLAM,无法处理复杂的三维场景。

4.1.2 启动 Gmapping 建图节点

在启动建图节点前,默认您已根据第一章 UGV Beast Jetson Orin ROS2 1. 准备工作里的内容已结束主程序且远程连接上 Docker 容器。

在一个新的 Docker 容器终端,点击左边侧栏中的“⭐”符号,双击打开 Docker 的远程终端,输入用户名:root,密码:jetson。


在容器中,进入该产品 ROS 2 项目的工作空间:

cd /home/ws/ugv_ws

将小车放置在需要构建地图的室内中,启动建图节点:

ros2 launch ugv_slam gmapping.launch.py use_rviz:=true


此时,RViz 界面显示的地图上只会显示出激光雷达所扫描到的区域,若还有未扫描到的区域需要建图,则可以控制小车移动来扫描建图。

在一个新的 Docker 容器终端中,运行手柄控制或键盘控制节点任意一个:

#手柄控制(确保手柄接收器插入 Jetson Orin Nano 中)
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,密码:jetson。

在容器中,进入该产品 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 容器终端中,运行手柄控制或键盘控制节点任意一个:

#手柄控制(确保手柄接收器插入 Jetson Orin Nano 中)
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,密码:jetson。

在容器中,进入该产品 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'}"”



5. 基于深度相机的三维建图

本教程将介绍如何通过 RTAB-Map 算法基于激光雷达和深度相机进行三维建图。我们提供两种可视化途径的建图,在启动建图节点前,默认您已根据 UGV Beast Jetson Orin ROS2 1. 准备工作里的内容已结束主程序且远程连接上 Docker 容器。

5.1 在 RTAB-Map 中可视化

RTAB-Map(Real-Time Appearance-Based Mapping)是一种用于同时定位与建图(SLAM,Simultaneous Localization and Mapping)的开源算法,广泛应用于机器人导航、自动驾驶汽车、无人机等领域。它采用视觉和激光雷达传感器的数据来构建环境地图并进行定位,属于基于回环检测(loop closure detection)的SLAM方法。

启动 RTAB-Map 的可视化节点:

ros2 launch ugv_slam rtabmap_rgbd.launch.py use_rviz:=false

在一个新的 Docker 容器终端中,运行手柄控制或键盘控制节点任意一个:

#手柄控制(确保手柄接收器插入 Jetson Orin Nano 中)
ros2 launch ugv_tools teleop_twist_joy.launch.py
#键盘控制(保持运行键盘控制节点处于激活状态)
ros2 run ugv_tools keyboard_ctrl

这样,你就能控制底盘移动,来实现对周边环境的建图了。建图完毕后,直接按 Ctrl+c 退出建图节点,系统将会⾃动保存地图。地图默认保存路径 ~/.ros/rtabmap.db。


5.2 在 RViz 中可视化

启动 RTAB-Map 的可视化节点:

ros2 launch ugv_slam rtabmap_rgbd.launch.py use_rviz:=true

在一个新的 Docker 容器终端中,运行手柄控制或键盘控制节点任意一个:

#手柄控制(确保手柄接收器插入 Jetson Orin Nano 中)
ros2 launch ugv_tools teleop_twist_joy.launch.py
#键盘控制(保持运行键盘控制节点处于激活状态)
ros2 run ugv_tools keyboard_ctrl

这样,你就能控制底盘移动,来实现对周边环境的建图了。建图完毕后,直接按 Ctrl+c 退出建图节点,系统将会⾃动保存地图。地图默认保存路径 ~/.ros/rtabmap.db。


6. 自动导航

6.1 启动导航

6.1.1 二维地图导航

在启动导航之前,首先先确定您已经建了一个名为 map 的环境地图,若您没有跟着前面的教程操作下来,则先需要根据 UGV Beast Jetson Orin ROS2 4. 基于激光雷达的二维建图或者 UGV Beast Jetson Orin ROS2 5. 基于深度相机的三维建图任一教程进行建图。

建图完成后,接着启动导航,我们提供了多种自主导航模式,你可以从以下自主导航模式任选一种进行机器人导航。


6.1.1.1 基于 AMCL 和 EMCL 的导航

1. AMCL 算法

Adaptive Monte Carlo Localization(AMCL)是 ROS 2 中的一种基于粒子滤波的定位算法,它使用 2D 激光雷达在给定的已知地图中估计机器人的位置和方向(即姿势)。AMCL 主要用于移动机器人导航,它通过激光传感器(如激光雷达)与现有地图相匹配,推算出机器人在地图中的位置和朝向。其核心思想是通过大量粒子表示机器人的可能位置,并逐步更新这些粒子来缩小机器人的位姿不确定性。

AMCL 的优势:

  • 自适应粒子数:AMCL会根据机器人位置的不确定性动态调整粒子的数量。
  • 适用于动态环境:虽然 AMCL 假设静态环境,但它能在一定程度上处理少量动态障碍物,如行人等移动物体,这使其在实际应用中更加灵活。
  • 可靠的定位能力:AMCL 在已知地图中的定位效果非常可靠,即使机器人位姿初始不确定,它也能够逐渐收敛到正确的位姿。

AMCL 是假设地图已知,不能自己创建地图。且依赖于高质量的静态地图,与传感器数据进行匹配。如果地图和真实环境有较大差异,定位效果会受影响。AMCL 常用于移动机器人自主导航,机器人在导航过程中可以通过 AMCL 确定自己的位姿,依赖已知的地图进行路径规划和避障。

在容器中,启动基于 AMCL 算法的导航,启动成功后可以看见前面所建地图的 RViz 画面:

ros2 launch ugv_nav nav.launch.py use_localization:=amcl use_rviz:=true

接着,你可以根据 6.2 初始化机器人的位置去确定机器人的初始位置。


2. EMCL 算法

EMCL 是 AMCL 的替代 Monte Carlo localization(MCL)包。与 AMCL 不同的是,KLD 采样和自适应 MCL 没有实现。相反,实现了扩展重置和其它功能。EMCL 不完全依赖自适应粒子滤波,而是引入了扩展重置等方法来改善定位性能。EMCL 实现了扩展重置策略,这是一个用于改善粒子集质量的技术,能够更好地处理定位中的不确定性和漂移。

启动基于 EMCL 算法的导航,启动成功后可以看见前面所建地图的 RViz 画面:

ros2 launch ugv_nav nav.launch.py use_localization:=emcl use_rviz:=true

接着,你可以根据 6.2 初始化机器人的位置去确定机器人的初始位置。


6.1.1.2 基于 Cartographer 的纯定位

Cartographer 是 Google 开源的一个可跨多个平台和传感器配置以 2D 和 3D 形式提供实时同时定位和建图(SLAM)的系统。

Cartographer 系统架构概述:可以看到左边可选的输入有深度信息、里程计信息、IMU数据、固定 Frame 姿态。


更多教程可以参考官方文档项目地址

启动基于 Cartographer 的纯定位,启动成功后可以看见前面所建地图的 RViz 画面:

注意:基于 Cartographer 纯定位的导航模式,必须使用 Cartographer 建图后,才可以进行使用。

ros2 launch ugv_nav nav.launch.py use_localization:=cartographer use_rviz:=true

接着,你可以根据 6.2 初始化机器人的位置去确定机器人的初始位置。

6.1.1.3 基于 DWA 和 TEB 算法

1. DWA 算法 动态窗口算法(Dynamic Window Approaches,DWA)是基于预测控制理论的一种次优方法,因其在未知环境下能够安全、有效的避开障碍物, 同时具有计算量小, 反应迅速、可操作性强等特点。DWA 算法属于局部路径规划算法。

该算法核心思想是根据移动机器人当前的位置状态和速度状态在速度空间 ( v , ω ) 中确定一个满足移动机器人硬件约束的采样速度空间,然后计算移动机器人在这些速度情况下移动一定时间内的轨迹, 并通过评价函数对该轨迹进行评价,最后选出评价最优的轨迹所对应的速度来作为移动机器人运动速度, 如此循环直至移动机器人到达目标点。

启动基于 DWA 算法的导航,启动成功后可以看见前面所建地图的 RViz 画面:

ros2 launch ugv_nav nav.launch.py use_localplan:=dwa use_rviz:=true

接着,你可以根据 6.2 初始化机器人的位置去确定机器人的初始位置。


2. TEB 算法

TEB 全称 Time Elastic Band Local Planner,该方法针对全局路径规划器生成的初始全局轨迹进行后续修正,从而优化机器人的运动轨迹,属于局部路径规划。在轨迹优化过程中,该算法拥有多种优化目标,包括但不限于:整体路径长度、轨迹运行时间、与障碍物的距离、通过中间路径点以及机器人动力学、运动学以及几何约束的符合性。

启动基于 TEB 算法的导航,启动成功后可以看见前面所建地图的 RViz 画面:

ros2 launch ugv_nav nav.launch.py use_localplan:=teb use_rviz:=true

接着,你可以根据 6.2 初始化机器人的位置去确定机器人的初始位置。

6.1.2 三维地图导航

上面介绍的都是基于激光雷达二维建的地图导航模式,根据 UGV Beast Jetson Orin ROS2 5. 基于深度相机的三维建图该教程所建的三维地图,则参考该小节的导航启动方式。

先开启 nav 定位:

ros2 launch ugv_nav rtabmap_localization_launch.py

需要等三维数据加载完毕后,等待一段时间出现如下图所显示的即可开启导航。

在一个新的终端中,开启导航,两种导航模式任选一种即可:

  • DWA 算法
ros2 launch ugv_nav rtabmap_localization_launch.py
  • TEB 算法
ros2 launch ugv_nav nav_rtabmap.launch.py use_localplan:=teb use_rviz:=true

根据上述所建的地图选择一种导航模式开启导航后,则接着以下内容进行使用。


6.2 初始化机器人的位置

默认情况下,启动导航后,机器人最初不知道自己在哪里,地图等待您为其提供大致的起始位置。

首先,找到机器人在地图上的位置,检查你的机器人在实际中的位置。在 RViz 中手动设置机器人的初始位姿。单击 2D Pose Estimate 按钮并在地图上指出机器人的位置。绿色箭头的方向是机器人云台向前所面对的方向。


保持好启动导航终端的运行,设置好机器人大致的初始位姿后,保证导航确保机器人在实际中的位置是大致对应地上的。也可以在一个新终端通过键盘控制小车,进行简单地移动旋转,协助进行初始定位。

ros2 run ugv_tools keyboard_ctrl


6.3 发送目标位姿

6.3.1 单点导航

在地图上为机器人选择一个目标位置。您可以使用 Nav2 Goal 工具向机器人发送目标位置和目标方向。在 RViz 地图上指出机器人想要自动导航至的位置(目标点),绿色箭头的方向是机器人云台向前所面对的方向。


设置好目标位姿后,导航将找到全局路径并开始在地图上导航机器人移动到目标位姿。现在,你可以看到机器人向实际中的目标位置移动。


6.3.2 多点导航

观察 RViz 界面中的左下角,有一个 Nav2 的RViz2 小插件【Waypoint/Nav Through Poses Mode】,可以进行导航模式的切换,点击【Waypoint/Nav Through Poses Mode】该按钮即切换至多点导航模式。

接着使用 RViz2 工具栏中的 Nav2 Goal 给定多个要移动的目标点,给定后,还是点击左下角【Start Waypoint Following】开始路径规划导航。机器人会根据所选目标点的先后顺序进行移动,到了第一个目标点后会自动前往下一个目标点,无需再进行操作。到达最后一个目标点后,小车会停止。


6.4 更改地图名称

根据 UGV Beast Jetson Orin ROS2 4. 基于激光雷达的二维建图该教程,我们所建地图名称默认都为 map,则上述启动导航的文件所调用的地图也都为 map。但是若您有在建图时更改地图的名称,则在启动导航之前,需要同步更改启动文件里调用地图的名称。

打开 /home/ws/ugv_ws/src/ugv_main/ugv_nav/launch 这个目录下的 nav.launch.py 脚本文件,如下图将“map.yaml”改为你所保存的地图名称。更改完后保存关闭。


接着重新编译一下 nav 包,在 Docker 容器终端中进入产品的工作空间进行 ugv_nav 包:

cd /home/ws/ugv_ws
colcon build --packages-select ugv_nav --symlink-install
source ~/.bashrc

若您使用 Cartographer 建图时,更改了保存的地图名称,除了上述的文件需要更改之外,还需要更改 /home/ws/ugv_ws/src/ugv_main/ugv_nav/launch/nav_bringup/ 这个目录下的 bringup_launch_cartographer.launch.py 脚本文件,如下图将“map.pbstream”更改为你所保存的地图名称。更改完后保存关闭,再编译一次 ugv_nav 包。




7. 导航与 SLAM 建图

本教程介绍了如何将 Nav2 与 SLAM 结合使用。以下步骤向您展示了如何生成占用栅格地图并使用 Nav2 移动机器人。默认您已根据第一章 UGV Beast Jetson Orin ROS2 1. 准备工作里的内容已结束主程序且远程连接上 Docker 容器。

在 Docker 容器中,启动机器人的 RViz 界面和导航:

ros2 luanch ugv_nav slam_nav.launch.py use_rviz:=true


7.1 手动探索

在 RViz 界面中可以手动发布导航点进行探索。使用 Nav2 Goal 工具向机器人发送目标位置和目标方向。在 RViz 界面中指出机器人想要探索的位置(目标点),绿色箭头的方向是机器人云台向前所面对的方向。


同时,也可以使用键盘、手柄进行遥控探索,在一个新的 Docker 容器终端中,运行手柄控制或键盘控制节点任意一个,具体可参考 UGV Beast Jetson Orin ROS2 3. 使用手柄或键盘控制章节的内容:

#手柄控制(确保手柄接收器插入 Jetson Orin Nano 中)
ros2 launch ugv_tools teleop_twist_joy.launch.py
#键盘控制(保持运行键盘控制节点处于激活状态)
ros2 run ugv_tools keyboard_ctrl

或者,通过 Web 端控制控制机器人移动进行探索,具体可参考 UGV Beast Jetson Orin ROS2 9. Web 端控制工具章节的内容。

这样,你就能控制底盘移动,来实现对周边环境的探索了,随着你对底盘的移动控制,在 RViz 界面中会逐渐显示机器人所移动过的地图。


7.2 自动探索

除了手动探索之外,还可以直接让机器人自动探索地图。注意:自动探索需要在封闭规则区域内才能进行。一般建议在封闭的小房间内进行自动探索,或者通过在 Gazebo 仿真地图中进行自动探索,具体可参考 UGV Beast Jetson Orin ROS2 11. Gazebo 仿真调试中的内容。

保持机器人 RViz 界面和导航指令的运行,再在一个新的 Docker 容器中,运行自动探索的指令:

ros2 launch explore_lite explore.launch.py

运行后,机器人会在该封闭规则区域内进行移动探索,同时,所探索的区域也会显示在 RViz 界面上。


7.3 保存地图

导航探索完,可以在一个新的 Docker 容器终端进行地图保存。打开一个新的 Docker 容器终端,点击左边侧栏中的“⭐”符号,双击打开 Docker 的远程终端,输入用户名:root,密码:jetson。

在容器中,进入该产品 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:这是地图的配置文件。


8. Web 端自然语言交互

本教程将介绍如何在 Web 端页面用自然语言直接控制机器人。在该教程中,我们使用 Ollama 命令行工具运行大型语言模型,通过命令行输入相应的命令来使用 Gemma 模型进行 JSON 指令生成,生成的 JSON 指令发送给机器人,支持机器人执行基础移动、辅助建图、导航等任务。


8.1 Ollama 简介

Ollama 是一个开源的大型语言模型服务工具,用于简化在本地运行大语言模型、降低使用大语言模型的门槛,同时还提供了一个丰富的预构建模型库,包括如 Qwen2、Llama3、Phi3、Gemma2 等开源的大型语言模型,可以轻松集成到各种应用程序中。Ollama 的目标是使大型语言模型的部署和交互变得简单,无论是对于开发者还是对于终端用户。


8.2 安装与配置 Ollama

1. 点击 Ollama 官网下载 Ollama 的安装包。官方 Ollama 支持不同操作系统下载,根据您的操作系统,选择相应的安装包进行下载。该教程中是在 Windows 操作系统安装的,下载完成后,运行安装包,按照提示完成安装过程。

2. 安装完成后,需要进行 Windows 系统环境变量配置。在“开始”菜单栏中,搜索“高级系统设置”,在系统设置中选择“环境变量”。

3. 在用户变量中选择“新建”,变量名填入:“OLLAMA_HOST”,变量值填入:“:11434”,如下图。填完后点击“OK”进行保存。



4. 如下图显示即为添加成功,最后点击“OK”保存环境变量的配置。



8.3 下载大模型到本地

Ollama 支持 Ollama 模型库上提供的一系列模型,以下是一些可以下载的示例模型,该教程中使用的是 Gemma2:9B 模型。


注意:你应该至少有 8GB RAM 内存大小来运行 7B 的模型,16GB RAM 内存大小来运行 13B 的模型,32GB RAM 内存大小来运行 33B 的模型。我们教程中使用的是 Gemma2:9B 的模型,则需要保证你的电脑 RAM 内存大小有 16GB 及以上。

1. 首先,先确定你的电脑 RAM 内存大小有 16 GB 及以上。在“开始”菜单栏中搜索“任务管理器”,选择“内存”查看内存大小是 16GB 及以上即可。


2. 接着在Windows 系统下,按 Ctrl+R 后输入“cmd”打开终端,通过 pull 命令从 Ollama 远程仓库完整下载大模型到本地。

ollama pull gemma2

3. 下载完成后,可以运行大模型进行测试,随机和 AI 进行对话测试。

ollama run gemma2



8.4 更改 IP 地址

首先,先确定你进行 Ollama 部署的本地 IP 地址是多少,记住这个 IP 地址。

  • Windows 系统

按 Ctrl+R,输入 cmd 打开终端,在终端中输入查看 IP 地址的指令:

ipconfig


记住这个 IP 地址,接着在 Jetson Orin Nano 操作系统中,打开 /home/ws/ugv_ws/src/ugv_main/ugv_chat_ai/ugv_chat_ai/ 这个目录下的 app.py 文件,如下图将第 85 行“:11434”前的 IP 地址更改为你前面所得到的本地 IP 地址。


更改后按 Ctrl+S 保存退出即可。


8.5 底盘驱动

在启动底盘驱动之前,默认您已根据第一章 UGV Beast Jetson Orin PI ROS2 1. 准备工作里的内容已结束主程序且远程连接上 Docker 容器。

在容器中,进入该产品 ROS 2 项目的工作空间:

cd /home/ws/ugv_ws

启动小车驱动节点:

ros2 launch ugv_bringup bringup_lidar.launch.py use_rviz:=true

此时,机器人云台会转至中位,摄像头面向前方,可以查看到该产品 Rviz2 模型界面,原地旋转小车可以看见模型中也会跟着一起旋转。



8.6 启动 Web 端 AI 应用

打开一个新的 Docker 容器终端,点击左边侧栏中的“⭐”符号,双击打开 Docker 的远程终端,输入用户名:root,密码:jetson。


运行 Web 端 AI 应用:

ros2 run ugv_chat_ai app

运行后成功后如下图所示:


接着在部署 Ollama 的操作系统的浏览器中,访问“IP 地址:5000”这个网址进入 AI 应用的界面。如上图所示,这里访问的网址为 “192.168.10.131:5000”。

在与 AI 的聊天界面中,我们需要先给 AI 发一些提示,让 AI 反馈 JSON 指令,从而去控制机器人运动。下面是我们提供的提示,可以直接复制发送给 AI:

You are an assistant helping me with the simulator for robots.Here are some tips you can use to command the robot.
{"T": "1", "type": type, "data": data}
type: drive_on_heading back_up spin stop
data: num
you should return only json in code,without explanation
for examples,
"user": "move 2 units forward."
"assistant": {"T": 1, "type": "drive_on_heading", "data": 2}

"user": "move 2 units back."
"assistant": {"T": 1, "type": "back_up", "data": 2}

"user": "turn left 30 degrees."
"assistant": {"T": 1, "type": "spin", "data": 30}

"user": "stop."
"assistant": {"T": 1, "type": "stop", "data": 0}

等待 1 分钟左右,AI 会反馈直走 2m 的 JSON 指令,如下图:


  • type:机器人运动类型。driver_on_heading:前进;back_up:后退;spin:旋转;stop:停止。
  • data:机器人运动的数值参数。前进或后退时,单位为 m;旋转时,单位为度。

接着,还需要启动机器人运动的相关接口,在 AI 反馈回 JSON 指令后,实际中的机器人才会进行相应地运动。打开一个新的 Docker 容器终端,运行以下指令:

ros2 run ugv_tools behavior_ctrl

运行完成后,未给机器人运动指令前不会有反馈出来。

示例:让机器人前进 1m。AI 应用会反馈前进 1m 的 JSON 指令,“ros2 run ugv_tools behavior_ctrl”这个指令会反馈出产品移动距离和现在距离等参数,完成 1m 的移动后机器人会停止。



9. Web 端控制工具

本章节介绍基于 Web 的控制台工具。该机器人项目使用的是 Vizanti Web 工具,Vizanti 是一个基于 Web 的可视化和控制工具,旨在更方便地操作机器人的 ROS2 功能。该应用程序试图尽可能精确地在浏览器上复制 RViz 的正交 2D 视图。第二个目标是允许通过自定义按钮和参数重新配置,规划和执行移动与任务指令,例如目标点和路径点。

默认您已根据第一章 UGV Beast Jetson Orin ROS2 1. 准备工作里的内容已结束主程序且远程连接上 Docker 容器。在容器中,启动 Web 应用,ip 为 Jetson Orin 的 IP 地址(也是登陆 Docker 容器的 IP 地址):

ros2 launch ugv_web_app bringup.launch.py host:=ip

运行成功后会如下显示:


然后再同一局域网的电脑上(也可以是 Jetson Orin 系统),打开浏览器(最好是谷歌浏览器),在地址栏输入 Jetson Orin 的 IP 地址 + :5100,例如:192.168.10.212:5100。

此时,由于没有启动机器人的相关节点,因此在 Web 界面中没有任何数据显示。


9.1 控制小车移动

9.1.1 运行小车驱动节点

打开一个新的 Docker 容器终端,点击左边侧栏中的“⭐”符号,双击打开 Docker 的远程终端,输入用户名:root,密码:jetson。


启动小车驱动节点:

ros2 launch ugv_bringup bringup_lidar.launch.py use_rviz:=true

启动后,Web 界面中会出现一个 TF 坐标系图,同时,也会出现该产品 RViz 2 模型界面。


下面介绍 Web 界面的通用工具:

  • Global Settings:全局设置。可以设置背景颜色和固定 TF 坐标系,还可以将相机视图重置为零和默认缩放。
  • Rosbridge Connection:桥连接。这里显示连接状态以及 URL 链接等信息。
  • Grid Renderer:网格。可调节的公制网格。
  • TF Frame Renderer:TF 坐标系。渲染 TF 坐标系,大部分选项与 RViz 中的选项相同,不用再设置。
  • Add Widgets:添加小组件。


9.1.2 控制小车移动

接着,我们先添加一个操纵杆小组件用来控制小车移动。点击“Add Widgets”,选择“Teleop Joystick”,会在 Web 界面出现一个圆圈按钮,通过这个按钮可以控制小车移动。



9.2 建图

在启动建图节点之前,先要确保上述底盘驱动节点已关闭运行。需要先参考 UGV Beast Jetson Orin ROS2 4. 基于激光雷达的二维建图或者 UGV Beast Jetson Orin ROS2 5. 基于深度相机的三维建图里的内容启动建图节点。

启动后,在 Web 界面中点击“Add Widgets”,选择“Map”。


接着,点击“Map”图标,将 Topic 选择为 /map,这样就能看见 RViz 界面中的地图了。


最后再通过手柄或者键盘控制小车移动进行建图,或者也可以通过前面添加的操纵杆小组件控制小车移动进行建图,建完图后也参考建图教程里的指令进行地图保存。


9.3 导航

建完图后,在 Docker 容器中,运行启动导航的指令:

ros2 launch ugv_nav nav.launch.py use_rviz:=true

该指令中没有指定 use_localization,默认使用的是基于 AMCL 算法的导航,详情可参考 UGV Beast Jetson Orin ROS2 6. 自动导航部分的教程说明。

通过将“Map”小组件里的 Topic 设置为 /map,则可以看见前面建图完成所保存的地图,该地图和 RViz2 界面中所显示的地图一致。


在 Web 界面中点击“Add Widgets”,选择“2D Pose Estimate”和“2D Nav Goal”这两个个小组件进行添加。


可以使用“2D Pose Estimate”在地图上指出机器人的位置,绿色箭头的方向是机器人云台朝前的方向。

在地图上为机器人选择一个目标位置。您可以使用“2D Nav Goal”工具向机器人发送目标位置和目标方向。在 Web 界面的地图上指出机器人想要自动导航至的位置(目标点),紫色箭头的方向是机器人云台朝前的方向。指出目标位置后松开鼠标,机器人会移动至该目标位置。

自此,可以通过 Web 端控制工具去控制机器人移动、建图及导航等。用户还可根据自己的需求去扩展和开发其余组件的功能。



10. 指令交互

本章教程主要介绍如何使用指令控制机器人进行基础移动和让机器人运动到导航点。在该教程开始之前,默认您已根据第一章 UGV Beast Jetson Orin ROS2 1. 准备工作里的内容已结束主程序且远程连接上 Docker 容器。

首先,在容器中启动机器人行为控制接口,保持这个指令的运行:

ros2 run ugv_tools behavior_ctrl


10.1 基础控制

在进行基础控制之前,先要确保机器人是放置在地面上的,机器人需要根据里程计判断机器人所行驶的距离是否完成目标。

接着打开一个新的 Docker 容器终端,点击左边侧栏中的“⭐”符号,双击打开 Docker 的远程终端,输入用户名:root,密码:jetson。

在容器中,进入该产品 ROS 2 项目的工作空间:

cd /home/ws/ugv_ws

启动小车驱动节点,保持这个指令的运行:

ros2 launch ugv_bringup bringup_lidar.launch.py use_rviz:=true

此时,机器人云台会转至中位,摄像头面向前方,可以查看到该产品 Rviz2 模型界面,手动旋转小车可以看见模型中也会跟着一起旋转。


10.1.1 前进

接着在一个新的 Docker 容器中,发送小车前进的动作目标,“data”为小车前进的距离,单位为米:

ros2 action send_goal /behavior ugv_interface/action/Behavior "{command: '[{\"T\": 1, \"type\": \"drive_on_heading\", \"data\": 0.5}]'}"

此时小车会前进指令中 data 所设定的距离,可以查看到该产品 Rviz2 模型界面中的模型也会跟着一起前进。

10.1.2 后退

发送小车后退的动作目标,“data”为小车前进的距离,单位为米:

ros2 action send_goal /behavior ugv_interface/action/Behavior "{command: '[{\"T\": 1, \"type\": \"back_up\", \"data\": 0.5}]'}"

此时小车会后退设定的距离,可以查看到该产品 Rviz2 模型界面中的模型也会跟着一起前进。

10.1.3 旋转

发送小车旋转的动作目标("data" 单位 度 正数左转 负数右转 ):

ros2 action send_goal /behavior ugv_interface/action/Behavior "{command: '[{\"T\": 1, \"type\": \"spin\", \"data\": -50}]'}"

此时小车会旋转设定的角度,可以查看到该产品 Rviz2 模型界面中的模型也会跟着一起旋转。

10.1.3 停止

发送小车停止的动作目标:

ros2 action send_goal /behavior ugv_interface/action/Behavior "{command: '[{\"T\": 1, \"type\": \"stop\", \"data\": 0}]'}"

此时小车会停止运动,可以查看到该产品 Rviz2 模型界面中的模型也会跟着停止运动。正常情况下,小车运动完所给定 data 参数的值也会停止运动。


10.2 获取当前点位置

在进行以下教程指令交互之前,需要先开启导航,开启导航前先确定您已经建了一个环境地图,若您没有跟着前面的教程操作下来,则先需要根据 UGV Beast Jetson Orin ROS2 4. 基于激光雷达的二维建图或者 UGV Beast Jetson Orin ROS2 5. 基于深度相机的三维建图任一教程进行建图。

建图完成后,将机器人放置所建地图实际中的位置,机器人需要根据里程计判断是否完成到目标位置的运动,在一个新的容器中运行启动导航的指令:

ros2 launch ugv_nav nav.launch.py use_rviz:=true

该指令中没有指定 use_localization ,默认使用的是基于 AMCL 算法的导航,详情可参考 UGV Beast Jetson Orin ROS2 6. 自动导航部分的教程说明。

在使用指令控制机器人运动至导航点之前,可以先保存几个目标位置为导航点。先获取当前点位置信息:

ros2 topic echo /robot_pose --once


10.3 保存为导航点

将前面获取到的位置信息保存为导航点,下述指令中,data 为导航点名称,可设置为 a~g 之间的任一字母:

ros2 action send_goal /behavior ugv_interface/action/Behavior "{command: '[{\"T\": 1, \"type\": \"save_map_point\", \"data\": \"a\"}]'}"


可以在 RViz 导航界面中通过 “Nav2 Goal” 让机器人运动至下一目标位置,将其保存为下一个导航点。


10.4 运动到导航点

保存好导航点后,发送控制指令让机器人运动到对应导航点,data 为前面所保存的导航点名称:

ros2 action send_goal /behavior ugv_interface/action/Behavior "{command: '[{\"T\": 1, \"type\": \"pub_nav_point\", \"data\": \"a\"}]'}"


保存的导航点信息也会存在 map_points.txt 文件里,该文件位于 /home/ws/ugv_ws/ 目录下。


11. Gazebo 仿真调试

本章主要对机器人仿真调试进行介绍。在我们手边没有实物机器人时,可以通过机器人三维物理仿真平台 Gazebo 来验证机器人算法、架构等。我们提供 Gazebo 机器人模型和完整的功能包用于在虚拟机上仿真调试,帮助用户在开发初期进行系统验证与测试。


11.1 Gazebo 介绍

Gazebo 是一款 3D 动态模拟器,能够准确高效地模拟复杂的室内外环境中的机器人群体。虽然与游戏引擎类似,Gazebo 提供保真度更高的物理模拟,支持复杂的环境和传感器模拟。用户可以创建 3D 模型,设置环境,并模拟各种传感器(如激光雷达、摄像头等)。

Gazebo 仿真平台的主要方面包括:

  • 物理引擎:Gazebo 使用多个物理引擎(如 ODE、Bullet、DART等),提供准确的动力学模拟,能够处理碰撞、摩擦和重力等物理现象。
  • 3D 建模:用户可以使用现有的模型库,或通过软件(如 Blender)自定义创建 3D 模型。这些模型可以是机器人、障碍物或环境元素。
  • 环境设置:Gazebo 允许用户设计复杂的仿真环境,包括城市、室内场景等,可以自由配置地形和光照。
  • 传感器模拟:Gazebo 支持多种传感器类型,如激光雷达、摄像头、IMU 等,能够提供实时数据流,便于算法测试。
  • ROS 集成:与 ROS 的结合使得用户能够轻松地将 Gazebo 作为仿真环境,进行算法开发和测试,支持 ROS 主题和服务。
  • 用户界面:Gazebo 提供直观的图形用户界面,用户可以通过可视化工具实时监控仿真进程,调整参数。


11.2 加载虚拟机镜像

我们提供配置好 Gazebo 仿真、机器人模型和完整的功能包这些软件的 Ubuntu 镜像,方便用户直接进行使用。本教程适用于在 Windows 系统电脑使用虚拟机来加载 Ubuntu 镜像进行 Gazebo 仿真调试。

11.2.1 下载配置好软件的 Ubuntu 镜像

使用我们配置好软件的 Ubuntu 镜像,无需自行再进行 Gazebo 仿真环境的安装配置,根据后续的教程进行该产品的仿真测试。

下载好后进行解压缩,解压缩后所有的文件都是镜像文件,有一些虚拟机的磁盘文件系统不支持 4G 以上的单独文件,因此将配置好的 Ubuntu 镜像分解成了多个文件。

11.2.2 安装 Oracle VM VirtualBox 虚拟机

下载并安装 Oracle VM VirtualBox,这是一款免费的虚拟机软件,可以让你在自己的电脑上运行虚拟操作系统,我们在 Windows 系统电脑上运行虚拟机来安装 Ubuntu 操作系统,接着在 Ubuntu 操作系统上安装配置 ROS2 来控制机械臂。

需要注意的是,虽然 ROS2 有 Windows 的版本,但是 Windows 版本的 ROS2 相关资料并不多,所以我们默认提供虚拟机的方案来运行 ROS2。

点击 Oracle VM VirtualBox 官方下载链接,安装过程很简单,一直点击下一步即可。如果已安装,则跳过这步。


11.3 镜像加载至虚拟机软件

  1. 在左边工具栏处,点击“新建”。

  2. 设置名称,类型设置为“Linux”,版本设置为“Ubuntu(64-bit)”,点击“下一步”。


  3. 内存大小设置为 4096MB,处理器设置为 2 个,接着点击“下一步”。


  4. 选择“不添加虚拟硬盘”,点击“下一步”会显示新虚拟电脑的配置,点击“完成”后弹出警告,点击“继续”。


  5. 选中刚刚创建的虚拟机,选择“设置”。


  6. 选择“存储”,点击控制器最右边的 +号添加虚拟硬盘。


  7. 选择注册,将前面解压缩的 ws.vmdk 镜像文件添加进去后点击右下角的“选择”,确认保存。


  8. 接着选择“显示”,勾选“启用 3D 加速”,勾选后点击“确定”,双击左边你刚刚创建的虚拟电脑就可以运行了。

运行该虚拟机电脑成功,可以根据后面的内容了解使用 Gazebo 仿真完成机器人的控制。


11.4 进入 Docker 容器

在主机终端中,先允许未授权用户访问图形界面,输入指令:

xhost +
【注意:在每次虚拟机重新运行后,需要在 Docker 容器中开可视化,该步骤必须要执行。】

接着执行进入 Docker 容器的脚本:

. ros_humble.sh

输入 1 进入 Docker 容器,进入后用户名会变成 root,如下图。



11.5 加载 Gazebo 机器人模型

该镜像模型默认即为履带型的 UGV Beast,因此我们可以直接加载 Gazebo 仿真环境和 UGV Beast 的机器人模型,且启动相应的 ROS 2 节点:

ros2 launch ugv_gazebo bringup.launch.py

启动需要等待一小段时间,如下图即启动成功,该指令在后续步骤中需要保持运行。



11.6 使用手柄或键盘控制

11.6.1 手柄控制

将手柄接收器接入电脑中,点击 Oracle VM VirtualBox 上方的“设备”→“USB”→带有 XBox 字样的设备名称,该设备名称前出现 √,则代表手柄连接到虚拟机上。

按 Ctrl+Alt+T 打开一个新的终端窗口,执行进入 Docker 容器的脚本,输入 1 进入 Docker 容器:

. ros_humble.sh

在容器中运行手柄控制节点:

ros2 launch ugv_tools teleop_twist_joy.launch.py

接着打开手柄背后的开关,看见手柄上亮红灯之后可以控制机器人模型运动。【标注手柄三个功能键手柄:R下面的那个键锁定or解锁,手柄的摇杆,左摇杆——前进,后退;右摇杆——左转,右转】

通过按 Ctrl+C 可以关闭手柄控制节点。


11.6.2 键盘控制

关闭手柄控制节点,可以接着再运行手柄控制节点的容器终端窗口中来运行键盘控制节点:

ros2 run ugv_tools keyboard_ctrl

保持这个窗口为激活状态(即确保操作按键时位于该终端窗口界面),通过以下按键来控制机器人模型运动:

键盘按键操作描述键盘按键操作描述键盘按键操作描述
字母 U左前进字母 I直前进字母 O右前进
字母 J左转字母 K停止运动字母 L右转
字母 M左后退符号 ,直后退符号 .右后退

通过按 Ctrl+C 可以关闭键盘控制节点。


11.7 建图

11.7.1 二维建图

1. 基于 Gmapping 的二维建图

保持加载 Gazebo 机器人模型的运行,按 Ctrl+Alt+T 打开一个新的终端窗口,执行进入 Docker 容器的脚本,输入 1 进入 Docker 容器:

. ros_humble.sh

在容器中运行启动建图节点:

ros2 launch ugv_gazebo gmapping.launch.py


此时,RViz 界面显示的地图上只会显示出 Gazebo 仿真地图中激光雷达所扫描到的区域,若还有未扫描到的区域需要建图,则可以通过手柄或者键盘控制小车移动来扫描建图。

在一个新的终端窗口,执行进入 Docker 容器的脚本,输入 1 进入 Docker 容器,运行手柄控制或键盘控制节点任意一个:

#手柄控制(确保手柄接收器插入虚拟机中)
ros2 launch ugv_tools teleop_twist_joy.launch.py
#键盘控制(保持运行键盘控制节点处于激活状态)
ros2 run ugv_tools keyboard_ctrl

这样,你就能控制底盘移动,来实现对周边环境的建图了。

建图完,保持建图节点的运行,在一个新的终端窗口,执行进入 Docker 容器的脚本,输入 1 进入 Docker 容器,给地图保存脚本增加可执行权限:

cd ugv_ws/
chmod +x ./save_2d_gmapping_map_gazebo.sh

接着运行地图保存脚本,如下图即地图保存成功:

./save_2d_gmapping_map_gazebo.sh


该脚本里的具体内容为:

cd /home/ws/ugv_ws/src/ugv_main/ugv_gazebo/maps
ros2 run nav2_map_server map_saver_cli -f ./map

执行完上述脚本文件后,会保存一个命名为 map 的 2D 栅格地图,该地图是保存于 /home/ws/ugv_ws/src/ugv_main/ugv_gazebo/maps 目录下,可以在上述目录里看见有两个文件生成,一个是 map.pgm,一个是 map.yaml。

  • map.pgm:这是地图的栅格图(通常是灰度图像文件);
  • map.yaml:这是地图的配置文件。

接着 Gmapping 建图节点可以通过 Ctrl+C 关闭。


2. 基于 Cartographer 的二维建图

保持加载 Gazebo 机器人模型的运行,按 Ctrl+Alt+T 打开一个新的终端窗口,执行进入 Docker 容器的脚本,输入 1 进入 Docker 容器:

. ros_humble.sh

在容器中运行启动建图节点:

ros2 launch ugv_gazebo cartographer.launch.py


此时,RViz 界面显示的地图上只会显示出 Gazebo 仿真地图中激光雷达所扫描到的区域,若还有未扫描到的区域需要建图,则可以通过手柄或者键盘控制小车移动来扫描建图。

在一个新的终端窗口,执行进入 Docker 容器的脚本,输入 1 进入 Docker 容器,运行手柄控制或键盘控制节点任意一个:

#手柄控制(确保手柄接收器插入虚拟机中)
ros2 launch ugv_tools teleop_twist_joy.launch.py
#键盘控制(保持运行键盘控制节点处于激活状态)
ros2 run ugv_tools keyboard_ctrl

这样,你就能控制底盘移动,来实现对周边环境的建图了。

建图完,保持建图节点的运行,在一个新的终端窗口,执行进入 Docker 容器的脚本,输入 1 进入 Docker 容器,给地图保存脚本增加可执行权限:

cd ugv_ws/
chmod +x ./save_2d_cartographer_map_gazebo.sh

接着运行地图保存脚本,如下图即地图保存成功:

./save_2d_cartographer_map_gazebo.sh


该脚本里的具体内容为:

cd /home/ws/ugv_ws/src/ugv_main/ugv_gazebo/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_gazebo/maps/map.pbstream'}"

执行完上述脚本文件后,会保存一个命名为 map 的 2D 栅格地图,该地图是保存于 /home/ws/ugv_ws/src/ugv_main/ugv_gazebo/maps 目录下,可以在该目录里看见有三个文件生成,分别是 map.pgm、map.yaml 和 map.pbstram。

接着 Cartographer 建图节点可以通过 Ctrl+C 关闭。


11.7.2 三维建图

1. 在 RTAB-Map 中可视化

RTAB-Map(Real-Time Appearance-Based Mapping)是一种用于同时定位与建图(SLAM,Simultaneous Localization and Mapping)的开源算法,广泛应用于机器人导航、自动驾驶汽车、无人机等领域。它采用视觉和激光雷达传感器的数据来构建环境地图并进行定位,属于基于回环检测(loop closure detection)的SLAM方法。

保持加载 Gazebo 机器人模型的运行,在容器中启动 RTAB-Map 的可视化节点:

ros2 launch ugv_gazebo rtabmap_rgbd.launch.py

在一个新的 Docker 容器终端中,运行手柄控制或键盘控制节点任意一个:

#手柄控制(确保手柄接收器插入虚拟机中)
ros2 launch ugv_tools teleop_twist_joy.launch.py
#键盘控制(保持运行键盘控制节点处于激活状态)
ros2 run ugv_tools keyboard_ctrl

这样,你就能控制底盘移动,来实现对周边环境的建图了。建图完毕后,直接按 Ctrl+c 退出建图节点,系统将会⾃动保存地图。地图默认保存路径 ~/.ros/rtabmap.db。


2. 在 RViz 中可视化

保持加载 Gazebo 机器人模型的运行,在容器中启动 RTAB-Map 的可视化节点:

ros2 launch ugv_gazebo rtabmap_rgbd.launch.py use_rviz:=true

在一个新的 Docker 容器终端中,运行手柄控制或键盘控制节点任意一个:

#手柄控制(确保手柄接收器插入虚拟机中)
ros2 launch ugv_tools teleop_twist_joy.launch.py
#键盘控制(保持运行键盘控制节点处于激活状态)
ros2 run ugv_tools keyboard_ctrl

这样,你就能控制底盘移动,来实现对周边环境的建图了。建图完毕后,直接按 Ctrl+c 退出建图节点,系统将会⾃动保存地图。地图默认保存路径 ~/.ros/rtabmap.db。


11.8 导航

11.8.1 启动导航

1. 二维地图导航

在启动导航之前,首先先确定您已经建了一个名为 map 的环境地图,若您没有跟着前面的教程操作下来,则先需要根据前面的教程进行建图。

建图完成后,接着启动导航,我们提供了多种自主导航模式,你可以从以下自主导航模式任选一种进行机器人导航。


  • AMCL 算法

Adaptive Monte Carlo Localization(AMCL)是 ROS 2 中的一种基于粒子滤波的定位算法,它使用 2D 激光雷达在给定的已知地图中估计机器人的位置和方向(即姿势)。AMCL 主要用于移动机器人导航,它通过激光传感器(如激光雷达)与现有地图相匹配,推算出机器人在地图中的位置和朝向。其核心思想是通过大量粒子表示机器人的可能位置,并逐步更新这些粒子来缩小机器人的位姿不确定性。

AMCL 的优势:

  • 自适应粒子数:AMCL会根据机器人位置的不确定性动态调整粒子的数量。
  • 适用于动态环境:虽然 AMCL 假设静态环境,但它能在一定程度上处理少量动态障碍物,如行人等移动物体,这使其在实际应用中更加灵活。
  • 可靠的定位能力:AMCL 在已知地图中的定位效果非常可靠,即使机器人位姿初始不确定,它也能够逐渐收敛到正确的位姿。

AMCL 是假设地图已知,不能自己创建地图。且依赖于高质量的静态地图,与传感器数据进行匹配。如果地图和真实环境有较大差异,定位效果会受影响。AMCL 常用于移动机器人自主导航,机器人在导航过程中可以通过 AMCL 确定自己的位姿,依赖已知的地图进行路径规划和避障。

在容器中,启动基于 AMCL 算法的导航,启动成功后可以看见前面所建地图的 RViz 画面:

ros2 launch ugv_gazebo nav.launch.py use_localization:=amcl

接着,你可以根据后续的教程去确定机器人的初始位置。


  • EMCL 算法

EMCL 是 AMCL 的替代 Monte Carlo localization(MCL)包。与 AMCL 不同的是,KLD 采样和自适应 MCL 没有实现。相反,实现了扩展重置和其它功能。EMCL 不完全依赖自适应粒子滤波,而是引入了扩展重置等方法来改善定位性能。EMCL 实现了扩展重置策略,这是一个用于改善粒子集质量的技术,能够更好地处理定位中的不确定性和漂移。

启动基于 EMCL 算法的导航,启动成功后可以看见前面所建地图的 RViz 画面:

ros2 launch ugv_gazebo nav.launch.py use_localization:=emcl

接着,你可以根据后续的教程去确定机器人的初始位置。


  • 基于 Cartographer 的纯定位

Cartographer 是 Google 开源的一个可跨多个平台和传感器配置以 2D 和 3D 形式提供实时同时定位和建图(SLAM)的系统。

Cartographer 系统架构概述:可以看到左边可选的输入有深度信息、里程计信息、IMU数据、固定 Frame 姿态。


更多教程可以参考 官方文档及 项目地址

启动基于 Cartographer 的纯定位,启动成功后可以看见前面所建地图的 RViz 画面:

注意:基于 Cartographer 纯定位的导航模式,必须使用 Cartographer 建图后,才可以进行使用。

ros2 launch ugv_gazebo nav.launch.py use_localization:=cartographer

接着,你可以根据后续的教程去确定机器人的初始位置。


  • DWA 算法

动态窗口算法(Dynamic Window Approaches,DWA)是基于预测控制理论的一种次优方法,因其在未知环境下能够安全、有效的避开障碍物, 同时具有计算量小, 反应迅速、可操作性强等特点。DWA 算法属于局部路径规划算法。

该算法核心思想是根据移动机器人当前的位置状态和速度状态在速度空间 ( v , ω ) 中确定一个满足移动机器人硬件约束的采样速度空间,然后计算移动机器人在这些速度情况下移动一定时间内的轨迹, 并通过评价函数对该轨迹进行评价,最后选出评价最优的轨迹所对应的速度来作为移动机器人运动速度, 如此循环直至移动机器人到达目标点。

启动基于 DWA 算法的导航,启动成功后可以看见前面所建地图的 RViz 画面:

ros2 launch ugv_gazebo nav.launch.py use_localplan:=dwa

接着,你可以根据后续的教程去确定机器人的初始位置。


  • TEB 算法

TEB 全称 Time Elastic Band Local Planner,该方法针对全局路径规划器生成的初始全局轨迹进行后续修正,从而优化机器人的运动轨迹,属于局部路径规划。在轨迹优化过程中,该算法拥有多种优化目标,包括但不限于:整体路径长度、轨迹运行时间、与障碍物的距离、通过中间路径点以及机器人动力学、运动学以及几何约束的符合性。

启动基于 TEB 算法的导航,启动成功后可以看见前面所建地图的 RViz 画面:

ros2 launch ugv_gazebo nav.launch.py use_localplan:=teb

接着,你可以根据后续的教程去确定机器人的初始位置。


2. 三维地图导航

上面介绍的都是基于激光雷达二维建的地图导航模式,根据前面教程所建的三维地图,则参考该小节的导航启动方式。

先开启 nav 定位:

ros2 launch ugv_gazebo rtabmap_localization_launch.py

需要等三维数据加载完毕后,等待一段时间出现如下图所显示的即可开启导航。

在一个新的终端中,开启导航,两种导航模式任选一种即可:

  • DWA 算法
ros2 launch ugv_gazebo nav_rtabmap.launch.py use_localplan:=dwa
  • TEB 算法
ros2 launch ugv_ngazebo nav_rtabmap.launch.py use_localplan:=teb

根据上述所建的地图选择一种导航模式开启导航后,则接着以下内容进行使用。


11.8.2 初始化机器人的位置

默认情况下,启动导航后,机器人最初不知道自己在哪里,地图等待您为其提供大致的起始位置。

首先,找到机器人在地图上的位置,检查你的机器人在实际中的位置。在 RViz 中手动设置机器人的初始位姿。单击 2D Pose Estimate 按钮并在地图上指出机器人的位置。绿色箭头的方向是机器人云台向前所面对的方向。


保持好启动导航终端的运行,设置好机器人大致的初始位姿后,保证导航确保机器人在实际中的位置是大致对应地上的。也可以在一个新终端通过键盘控制小车,进行简单地移动旋转,协助进行初始定位。

ros2 run ugv_tools keyboard_ctrl


11.8.3 发送目标位姿

1. 单点导航

在地图上为机器人选择一个目标位置。您可以使用 Nav2 Goal 工具向机器人发送目标位置和目标方向。在 RViz 地图上指出机器人想要自动导航至的位置(目标点),绿色箭头的方向是机器人云台向前所面对的方向。


设置好目标位姿后,导航将找到全局路径并开始在地图上导航机器人移动到目标位姿。现在,你可以看到机器人向实际中的目标位置移动。


2. 多点导航

观察 RViz 界面中的左下角,有一个 Nav2 的RViz2 小插件【Waypoint/Nav Through Poses Mode】,可以进行导航模式的切换,点击【Waypoint/Nav Through Poses Mode】该按钮即切换至多点导航模式。

接着使用 RViz2 工具栏中的 Nav2 Goal 给定多个要移动的目标点,给定后,还是点击左下角【Start Waypoint Following】开始路径规划导航。机器人会根据所选目标点的先后顺序进行移动,到了第一个目标点后会自动前往下一个目标点,无需再进行操作。到达最后一个目标点后,小车会停止。




[教程导航]