YOLO 感知与 MLP 八字轨迹控制

本示例通过 ROS 2 接入 OpenHUTB/AirSim,使用 YOLO11n 检测 RGB 图像中的目标,并使用 MLP 控制器跟踪八字轨迹。YOLO 感知与八字轨迹控制分别运行。运行前请完成环境配置。

系统架构

OpenHUTB / AirSim
       ^
       | RPC
       v
+-------------------+
|   airsim_bridge   |
+-------------------+
   |            ^
   |            |
   |            +---------------- /openhutb/cmd_vel
   |
   +-- /openhutb/camera/rgb --> yolo_detector
   |                              |
   |                              +-- /openhutb/detections
   |                              +-- /openhutb/yolo/image
   |
   +-- /openhutb/odom ----------> mlp_controller
                                   ^          |
                                   |          +-- /openhutb/cmd_vel
                                   |
trajectory_target ----------------+
       |
       +-- /openhutb/target
       +-- /openhutb/trajectory_done

YOLO 感知链路与八字轨迹控制链路可以分别运行,也可以通过 main.launch.py 同时启动。

功能与节点

节点 作用 主要输入/输出
airsim_bridge 连接 OpenHUTB/AirSim,将模拟器数据转换为 ROS 2 消息,并执行控制指令 发布图像、里程计;订阅速度指令
yolo_detector 对 RGB 图像执行 YOLO11n 实时目标检测 订阅 /openhutb/camera/rgb;发布检测结果和标注图像
trajectory_target 根据无人机当前位置生成八字形目标轨迹 订阅 /openhutb/odom;发布 /openhutb/target
mlp_controller 根据当前位置、速度和目标点预测速度控制量 订阅里程计与目标点;发布 /openhutb/cmd_vel

主要 ROS 2 话题如下:

话题 消息类型 含义
/openhutb/camera/rgb sensor_msgs/Image OpenHUTB 相机 RGB 图像
/openhutb/odom nav_msgs/Odometry 无人机位置和速度
/openhutb/detections vision_msgs/Detection2DArray YOLO 检测结果
/openhutb/yolo/image sensor_msgs/Image 带检测框的图像
/openhutb/target geometry_msgs/PointStamped 当前八字轨迹目标点
/openhutb/cmd_vel geometry_msgs/Twist 控制器输出的速度指令
/openhutb/trajectory_done std_msgs/Bool 八字轨迹完成标志

MLP 八字轨迹控制

MLP 控制器输入为:[ex, ey, ez, vx, vy, vz]。

其中 ex、ey、ez 为目标位置与当前位置之间的误差,vx、vy、vz 为当前速度。

网络输出为:[vx_cmd, vy_cmd, vz_cmd]。

控制器通过 /openhutb/cmd_vel 发布 geometry_msgs/Twist。

当前 ROS 接口保持 OpenHUTB/AirSim 使用的 NED 坐标约定。轨迹生成器使用无人机开始执行轨迹时的当前高度,不强制跳变到固定高度,从而降低轨迹开始阶段的瞬时垂直误差。

软件包内提供 mlp_controller.pth,其中包含 MLP 网络参数以及运行所需的输入、输出归一化信息。安装 ROS 2 包后,trajectory_control.launch.py 和 main.launch.py 会通过 ROS 2 package share 路径自动定位该模型,通常不需要手动指定路径。

如需重新生成训练数据并训练模型,可执行:

ros2 run openhutb_yolo_mlp_control generate_training_data
ros2 run openhutb_yolo_mlp_control train_mlp

运行方式

运行前先启动 OpenHUTB AIR 模式,并确认 RPC 端口能够访问。

如果是原生 Linux 同机运行:

export AIRSIM_IP=127.0.0.1

如果是 WSL2 连接 Windows 主机上的 OpenHUTB:

export AIRSIM_IP=$(ip route | awk '/default/ {print $3; exit}')

建议在正式启动前执行:

nc -vz "$AIRSIM_IP" 41451
test -f "$HOME/models/yolo11n.pt"

运行 YOLO 感知

在支持 WSLg 或原生 Linux 图形桌面的环境中,优先显示实时 YOLO 检测窗口,便于直接观察目标检测结果:

ros2 launch openhutb_yolo_mlp_control perception.launch.py \
  airsim_ip:="$AIRSIM_IP" \
  model_path:="$HOME/models/yolo11n.pt" \
  show_window:=true

该模式不会接管无人机轨迹控制,只发布相机图像、检测结果和标注后的图像,并显示实时检测窗口。

如果当前环境没有图形界面,例如通过纯 SSH 终端运行,可以关闭窗口显示:

ros2 launch openhutb_yolo_mlp_control perception.launch.py \
  airsim_ip:="$AIRSIM_IP" \
  model_path:="$HOME/models/yolo11n.pt" \
  show_window:=false

仅运行八字轨迹控制

