0
| 本文作者: AI研習社 | 2017-03-22 15:14 |
雷鋒網按:本文作者趙智沉,Google軟件工程師。來自知乎專欄:趙智沉的作坊。雷鋒網獲授權轉載。

從買第一個Arduino套裝開始,我接觸機器人有好幾年了,但直到最近才開始做完整的課題。期間有兩項技能為我打開了新世界的大門:Python和Linux。他們背后,是強大的開源社區。掌握了這兩樣工具的工具(元工具),你感覺網上遍地是趁手的兵器。
上周在公司內部編程培訓時,有一句話深得我心:我們是軟件工程師,不是程序員。我們的工作不是寫程序,而是合理使用工具解決問題。在Google,如果你覺得自己不得不從零開始寫某項功能,只是你還沒有找到相應的工具罷了。在開源社區更是如此。
這是一個遙控小車,通過紅外遙控或無線鍵盤可以控制小車的行動和攝像頭的角度。TensorFlow實時監測攝像頭拍攝到的畫面,語音讀出它識別出的物體。所有代碼都放在我的GitHub上。
這個想法不是我的原創,來自Lukas Biewald去年九月寫的這篇博客。核心部分,TensorFlow識別攝像頭圖像并語音輸出,是我司人工智能工程師Pete Warden的開源工作。和原博客不同的是,制作過程中我加入了Arduino作為機械總控,也了解了Arduino和樹莓派對話的方法(串口通信)。期間用到了許多有用的技能和工具,在這里整理一下,歡迎同好們留言交流!
整個課題在命令行環境完成,沒有圖形界面。如果你不懂Linux系統,可能有些吃力。但是,你都開始玩機器人了,怎么能不學Linux呢?我是通過《鳥哥的Linux私房菜》自學Linux的,后來又嘗試從源代碼搭建Linux,終于克服在Windows系統環境長大產生的對命令行的抗拒心理。相信我,克服這個障礙,你將打開新世界的大門。何況,用命令行工作才顯得更酷更極客,不是嗎?除了Linux,你還要懂C++和Python來完成這個課題。
另外,這篇文章主要介紹電子部分,不講機械和美工。如你看到的,這個小車丑破了我的審美底線,我沒花心思在外觀上。我希望以后做一些兼具美學和功能的電子課題,或許會和設計師朋友們合作!
首先,你需要一個最新款的Raspberry Pi,安裝好定制的Linux系統,連上無線網。你還需要一個官配攝像頭,并在樹莓派中設置為可用。你可以將樹莓派通過HDMI連接到顯示器,但更方便的做法是ssh遠程登錄,這樣你就不用在調試過程中反復地把樹莓派從小車上拔線、取下、連屏幕、然后安裝回小車了,你可以實時遠程修改小車的內核。甚至,我的Arduino程序也是通過樹莓派編寫、上傳、通信的,于是也免去了電腦連接Arduino的步驟,讓一切更流暢無縫。
樹莓派的Linux系統支持圖形桌面,你可以使用RealVNC(用于Windows)或TightVNC(用于Mac)遠程登錄圖形桌面。(這個課題里不需要)
這是課題的核心部分,反而操作起來最簡單,因為一切都在這里寫清楚了,按部就班就行。運行代碼在這里。
注意:這里用了訓練好的模型,即TensorFlow中預先給定了訓練好的參數集,訓練圖片庫是ImageNet。也就是說,小車識別出的物體只能是圖片庫里包含的labels,也沒有“學習”的過程。
小車套件(robot chassis)很多,選你喜歡的一款。標準的套件包括一個基座,兩組馬達+輪子,一個萬向輪,一個電池盒。這個課題不需要四驅,而且之后要用到的馬達控制器可能只支持兩個馬達。我用的是張堯姐送給我的第一個DIY套件:一個戳了很多洞的木板和3D打印出來的輪子和連接部件。這個恐怕是蘿卜太辣最早的套件,來自硅谷的創客空間。
現在,蘿卜太辣正式出品的“起源”套件已很完善,線上也有成熟的教學資源。這個課題里用到的舵機和金屬連接部件都來自堯姐送給我的第二個套件——“起源”套件。但從感情上來講,那套粗糙的木板套件讓我更親近,符合“用最簡單的材料實現原型”的理念。
電源:樹莓派需要5V、2A電源,放在小車上的話需要一個電流足夠大的充電寶。連接樹莓派和Arduino的連接線同時也為Arduino供電。但是,馬達我用了外部電源(電池盒)。你會發現即使沒有外部電源,充電寶依然可以帶動馬達(盡管很慢)。但是,好的習慣是機械部分獨立供電;邏輯電路部分由充電寶提供。
下一步,操控小車。這里有兩個方案,第一個不需要Arduino。我使用的是第二個。
我認為單片機的精髓,不是尺寸小,而是豐富的GPIO(General Purpose Input-Output),它們是程序與外部世界對話的窗口。你看到的各種電子部件、探頭、焊接、面包板,都是在和GPIO打交道。你需要了解基本的電路知識,也需要知道它們在單片機上的排布。樹莓派有一個非常好用的GPIO Python庫:gpiozero,使用方法一目了然。
通常用四個端口控制馬達,分別連接兩個馬達的正負級,通過每個馬達的正向/逆向旋轉來實現小車的前進/后退/轉向。實現雙向電流的標準電路模型是H橋接。你可以選購一款最基本的H-bridge模塊。
因為我手頭沒有H橋接,所以這個方案我沒有實現。
我沒有H橋接,但有一個用于Arduino的Motor stacking shield,即Arduino上的H橋接。于是我干脆用Arduino負責機械(馬達+舵機),相當于身體;樹莓派只負責圖像識別,相當于大腦。
Arduino不是Linux系統,不能直接ssh進去寫程序,需要在外寫好后編譯上傳。我用數據線連接了樹莓派和Arduino,在樹莓派上寫好程序后上傳。我發現一個非常好用的命令行IDE:PlatformIO(也有很棒的圖形界面編輯器)。Linux上的安裝過程基于Python 2.7。你需要一些初始化,如果像我一樣是Arduino Uno主板,輸入以下命令即可:
pio init -b uno
Arduino的C++源代碼在這里。進入這個文件夾后,輸入以下命令即可上傳:
pio run –target upload
后來我發現PlatformIO對于Arduino主板好像不支持C++11,如果你有這個需要,可以考慮inotool。
同樣有兩個方案:無線鍵盤,紅外遙控。兩個方案我都實現了。
如果你在上一步用了3.1,無線鍵盤操控模塊就可以直接嵌入到機械操控代碼中(我沒有實現)。如果你在上一步用了3.2,那么需要在樹莓派上將按鍵操作轉為機械控制信號(文本形式),通過串口通信(Serial Port)操控Arduino。
python代碼在這里,用到了我自己寫的庫,用來檢測鍵盤按鍵。這個庫將單次按鍵匹配到前進/后退/轉/停止等行為;但我希望實現的是長按鍵前進/后退/轉,不按鍵時停止。但我始終沒有找到現成的庫(Update:據說在PyGame里有)。
后來我試著通過背景線程(threading)和系統延時的方法寫了一個庫,但效果不太理想,系統延時和程序運行時間帶來的誤差總是匹配不好,就放棄了。現在代碼里用的是單次按鍵行動/停止的方案。如果讀者有好的庫,請推薦!
有一點要注意,使用串口通信前需要disable login(既然你已經ssh遠程登錄了),這篇解釋比較清楚。
紅外的長按返回的是一個單獨的值(REPEAT),這點就可以讓我很容易實現“長按-車動,不按-車停”。此外,紅外遙控的代碼直接寫在Arduino的C++代碼里,不需要通過樹莓派和串口通信,更符合Arduino作為機械總控的設計原則。
PlatformIO不自帶紅外的庫,我用的是這個。PlatformIO使用第三方庫實在太簡單了,不需要下載安裝,直接在配置里加上GitHub鏈接即可,參考我的配置文件。
還有一點,每一個紅外遙控都不一樣。家里的電視機、音響、空調遙控都可以用,你只需要在使用前匹配好按鍵和對應的碼。我在代碼里define的一堆KEY只適用于我的遙控器。你可以用這個代碼來獲得鍵碼。注意:紅外遙控有幾種模式,我的遙控用的是最常見的NEC模式,如果你匹配出來一堆亂碼,可以考慮庫里的其他幾個模式。
對了,如果你用紅外遙控,你還需要在車上裝一個IR Receiver。我裝在Arduino上,用8號端口。
如果你用了方案3.1,你也可以直接將IR Receiver裝在樹莓派的GPIO上。
這些已經夠你開車上路了。我在車上裝了舵機(Servo),控制攝像頭的上下轉動。操作很直觀,看代碼就能理解。我沒有裝超聲探頭,這個可以幫助你檢測障礙,在撞墻前強行停止。
如果你想遠程看攝像頭的實時畫面,VNC不能勝任。可以考慮這個方案。但這樣的話TensorFlow就不能再用攝像頭了。應該有一個共用的方案,我沒有探究。
差不多就這些了,我的代碼沒有太多注釋,等有空往上加。如果你有疑問,可以留言問我。
福利:這里有一個延時攝影的簡單程序,我在crontab里設置為每隔一分鐘拍一張照,然后每天半夜將當天拍的照轉成錄像。下周打算帶到公司里,找個風景好的位置,放幾天,拍紐約的24小時風景。
雷峰網版權文章,未經授權禁止轉載。詳情見轉載須知。