譯者 | 朱先忠
審校 | 重樓

LOONARR-1搭載ArduRover
如果你曾經(jīng)嘗試構(gòu)建搭載計算機視覺的自主系統(tǒng),你就會知道入門有多么困難。當(dāng)平臺是空中平臺時,例如FPV無人機或飛機,難度會更大——飛行過程中的任何失誤都可能導(dǎo)致墜機和嚴(yán)重?fù)p壞。相比之下,使用像Rover這樣的地面機器人平臺就可以消除這些風(fēng)險。由于它始終停留在地面上,因此你可以安全地調(diào)試和開發(fā)自動駕駛儀或其他功能,風(fēng)險要低得多。
在本文中,我將提供一份全面的搭建試驗指南,教你如何從零開始構(gòu)建一臺漫游車,并將自動駕駛儀與計算機視覺集成,用于地面目標(biāo)跟蹤。在本試驗中,我們將使用ArduRover固件、MAVLink協(xié)議、配套計算機(Raspberry Pi 5)以及OpenCV和YOLO進行物體檢測(識別)。
一般設(shè)計方案
漫游車運行ArduRover固件,并使用樹莓派(RaspberryPi)作為配套計算機。連接到樹莓派的攝像頭可捕捉圖像,用于基于人工智能的自主導(dǎo)航。在跟隨模式下,漫游車的自動駕駛儀采用YOLO計算機視覺模型進行目標(biāo)檢測(識別),計算目標(biāo)在NED坐標(biāo)系中的位置,然后跟隨目標(biāo)。一旦漫游車足夠接近目標(biāo),它就會停止,關(guān)閉電機,完成任務(wù)。
因此,我們的示例重點關(guān)注基于AI的自主導(dǎo)航,使用在GNSS環(huán)境(GPS+指南針)中運行的地面機器人平臺,并使用YOLO計算機視覺模型作為目標(biāo)檢測器。
作為開發(fā)的基礎(chǔ),我們使用4WD底盤機器人框架和Dake FPV F405飛行控制器作為我們原理圖的核心。
系統(tǒng)架構(gòu)
與任何電子設(shè)備一樣,Rover也有一個電路圖,用于顯示其組件的連接方式。雖然Rover的電路可能并不簡單;但是,我還是為你繪制了一個示意圖。在開始組裝和焊接組件之前,請花點時間查看一下。

我們的試驗?zāi)繕?biāo)漫游車的電路圖設(shè)計
從上圖可以看出,有許多組件必須相互連接。
接線組織如下:
- 電池組(6S2P)通過正面的8線JST接口連接到飛控(FC)。接線方式:BAT→+,GND→?。電源輸入端必須安裝1000μF電容以穩(wěn)定電壓。
- XL4015DC-DC轉(zhuǎn)換器配置為輸出6.5V/3A,為TT黃色電機提供足夠的電流給電機驅(qū)動器。
- 兩個BTS7960驅(qū)動器上的B+/B?連接到XL4015轉(zhuǎn)換器的VOUT/GND。
- TT電機(左側(cè))通過M+和M-。焊盤與左側(cè)BTS7960驅(qū)動器并聯(lián)。
- TT電機(右側(cè))通過M+和M-。焊盤并聯(lián)連接到右側(cè)BTS7960驅(qū)動器。

第一級(XL4015、驅(qū)動器和電機)
- BTS7960(左驅(qū)動器)通過前面的8線JST插孔連接到FC:
S1→R_PWM、S2→L_PWM、5V→VCC、GND→GND、
R_EN/L_EN必須連接到VCC才能保持驅(qū)動器啟用。 - BTS7960(右驅(qū)動器)通過前面的8線JST插孔連接到FC:
S3→R_PWM、S4→L_PWM、5V→VCC、GND→GND
R_EN/L_EN必須連接到VCC才能保持驅(qū)動器啟用。

