三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

告别单机调试:ROS1多机协同实战,让机器人A控制机器人B运动(基于Wheeltec底盘案例)

告别单机调试:ROS1多机协同实战,让机器人A控制机器人B运动(基于Wheeltec底盘案例)

ROS1多机协同实战:用主机控制从机底盘运动(Wheeltec案例)

第一次看到两台机器人像跳探戈一样默契配合时,那种震撼感至今难忘。作为从单机ROS开发转向多机协同的必经之路,让主机远程控制从机底盘运动看似简单,却藏着不少"坑"。本文将手把手带你完成这个经典Demo——用一台机器人的速度指令控制另一台Wheeltec底盘的运动,同时用Rviz实时监控双机状态。

1. 多机协同的基础准备

在开始编码之前,我们需要确保硬件和网络环境就绪。不同于单机开发,多机协同对网络配置的稳定性要求更高。根据实测经验,建议使用千兆路由器组建局域网,避免使用无线中继等不稳定连接方式。

1.1 硬件连接与网络配置

两台Wheeltec机器人需要连接到同一个局域网。推荐以下检查清单:

  • 物理连接:使用网线直连路由器,比Wi-Fi更稳定
  • IP分配:建议为每台机器设置静态IP,避免DHCP变动导致连接中断
  • 基础工具:确保每台机器安装net-tools和openssh-server
# 检查网络接口(两台机器分别执行) ifconfig | grep "inet " # 测试双向连通性(在主机执行) ping 192.168.1.2 # 从机IP

1.2 系统级配置

修改/etc/hosts文件是常被忽视的关键步骤。两台机器都需要添加对方的IP和主机名映射:

# 主机/etc/hosts添加 192.168.1.2 slave-bot # 从机/etc/hosts添加 192.168.1.1 master-bot

验证配置是否生效:

# 在主机执行 ping slave-bot # 在从机执行 ping master-bot

2. ROS环境搭建与Master配置

ROS1采用中心化的Master节点架构,这是多机通信的核心。我们的配置原则是:主机作为Master,从机作为Client。

2.1 主从机环境变量设置

在主机(Master)的~/.bashrc中添加:

export ROS_MASTER_URI=http://$(hostname -I | awk '{print $1}'):11311 export ROS_IP=$(hostname -I | awk '{print $1}')

在从机的~/.bashrc中则指向主机的IP:

export ROS_MASTER_URI=http://192.168.1.1:11311 # 主机IP export ROS_IP=$(hostname -I | awk '{print $1}')

注意:每次修改.bashrc后需要执行source ~/.bashrc或重新打开终端

2.2 验证ROS Master状态

在主机启动roscore:

roscore

在从机检查连接状态:

rostopic list # 应该能看到/rosout等默认话题

常见问题排查表:

现象可能原因解决方案
从机无法获取话题列表防火墙阻挡sudo ufw allow 11311
延迟高网络带宽不足改用有线连接或升级路由器
时断时续IP冲突检查DHCP范围与静态IP设置

3. 底盘控制话题的重映射实战

Wheeltec底盘通常订阅/cmd_vel话题接收运动指令。多机控制的关键在于:让从机订阅主机发布的控制话题。

3.1 主机控制节点配置

在主机创建发布速度指令的节点:

#!/usr/bin/env python import rospy from geometry_msgs.msg import Twist def controller(): pub = rospy.Publisher('/master/cmd_vel', Twist, queue_size=10) rospy.init_node('master_controller', anonymous=True) rate = rospy.Rate(10) # 10Hz while not rospy.is_shutdown(): cmd = Twist() cmd.linear.x = 0.2 # 前进速度0.2m/s cmd.angular.z = 0.5 # 旋转速度0.5rad/s pub.publish(cmd) rate.sleep() if __name__ == '__main__': try: controller() except rospy.ROSInterruptException: pass

3.2 从机启动文件修改

修改从机的bringup.launch文件,添加话题重映射:

<launch> <node pkg="turn_on_wheeltec_robot" type="wheeltec_robot_node" name="wheeltec_robot" output="screen"> <remap from="/cmd_vel" to="/master/cmd_vel"/> </node> </launch>

关键参数说明:

  • remap:将本地/cmd_vel重映射到主机发布的/master/cmd_vel
  • output="screen":方便调试时查看节点输出

4. 可视化监控与调试技巧

同时观察两台机器人的状态是调试的关键。Rviz配合tf变换可以完美实现这个需求。

4.1 统一坐标系设置

在两台机器人的URDF或启动文件中,确保使用相同的全局坐标系:

<!-- 主机和从机的launch文件都添加 --> <param name="tf_prefix" value="master"/> <!-- 主机 --> <param name="tf_prefix" value="slave"/> <!-- 从机 -->

4.2 Rviz多机显示配置

在主机上启动Rviz并添加以下显示项:

  1. RobotModel:分别添加主机和从机的描述文件路径
  2. TF:勾选"Show Names"查看坐标系前缀
  3. MarkerArray:如需显示传感器数据

调试时常用的命令组合:

# 在主机终端1:启动Master roscore # 终端2:启动主机底盘节点 roslaunch turn_on_wheeltec_robot turn_on_wheeltec_robot.launch # 终端3:启动控制节点 rosrun your_pkg master_controller.py # 在从机终端: roslaunch turn_on_wheeltec_robot bringup.launch

4.3 网络延迟优化

实测中发现,当控制指令频率超过20Hz时,网络延迟会影响控制精度。推荐以下优化措施:

  • 使用rostopic hz /master/cmd_vel监控实际发布频率

  • 在QoS配置中启用tcp_nodelay:

    pub = rospy.Publisher('/master/cmd_vel', Twist, queue_size=1, tcp_nodelay=True)
  • 考虑使用topic_tools中的throttle节点控制带宽

5. 进阶:多机协同的扩展应用

基础Demo跑通后,可以尝试以下扩展场景:

5.1 双向通信实现

让从机将传感器数据回传给主机:

<!-- 在从机launch文件中添加 --> <node pkg="topic_tools" type="relay" name="scan_relay" args="/scan /slave/scan"/>

5.2 动态参数调节

使用rqt_reconfigure动态调整控制参数:

# 在主机控制节点中添加 from dynamic_reconfigure.server import Server from your_pkg.cfg import ControllerConfig def callback(config, level): global speed_factor speed_factor = config.speed_scale return config srv = Server(ControllerConfig, callback)

5.3 异常处理机制

为网络中断添加容错处理:

def check_connection(): try: rospy.wait_for_message('/master/cmd_vel', Twist, timeout=1) return True except: return False # 在控制循环中添加 if not check_connection(): emergency_stop()

最后分享一个实用技巧:在长期运行的多机系统中,使用chrony同步两台机器的时间可以避免很多奇怪的时序问题。配置成功后,两台机器的时间差应小于1毫秒:

# 在两台机器上执行 sudo apt install chrony sudo service chrony restart ntpq -p
← 返回列表