[轉]使用rosbridge協議實現安卓跟ros的解耦
安卓與ROS通信的現狀
因為ROS官方支持的語音綁定只有C++和Python,所以目前安卓想與ROS通信,必須借助半官方的rosjava包,而Rosjava太重了,因為它跟C++/Python一樣,是一個全功能的ROS綁定,意即你可以在Java(android)平臺上創建Master Node,然後其他Node(C++/Python)可以連上這個Master,進行分布式通信!這對於桌面Java或許還能接受,但對於android實在是過於復雜了。
另外,rosjava的gradle腳本太復雜,需要很深的gradle知識才能將其集成到自己的android工程,很多公司(比如我們-_-!)嫌麻煩直接導入rosjava的demo工程,然後將自己的代碼添加進去,團隊裏如果有新人加入,則還要重新搭建一個rosjava環境,太麻煩了
rosbridge協議
很多人都覺得移動平臺or嵌入式系統要實現跟ROS進行分布式通信成本太高昂,大家尋思用C/S架構可能更符合移動平臺的需求,於是提出了rosbridge協議,該協議的基本思想是將節點間的分布式通信,改成client節點與一個代理節點進行C/S通信,然後代理節點再將請求轉發給server節點,這樣移動端就不需要實現整個ROS平臺,只需要跟代理節點通信即可。
這是一篇比較rosjava跟rosbridge優劣的pdf,簡單來說,就是移動平臺以犧牲做server節點的代價,換來了輕量級ROS交互的能力。不過特殊情況下rosjava還是有用的,比如機器人的底盤調用機械臂的service,如果機械臂只支持rosbridge,則調用不可行——不過這種情況通過pub/sub應該也能解決。
ROSBridgeClient庫
要讓android能收發rosbridge消息,首先要支持WebSocket這種特殊的傳輸通道才能實現android接收ROS端publish(推送)過來的消息,目前實現WebSocket的大部分集中在桌面Java,比如Jetty、Netty等,其中Jetty因為用到了某些Dalvik VM不支持的java類而導致不能在android上使用。另外android自身的webview對WebSocket的支持較晚,不能保證全機型覆蓋,所以Java-WebSocket這個用java.nio包裏的類實現的WebSocket就脫穎而出。
有了傳輸通道,剩下的就是怎麽組包發送了,這個庫不僅要將發送的Java類型轉換成語言無關的ROS消息類型(反之亦然),還要將ROS操作(訂閱、發布、調用service、廣播topic等)轉換成rosbridge裏規定的json串,在評估了java_rosbridge庫和ROSBridgeClient庫後,我選擇了後者,因為前者雖然更小巧,但是用的jetty來實現WebSocket通信,沒法跑在android上
添加std_msgs包裏的消息類型
在試用ROSBridgeClient庫的過程中,我發現作者連std_msgs裏的消息類型——例如String——都沒有實現,卻而代之的,是一個精巧的註解加反射機制實現的meta message類型,要擴展很簡單,見我fork出來的repo
在摸索std_msgs的過程中,我弄明白一個機制:ROS的內置類型其實並不是實際存在的,它必須對應到具體語言的內置類型,所以為了跨語言通信,所有Message只能使用Wrapper類型,這就解釋了為什麽std_msgs包裏一堆wrapper了,因為每個msg文件裏的內置類型(比如string),都是不存在的,必須對應到Java的String,或Python的str、或C++的std::string,唯獨不能對應ROS的string,因為ROS不是一門語言。
[轉]使用rosbridge協議實現安卓跟ros的解耦