如果无人机已经处于空中,可以关闭自动起飞,并将轨迹数据保存到 ~/openhutb_results:

mkdir -p ~/openhutb_results

ros2 launch openhutb_yolo_mlp_control trajectory_control.launch.py \
  airsim_ip:="$AIRSIM_IP" \
  auto_takeoff:=false \
  figure8_scale:=10.0 \
  figure8_points:=160 \
  use_vertical_control:=true \
  result_dir:="$HOME/openhutb_results"

默认情况下会自动加载软件包中的 models/mlp_controller.pth。轨迹执行过程中,控制器会将目标位置、实际位置、误差和控制指令记录到:~/openhutb_results/eight_trajectory.csv。

轨迹完成后,结束当前 launch 进程,再运行分析脚本生成轨迹图:

python -m openhutb_yolo_mlp_control.analyze_eight_trajectory \
  --csv "$HOME/openhutb_results/eight_trajectory.csv" \
  --outdir "$HOME/openhutb_results/analysis"

分析结果保存在 ~/openhutb_results/analysis,其中主要包括:

trajectory_xy.png
tracking_error.png
path_tracking_error.png

三张图片分别用于观察目标轨迹与实际轨迹的平面形状、离散航点跟踪误差以及连续路径跟踪误差。

一键运行 YOLO + 八字轨迹控制

main.launch.py 会同时启动 OpenHUTB/AirSim ROS 2 桥接、YOLO11n 实时检测、八字形目标轨迹生成和 MLP 轨迹控制器。

mkdir -p ~/openhutb_results

ros2 launch openhutb_yolo_mlp_control main.launch.py \
  airsim_ip:="$AIRSIM_IP" \
  yolo_model_path:="$HOME/models/yolo11n.pt" \
  auto_takeoff:=false \
  figure8_scale:=10.0 \
  figure8_points:=160 \
  result_dir:="$HOME/openhutb_results" \
  show_window:=false

如果希望由系统自动执行起飞流程,可将 auto_takeoff:=true 传给启动文件。

main.launch.py 默认从安装后的 ROS 2 package share 目录读取 models/mlp_controller.pth,因此 MLP 模型路径不依赖启动命令所在的当前目录。

可通过以下命令查看 launch 支持的参数:

ros2 launch openhutb_yolo_mlp_control main.launch.py --show-args

ROS 2 节点与话题检查

完整系统启动后,可在另一个已经加载 ROS 2 工作空间的终端中执行:

ros2 node list
ros2 topic list

正常情况下可以看到:

/airsim_bridge
/yolo_detector
/trajectory_target
/mlp_controller

检查主要话题频率:

ros2 topic hz /openhutb/odom
ros2 topic hz /openhutb/camera/rgb
ros2 topic hz /openhutb/target
ros2 topic hz /openhutb/cmd_vel

查看 YOLO 检测消息:

ros2 topic echo /openhutb/detections

轨迹结果与分析

mlp_controller 会在 result_dir 中生成:eight_trajectory.csv。

CSV 记录目标位置、实际位置、位置误差和控制指令等信息。

轨迹分析脚本支持 --csv 和 --outdir 参数:

python -m openhutb_yolo_mlp_control.analyze_eight_trajectory \
  --csv ~/openhutb_results/eight_trajectory.csv \
  --outdir ~/openhutb_results/analysis

分析脚本会生成:

trajectory_xy.png
tracking_error.png
path_tracking_error.png
trajectory_stats.json
trajectory_report.txt

其中:

  • trajectory_xy.png:目标八字轨迹与实际飞行轨迹对比;
  • tracking_error.png:当前位置到当前离散 waypoint 的误差;
  • path_tracking_error.png:当前位置到完整理想八字轨迹最近线段的距离;
  • trajectory_stats.json:轨迹统计数据;
  • trajectory_report.txt:实验统计报告。

tracking_error.png 会受到 waypoint 切换影响,因此可能出现周期性峰值。评价连续路径跟踪质量时,可以结合 trajectory_xy.png 和 path_tracking_error.png 观察整体轨迹形状与连续路径偏差。

实验效果

八字形目标轨迹与实际轨迹

下图对比目标八字形路径和无人机实际路径,用于观察轨迹形状和整体跟踪效果。

八字形目标轨迹与实际轨迹

航点跟踪误差

下图表示无人机当前位置到当前离散 waypoint 的距离。轨迹目标从一个 waypoint 切换到下一个 waypoint 时,误差可能发生跳变。

航点跟踪误差

连续路径跟踪误差

下图计算实际位置到完整理想八字轨迹最近线段的距离。相比离散 waypoint 误差,该指标能够减少 waypoint 切换造成的误差跳变,更适合观察连续路径跟踪偏差。

连续路径跟踪误差

OpenHUTB + YOLO 实时检测

下图展示 OpenHUTB 相机图像经过 YOLO11n 后的实时检测效果。检测窗口可以显示 FPS、YOLO 推理耗时、OpenHUTB/AirSim 图像获取耗时、检测目标数量和推理设备等运行信息。

