摘要:如果你曾经尝试构建搭载计算机视觉的自主系统,你就会知道入门有多么困难。当平台是空中平台时,例如FPV无人机或飞机,难度会更大——飞行过程中的任何失误都可能导致坠机和严重损坏。相比之下,使用像Rover这样的地面机器人平台就可以消除这些风险。由于它始终停留在地面
译者 | 朱先忠
审校 | 重楼
LOONARR-1搭载ArduRover
如果你曾经尝试构建搭载计算机视觉的自主系统,你就会知道入门有多么困难。当平台是空中平台时,例如FPV无人机或飞机,难度会更大——飞行过程中的任何失误都可能导致坠机和严重损坏。相比之下,使用像Rover这样的地面机器人平台就可以消除这些风险。由于它始终停留在地面上,因此你可以安全地调试和开发自动驾驶仪或其他功能,风险要低得多。
在本文中,我将提供一份全面的搭建试验指南,教你如何从零开始构建一台漫游车,并将自动驾驶仪与计算机视觉集成,用于地面目标跟踪。在本试验中,我们将使用ArduRover固件、MAVLink协议、配套计算机(Raspberry Pi 5)以及OpenCV和YOLO进行物体检测(识别)。
一般设计方案
漫游车运行ArduRover固件,并使用树莓派(RaspberryPi)作为配套计算机。连接到树莓派的摄像头可捕捉图像,用于基于人工智能的自主导航。在跟随模式下,漫游车的自动驾驶仪采用YOLO计算机视觉模型进行目标检测(识别),计算目标在NED坐标系中的位置,然后跟随目标。一旦漫游车足够接近目标,它就会停止,关闭电机,完成任务。
因此,我们的示例重点关注基于AI的自主导航,使用在GNSS环境(GPS+指南针)中运行的地面机器人平台,并使用YOLO计算机视觉模型作为目标检测器。
作为开发的基础,我们使用4WD底盘机器人框架和Dake FPV F405飞行控制器作为我们原理图的核心。
系统架构
与任何电子设备一样,Rover也有一个电路图,用于显示其组件的连接方式。虽然Rover的电路可能并不简单;但是,我还是为你绘制了一个示意图。在开始组装和焊接组件之前,请花点时间查看一下。
我们的试验目标漫游车的电路图设计
从上图可以看出,有许多组件必须相互连接。
接线组织如下:
电池组(6S2P)通过正面的8线JST接口连接到飞控(FC)。接线方式:BAT→+,GND→−。电源输入端必须安装1000µF电容以稳定电压。
XL4015DC-DC转换器配置为输出6.5V/3A,为TT黄色电机提供足够的电流给电机驱动器。
两个BTS7960驱动器上的B+/B−连接到XL4015转换器的VOUT/GND。
TT电机(左侧)通过M+和M-。焊盘与左侧BTS7960驱动器并联。
TT电机(右侧)通过M+和M-。焊盘并联连接到右侧BTS7960驱动器。
第一级(XL4015、驱动器和电机)
BTS7960(左驱动器)通过前面的8线JST插孔连接到FC:
S1→R_PWM、S2→L_PWM、5V→VCC、GND→GND、
R_EN/L_EN必须连接到VCC才能保持驱动器启用。
BTS7960(右驱动器)通过前面的8线JST插孔连接到FC:
S3→R_PWM、S4→L_PWM、5V→VCC、GND→GND
R_EN/L_EN必须连接到VCC才能保持驱动器启用。
第二层(FC、GPS、指南针、ELRS、3DR、RPi、蜂鸣器)
ELRS接收器通过正面的4线JST插孔将SpeedyBee ELRS Nano接收器2.4GHz连接到Dake FPV F405 FC,或通过直接接线:T2→RX、R2→TX、GD→GND、5V→VCC。
GPS模块(BN-220)连接4根线:5V→VCC、GND→GND、T1→RX、R1→TX。
指南针(QMC5883L)连接4根线:SDA→SDA、SCL→SCL、5V→VCC、GND→GND。
蜂鸣器
连接到FC:BZ+→VCC,BZ−→GND。
3DR遥测模块连接4根线:T4→RX,R4→TX,GND→GND,5V→VCC。
第三层(电池、RPi的DC-DC转换器)
Raspberry Pi 5通过底部的6线JST插孔连接到FC:
T5→UART0_RXD、R5→UART0_TXD、GND→GND
Raspberry Pi由专用5V/5ADC-DC转换器供电,该转换器通过XT60连接器连接到电池组。
由于系统复杂(三个层级),上面的示意图并非完整的电路原理图。部分元件(例如Raspberry Pi的专用DC-DC转换器或XL4015输出端的肖特基二极管)未显示,但最终设备必须包含这些元件。
我相信每次搭建都是一次新的实验,学习过程的一部分就是逐步完成布线。这种方法能帮助你更深入地理解设计,甚至基于这些知识创建自己的原理图。
软件配置
正确焊接所有组件并在Dake FPV F405飞行控制器上安装ArduRover固件后,下一步是使用Mission Planner软件配置你的模型。
你必须相应地配置以下参数:
FRAME_CLASS=1—流动站
FRAME_TYPE=0—未定义
MOT_PWM_TYPE=4—BrushedBiPolar流动站,可通过4WD电机实现前进和后退运动
SERVO1_FUNCTION=73—油门左
SERVO2_FUNCTION=73(已检查反向)—ThrottleLeft(反向)
SERVO3_FUNCTION=74—油门右
SERVO4_FUNCTION=74(已选中反向)—ThrottleRight(反向)
RC5_OPTION=153—布防/撤防控制
ARMING_CHECK=0—临时(禁用安全检查)
RC7_OPTION=55—切换至引导模式
GPS1_TYPE=2—UBlox(如果使用BN-220)
SERIAL1_BAUD=38–38400GPS波特率
EK3_GPS_CHECK=0—临时(禁用GPS检查)
SERIAL4_BAUD=57–遥测模块的波特率为57600
SERIAL4_PROTOCOL=42—MAVLink2(通过Mission Planner的无线电链路实现流动站控制)
WP_SPEED=0.5—GUIDED模式下的最大速度设置为0.5m/s(50cm/s)正确的配置是ArduRover固件和自动驾驶仪可靠运行的基础。此外,你需要通过基本设置将Radio Master Pocket 2.4 GHz发射器与Rover绑定,并确保模型至少可以在手动模式下运行,然后再继续操作。
自动驾驶仪
在配套计算机(Raspberry Pi)上运行并通过MAVLink与飞行控制器通信以实现自主操作的特殊软件称为自动驾驶仪。
该自动驾驶仪的完整源代码可以在下面的链接处下载:
ArduRover的目标跟踪自动驾驶仪(开发版)
我之前发布的原始实现的通用版本见下面的链接:
用于FPV战斗无人机的带目标跟踪的自动驾驶仪(模拟器版本)
如果需要,这两个版本都可以轻松适应你的特定FPV无人机、飞机或探测车模型,并且可以自由使用,无需任何担保。
软件架构
我们的自动驾驶仪LOONARR采用多线程设计,围绕中央命令队列和命令路由器构建。路由器线程处理排队的命令,而遥测线程和跟随线程则简单地将新命令附加到队列中。
ArduRover自动驾驶仪开发的软件架构
每个模块的详细描述,包括其配置参数和工作流程,都可以在我上面提到的源代码仓库中的README_DEV.md文件中找到。恕我不会在这里详细介绍。
计算机视觉
CV模块是目标跟踪过程的基石,也是我们解决方案的关键组件。它就像系统的“眼睛”,能够检测和跟踪(跟随)目标。因此,我将在本节中对它作简要介绍。
该自动驾驶仪使用YOLOv8模型进行物体检测,具体来说是yolov8n.pt模型,使用Person类(class0)。为了处理视频帧、与Raspberry Pi摄像头连接以及管理不同的分辨率,自动驾驶仪依赖于OpenCV和Picamera2。
物体检测和目标跟踪在工作过程中涉及几个复杂的任务,包括:
将目标位置从图像帧转换为笛卡尔坐标(NED—北,东,下)
根据需要调整探测车的位置和速度
考虑比例和转换因素
所有这些功能都是在位于vision.py文件中的计算机视觉模块中实现的。
import cv2
import definitions as vars
from datetime import datetime
from picamera2 import Picamera2
from ultralytics import YOLO
model = YOLO(vars.vision_model)
image_width = vars.camera_width
image_height = vars.camera_height
yaw_conversion_factor = 0.002
threshold_percentage=0.40
approach_factor = 0.8
pi_camera_index = 255
def configure_camera:
camera = {}
if vars.video_source == pi_camera_index:
camera = Picamera2
config = camera.create_preview_configuration(
main={"size": (vars.camera_width, vars.camera_height),
"format": "RGB888"})
camera.configure(config)
camera.start
else:
camera = cv2.VideoCapture(vars.video_source)
if not camera.isOpened:
print('VISION: Camera is not ready!')
return camera
cam = configure_camera
def get_camera_image:
result = {}
png_file_name = \
f'{vars.logger_directory}/img_{datetime.now.strftime("%Y-%m-%d_%H-%M-%S")}.png'
frame = cam.capture_array
result = get_anotated_frame(frame,
png_file_name)
else:
success, frame = cam.read
if success:
png_file_name)
cv2.destroyAllWindows
return result
def get_anotated_frame(frame, png_file_name):
results = model(frame, classes=vars.vision_classes,
imgsz=vars.camera_width, verbose=False)
anotated_frame = results[0].plot
cv2.imwrite(png_file_name, anotated_frame)
result = results[0]
return result
def get_ned_coordinates(x1, y1, x2, y2, altitude):
target_x = (x1 + x2) / 2
target_y = (y1 + y2) / 2
relative_x = (2 * target_x / image_width) - 1
relative_y = (2 * target_y / image_height) - 1
N_coord = relative_y * altitude
D_coord = 0
return N_coord, E_coord, D_coord
def get_yaw_angle(x1, y1, x2, y2):
target_x = (x1 + x2) / 2
yaw_angle = (target_x - image_width / 2) * yaw_conversion_factor
return yaw_angle
def get_target_threshold_area(x1, y1, x2, y2):
target_area = (x2 - x1) * (y2 - y1)
threshold_area = \
image_width * image_height * threshold_percentage
return target_area, threshold_area
def is_target_close_enough(x1, y1, x2, y2):
target_area, threshold_area = \
get_target_threshold_area(x1, y1, x2, y2)
return target_area > threshold_area
def get_ned_target(x1, y1, x2, y2, altitude):
N_coord, E_coord, D_coord = get_ned_coordinates(
x1, y1, x2, y2, altitude)
yaw_angle = get_yaw_angle(x1, y1, x2, y2)
target_area, threshold_area = \
get_target_threshold_area(x1, y1, x2, y2)
long_factor = threshold_area / target_area
return round(N_coord * long_factor * approach_factor, 4), \
round(E_coord, 4), round(D_coord, 4), round(yaw_angle, 4)
如上代码所示,该系统使用由YOLOv8驱动的目标跟踪模块。其中,OpenCV从USB摄像头或RPI摄像头(基于配置)捕获实时视频,YOLO检测人员自定义函数,将这些检测转换为导航命令(NED坐标和偏航),以便探测车跟踪目标。
NED坐标计算
如上图所示,上坡的人被YOLO模型检测为目标。代码计算边界框(红色)的中心,并在NED(北、东、下)坐标系中相应地调整Rover的移动,如图所示。
例如,NED(4.21,-1.83,-2.29)表示探测车应从当前位置向北移动4.21米,向西移动1.83米(由于值为负,因此与向东方向相反),向上移动2.29米(与向下方向相反),以跟随斜坡上的目标。
在RPi上安装
如前面的架构部分所述,Raspberry Pi(RPi)在此设置中充当配套计算机,通过MAVLink与飞行控制器上的ArduRover固件进行通信。
按照以下步骤在RPi上安装自动驾驶仪代码:
1.下载并将存储库解压到目录:/home/pi/Apps/loonarr
2.将服务和脚本文件复制config/run_autopilot.service到config/run_autopilot.sh:/etc/systemd/system
3.设置必要的权限
sudo chmod +x /etc/systemd/system/run_autopilot.sh
4.启动时启用Autopilot服务
sudo systemctl enable run_autopilot.service
sudo reboot
5.验证日志:
树莓派重启后,前往logs文件夹检查是否有新文件生成。
如果没有,请检查definitions.py并根据需要调整设置。
此时,你的Rover、自动驾驶仪以及所有相关组件应该已准备好进行首次启动和测试。请按照下一节中的说明进行操作。
用法
现在,你已经完成了所有艰苦的工作,是时候测试你的作品了,看看它在实际应用中的表现如何。前往一片空旷的地方,带上你的Rover(搭载了树莓派)、RadioMaster Tx以及你的笔记本电脑(笔记本电脑的USB端口已插入3DR遥测模块)。然后按照图片下方的说明测试你的最终组装。
GPS:3D定位(准备执行任务)
检查设备功能的步骤是:
打开你的RadioMaster TX(或另一个ELRS发射器)。
将电池组连接到Rover的XT60输入。
验证流动站响应:切换模式、布防/撤防,并在手动模式下驾驶。
使用计算机上的3DR Telemetry检查GPS信号。
将RC7(chan7_raw)切换到GUIDED模式。
武装好Rover并站在摄像机前。
等待约2秒—探测车就会朝你驶来。
完成:一旦探测车到达你身边,它将自动解除武装并且蜂鸣器会响起。
如果你做的一切都正确,那么探测车就会像本文开头的第一张插图中所示那样跟随你。
飞行记录
出于安全原因和飞行后分析,自动驾驶仪在运行期间会生成日志文件,并将导航中使用的带有边界框的所有图像保存到日志文件夹中。
目标跟踪帧
这些飞行记录在必要时可作为正确操作的宝贵证据,也可用于调查飞行过程中的碰撞或不当行为(这对Rover来说很重要)。
日志文件中的飞行记录
如图所示,自动驾驶仪几次失去目标,然后重新获得目标并继续跟踪,直到距离足够近,可以成功完成任务。
与往常一样,我建议将记录器设置为“调试”模式,以便最大限度地利用这些飞行记录。这将帮助你在每次飞行中改进自动驾驶系统。
一些注意事项
如果上述所有操作均已完成并正常运行,那么许多新的可能性就会随之而来。从这一点开始,利用你从本文中获得的方法和知识,你可以构建其他地面机器人平台,包括但不限于:
疏散流动车
医疗用品流浪者队
有效载荷运载工具
侦察平台
等等。
无论你是出于兴趣爱好还是实际使用而创建设备,都可以考虑提供经过测试的第一视角(FPV)无人机、侦察固定翼飞机,甚至大型探测车(如果你决定建造的话),以用于民用、国防保护等领域应用。
你可以在Twitter上提问:https://twitter.com/dmytro_sazonov
译者介绍
朱先忠,51CTO社区编辑,51CTO专家博客、讲师,潍坊一所高校计算机教师,自由编程界老兵一枚。
来源:汽车驾驶员
