一路踩坑,一路填坑。当虚拟机Ubuntu里的RViz终于看到RDK X5传来的摄像头画面,当两个海龟在重映射下翩翩起舞------那种成就感,值得记录下来。
一、分布式通信:把Windows、虚拟机、RDK X5连成一张网
1.1 网络拓扑
- 宿主机:Windows(192.168.0.102)
- 虚拟机:Ubuntu 22.04(192.168.0.101,桥接模式)
- 物理设备:RDK X5(192.168.0.104)
三者都在同一网段(192.168.0.x/24),通过路由器互联。
1.2 关键步骤:桥接 + 环境变量
-
虚拟机网络改为桥接模式(不要用NAT),并桥接到宿主机的物理网卡。
-
测试连通性 :
bashping 192.168.0.104 # 虚拟机 ping RDK X5 -
统一ROS_DOMAIN_ID (例如31):
bashexport ROS_DOMAIN_ID=31 export ROS_LOCALHOST_ONLY=0 export ROS_IP=192.168.0.101 # 每台设备填自己的IP -
验证发现 :
bashros2 node list # 应该能看到所有设备的节点
💡 成就感来源:第一次在虚拟机里
ros2 node list看到RDK X5的摄像头节点,就知道网络真的通了。
1.3 DDS内部机制
DDS(Data Distribution Service)是ROS2的通信骨架,它通过Domain ID 隔离网络,通过QoS 控制可靠性。当两台设备的Domain ID相同,DDS的参与者发现协议会自动寻找对方并建立连接。相当于机器人的神经网络。

二、Launch文件:没有class,只有一个函数,它是如何被调用的?
许多初学者看到launch.py文件里只有一个generate_launch_description()函数,没有类,会疑惑:这是怎么被执行的?
2.1 调用原理
ros2 launch命令会:
- 将你的
.launch.py文件作为Python模块导入。 - 在模块中查找固定名称 的函数
generate_launch_description。 - 调用该函数,获取返回的
LaunchDescription对象。 - 根据描述对象执行节点启动、参数设置等操作。
所以,不需要类,只需要这个约定好的函数名。
python
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description(): # 固定函数名
return LaunchDescription([
Node(package='turtlesim', executable='turtlesim_node'),
])
2.2 为什么这样设计?
- 约定优于配置:避免复杂的继承体系,简单直接。
- 灵活性 :你可以在函数内部写任何Python逻辑(循环、条件、读取文件等)来动态生成
LaunchDescription。
三、资源重映射:让海龟模仿另一只海龟
3.1 场景需求
启动两只小海龟,让第二只完全跟随 第一只的运动轨迹。这需要mimic节点将海龟1的位姿话题重映射到海龟2的速度控制话题。
3.2 错误命令 vs 正确命令
古月老师的21讲中,命令可能有笔误。实际正确的启动方式如下:
bash
# 启动launch文件(注意包名是learning_launch,不是learning_topic)
ros2 launch learning_launch remapping.launch.py
# 然后发布速度指令(注意话题名)
ros2 topic pub --rate 1 /turtle1/cmd_vel geometry_msgs/msg/Twist \
"{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
# 如果需要直接控制第一只海龟(mimic示例中可能是/turtlesim1/turtle1/cmd_vel)
ros2 topic pub /turtlesim1/turtle1/cmd_vel geometry_msgs/msg/Twist \
"{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
3.3 重映射的含义
在mimic节点的launch配置中:
python
remappings=[
('/input/pose', '/turtlesim1/turtle1/pose'), # 订阅海龟1的位置
('/output/cmd_vel', '/turtlesim2/turtle1/cmd_vel') # 发布速度给海龟2
]
这样,mimic节点内部虽然写着/input/pose和/output/cmd_vel,但实际上已经被"重定向"到了真实的话题。
四、虚拟机性能优化:告别卡顿和发热
在虚拟机中同时运行Gazebo和RViz2,很容易导致电脑发烫、风扇狂转。经过多次尝试,以下方法最有效:
4.1 环境变量(软件渲染)
bash
export LIBGL_ALWAYS_SOFTWARE=1
export SVGA_VGPU10=0
建议写入~/.bashrc,让Gazebo和RViz2使用CPU渲染,避免虚拟显卡冲突。
4.2 虚拟机设置
- CPU核心数:2~4个(不是越多越好,反而减少宿主机调度压力)
- 内存:4~6GB(不必超过8GB)
- 关闭3D加速:在虚拟机显示设置中取消勾选"加速3D图形"
4.3 模型库离线下载
Gazebo首次启动会自动下载模型(~/.gazebo/models/),网络差时易失败。手动克隆完整模型库:
bash
cd ~/.gazebo
git clone https://github.com/osrf/gazebo_models.git models
五、我的学习笔记(第12-21讲核心速记)
| 讲数 | 主题 | 关键点 |
|---|---|---|
| 12 | DDS | Domain ID、QoS、发现机制 |
| 13 | 通信接口 | 话题、服务、动作 |
| 14 | 参数 | 动态参数、yaml配置文件 |
| 15 | Launch | 多节点启动、参数传递、包含关系 |
| 16 | TF | 四元数与欧拉角、静态/动态广播、监听 |
| 17 | URDF | link、joint、惯性参数、碰撞模型 |
| 18 | Gazebo | 模型库、spawn、物理仿真、虚拟机优化 |
| 19 | RViz2 | 可视化机器人模型、TF、图像 |
| 20 | RQT | 图形化调试:rqt_graph、rqt_console |
六、踩坑与解决(真实案例)
6.1 分布式通信失败
- 现象 :
ros2 node list看不到对方节点。 - 解决 :检查桥接模式、
ROS_DOMAIN_ID一致、关闭防火墙、ROS_LOCALHOST_ONLY=0。
6.2 虚拟机Gazebo无模型
- 原因 :缺少URDF中的
<inertial>标签,或模型库未下载。 - 解决 :为每个
<link>添加质量和惯量,手动下载模型库。
6.3 电脑过热
- 原因:同时运行Gazebo和RViz2,且虚拟机开启了3D加速。
- 解决:使用软件渲染、降低虚拟机资源、分时运行(只开RViz2,Gazebo远程跑)。
6.4 Launch文件找不到
- 原因 :包名或可执行文件名写错,比如
learning topic多了空格。 - 解决 :检查
package=和executable=,注意下划线和空格。
七、成就感时刻
当你在虚拟机Ubuntu中,通过桥接网络,成功ping通RDK X5;
当你设置好ROS_DOMAIN_ID,在虚拟机里ros2 node list看到/camera_node;
当你运行ros2 run image_view image_view --ros-args -r image:=/image_raw/compressed,弹窗里出现实时画面------那种"通了!"的感觉,就是学ROS2最幸福的瞬间。

学习过程难免遇到各种坑,但每一个坑都是进步的阶梯。希望这篇博客能帮你少走一些弯路。
如果觉得有用,欢迎点赞、收藏、评论交流~