OpenHUTB 与 YOLO 实时检测

OpenHUTB 控制接口说明

当前实现中,airsim_bridge 对外保持标准的 geometry_msgs/Twist 速度控制接口。桥接层负责将 ROS 2 控制指令转换为 OpenHUTB/AirSim 可以执行的控制调用。

因此控制器只依赖 /openhutb/odom、/openhutb/target 和 /openhutb/cmd_vel 等 ROS 2 接口。后续如果替换控制后端,主要调整桥接层即可,不需要改变 MLP 控制节点的 ROS 2 接口。

软件包结构

openhutb_yolo_mlp_control/
├── package.xml
├── setup.py
├── setup.cfg
├── requirements.txt
├── README.md
├── config/
│   └── openhutb_ros.yaml
├── launch/
│   ├── main.launch.py
│   ├── perception.launch.py
│   └── trajectory_control.launch.py
├── models/
│   └── mlp_controller.pth
├── resource/
│   └── openhutb_yolo_mlp_control
├── tools/
│   └── vendor_openhutb_pythonclient.ps1
└── openhutb_yolo_mlp_control/
    ├── __init__.py
    ├── airsim_bridge_node.py
    ├── yolo_node.py
    ├── trajectory_target_node.py
    ├── mlp_control_node.py
    ├── mlp_model.py
    ├── generate_training_data.py
    ├── train_mlp.py
    ├── evaluate_trajectories.py
    ├── analyze_eight_trajectory.py
    └── vendor/

常见问题

ConnectionRefusedError: [Errno 111] Connection refused

该错误表示 airsim_bridge 已经尝试建立 TCP/RPC 连接,但目标地址的 41451 端口没有接受连接。

先检查当前使用的地址:

echo "$AIRSIM_IP"
nc -vz "$AIRSIM_IP" 41451

如果 ROS 2 运行在 WSL2、OpenHUTB 运行在 Windows,不要只根据默认参数假定 127.0.0.1 可以访问 Windows 侧服务。可以重新获取 WSL2 默认网关:

export AIRSIM_IP=$(ip route | awk '/default/ {print $3; exit}')
nc -vz "$AIRSIM_IP" 41451

仍然无法连接时,应确认:

  • OpenHUTB 已经进入 AIR 模式并完成加载;
  • Windows 防火墙允许对应网络上的 RPC 连接;
  • 端口 41451 没有被其他程序占用;
  • WSL2 与 Windows 主机之间网络可达。

YOLO 启动时尝试联网下载并出现 403 Forbidden

如果日志中出现类似:

Loading YOLO model: yolo11n.pt
Download failure ... 403 Client Error: Forbidden

通常表示本地没有找到 yolo11n.pt,Ultralytics 随后尝试从网络自动下载模型,但当前网络无法访问下载地址。

先检查本地模型:

ls -lh ~/models/yolo11n.pt

然后显式传入本地绝对路径:

ros2 launch openhutb_yolo_mlp_control main.launch.py \
  airsim_ip:="$AIRSIM_IP" \
  yolo_model_path:="$HOME/models/yolo11n.pt" \
  show_window:=false

建议不要依赖运行时自动下载模型。

YOLO 模型可以找到,但节点仍无法加载

可以在当前虚拟环境中单独测试模型加载:

python - <<'PY'
from pathlib import Path
from ultralytics import YOLO

path = Path.home() / "models" / "yolo11n.pt"
YOLO(str(path))
print(f"YOLO model loaded successfully: {path}")
PY

如果这里仍然报错,应优先检查当前虚拟环境中的 torch、ultralytics 版本以及模型文件是否完整。

WSL2 中无法显示 YOLO OpenCV 窗口

检测本身不依赖 GUI。没有 WSLg 或图形转发环境时,使用:show_window:=false。

仍可通过 ROS 2 的 /openhutb/yolo/image 话题获取标注图像。

MLP 控制器找不到模型

正常安装后,launch 文件会自动加载软件包中的 models/mlp_controller.pth。可检查 ROS 2 是否已经找到该包:

ros2 pkg prefix openhutb_yolo_mlp_control

如果刚修改过 setup.py、模型文件或安装配置,应重新构建:

colcon build \
  --packages-select openhutb_yolo_mlp_control \
  --symlink-install
source install/setup.bash

无人机已经起飞但启动后再次执行起飞动作

启动时使用:auto_takeoff:=false。

航点误差存在周期性峰值

tracking_error.png 记录当前位置到当前离散 waypoint 的距离,目标点切换时可能产生跳变。连续轨迹跟踪效果可以结合 path_tracking_error.png 和 XY 轨迹图进行判断。

返回文档目录。

说明

本文档整理、代码重构和问题排查过程中使用了大模型辅助;提交者已检查全部内容并对最终结果负责。