第二層(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轉(zhuǎn)換器)
- Raspberry Pi 5通過底部的6線JST插孔連接到FC:
T5→UART0_RXD、R5→UART0_TXD、GND→GND
Raspberry Pi由專用5V/5ADC-DC轉(zhuǎn)換器供電,該轉(zhuǎn)換器通過XT60連接器連接到電池組。
由于系統(tǒng)復(fù)雜(三個層級),上面的示意圖并非完整的電路原理圖。部分元件(例如Raspberry Pi的專用DC-DC轉(zhuǎn)換器或XL4015輸出端的肖特基二極管)未顯示,但最終設(shè)備必須包含這些元件。
我相信每次搭建都是一次新的實驗,學(xué)習(xí)過程的一部分就是逐步完成布線。這種方法能幫助你更深入地理解設(shè)計,甚至基于這些知識創(chuàng)建自己的原理圖。
軟件配置
正確焊接所有組件并在Dake FPV F405飛行控制器上安裝ArduRover固件后,下一步是使用Mission Planner軟件配置你的模型。
你必須相應(yīng)地配置以下參數(shù):
- FRAME_CLASS=1—流動站
- FRAME_TYPE=0—未定義
- MOT_PWM_TYPE=4—BrushedBiPolar流動站,可通過4WD電機實現(xiàn)前進和后退運動
- SERVO1_FUNCTION=73—油門左
- SERVO2_FUNCTION=73(已檢查反向)—ThrottleLeft(反向)
- SERVO3_FUNCTION=74—油門右
- SERVO4_FUNCTION=74(已選中反向)—ThrottleRight(反向)
- RC5_OPTION=153—布防/撤防控制
- ARMING_CHECK=0—臨時(禁用安全檢查)
- RC7_OPTION=55—切換至引導(dǎo)模式
- 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的無線電鏈路實現(xiàn)流動站控制)
- WP_SPEED=0.5—GUIDED模式下的最大速度設(shè)置為0.5m/s(50cm/s)正確的配置是ArduRover固件和自動駕駛儀可靠運行的基礎(chǔ)。此外,你需要通過基本設(shè)置將Radio Master Pocket 2.4 GHz發(fā)射器與Rover綁定,并確保模型至少可以在手動模式下運行,然后再繼續(xù)操作。
自動駕駛儀
在配套計算機(Raspberry Pi)上運行并通過MAVLink與飛行控制器通信以實現(xiàn)自主操作的特殊軟件稱為自動駕駛儀。
該自動駕駛儀的完整源代碼可以在下面的鏈接處下載:
ArduRover的目標(biāo)跟蹤自動駕駛儀(開發(fā)版)
我之前發(fā)布的原始實現(xiàn)的通用版本見下面的鏈接:
用于FPV戰(zhàn)斗無人機的帶目標(biāo)跟蹤的自動駕駛儀(模擬器版本)
如果需要,這兩個版本都可以輕松適應(yīng)你的特定FPV無人機、飛機或探測車模型,并且可以自由使用,無需任何擔(dān)保。
軟件架構(gòu)
我們的自動駕駛儀LOONARR采用多線程設(shè)計,圍繞中央命令隊列和命令路由器構(gòu)建。路由器線程處理排隊的命令,而遙測線程和跟隨線程則簡單地將新命令附加到隊列中。

ArduRover自動駕駛儀開發(fā)的軟件架構(gòu)
每個模塊的詳細(xì)描述,包括其配置參數(shù)和工作流程,都可以在我上面提到的源代碼倉庫中的README_DEV.md文件中找到。恕我不會在這里詳細(xì)介紹。
計算機視覺
CV模塊是目標(biāo)跟蹤過程的基石,也是我們解決方案的關(guān)鍵組件。它就像系統(tǒng)的“眼睛”,能夠檢測和跟蹤(跟隨)目標(biāo)。因此,我將在本節(jié)中對它作簡要介紹。
該自動駕駛儀使用YOLOv8模型進行物體檢測,具體來說是yolov8n.pt模型,使用Person類(class0)。為了處理視頻幀、與Raspberry Pi攝像頭連接以及管理不同的分辨率,自動駕駛儀依賴于OpenCV和Picamera2。
物體檢測和目標(biāo)跟蹤在工作過程中涉及幾個復(fù)雜的任務(wù),包括:
- 將目標(biāo)位置從圖像幀轉(zhuǎn)換為笛卡爾坐標(biāo)(NED—北,東,下)
- 根據(jù)需要調(diào)整探測車的位置和速度
- 考慮比例和轉(zhuǎn)換因素
所有這些功能都是在位于vision.py文件中的計算機視覺模塊中實現(xiàn)的。
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'
if vars.video_source == pi_camera_index:
frame = cam.capture_array()
result = get_anotated_frame(frame,
png_file_name)
else:
success, frame = cam.read()
if success:
result = get_anotated_frame(frame,
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
E_coord = relative_x * 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)如上代碼所示,該系統(tǒng)使用由YOLOv8驅(qū)動的目標(biāo)跟蹤模塊。其中,OpenCV從USB攝像頭或RPI攝像頭(基于配置)捕獲實時視頻,YOLO檢測人員自定義函數(shù),將這些檢測轉(zhuǎn)換為導(dǎo)航命令(NED坐標(biāo)和偏航),以便探測車跟蹤目標(biāo)。

