為ArduRover裝上“眼睛”:基于計算機視覺的自主漫游車實戰
譯者 | 朱先忠
審校 | 重樓

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與飛行控制器通信以實現自主操作的特殊軟件稱為自動駕駛儀。
該自動駕駛儀的完整源代碼可以在下面的鏈接處下載:
我之前發布的原始實現的通用版本見下面的鏈接:
??用于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'
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)如上代碼所示,該系統使用由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上安裝自動駕駛儀代碼:
- 下載并將存儲庫解壓到目錄:/home/pi/Apps/loonarr
- 將服務和腳本文件復制config/run_autopilot.service到config/run_autopilot.sh:/etc/systemd/system
- 設置必要的權限
sudo chmod +x /etc/systemd/system/run_autopilot.sh- 啟動時啟用Autopilot服務
sudo systemctl enable run_autopilot.service
sudo reboot- 驗證日志:
樹莓派重啟后,前往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專家博客、講師,濰坊一所高校計算機教師,自由編程界老兵一枚。
原文標題:??Building an autonomous ArduRover that sees with Computer Vision??,作者:Dmytro Sazonov

















