使用mavros启动多机SITL仿真
为多个PX4 SITL无人机分别启动各自的 mavros 实例进行通信。每架无人机都用一组不同的 UDP 和 TCP 端口进行连接。我们只需要为每架无人机配置一组唯一的 fcu_url 来启动多个 mavros 节点。
方式1:使用roslaunch一键启动
Step1:创建一个新的 ROS 包或放到现有包里
cd ~/catkin_ws/src
catkin_create_pkg my_multi_mavros
mkdir -p my_multi_mavros/launch
cd ~/catkin_ws/src/my_multi_mavros/launch
touch multi_mavros.launch
Step2:编辑 multi_mavros.launch
<launch>
<!-- UAV1 -->
<group ns="uav1">
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="udp://:20101@127.0.0.1:20100"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="1"/>
</include>
</group>
<!-- UAV2 -->
<group ns="uav2">
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="udp://:20103@127.0.0.1:20102"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="2"/>
</include>
</group>
<!-- UAV3 -->
<group ns="uav3">
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="udp://:20105@127.0.0.1:20104"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="3"/>
</include>
</group>
<!-- UAV4 -->
<group ns="uav4">
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="udp://:20107@127.0.0.1:20106"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="4"/>
</include>
</group>
</launch>
Step3:构建工作空间并 source 环境
cd ~/catkin_ws
catkin_make
source devel/setup.bash
Step4:构建工作空间并 source 环境
roslaunch my_multi_mavros multi_mavros.launch

方式2:启动单架无人机 MAVROS
也可以单独启动 MAVROS 实例,比如:
roslaunch mavros px4.launch fcu_url:=udp://:20101@127.0.0.1:20100 \
__ns:=uav1 tgt_system:=1
roslaunch mavros px4.launch fcu_url:=udp://:20103@127.0.0.1:20102 \
__ns:=uav2 tgt_system:=2
roslaunch mavros px4.launch fcu_url:=udp://:20105@127.0.0.1:20104 \
__ns:=uav3 tgt_system:=3
roslaunch mavros px4.launch fcu_url:=udp://:20107@127.0.0.1:20106 \
__ns:=uav4 tgt_system:=4
问题1: PX4 SITL 启动时日志里写的是 17541/16541,那为什么 mavros 的 fcu_url 要用 20100/20101 而不是 17541/16541?
20100 和 20101 是你自己在仿真系统(例如Gazebo )中 人为分配给 MAVROS 与 PX4 通信的中间桥接端口对,它们并不等于 PX4 SITL 启动时用的 17541/16541 内部端口。
问题2: 为什么 uav1 用的是 20101/20100,而 uav2 用的是 20103/20102?为什么不是 20101/20100 和 20102/20101?
启动时已经为每架 MAVROS 与 PX4 的通信创建了一对端口:一个接收端(MAVROS本地端口)+一个发送端(PX4目标端口)。
端口增加“2”其实是人为设计的一种“互不冲突 + 成对编号”的方式 —— 每架无人机占用两个连续端口,一个作为收,一个作为发。
✅ MAVROS 与 PX4 通信是双向的:需要两个端口
fcu_url:=udp://:20101@127.0.0.1:20100
含义是:
- MAVROS 接收数据:监听
20101(MAVROS本地UDP接收端) - MAVROS 发送数据:发到 PX4 的
127.0.0.1:20100
所以:
PX4要配置为 将 MAVLink 数据发到20101PX4要监听20100来接收来自 MAVROS 的数据
这对端口从 MAVROS 视角是:
本地:20101 ← PX4:20100
问题1: WSL 与 NX 的运行环境或网络配置存在差异
在 WSL 中可以同时启动 4 个 roslaunch(即 4 个 MAVROS 实例),但在 NX(NVIDIA Jetson)上只能启动 1 个,这说明 WSL 与 NX 的运行环境或网络配置存在差异。
排查方案:
在 NX 上查看端口使用情况:
sudo netstat -anu | grep 201
或者使用:
sudo lsof -iUDP -P | grep 201
看是否端口已被占用。
结果显示没有任何输出
都没有任何输出,说明当前系统:
- 没有任何进程监听或占用
20100、20101、20102、20103等 MAVROS/PX4 的 UDP 端口。 - 所以“端口占用或冲突”不是无法同时启动多个 MAVROS 的根本原因。
接下来进入 第二阶段排查:
步骤 1:确认 PX4 SITL 是否给每个 MAVROS 实例发包
在 Jetson 上可以使用 tcpdump 来监听 loopback(127.0.0.1)上的 MAVLink 流量:
sudo apt update
sudo apt install tcpdump
sudo tcpdump -i lo udp port 20100 or port 20102
然后尝试启动其中一个 MAVROS 实例,例如:
roslaunch mavros px4.launch fcu_url:=udp://:20101@127.0.0.1:20100 __ns:=uav1
观察是否有数据包在收发。抓包结果如下:
localhost.20101 > localhost.20100: UDP, length 28
...
这说明PX4 正在不断地向 20100 接收数据,来自 MAVROS 的 20101 端口
这意味着:
- MAVROS 正常启动了,并在
20101发数据。 - PX4 正常监听了
20100,并收到了这些 MAVLink 数据包。 - PX4 的 UDP 输入没问题,MAVROS 发包正常。
但问题来了,监听的是:
sudo tcpdump -i lo udp port 20100 or port 20102
说明并没有看到 PX4 发回给 MAVROS 的包(比如 localhost.20100 > localhost.20101),这说明:
PX4 只收了 MAVROS 发的包,但没有回发心跳等响应包
问题2:MAVROS 一直在等待心跳
MAVROS卡在:
MAVROS started. MY ID 1.240, TARGET ID 3.1
(表示它在等待心跳,但 PX4 根本没发)
最终解决方案:
执行完 mavros.py 后再启动 roslaunch
mavros.py通知了 PX4 开启了 UDP 回传;- PX4 开始向 Jetson 的某个端口发 MAVLink 心跳;
- 此时再
roslaunchMAVROS,它就能接收到心跳并完成握手。
mvros.py是一个自定义的py程序,用于开启UDP回传。MAVROS 实际上依赖 mavros.py 激活 PX4 的 UDP 通道与通信模式,否则 PX4 根本不会发送任何 MAVLink 包给 MAVROS。
104




被折叠的 条评论
为什么被折叠?



