Rust如何改變機器人:
- 在大約九個月的時間裡用Rust從頭開始編寫了整個設施控制系統
- 我們用Rust編寫了一個完整的10萬行工廠控制器,我們從來沒有使用過不安全的C
以下是對 AMP Robotics 機器人架構師 Carter Schultz 的採訪,他是AMP Robotics的機器人架構師。AMP Robotics是一家專注於回收領域的尖端機器人技術公司。採訪中,Carter分享了他的背景、AMP正在做的工作,以及他對Rust如何根本改變典型機器人架構的思考。
教育成長
Carter在高中時期透過參與機器人競賽隊對機器人技術產生了濃厚的興趣,並在大學期間獲得了機械工程學位,同時選修了許多電氣工程課程。
本科畢業後,我的計劃是讀研究生。我是整個家族中唯一沒有研究生學位的人。所以,我以為這就是出路。我被錄取去佐治亞理工學院攻讀博士學位,或去卡內基梅隆大學攻讀碩士學位。我當時正在篩選這些選擇,然後我隨意地向 SpaceX 投了簡歷。我沒怎麼想,直到我接到了面試電話。大學四年後,我決定也許工作會更好。
所以,我在最後一刻做出了轉變。我最終在 SpaceX 的一個叫做運載工具操作開發的小組工作,該小組負責自動處理發射場的火箭。大部分工作都在卡納維拉爾角進行。
該小組正在製造用於拾取火箭、轉動火箭等的裝置。我花了很多時間在機庫內起重機的軟體控制上。
我被錄用的小組只有機械工程師。當時 SpaceX 正遭受著部落主義和工作阻礙。該小組負責製造機器人,但全部由機械工程師組成。因此,機械工程師會設計機器人,然後他們會被困幾個月等待電氣工程小組,然後電氣工程小組又會等待軟體小組。將整個整合系統整合在一起是一項真正的挑戰。
因此,我被聘為機械工程系的軟體工程師。我幾乎什麼都不做,只是為他們編寫軟體。
入職AMP
當我第一次來到 AMP 時,我非常不確定這是否是我想要做出的選擇。我之所以能來到這裡,很大程度上是因為我打電話詢問了業內人士 Matanya 的情況,他享有金童般的聲譽。人們會說,“我甚至不知道 AMP 在做什麼,但如果 Matanya 在做這件事,你應該去那裡工作。”最後,Matanya 帶我出去吃飯,我當時想,好吧,計劃是什麼?當時,他們剛剛開始生產第一批拾取和放置回收機器人,而他根本沒有談論它們。這些只是飛輪,最終將讓 AMP 建造全新的未來回收設施。
當我加入公司時,公司已經運營了兩年半左右,公司裡的每個人都在給回收的幀貼標籤,以建立初始資料集。好像公司裡沒有不給幀貼標籤的人:離總部 15 分鐘路程的地方有一個回收設施,基本上給我們提供了一段傳送帶,讓我們想做什麼就做什麼。所以,最初的團隊立即就把相機放下來,開始將幀上傳到雲端。
AMP 在物體分類領域還處於早期階段,當時還沒有現成的解決方案來構建自己的資料集。因此,我們不得不從頭開始編寫自己的標記工具。如今,有大約 20 家公司向我們敲門。因此,無論好壞,我們最終都從頭開始構建了大量的基礎設施。
轉向Rust
Carter的職位涉及多個領域,他負責為專案設定技術基礎和結構,確保最終產品符合預期。
Carter對C++感到失望,因此開始探索使用Rust作為替代語言。AMP決定在其新建的回收設施中使用Rust從頭開始構建控制系統,Carter認為這是一個正確的決定。
最終,一個大型綠地專案的機會出現了。AMP 決定首次建造自己的回收設施,我們需要一個可以執行整個設施的控制系統。該系統將與網路上的數十個子系統和數百臺裝置進行通訊。這不是一件非常複雜的事情,但由於它控制著整個設施,所以它必須是萬無一失的。
所以,這是一個足夠新的專案,我們可以用 Rust 從頭開始。我決定用 Rust 來做,我堅信這是正確的決定。
我們一開始只是對 Rust 進行了一些嘗試,每個人都同意他們喜歡它並且它會起作用,所以我們繼續前進。所以,我們在大約九個月的時間裡用 Rust 從頭編寫了一個完整的設施控制系統。實際上,我在 RustConf 2023 上發表了關於構建這個系統的演講。該專案的成功基本上讓我成為了一名完整的 Rust 佈道者。現在,我想知道我們能多快擺脫 C++ 並將所有內容轉移到 Rust?
我不是瘋子。我知道把我們所有的 C++ 程式碼都扔掉並說現在一切都是 Rust 是不對的。我們必須逐步遷移。我們必須尊重遺留程式碼,找到與 C++ 功能相匹配的庫,並重新培訓開發人員。但是,我現在肯定會盡我所能,在 AMP 上轉向 Rust。
機器人作業系統 ROS
首先,ROS 不是一個作業系統,而是一個框架。更重要的是,它是機器人的微服務。基本上,有一個訊息匯流排,您可以使用它來編寫機器人應用程式,它是一堆微服務,它們相互發布和訂閱訊息。這是機器人堆疊的基本架構。
所以我深受微服務文化的影響。這是我過去 10 年編寫軟體的方式。我相信微服務是機器人的基本架構。因此,該程序間通訊層允許您使用不同的語言編寫每個微服務,並且它們可以相互操作,因為它們只是傳遞訊息。
因此,我們實際上可以透過一次重寫一個微服務來逐步遷移堆疊。我希望我們可以在重寫這些服務時逐一重寫它們。
當我開始在 AMP 工作時,我們的程式碼庫大約 40% 是 Python,60% 是 C++。這兩種語言是 ROS 支援的兩種主要語言。
很多人在開始使用 ROS 構建東西時,會用 Python 編寫所有內容,因為這樣開發速度更快。我認為這也是一個很好的開始方式。然後,一旦你把所有東西都放到了正確的位置,你就可以開始尋找瓶頸。
我想我職業生涯的四分之一都在用 C++ 重寫 Python,使其速度提高 100-200 倍。我不是 Python 的反對者。你可以編寫非常快的 Python 程式碼。但是,通常我會選擇人們匆忙編寫的程式碼,根本不考慮效能。所以,我們真的有很多機會重寫微服務。
我在 ROSCon 上發表了一個演講,介紹了 roslibrust,這是一個 ROS 到 Rust 的介面庫。這是我們的控制系統與設施中的所有 ROS 裝置通訊所必需的,所以我們非常頻繁地使用它。它的架構和實施方式不利於同一臺計算機上的微處理器之間的通訊。它的開銷相當高。但是,它非常靈活,這對於我們需要中央控制器完成的工作非常有用。
當我們談論同一臺計算機上的兩個程序來回傳遞 GB 的影像資料時,我們確實需要為此獲得正確的工具。
有幾個庫可以做到這一點。我認識這些庫的一些維護者。但不幸的是,這裡更廣泛的背景是,ROS 可以很容易地建立機器人堆疊,但沒有標準方法來執行諸如在世界各地部署的系統上更新軟體之類的事情。
而且,ROS 沒有現成的打包和分發解決方案。因此,圍繞我們的 C++ 程式碼,我們擁有一個完整的 CI 基礎架構,而所有內容實際上都是在 Docker 之上構建的。我們有來自其他 Docker 映象的 Docker 映象,將 Nvidia 驅動程式、TensorFlow 和 OpenCV 以及我們依賴的所有這些軟體安裝到最終的 Docker 映象中,然後可以部署。
而且,我們擁有所有這些有關如何部署這些 Docker 映象的工具。因此,很多東西都必須更新才能支援另一個編譯器、另一種語言和另一組依賴項。
ROS 的未來可能有點不明朗,或者說人們渴望改變。
在過去四年左右的時間裡,ROS 的框架發生了重大變化,最終發展為 ROS 2。我理解他們為什麼在 ROS 2 中做出這些改變,但他們這樣做並沒有考慮到向後相容性。而且,他們為 ROS 2 做出的設計選擇只適合某些人的需求。例如,在我看來,它們適合許多學術界、群體機器人和透過不良網路通訊相互通訊的機器人組。
這些對我們來說都不重要,我們在嵌入在一個位置的一臺計算機上執行一個堆疊,並且我們有一個硬線乙太網電纜連線到它。
因此,業內很多人並沒有遷移到 ROS 2。
我認為今年是 ROS 2 下載量超過 ROS 1 下載量的第一年。越來越多的教育材料和學習 ROS 的新人正在轉向 ROS 2,但有大量公司仍在使用 ROS 1,可能不會放棄它。我親自與其中幾家公司交談過,遷移故事相當殘酷。所以,這是關於 ROS 的第一個重要知識點。
第二個重要知識點是,ROS 不僅僅是一個程序間通訊框架,它還可以讓微服務相互傳送資料。ROS 1 發明了自己的通訊協議,用於序列化和反序列化訊息。我對所有這些都非常熟悉,因為我已經用 Rust 從頭開始重新實現了很多。
但無論如何,這是 ROS 自己開發的東西。在編寫 ROS 1 時,還沒有現成的優秀等效產品。因此,編寫自己的產品是合理的。從那時起,現在有幾十種產品可以為您做到這一點。一個很好的例子就是協議緩衝區。協議緩衝區解決了許多與 ROS 相同的問題。因此,這是 ROS 生態系統的重要組成部分,現在有更多標準的現成解決方案。因此,當他們轉向 ROS 2 時,他們決定這次不會推出自己的通訊系統。
他們從貨架上拿來的一個東西就是 DDS,我不是這方面的專家,所以我不能很好地談論它。我認為它來自汽車行業或航空航天行業。但是,DDS 很混亂。使用 ROS 實現 DDS 的方法不止一種。有三個 DDS 後端是外掛,它們之間有奇怪的差異,在不同的系統上表現不同。所以,一般來說,ROS 社群都覺得 DDS 有點糟糕。所以,這是人們還沒有轉向 ROS 2 的原因之一。
去年在 ROSCon 上,Alphabet 宣佈收購了開源機器人基金會的一部分。我認為這是件好事,因為至少從理論上講,他們將擁有更多火力來對抗 ROS。但是,他們還宣佈將在 ROS 2 中提供 DDS 的替代方案。他們選擇的替代方案是 Zenoh。而且,它是用 Rust 編寫的!
因此,ROS 即將把 Rust 置於專案的核心。
他們有很多部落格文章介紹 Zenoh 為何如此優秀,因為它是用 Rust 編寫的,Rust 更好、更可靠。有點搞笑的是,他們不會讓你直接用 Rust 和 Zenoh 對話!看,在 ROS 1 中,他們決定定義這種通訊機制,然後每種語言都必須實現該通訊協議。這導致了大量錯誤和社群相容性問題。
例如,Java 處理事情的方式與 Python 略有不同,當 Python 與 Java 對話時會出現奇怪的錯誤。因此,對於 ROS 2,他們決定找到一個 C 庫作為機器人中介軟體,每種語言都會呼叫該 C 庫。因此,他們將 Rust Zenoh 層放在該 C 庫後面。您仍將呼叫 C 庫,然後在它的另一端是 Rust。因此,您必須經過一堆奇怪的間接層。您不會感受到 Rust 的原生感覺,而且您必須處理連結和安裝。
ROS 正在向 Rust 靠攏
我認為你不需要 ROS,因為如果你使用 Rust,我不知道你是否真的需要微服務。
使用微服務的第一個根本原因是非同步和並行。你想將機器人思維的概念描述為一個非同步計算圖,其中你在一端接收感測器輸入,在另一端輸出操作。資訊流經該圖,每個節點都儘可能快地處理最新可用的資料。這是編寫機器人的一種非常好的方法。你不想用中央迴圈或類似的東西來編寫機器人。這會給你帶來很多效能瓶頸問題。
因此,最好將應用程式分解成許多非同步任務,這些任務動態地相互傳送和接收資訊。這可以讓你更好地利用現代計算硬體,並行執行更大、更重的演算法。
在 C++ 中,很難有效地編寫,而不會出現各種記憶體洩漏、各種執行緒鎖定問題和互斥地獄。在 Python 中,由於 GIL 和多執行緒 Python 的效能問題,這幾乎不可能實現。因此,ROS 提供了一種將所有這些作為單獨程序編寫的方法。因此,如果任何單個微服務分段發生故障或丟失記憶體,它將終止該節點。該節點將重新啟動,但整個應用程式不會關閉,因為記憶體損壞和未定義行為被鎖定在各個節點的程序邊界上。所有這些都會帶來大量開銷,因為序列化所有這些訊息並透過 ipc 層傳送它們比共享記憶體訪問要慢得多。
那麼,如果我現在有了 Rust 會怎樣?這是一種語言,我可以在其中編寫一個相互連線的各個任務的非同步圖,並且可以知道其中任何一個任務都不會發生未定義的行為。我知道不會發生記憶體損壞,其中一個任務會拖垮其他任務。而且,您不必使用 ipc 層來序列化資料並透過套接字傳送出去,而是可以使用 Rust 的通道和低階同步機制免費傳遞資料。這取代了我主張使用 ROS 的大多數理由。
現在,實現任何這些目標都面臨一個巨大的障礙。那就是驅動程式。驅動程式是我整個職業生涯中都在處理的一大問題。例如,我們在機器人上執行的應用程式可能有 150,000-200,000 行 C++ 程式碼。但是,我們呼叫了其他人的四百萬行 C++ 程式碼。你根本無法完全靠自己編寫機器人。你必須引入其他人的東西,而且所有這些程式碼仍然是用 C++ 編寫的,並且仍然有缺陷。
所以,今天我不能說你應該將整個機器人應用程式編寫成一個 Rust 整體,因為現實情況是,一旦你開始呼叫一些供應商程式碼,它就會開始破壞記憶體。它會拖垮你的整個應用程式。
所以,我們還沒有到那一步。但是,看看 Rust 已經走了多遠。如果 10 年後我的相機驅動程式是用 Rust 編寫的,我的電機控制器驅動程式是用 Rust 編寫的,我使用的路徑規劃庫是用 Rust 編寫的,那麼我可以將我的整個應用程式作為一個 Rust 整體來執行。這比我現在使用一組 ipc 微服務所花的開銷要低得多。我還認為除錯和釋出會更容易。
ROS 有一個減少一些開銷的解決方案,即你可以在單獨的程序中編寫所有內容,然後翻轉標誌以將它們編譯為節點。因此,看似單獨的程序會被編譯成一個程序。你可以在 ROS 中以這種方式進行共享記憶體訪問以消除一些開銷。
但是,你仍然會遇到一個問題,即如果其中一個失敗,它會導致整個集合崩潰。如果不這樣做,我們可能會損失 10-20% 的效能。但我認為更大的問題是,將所有內容編寫為單獨編譯的單獨程序會限制編譯器進行大量良好檢查的能力。如果將所有內容編譯為一個 Rust 應用程式,借用檢查器可以跨任務邊界進行檢查,而當你編譯所有內容時,你無法做到這一點。
許多公司都加入進來,在 ROS 之上構建了層,以使其更容易使用。Formant 是一家大公司。Foxglove 是該領域的另一家大公司。他們擴充套件了免費的 ROS。然後,還有一家名為 Viam 的公司。Viam 基本上是在編寫 ROS 的替代品,據說這種替代品更加友好,使用起來也更方便。我認為他們的做法完全錯了。他們試圖透過建立 Web 介面之類的東西,讓你進一步遠離原始碼,你可以在其中進行 json 配置之類的操作。這不是一件瘋狂的事情。它確實解決了使用 ROS 的許多挑戰,但我擔心他們會被現代軟體開發潮流打敗。當你擁有像 rust 這樣的語言時,對許多抽象層的需求就會消失,這種語言可以讓你按照實際應該編寫的方式編寫 API。
有很多軟體工程師對機器人感興趣。您會給這些人提供什麼建議或想法?
我有很多建議,可能涉及幾個不同的方向。首先我想說的是學習 ROS。這是我哥哥給我的建議。我早期用 ROS 做過一個個人專案。這對招聘機器人工程師的人來說非常有吸引力。ROS 目前在世界上大多數地方都是王者,它是一個很好的框架,值得了解,也是一件值得學習的事情。所以,這是非常具體的事情。剛開始有點痛苦,但也不是那麼糟糕。
第二點我想說的是去製造機器人。即使它們很糟糕,即使這個想法很愚蠢,也要自己從頭開始做。你應該用 CAD 設計它,用 3D 列印零件,從 SparkFun 購買電機,把它們連在一起,裝上軟體,讓它做最愚蠢的事情。自己經歷整個過程,瞭解基礎知識,會讓你變得非常有價值。你會比僅僅成為一名軟體開發人員更有價值。你需要知道機械師們在談論扭矩、電流或諸如此類的東西時在說什麼。擁有廣泛的基礎,瞭解一切工作原理,會讓事情變得更好。
此外,實際動手經驗很重要。自己動手做東西比參加無數次講座學到的東西要多得多。
在找工作方面,做一個作品集網站。讓我興奮的是 YouTube 上有人制作的機器人很糟糕的影片。向我展示你做過的東西是十分重要的。我要強調的另一件事是自己解決問題。你遵循的教程越多,你從中獲得的經驗就越少。
機器人技術的一個著名特點是,機器人比人們想象的要難得多。
所以,你會想出一個太難的想法,你會做到一半,意識到它有多複雜,然後你會拋棄它,想出一個更簡單的想法,並真正做到這一點。我見過五隻機械臂組成的時鐘,可以在白板上寫上時間。聽起來很簡單,但這些專案很難!如果你真的能做到,我會為你鼓掌。我知道這需要多長時間才能完成。