NED坐標(biāo)計算
如上圖所示,上坡的人被YOLO模型檢測為目標(biāo)。代碼計算邊界框(紅色)的中心,并在NED(北、東、下)坐標(biāo)系中相應(yīng)地調(diào)整Rover的移動,如圖所示。
例如,NED(4.21,-1.83,-2.29)表示探測車應(yīng)從當(dāng)前位置向北移動4.21米,向西移動1.83米(由于值為負(fù),因此與向東方向相反),向上移動2.29米(與向下方向相反),以跟隨斜坡上的目標(biāo)。
在RPi上安裝
如前面的架構(gòu)部分所述,Raspberry Pi(RPi)在此設(shè)置中充當(dāng)配套計算機,通過MAVLink與飛行控制器上的ArduRover固件進行通信。
按照以下步驟在RPi上安裝自動駕駛儀代碼:
- 下載并將存儲庫解壓到目錄:/home/pi/Apps/loonarr
- 將服務(wù)和腳本文件復(fù)制config/run_autopilot.service到config/run_autopilot.sh:/etc/systemd/system
- 設(shè)置必要的權(quán)限
sudo chmod +x /etc/systemd/system/run_autopilot.sh- 啟動時啟用Autopilot服務(wù)
sudo systemctl enable run_autopilot.service
sudo reboot- 驗證日志:
樹莓派重啟后,前往logs文件夾檢查是否有新文件生成。
如果沒有,請檢查definitions.py并根據(jù)需要調(diào)整設(shè)置。
此時,你的Rover、自動駕駛儀以及所有相關(guān)組件應(yīng)該已準(zhǔn)備好進行首次啟動和測試。請按照下一節(jié)中的說明進行操作。
用法
現(xiàn)在,你已經(jīng)完成了所有艱苦的工作,是時候測試你的作品了,看看它在實際應(yīng)用中的表現(xiàn)如何。前往一片空曠的地方,帶上你的Rover(搭載了樹莓派)、RadioMaster Tx以及你的筆記本電腦(筆記本電腦的USB端口已插入3DR遙測模塊)。然后按照圖片下方的說明測試你的最終組裝。

GPS:3D定位(準(zhǔn)備執(zhí)行任務(wù))
檢查設(shè)備功能的步驟是:
- 打開你的RadioMaster TX(或另一個ELRS發(fā)射器)。
- 將電池組連接到Rover的XT60輸入。
- 驗證流動站響應(yīng):切換模式、布防/撤防,并在手動模式下駕駛。
- 使用計算機上的3DR Telemetry檢查GPS信號。
- 將RC7(chan7_raw)切換到GUIDED模式。
- 武裝好Rover并站在攝像機前。
- 等待約2秒—探測車就會朝你駛來。
- 完成:一旦探測車到達你身邊,它將自動解除武裝并且蜂鳴器會響起。
如果你做的一切都正確,那么探測車就會像本文開頭的第一張插圖中所示那樣跟隨你。
飛行記錄
出于安全原因和飛行后分析,自動駕駛儀在運行期間會生成日志文件,并將導(dǎo)航中使用的帶有邊界框的所有圖像保存到日志文件夾中。

目標(biāo)跟蹤幀
這些飛行記錄在必要時可作為正確操作的寶貴證據(jù),也可用于調(diào)查飛行過程中的碰撞或不當(dāng)行為(這對Rover來說很重要)。

日志文件中的飛行記錄
如圖所示,自動駕駛儀幾次失去目標(biāo),然后重新獲得目標(biāo)并繼續(xù)跟蹤,直到距離足夠近,可以成功完成任務(wù)。
與往常一樣,我建議將記錄器設(shè)置為“調(diào)試”模式,以便最大限度地利用這些飛行記錄。這將幫助你在每次飛行中改進自動駕駛系統(tǒng)。
一些注意事項
如果上述所有操作均已完成并正常運行,那么許多新的可能性就會隨之而來。從這一點開始,利用你從本文中獲得的方法和知識,你可以構(gòu)建其他地面機器人平臺,包括但不限于:
- 疏散流動車
- 醫(yī)療用品流浪者隊
- 有效載荷運載工具
- 偵察平臺
- 等等。
無論你是出于興趣愛好還是實際使用而創(chuàng)建設(shè)備,都可以考慮提供經(jīng)過測試的第一視角(FPV)無人機、偵察固定翼飛機,甚至大型探測車(如果你決定建造的話),以用于民用、國防保護等領(lǐng)域應(yīng)用。
聯(lián)系我們
你可以在Twitter上提問:https://twitter.com/dmytro_sazonov
譯者介紹
朱先忠,51CTO社區(qū)編輯,51CTO專家博客、講師,濰坊一所高校計算機教師,自由編程界老兵一枚。
原文標(biāo)題:Building an autonomous ArduRover that sees with Computer Vision,作者:Dmytro Sazonov
































