随着无人机应用场景的不断拓展,仅依赖GPS和惯性测量单元(IMU)的传统导航方案已无法满足复杂环境下的自主飞行需求。计算机视觉技术为无人机提供了环境感知、目标识别和精确定位的能力。本章将系统介绍视觉SLAM、目标检测、点云处理、视觉避障以及与PX4飞控的视觉导航闭环集成。
本章学习目标:理解SLAM技术原理并能够集成ORB-SLAM3和VINS-Fusion;掌握YOLO系列目标检测在Jetson平台上的部署方法;熟练使用PCL进行点云处理与滤波;设计并实现视觉避障系统;完成PX4视觉导航的闭环集成。
18.1 深度学习目标检测概述
现代目标检测算法主要分为两阶段检测器(Faster R-CNN)和单阶段检测器(YOLO、SSD)。无人机场景的特殊挑战包括小目标检测、运动模糊、光照变化、背景复杂和机载计算资源有限。
• 小目标检测:无人机俯视角度下目标占像素较少
• 运动模糊:无人机快速运动导致图像模糊
• 光照变化:从日出到日落光照条件剧烈变化
• 资源受限:机载计算平台算力有限
18.2 YOLOv4使用与目标物坐标转换
进阶功能------YOLOv4使用与目标物坐标转换
一、功能说明
本节记录在超维空间 M1 机载电脑上,通过 MobaXterm 成功复现 YOLOv4 目标识别与目标物坐标转换 的完整过程。
本次实际实现的功能链路为:
plain
USB摄像头
↓
/usb_cam/image_raw
↓
darknet_ros
↓
YOLOv4 dibiao 模型
↓
识别 landing
↓
/darknet_ros/bounding_boxes
↓
object_darknet
↓
/object_position
↓
输出目标中心 x、y 像素坐标
本次最终已经实际看到:
plain
frame_id: "landing"
point:
x: 479.0
y: 291.0
z: 0.0
下一帧继续输出:
plain
frame_id: "landing"
point:
x: 481.0
y: 292.0
z: 0.0
因此本章功能已经复现成功。
二、当前环境与功能包
机载电脑登录后终端提示:
cwkj@cwkj:~$
ROS 环境:
ROS1 Noetic
工作空间:
/home/cwkj/cwkj_ws
本节主要使用三个功能包:
plain
usb_cam
darknet_ros
object_darknet
本功能只是完成视觉识别和目标中心坐标输出,因此本节不需要启动:
plain
MID360
FAST-LIO
MAVROS
lidar_to_mavros
OFFBOARD
三、MobaXterm 连接
笔记本先连接机载电脑所在网络,然后使用 MobaXterm SSH 登录:
plain
IP:192.168.0.100
用户名:cwkj
登录成功后看到:
cwkj@cwkj:~$
即可开始。
四、加载 ROS 环境
每个新开的 MobaXterm 终端都建议先执行:
source /opt/ros/noetic/setup.bash
作用:加载 ROS1 Noetic。
再执行:
source /home/cwkj/cwkj_ws/devel/setup.bash
作用:加载 M1 自己的 ROS 工作空间,使 ROS 能找到项目中的功能包。
五、检查功能包
检查 USB 摄像头功能包:
rospack find usb_cam
检查 YOLOv4 功能包:
rospack find darknet_ros
检查目标坐标转换功能包:
rospack find object_darknet
本次 <font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">object_darknet</font> 实际路径为:
/home/cwkj/cwkj_ws/src/object_darknet
六、检查 darknet_ros 默认模型
执行:
grep -n "network_param_file" $(rospack find darknet_ros)/launch/darknet_ros.launch
第一次检查时,原机载电脑默认加载的是:
yolov4-tiny-tank.yaml
也就是说,当时默认模型是 <font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">tank</font> 模型。
但本次需要复现的是 <font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">landing</font> 靶标识别,因此需要切换到:
yolov4-tiny-dibiao.yaml
七、检查 dibiao 配置是否存在
执行:
ls $(rospack find darknet_ros)/config
本次实际确认存在:
plain
yolov4-tiny-dibiao.yaml
yolov4-tiny-tank.yaml
yolov4-tiny.yaml
yolov4.yaml
继续查看 dibiao 配置:
cat $(rospack find darknet_ros)/config/yolov4-tiny-dibiao.yaml
实际内容中确认:
plain
config_file:
name: yolov4-tiny-dibiao.cfg
weight_file:
name: yolov4-tiny-dibiao.weights
threshold:
value: 0.2
可识别类别为:
plain
ring
landing
square
所以本次坐标转换使用:
landing
目标。
八、检查 cfg 和 weights 文件
执行:
find $(rospack find darknet_ros) -type f ( -name "dibiao .cfg" -o -name "dibiao.weights" )
本次实际找到:
/home/cwkj/cwkj_ws/src/darknet_ros/darknet_ros/yolo_network_config/weights/yolov4-tiny-dibiao.weights
以及:
/home/cwkj/cwkj_ws/src/darknet_ros/darknet_ros/yolo_network_config/cfg/yolov4-tiny-dibiao.cfg
说明模型结构文件和权重文件都存在,可以正常加载。
九、修改 darknet_ros.launch
打开:
nano $(rospack find darknet_ros)/launch/darknet_ros.launch
找到:
plain
<arg name="network_param_file"
default="$(find darknet_ros)/config/yolov4-tiny-tank.yaml"/>
把:
tank
修改为:
dibiao
最终变成:
plain
<arg name="network_param_file"
default="$(find darknet_ros)/config/yolov4-tiny-dibiao.yaml"/>
保存:
plain
Ctrl + O
Enter
Ctrl + X
检查:
grep -n "network_param_file" $(rospack find darknet_ros)/launch/darknet_ros.launch
应看到:
yolov4-tiny-dibiao.yaml
这里仅修改 Launch 配置,因此:
不需要重新 catkin_make
十、确认 object_darknet 的实际 Launch 文件
执行:
ls $(rospack find object_darknet)
本次实际能看到:
plain
CMakeLists.txt
darknet_ros_msgs
include
launch
lib
msg
package.xml
src
继续:
ls $(rospack find object_darknet)/launch
本次实际只有:
object_darknet.launch
因此正确启动命令是:
roslaunch object_darknet object_darknet.launch
不是:
roslaunch object_darknet darknet_position.launch
后者会报:
plain
RLException:
[darknet_position.launch] is neither a launch file in package [object_darknet]
十一、终端1:启动 USB 摄像头
新开终端1:
plain
source /opt/ros/noetic/setup.bash
source /home/cwkj/cwkj_ws/devel/setup.bash
roslaunch usb_cam usb_cam-test.launch
这个终端保持运行。
临时检查摄像头:
rostopic hz /usb_cam/image_raw
正常应持续出现:
average rate: ...
说明:
plain
USB摄像头
↓
usb_cam
↓
/usb_cam/image_raw
已经正常。
十二、终端2:启动 YOLOv4
新开终端2:
plain
source /opt/ros/noetic/setup.bash
source /home/cwkj/cwkj_ws/devel/setup.bash
roslaunch darknet_ros darknet_ros.launch
此时加载的应是:
plain
yolov4-tiny-dibiao.cfg
+
yolov4-tiny-dibiao.weights
模型能够识别:
plain
ring
landing
square
该终端保持运行。
十三、检查 darknet_ros 是否正常
新开临时终端:
rostopic list | grep darknet
本次实际成功后看到:
plain
/darknet_ros/bounding_boxes
/darknet_ros/check_for_objects/cancel
/darknet_ros/check_for_objects/feedback
/darknet_ros/check_for_objects/goal
/darknet_ros/check_for_objects/result
/darknet_ros/check_for_objects/status
/darknet_ros/detection_image
/darknet_ros/found_object
最关键的是:
/darknet_ros/bounding_boxes
这说明 YOLO 检测结果话题已经建立。
十四、确认 YOLO 识别到 landing
执行:
rostopic echo /darknet_ros/bounding_boxes
将摄像头对准 <font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">landing</font> 靶标。
识别成功时,应看到类似:
plain
Class: "landing"
probability: ...
xmin: ...
ymin: ...
xmax: ...
ymax: ...
只要出现:
Class: "landing"
就说明:
plain
USB摄像头
↓
YOLOv4 dibiao
↓
landing识别
已经成功。
十五、终端3:启动目标坐标转换
新开终端3:
plain
source /opt/ros/noetic/setup.bash
source /home/cwkj/cwkj_ws/devel/setup.bash
roslaunch object_darknet object_darknet.launch
本次实际启动成功后终端显示:
plain
PARAMETERS
* /object_name: landing
* /rosdistro: noetic
* /rosversion: 1.17.4
同时看到:
plain
NODES
/
object_darknet (object_darknet/object_darknet)
以及:
processobject_darknet-1: started with pid ...
说明 <font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">object_darknet</font> 节点已经正常启动。
十六、关于 No object detected
启动 <font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">object_darknet</font> 后,可能看到:
INFO ... No object detected
这不是报错。
它表示:
plain
object_darknet 已经正常运行
但这一帧没有检测到 landing
这时检查:
rostopic echo /darknet_ros/bounding_boxes
确认 YOLO 是否真正输出:
Class: "landing"
十七、终端4:查看最终目标坐标
新开终端4:
plain
source /opt/ros/noetic/setup.bash
source /home/cwkj/cwkj_ws/devel/setup.bash
rostopic echo /object_position
摄像头对准 <font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">landing</font> 靶标。
本次实际已经成功输出:
plain
header:
frame_id: "landing"
point:
x: 479.0
y: 291.0
z: 0.0
下一帧:
plain
header:
frame_id: "landing"
point:
x: 481.0
y: 292.0
z: 0.0
说明:
plain
YOLO识别成功
+
landing筛选成功
+
目标中心计算成功
+
/object_position发布成功
十八、坐标含义
当前输出:
plain
x: 481
y: 292
z: 0
其中:
x
表示目标检测框中心在图像水平方向的像素坐标。
y
表示目标检测框中心在图像垂直方向的像素坐标。
当前:
z = 0
不表示目标距离摄像头为 0 米。
这套普通 USB 单目摄像头程序目前主要用于二维图像目标中心定位,并没有直接得到真实三维距离。
十九、移动目标验证
为了进一步验收,可以保持:
rostopic echo /object_position
持续运行。
把 <font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">landing</font> 靶标向左右移动。
观察:
x
是否跟着变化。
把靶标向上下移动。
观察:
y
是否跟着变化。
如果目标移动时 <font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">x、y</font> 能连续变化,就说明目标坐标转换功能正常。
二十、查看 YOLO 检测画面
如果 MobaXterm 已配置 X11 转发,可以运行:
rqt_image_view
选择:
/darknet_ros/detection_image
用于查看:
plain
摄像头画面
+
YOLO检测框
+
landing目标
这一项属于可视化验证,不是 <font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">/object_position</font> 成功的必要条件。
二十一、断电后固定启动顺序
以后机载电脑断电重启后,之前修改好的 <font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">yolov4-tiny-dibiao.yaml</font> 选择不会丢失。
重新上电后固定使用以下四个终端。
终端1:USB摄像头
plain
source /opt/ros/noetic/setup.bash
source /home/cwkj/cwkj_ws/devel/setup.bash
roslaunch usb_cam usb_cam-test.launch
终端2:YOLOv4
plain
source /opt/ros/noetic/setup.bash
source /home/cwkj/cwkj_ws/devel/setup.bash
roslaunch darknet_ros darknet_ros.launch
终端3:目标坐标转换
plain
source /opt/ros/noetic/setup.bash
source /home/cwkj/cwkj_ws/devel/setup.bash
roslaunch object_darknet object_darknet.launch
终端4:查看目标坐标
plain
source /opt/ros/noetic/setup.bash
source /home/cwkj/cwkj_ws/devel/setup.bash
rostopic echo /object_position
最终再次看到:
plain
frame_id: "landing"
point:
x: ...
y: ...
z: 0.0
即可确认断电后复现恢复成功。
二十二、常见问题
1. darknet_ros 仍加载 tank 模型
检查:
grep -n "network_param_file" $(rospack find darknet_ros)/launch/darknet_ros.launch
如果显示:
yolov4-tiny-tank.yaml
重新改成:
yolov4-tiny-dibiao.yaml
2. YOLO 不识别 landing
检查:
rostopic echo /darknet_ros/bounding_boxes
如果持续:
bounding_boxes: \[\]
检查:
- 是否使用正确的
<font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">landing</font>靶标; - 靶标是否完整;
- 光照是否正常;
- 靶标是否太远;
- 靶标是否在画面中太小;
- 摄像头是否清晰;
<font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">darknet_ros</font>是否加载了 dibiao 模型。
3. 启动 darknet_position.launch 报错
错误:
roslaunch object_darknet darknet_position.launch
正确:
roslaunch object_darknet object_darknet.launch
因为本机实际 Launch 文件就是:
object_darknet.launch
4. object_darknet 显示 No object detected
不是节点启动失败。
先检查:
rostopic echo /darknet_ros/bounding_boxes
确认是否出现:
Class: "landing"
5. /object_position 没有输出
按顺序检查:
plain
1. /usb_cam/image_raw 是否有数据
2. darknet_ros 是否正常运行
3. /darknet_ros/bounding_boxes 是否有 landing
4. object_darknet 是否启动
5. /object_name 是否为 landing
二十三、成功判定标准
本次已经实际满足:
- USB 摄像头正常启动
<font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">/usb_cam/image_raw</font>正常<font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">darknet_ros</font>正常启动<font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">yolov4-tiny-dibiao.yaml</font>已设置<font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">yolov4-tiny-dibiao.cfg</font>存在<font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">yolov4-tiny-dibiao.weights</font>存在- YOLO 能识别
<font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">landing</font> <font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">/darknet_ros/bounding_boxes</font>正常<font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">object_darknet</font>正常启动<font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">/object_name = landing</font><font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">/object_position</font>正常发布<font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">frame_id = "landing"</font><font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">x、y</font>坐标能够持续输出
因此:
"进阶功能------YOLOv4使用与目标物坐标转换"已经完整复现成功。
二十四、下一阶段
本节完成的是:
plain
目标识别
↓
目标中心坐标输出
下一阶段如果继续扩展,可以在 <font style="color:rgb(51, 51, 51);background-color:rgb(243, 244, 244);">/object_position</font> 基础上加入:
plain
MAVROS
↓
无人机运动控制
↓
目标自动对准
↓
精准投放 / 自动降落
这属于下一项功能,不属于本节复现成功的必要内容。
18.3 进阶功能------yolov8使用
本镜像中提供了YoloV8模型,包含基础的目标识别功能。
视频教程:
启动 YoloV8 节点
使用以下 launch 文件启动 YoloV8 节点
c
<?xml version="1.0" encoding="utf-8"?>
<launch>
<!-- false表示使用GPU -->
<param name="use_cpu" value="false"/>
<node pkg="yolov8_ros"
type="yolo_v8.py"
name="yolov8_ros"
output="screen">
<!-- 使用已经验证成功的通用YOLOv8n模型 -->
<param name="weight_path"
value="$(find yolov8_ros)/weights/yolov8n.pt"/>
<!-- USB摄像头图像输入 -->
<param name="image_topic"
value="/usb_cam/image_raw"/>
<!-- 检测框结果输出 -->
<param name="pub_topic"
value="/yolov8/BoundingBoxes"/>
<param name="camera_frame"
value="usb_cam"/>
<param name="visualize"
value="false"/>
<param name="conf"
value="0.3"/>
</node>
</launch>
启动步骤
- 终端1:启动摄像头节点(以 USB 摄像头为例)
c
ssh ubuntu@192.168.100.200
c
roslaunch usb_cam usb_cam-test.launch

