樹莓派智能小車,實現功能:基於超聲波和紅外的自動避障、樹莓派端向PC端的實時圖像傳輸、基於視覺的車道線循跡、基於Tensorflow Object Detection的目標檢測、基於視覺的網球追蹤。 ...
簡介
本項目的GitHub鏈接
本項目是學校項目設計課程內的項目,要求是使用一個基於樹莓派的小車來實現一些簡單的功能。
本項目適合初次接觸樹莓派,希望利用樹莓派及小車配件實現一些簡單功能的同學們。
目前我們實現的功能有:
- 自動避障:基於超聲波和紅外,使小車在運行過程中不會撞上障礙物;
- 實時圖像傳輸:將樹莓派攝像頭拍攝到的視頻流傳到PC端,併在PC端查看;
- 視覺車道循跡:基於視覺,使小車沿車道線行駛;
- 目標檢測:識別並定位攝像頭圖像中的各類常見物體;
- 網球追蹤:基於視覺,使小車追蹤一個移動的網球,並與網球保持一定距離。
學校提供的小車的商家是慧凈電子,商家提供了一些使用教程,適合初學,基於C語言,實現了一些簡單的紅外避障、紅外尋跡、超聲波避障和攝像頭調用。
本項目選用Python作為編程語言,有幾點原因:Python相比較C語言更簡明;我們對Python的掌握情況更好一些(C語言沒學好啊);方便之後使用tensorflow做一些深度學習的功能。但同時帶來的缺點就是運行速度會差一點。
下麵我們會對小車配置、功能實現和使用方法進行詳細的介紹。本文結構如下:
- 配置要求
- 項目架構
- 準備工作
- 硬體調試
- 功能實現(原理介紹)
- 功能實現(使用教程)
若想成功實現本項目的功能,請:
- 首先確保完成準備工作
- 之後進行硬體調試
- 之後在閱讀過功能實現-原理介紹的基礎上
- 根據功能實現-使用教程來運行相應程式、實現功能
配置要求
- 樹莓派3
- 驅動板(L298N)
- CSI攝像頭
- 超聲波測距感測器
- 紅外避障感測器
- 小車車體 + 4個電機
- 電腦 (Ubuntu18.04)
項目架構
我們的源代碼全部放在PythonCode文件夾內。
我們對每個感測器定義了一個類,放在相應的py文件里,由此可以很清晰方便地對每個感測器進行單獨的調試。
名稱以main開頭的文件是實現相應功能的主程式,在主程式里定義了一個Car類,該類繼承了所有感測器的類。
準備工作
重裝樹莓派的系統
商家給樹莓派預裝了系統,應該是商家自己改過的,也是幾年前的了。強烈建議自己將樹莓派的系統進行重裝(重裝後opencv和tensorflow的安裝都會簡單很多),推薦安裝樹莓派的官方系統Raspbian。安裝方法百度一下,教程很多,也很簡單。
關於樹莓派教程,推薦樹莓派實驗室|開箱上手必讀,裡面的教程基本準確好用。
使用SSH登錄,操作樹莓派
對樹莓派進行操作的方法有很多:
我們基本上是使用SSH登錄到樹莓派進行操作的,也就是使用putty登錄。這需要樹莓派和PC在同一個區域網下,我們選擇讓樹莓派創建一個WiFi熱點,然後讓PC連接這個WiFi熱點。方法:創建WiFi熱點並開機自啟動,其中使用了github上一個開源的庫create_ap。同時,還要設置熱點開機自動啟動。另外註意要設置開啟樹莓派的SSH服務,否則putty連接會顯示失敗。
更換下載源
使用官方的源因為眾所周知的原因會非常慢且不穩定,所以要換成國內的源。
OpenCV安裝
使用最新版樹莓派系統,可以直接用pip3安裝OpenCV。
硬體調試
首先需要確定樹莓派、驅動板、感測器之間的連線是正確的。
電機
- 工作原理
- H橋
- PWM
電機相關代碼在move.py內。需要註意GPIO埠號的設置,python用的是BCM編碼。
在move.py中,定義了前進、後退、左轉、右轉、停車功能。轉彎是通過左右輪差速實現的。
超聲波測距感測器
- 超聲波測距基本原理
- 超聲波測距程式實現
- 提升測距準確性的方法
超聲波相關代碼在ultrasound.py內,實現了超聲波測距和對測距進行移動平均來減小誤差。
紅外避障感測器
紅外避障相關代碼在infrared.py內,InfraredMeasure函數是小車左右的兩個紅外避障感測器,TrackingMeasure是小車底部兩個紅外尋線感測器。
註意,紅外避障感測器傳回0表示前方有障礙物,傳回1表示前方無障礙物。
攝像頭
調用攝像頭需要先在sudo raspi-config
中啟用Camera,然後重啟。
python調用攝像頭有兩種方式:
- 使用picamera
- 使用opencv
我們使用的是picamera方式,因為我們發現使用OpenCV的方式會有延時,它返回的第一幀圖像是在鏡頭初始化那一刻的圖像,而不是主程式請求時的圖像。
具體調用方法參考 樹莓派(Raspberry Pi)中PiCamera+OpenCV的使用。
攝像頭相關代碼在camera.py中,其中實現了:
- 攝像頭初始化
- 實時圖像傳輸(發送端),註意HOST為PC在此WiFi網路下的IP地址(通過ifconfig查看),PORT設置一個和接收端相同的埠號就可以。
另外註意,程式終止是一定要關閉攝像機(camera.close()),否則下次無法正常打開。
功能實現(原理介紹)
自動避障
基於超聲波和紅外,使小車在運行過程中不會撞上障礙物。
主程式為main_obstacle_avoidance.py,其思想很簡單,超聲波感測器測出小車距離前方障礙物的距離,兩邊的紅外感測器測出兩邊是否有障礙物,根據測量結果進行運動決策和電機控制。
實時圖像傳輸
將樹莓派攝像頭拍攝到的視頻流傳到PC端,併在PC端查看。目的是為了便於攝像頭姿態的調整和圖像處理演算法的調試。另外,如果需要的話可以使用傳輸到PC的圖像在PC端進行處理(我們沒有實現此功能)。
可選擇的傳輸協議有兩種:
- TCP:面向連接,提供可靠地服務,無差錯,不丟失,不重覆;實時性差,效率低;系統資源要求較多。
- UDP:可以無連接;盡最大努力交付,即不保證可靠交付;實時性強,效率高;系統資源要求較少。
我們使用UDP傳輸協議進行圖像傳輸。具體實現主要分為發送端和接收端兩部分:
- 發送端:(camera.py VideoTransimssion)
- 圖像編碼(cv2.imencode)
- 校驗數據發送(數據長度作為校驗)
- 編碼數據發送(socket.sendall)
- 接收端:(pc_receiver.py)
- 接收校驗數據(4位元組數據)
- 接收圖像編碼(校驗數據後的第一個數據包)
- 簡單校驗(校驗數據 == 編碼數據長度)
- 圖像解碼(cv2.imdecode)
其中,發送端在樹莓派端運行,接收端在PC端運行。二者同時運行。
視覺車道循跡
基於視覺,使小車沿車道線行駛。環境要求為白色的地板,黑色(深色)的車道線。
主程式為main_lane_tracking.py,其流程大致如下:
- 車道線檢測
- 圖像二值化,提取車道線
- 提取車道線的內側點:在圖像的特定行,從中間向兩側檢索,檢測到0像素點及為車道線點。圖像左半邊檢測到的點即為左車道線點,右半邊檢測到的點即為右車道線點。(為防止因各種原因車道線部分缺失,我們選擇圖像4個行提取4組車道線內側點)
- 運動控制
- 運動決策
- 如果兩側車道線都能檢測到,則直行
- 如果只能檢測到一側車道線,則有三種情況:
- 該側車道線靠近圖像邊緣,則還可以繼續直行
- 該側車道線靠近圖像中央,則急需轉彎,原地旋轉
- 該側車道線位置適中,則緩慢轉彎,在前進中轉彎
- 如果兩側車道線都檢測不到,則維持之前的動作
- 電機控制:根據決策結果,控制小車電機輸出
- 運動決策
在本實驗中,車道線檢測部分較容易實現,我們發現,在這種簡單的環境下,固定閾值的二值化效果比大津法好。另外,因為我們的車道線偏藍色,我們選擇提取圖像的R通道進行二值化。檢測效果如圖:
運動控制部分相對較為複雜,我們只採用了一個簡單的邏輯,效果還可以。
目標檢測
識別並定位攝像頭圖像中的各類常見物體。
主程式為main_object_detection.py,其調用了TensorFlow Object Detection API,使用了訓練好的的SSDLite目標檢測模型,在樹莓派端進行目標檢測。
TensorFlow安裝方法及TensorFlow Object Detection API配置方法可以完全參考此文檔:EdjeElectronics/Tutorial to set up TensorFlow Object Detection API on the Raspberry Pi
或者TensorFlow Object Detection API可以直接clone這位的 xyc2690/Raspberry_ObjectDetection_Camera,可以不用配置TensorFlow Object Detection API,下載即用。
我們使用的SSDLite模型主要優點是運行速度快、占用記憶體小,適合在樹莓派端進行運算。據我們測試,幀率大概為0.8幀/s。我們使用的是樹莓派3,如果是更新的型號,速度會更快一點。
網球追蹤
基於攝像頭,使小車追蹤一個移動的網球,並與網球保持一定距離。
主程式在main_tennis_tracking.py中,網球追蹤流程大概如下:
實驗顯示:
在不同光照條件下,網球的色調(H)基本上保持一致,範圍大致在25至50 (OpenCV範圍),在可靠明亮的光照條件下,範圍大致在30至40。
網球檢測的程式在detect_new.py中,具體流程如下:
- 關註區域裁切:裁掉不可能出現網球的區域
- 高斯濾波:去除一定雜訊
- 霍夫圓檢測:檢測出圖像中所有可能存在的圓(視頻中的綠色圓)
- 針對每個檢測出的圓的內切正方形:
- RGB to HSV
- 利用HSV域計算符合網球顏色的像素點數目
- 統計上述像素點數目占比
- 選出占比最大的圓,若其占比大於設定閾值,則認為是網球(視頻中的紅色圓)
經測試,幀率大概在15幀/s。
運動控制的程式在main_tennis_tracking.py中,具體流程如下:
- 移動平均:對檢測得網球位置進行移動平均,減小誤差
- 決策:根據當前網球相對於小車的位置,決策下一步的動作
- 根據網球x坐標決策轉向動作
- 根據網球半徑r決策前進後退動作
- 控制:根據決策結果,控制小車電機輸出
目前存在的問題:
- 我們使用的小車是4電機四驅差速轉向小車,但在沒有細緻調教的差速控制演算法的情況下,這樣的配置使得在小車在轉彎的時候存在較大的滑動摩擦(a skidding turn),所以轉向時小車存在一個“最低啟動速度”,當PWM的占空比小於一定值時,小車由於摩擦力的原因無法真的轉起來,在原地“蹩著”,所以要小車轉起來,只能給一個相對大的速度,這樣就很容易轉向過度。
- 同時,由於摩擦力,小車在轉向時也存在明顯的車身抖動,使得轉向時拍攝的圖像發飄發糊,導致此時網球檢測得效果也收到影響,進一步影響了轉向追網球的準確性。
- 網球檢測的效果受光照的影響還是挺大的,白天光照充足的環境下(白天室外)效果會好很多。
功能實現(使用教程)
自動避障
在樹莓派終端中輸入:
cd PythonCode
python3 main_obstacle_avoidance.py
實時圖像傳輸
樹莓派發送圖像,在樹莓派終端輸入:
cd PythonCode
python3 camera.py
同時,如果想在PC端接收圖像,在PC終端輸入:
cd PythonCode
python3 pc_receiver.py
NOTICE:camera.py和pc_receiver.py均需要根據具體情況配置HOST和POST:
- 二者中的HOST均為PC在此WiFi網路下的IP地址(通過ifconfig查看)
- 二者的PORT設置為同一個埠號就可以(eg:8000)。
視覺車道循跡
在樹莓派終端輸入:
cd PythonCode
python3 main_lane_tracking.py
如果想在PC端接收車道檢測圖像,則在PC終端輸入:
cd PythonCode
python3 pc_receiver.py
目標檢測
在樹莓派終端中輸入:
cd PythonCode
python3 main_object_detection.py
如果想在PC端接收圖像,則在PC終端輸入:
cd PythonCode
python3 pc_receiver.py
NOTICE:Tensorflow Object Detection API 和 ssdlite模型並未上傳至此倉庫,需要自行安裝。二者的安裝和配置方法請參考此文檔:EdjeElectronics/Tutorial to set up TensorFlow Object Detection API on the Raspberry Pi
; 或者TensorFlow Object Detection API可以直接clone這位的 xyc2690/Raspberry_ObjectDetection_Camera,可以不用配置TensorFlow Object Detection API,下載即用。
網球追蹤
在樹莓派終端輸入:
cd PythonCode
python3 main_tennis_tracking.py
如果想在PC端接收網球檢測圖像,則在PC終端輸入:
cd PythonCode
python3 pc_receiver.py
Notes
All tutorials on Raspberry-Pi | GitHub