基于树莓派5与PX4飞控的视觉识别无人机开发与部署全流程指南
无人机技术的快速发展和人工智能的结合,赋予了无人机更强的感知能力与智能化功能。本文详细阐述了如何基于树莓派5与PX4飞控开发一套完整的视觉识别无人机系统,包括模型训练、代码实现、硬件部署和运行调试,帮助开发者快速构建功能完善的智能无人机。
视觉识别无人机的开发过程和软硬件架构设计(以 PX4 飞控和树莓派 5 为例)概述:
项目开发流程
1. 需求分析
- 确定应用场景:目标识别(如人、车辆等)、环境感知(如避障、地图构建)或其他任务。
- 明确性能要求:实时性(图像帧率)、精度、飞行稳定性等。
- 定义开发目标:是否需要自主飞行,支持的控制模式(手动、半自动或全自动)。
2. 系统设计
- 飞行控制系统:基于 PX4 飞控的稳定性和扩展性。
- 边缘计算模块:树莓派 5 处理视觉识别任务,提供额外的计算能力。
- 通信机制:PX4 和树莓派之间通过 MAVLink 协议通信。
3. 软硬件准备
硬件:
- 飞控:Pixhawk 系列支持 PX4 固件。
- 计算单元:树莓派 5(支持 Wi-Fi 6、USB 3.0 接口和更高性能的 GPU)。
- 摄像头:支持高分辨率和高速帧率的 USB 摄像头或树莓派相机模块。
- 电源管理模块:提供树莓派和其他传感器所需的稳定电压。
- 机体:四轴或六轴飞行器,搭载足够负载的无刷电机。
软件:
- PX4 固件(飞控)
- 树莓派上的 Linux 系统(如 Raspberry Pi OS)
- 视觉算法:基于 TensorFlow Lite、PyTorch 或 OpenCV 的深度学习模型。
- 通信协议:MAVLink + 自定义脚本。
4. 视觉算法开发
- 数据采集:获取目标场景下的训练数据。
- 数据预处理:包括图像标注、增强和格式转换。
- 模型训练:选择合适的神经网络(如 YOLOv8、MobileNet),并在 GPU 服务器上训练。
- 模型优化:使用 TensorRT 或 ONNX 进行模型量化和加速。
- 部署:将优化后的模型部署到树莓派,验证模型的推理速度和准确性。
5. 系统集成
- PX4 与树莓派通信调试:通过 UART 或 Wi-Fi 使用 MAVLink 协议进行指令传递。
- 数据流整合:摄像头数据实时传输到树莓派,树莓派完成处理后将决策数据发送给 PX4。
- 电源调试:确保飞控和计算单元在飞行过程中供电稳定。
6. 测试与优化
- 室内测试:测试飞行稳定性和视觉算法准确性。
- 室外测试:模拟真实环境,优化目标识别、环境感知和避障算法。
- 飞行时间优化:通过优化任务分配、模型效率和电池管理延长续航时间。
整个项目软硬件架构如下
1. 硬件架构
+--------------------------------+ | 摄像头(USB/CSI接口) | +--------------------------------+ │ │ +--------------------------------+ | 树莓派 5 | | - 摄像头数据采集 | | - 图像处理与目标检测 | | - 决策计算(路径规划等) | | - MAVLink 数据发送 | +--------------------------------+ │ │ UART/Wi-Fi +--------------------------------+ | PX4 飞控(Pixhawk 4等) | | - 姿态稳定控制 | | - 电机控制 | | - 数据接收与飞行任务执行 | +--------------------------------+ │ │ PWM 信号 +--------------------------------+ | 电机+螺旋桨系统 | +--------------------------------+ │ │ 电池 +--------------------------------+ | 电源管理单元(PMU) | +--------------------------------+
2. 软件架构
+-----------------------------------+ | 树莓派(边缘计算) | | - 摄像头驱动 | | - OpenCV 图像处理库 | | - 目标检测算法(TensorFlow Lite) | | - 数据传输模块(MAVLink) | +-----------------------------------+ │ │ UART/Wi-Fi +-----------------------------------+ | PX4 飞控固件 | | - 姿态控制(PID) | | - 飞行模式(Offboard/Auto) | | - MAVLink 接口 | +-----------------------------------+
重点部分和要考虑的内容
视觉算法
- 目标检测:基于 YOLO 系列模型进行实时识别,优化轻量化性能以满足树莓派计算能力。
- 避障算法:利用深度相机或双目相机,结合 SLAM(如 ORB-SLAM2)构建地图并规划路径。
通信协议
- 使用 MAVLink 将树莓派的指令(如目标坐标或飞行路径)发送给 PX4 飞控。
- 通过 PX4 实现姿态控制和路径执行,同时将飞控状态数据反馈到树莓派进行处理。
实时性保障
- 软件优化:在树莓派上使用多线程处理图像数据和通信任务,避免延迟。
- 硬件优化:通过 GPU 加速(如树莓派 5 的 VideoCore VII)提升图像处理速度。
飞行模式
- 初期使用 Offboard 模式,由树莓派发送实时控制指令。
- 后期可集成自主导航功能,实现全自动飞行模式。
安全性设计
- 加入冗余机制:如通信中断时切换到飞控自主模式。
- 设定地理围栏,限制飞行区域。
整个系统的软硬件结构明确以后,接下来我们重点看一下无人机的视觉处理部分是怎么样实现:
下面详细描述如何配置和训练 YOLOv8 的视觉识别模型、数据处理流程、封装与部署方式,以及在树莓派 5 上的调用实现。视觉开发系统环境配置
1. 训练环境
训练模型需要一个性能较强的计算环境,例如支持 GPU 加速的深度学习训练服务器或云端平台。推荐配置:
- 操作系统:Ubuntu 20.04
- GPU:NVIDIA RTX 3080 或更高
- CUDA:>= 11.3
- cuDNN:>= 8.0
- Python:>= 3.8
- 开发库:PyTorch >= 1.13.1,Ultralytics YOLOv8
2. 训练环境搭建
安装 PyTorch 和 YOLOv8:
# 安装 PyTorch 和 GPU 支持 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 安装 Ultralytics 的 YOLOv8 pip install ultralytics
数据准备
1. 训练数据格式
YOLOv8 采用的训练数据格式为 YOLO 格式,包括:
- 图像文件(JPEG/PNG 格式):包含标注目标的图片。
- 标注文件(TXT 格式):与图像文件同名,存储每个目标的边界框和类别信息,格式如下:
<class_id> <x_center> <y_center> <width> <height>
<class_id>
:类别编号,从 0 开始。<x_center>
和<y_center>
:归一化后的目标框中心点坐标(范围为 0~1)。<width>
和<height>
:归一化后的目标框宽度和高度。
2. 数据集组织结构
将数据集整理为以下目录结构:
dataset/ ├── images/ │ ├── train/ # 训练集图片 │ ├── val/ # 验证集图片 ├── labels/ │ ├── train/ # 训练集标签 │ ├── val/ # 验证集标签 ├── data.yaml # 数据集配置文件
data.yaml
配置文件内容示例:
train: dataset/images/train val: dataset/images/val nc: 2 # 类别数量 names: ['class1', 'class2'] # 类别名称
模型训练
1. 运行训练代码
使用 YOLOv8 提供的命令行工具进行训练:
yolo task=detect mode=train model=yolov8n.pt data=dataset/data.yaml epochs=100 imgsz=640
model=yolov8n.pt
:指定模型权重(nano 版,轻量化)。data=dataset/data.yaml
:数据集配置文件路径。epochs=100
:训练轮数。imgsz=640
:输入图像尺寸。
2. 训练完成后输出
训练完成后,权重文件将保存在 runs/detect/train/weights/best.pt
。
模型封装与部署
1. 模型优化与封装
将训练好的 PyTorch 模型转换为轻量化模型(如 ONNX 或 TensorRT 格式)。
安装 ONNX 支持库
pip install onnx onnx-simplifier
转换模型为 ONNX 格式
from ultralytics import YOLO # 加载模型 model = YOLO('runs/detect/train/weights/best.pt') # 导出为 ONNX 格式 model.export(format='onnx')
优化 ONNX 模型
使用 ONNX-Simplifier 优化模型:python -m onnxsim model.onnx model_simplified.onnx
2. 部署到树莓派 5
在树莓派 5 上安装必要的依赖并部署模型:
安装依赖库
sudo apt update && sudo apt install -y libopencv-dev pip install numpy onnxruntime opencv-python
部署模型文件
将model_simplified.onnx
上传到树莓派(通过 SCP 或 U 盘)。
3. 调用方式
以下为模型推理的 Python 实现:
import cv2 import numpy as np import onnxruntime as ort # 加载 ONNX 模型 model_path = 'model_simplified.onnx' #我们训练的模型
session = ort.InferenceSession(model_path) # 输入大小 input_shape = (640, 640) # 加载摄像头 cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() if not ret: break # 预处理:调整大小并归一化 input_image = cv2.resize(frame, input_shape) input_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2RGB) input_image = input_image.astype(np.float32) / 255.0 input_image = np.transpose(input_image, (2, 0, 1)) # HWC to CHW input_image = np.expand_dims(input_image, axis=0) # Add batch dimension # 推理 outputs = session.run(None, {'images': input_image})[0] # 后处理:绘制检测框 for det in outputs: x1, y1, x2, y2, conf, class_id = det if conf > 0.5: # 置信度阈值 cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) cv2.putText(frame, f'Class {int(class_id)}: {conf:.2f}', (int(x1), int(y1) - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) # 显示 cv2.imshow("Detection", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
关于输入输出的说明
输入
- 实时摄像头图像帧或本地图像文件。
- 图像尺寸:
(640, 640)
(根据训练时的输入尺寸调整)。
输出
- 检测框信息:目标的
(x1, y1, x2, y2)
坐标、置信度和类别编号。 - 在图像上显示检测结果,标注目标类别和置信度。
- 检测框信息:目标的
我们再来重硬件结构开始,重新的梳理一遍具体的流程:
接着以树莓派 5 上摄像头对场景进行扫描识别并在识别到指定目标后与 PX4 飞控通信,然后飞到目标上方这样的一个简单的任务来详细描述具体的过程。
摄像头扫描识别的过程
1. 摄像头连接与初始化
树莓派 5 通过 CSI 接口或 USB 接口连接摄像头。
- 使用
cv2.VideoCapture
获取实时视频流。 - 摄像头帧的采样率和分辨率需与模型输入要求一致(例如 640x640)。
2. 实时识别流程
- 采集视频帧:从摄像头读取帧。
- 预处理:对图像进行归一化、尺寸调整以匹配 YOLOv8 的输入格式。
- 推理:使用 ONNX 模型对帧进行目标检测。
- 后处理:解析检测结果,提取目标位置、置信度和类别信息。
代码实现(摄像头扫描识别)
import cv2 import numpy as np import onnxruntime as ort # 加载模型 model_path = 'model_simplified.onnx' session = ort.InferenceSession(model_path) input_name = session.get_inputs()[0].name input_shape = session.get_inputs()[0].shape # 模型输入形状 (1, 3, 640, 640) # 摄像头初始化 cap = cv2.VideoCapture(0) # 0 表示默认摄像头 cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) def preprocess(frame): """将帧处理为模型输入格式""" input_image = cv2.resize(frame, (input_shape[2], input_shape[3])) input_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2RGB) input_image = input_image.astype(np.float32) / 255.0 input_image = np.transpose(input_image, (2, 0, 1)) # HWC to CHW input_image = np.expand_dims(input_image, axis=0) # 添加批次维度 return input_image def postprocess(detections, frame): """解析模型输出并绘制检测结果""" height, width, _ = frame.shape for det in detections: x1, y1, x2, y2, conf, class_id = det if conf > 0.5: # 设置置信度阈值 # 将归一化坐标转换为像素坐标 x1, y1, x2, y2 = int(x1 * width), int(y1 * height), int(x2 * width), int(y2 * height) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(frame, f'Class {int(class_id)}: {conf:.2f}', (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) return frame while True: ret, frame = cap.read() if not ret: break # 图像预处理 input_image = preprocess(frame) # 推理 outputs = session.run(None, {input_name: input_image})[0] # 假设输出在第一个 tensor # 后处理并显示结果 processed_frame = postprocess(outputs, frame) cv2.imshow("Detection", processed_frame) if cv2.waitKey(1) & 0xFF == ord('q'): # 按 'q' 键退出 break cap.release() cv2.destroyAllWindows()
识别目标后向飞控发送指令
1. 与 PX4 飞控通信
树莓派 5 和 PX4 飞控通过 MAVLink 协议 通信。可以使用 pymavlink
库发送和接收控制指令。
- 通过 UART 接口或 Wi-Fi 建立连接。
- 树莓派根据目标检测结果计算目标的像素位置与无人机当前位置的偏移。
- 使用 Offboard 模式发送飞行控制指令,调整无人机飞向目标上方。
2. 代码实现(MAVLink 通信)
以下为检测到目标后,向 PX4 发送飞行指令的实现:
from pymavlink import mavutil # 初始化 MAVLink 连接 connection = mavutil.mavlink_connection('/dev/serial0', baud=57600) # UART 连接 connection.wait_heartbeat() # 等待飞控心跳包 def send_position_target(x, y, z, vx=0, vy=0, vz=0): """发送位置目标指令(Offboard 模式)""" connection.mav.set_position_target_local_ned_send( 0, # 时间戳 connection.target_system, connection.target_component, mavutil.mavlink.MAV_FRAME_LOCAL_NED, 0b110111111000, # 控制掩码(只控制位置和速度) x, y, -z, # 目标位置 (NED 坐标) vx, vy, vz, # 目标速度 0, 0, 0, # 加速度 0, 0 # 偏航角和角速度 ) def calculate_position(offset_x, offset_y, current_altitude): """根据图像目标计算飞行器的移动目标""" # 假设摄像头视野角度和无人机距离目标高度已知 fov = 60 # 摄像头水平视野角度(度) image_width = 640 image_height = 480 fov_per_pixel = fov / image_width # 每像素对应的视野角度 # 计算目标相对于中心的偏移角度 angle_x = offset_x * fov_per_pixel angle_y = offset_y * fov_per_pixel # 根据偏移角度和当前高度,计算目标相对位置 delta_x = current_altitude * np.tan(np.radians(angle_x)) delta_y = current_altitude * np.tan(np.radians(angle_y)) return delta_x, delta_y # 检测到目标时,计算位置并发送指令 if target_detected: offset_x = detected_x - image_width / 2 offset_y = detected_y - image_height / 2 target_x, target_y = calculate_position(offset_x, offset_y, current_altitude=10) # 假设当前高度 10 米 send_position_target(target_x, target_y, z=10)
流程总结
摄像头扫描
- 实时采集视频帧并执行目标检测。
- 如果检测到目标,提取目标的像素坐标。
计算目标偏移
- 计算目标相对无人机中心的偏移角度。
- 根据无人机的飞行高度,将偏移角度转换为实际的地面坐标偏移。
发送飞行指令
- 使用 MAVLink 发送目标位置到 PX4 飞控。
- PX4 根据指令调整无人机的位置,使其飞到目标上方/或者按照其他需要执行其他任务。
经过调试和测试后,接下来就是部署到真机,也就是装机的部分了:
前置准备
开发环境准备
- 确保树莓派 5 的系统已安装最新的 Raspberry Pi OS(支持 Python 环境)。
- 检查摄像头连接是否正常工作:使用
raspistill
或libcamera
测试摄像头。 - 确保 PX4 飞控已配置为接受 MAVLink Offboard 指令。
硬件连接
- 摄像头:连接到树莓派的 CSI 接口或通过 USB 连接。
- 飞控:通过树莓派的 UART 接口连接 PX4 飞控(需启用树莓派的串口)。
- 启用串口:编辑
/boot/config.txt
,添加或解开以下行:enable_uart=1
- 禁用串口登录:运行
sudo raspi-config
,在 Interface Options -> Serial Port 中禁用登录但启用串口硬件。
- 启用串口:编辑
依赖库安装
在树莓派上安装必要的依赖库:sudo apt update sudo apt install -y python3-pip python3-opencv libopencv-dev pip3 install numpy onnxruntime pymavlink
代码部署到树莓派
1. 上传代码和模型到树莓派
将 Python 脚本和 ONNX 模型文件上传到树莓派上的指定目录(例如 /home/pi/drone_project
)。
- 使用 SCP 工具上传:
scp main.py model_simplified.onnx pi@<树莓派IP地址>:/home/pi/drone_project/
2. 编译为可执行程序(可选)
可以使用 pyinstaller
将 Python 脚本打包为可执行文件,以减少运行时依赖:
pip install pyinstaller pyinstaller --onefile main.py
编译成功后,生成的可执行文件会保存在 dist/
目录下(例如 /home/pi/drone_project/dist/main
)。
将编译后的文件上传到树莓派,或直接在树莓派上使用 pyinstaller
进行编译。
运行部署代码
1. 手动运行程序
在树莓派中,通过命令行运行代码以测试:
cd /home/pi/drone_project python3 main.py # 如果使用了 pyinstaller 打包: ./dist/main
2. 运行时验证
- 确认摄像头工作正常:启动程序后应能实时显示检测框。
- 确认 PX4 飞控响应:当检测到目标后,无人机应向目标移动。
将程序设置为开机自启动
为了在无人机上实现自动化部署,可以将程序配置为开机自启动:
1. 创建 Systemd 服务
在树莓派上创建服务文件:
sudo nano /etc/systemd/system/drone_ai.service
文件内容如下:
[Unit] Description=Drone AI Service After=network.target [Service] ExecStart=/usr/bin/python3 /home/pi/drone_project/main.py Restart=always User=pi WorkingDirectory=/home/pi/drone_project StandardOutput=inherit StandardError=inherit [Install] WantedBy=multi-user.target
2. 启用并启动服务
sudo systemctl daemon-reload sudo systemctl enable drone_ai.service sudo systemctl start drone_ai.service
3. 检查运行状态
通过以下命令查看服务状态:
sudo systemctl status drone_ai.service
如果一切正常,程序将在树莓派开机时自动运行。
运行调试与优化
性能优化
- 使用
htop
检查 CPU 和内存占用情况。 - 如果性能瓶颈在于模型推理,可以尝试使用 TensorRT 进一步优化 ONNX 模型(需安装 NVIDIA Jetson 设备或 GPU 支持)。
- 使用
日志与调试
- 在代码中添加日志功能(如
logging
模块)以记录运行信息。 - 在
/var/log/syslog
中查看程序输出日志。
仿真环境验证
1. 测试无人机响应
将无人机飞控切换到 Offboard 模式,运行程序,测试目标检测和飞行指令执行是否正确。
2. 模拟环境测试
使用 PX4 仿真环境(如 Gazebo 或 SITL)验证目标识别和飞行控制逻辑,确保安全。
通过以上步骤,您的 Python 项目可成功部署到树莓派 5 上,并在真机中执行目标检测和无人机飞行控制任务。
当然,除了树莓派5,还有其他的嵌入式平台可以作为智能无人机的大脑,然后3D打印出无人机框架和外壳,就可以实现自己的无人机了
全部 0条评论