**
**2. 终端2:启动 YoloV8 节点:
c
ssh ubuntu@192.168.100.200
c
source ~/venvs/yolov8/bin/activate
c
roslaunch yolov8_ros yolo_v8_coco.launch

**3. 终端3: 启动RQT :
**
c
ssh -Y -C ubuntu@192.168.100.200
c
rqt_image_view

RQT选择正确的话题, 在 rqt_image_view 顶部的话题下拉框中选择:
/yolov8/detection_image
查看处理结果
- **查看视频流: 可以使用
**rqt_image_view**工具查看 YoloV8 处理后的视频流,确保视频流数据已经正确处理。需要选择对应视频话题,这里的是**/yolov8/detection_image**。
****查看识别结果: 可以通过以下命令查看 YoloV8 发布的对象位置信息
****这里的**pub_topic**参数设置为**/yolov8/BoundingBoxes**,因此在终端中可以通过**rostopic echo**命令查看 YoloV8 发布的话题数据。
**
c
rostopic echo /yolov8/BoundingBoxes
- **

**
注意事项
- CPU/GPU 设置:
**use_cpu**参数决定了是否使用 CPU 进行计算。如果您的机器支持 GPU,并且已经正确配置 CUDA 环境,可以将其设置为**false**,以加速模型推理。 - 图像话题 **: 确保
**image_topic**设置为当前摄像头话题。否则,YoloV8 模型将无法从正确的图像流中获取数据进行处理。** - 权重文件: 确保
**weight_path**指向有效的权重文件路径。若需要使用不同的模型版本或自定义权重文件,修改该参数即可。