高手可以談談ROS機器人操作平台開發的一些經驗嗎?

據說國外開發機器人用的是ROS,可是ROS網站的說明不太好理解,所以想請教一些使用ROS的經驗。


前言

我在大二的時候加入到了西北工業大學舞蹈機器人基地RoboCup@Home項目組,主要負責家政服務機器人曉萌機械臂的軟體開發部分。在開發的過程中,我曾遇到並解決過一些問題,也算是積累了一些機械臂開發的經驗,因此現在我打算將這些經驗分享出來,希望能給那些正在使用ROS來開發機械臂的後來者們提供一些幫助。當然,寫得不對的地方歡迎各位大神指正。

以下,我從技術介紹和學習流程兩個方面來進行講解。其中技術介紹方面又分為機械、電子和軟體三個章節。由於我在項目組裡做的是軟體開發工作,對機械和電子了解得相對較少,因此機械和電子這兩個章節的內容我會簡略地介紹,而講解的重點自然便是軟體章節。最後關於學習流程方面,我從基礎、進階、高級以及資源這四個章節來分別進行敘述,力求將自己的學習方法完整地呈現出來。

技術介紹

機械臂作為機器人最為重要的執行器,賦予了機器人與外部世界環境進行物理交互的能力。這使得機器人的智能不僅僅停留在識別和規劃層上,還能通過實際的操作將其真正的表達出來。目前國內外機械臂研究的熱點主要集中在機械臂自主精確抓取、放置物體上,而根據本人之前的開發經歷,要想讓機械臂能完美地執行一系列複雜且精確的操作從而使末端執行器到達預定的位置是很難的,這需要我們理解並掌握很多與機械臂解算相關的數學知識。我相信這會讓很多非專業開發者感到頭疼,不過藉助於第三方開源軟體,比如ROS和MoveIT!機械臂的開發就會相對來說簡單很多。下面,我分機械、電子和軟體三個方面,詳細地講解一下自己在開發過程中所總結的一些技術要點。最後,你可以在開發代碼(在ROS Indigo下能成功編譯並運行,不支持ROS Kinetic)和問題匯總中找到我之前整理的相關資料。

機械

我們機器人的機械臂在機械設計上有一些不一樣的地方。相比於其他使用大扭矩舵機或電機作為關節的機械臂,我們使用了由同步輪和同步帶所組成的機械結構,這種獨特的結構使得我們的機械臂在一定程度上擁有了抓取更重物體的負載能力。除此之外,機械臂末端的手爪也由上一代的對稱張開閉合的結構變成了平行夾緊的形式,即兩個金屬滑塊可以通過在滑軌上對稱平行的移動。這使得手爪可以適應不同粗細、形狀的物體,為抓緊物體提供最基本的保障。當然,這個機械臂也曾經給我造成過一些小困擾,我會在下面的軟體部分講到,通過這個困擾的解決,你就可以理解為什麼機械的設計在某種程度上會影響軟體代碼的編寫。

電子

電子部分作為連接機械臂軟硬體的重要組成部分,主要的任務是負責將軟體組通過RS-485傳過來的數據進行解析,並且以最快的速度傳遞給接有驅動盒的電機來實時地控制機械臂。同樣的,通過電機編碼器返回的數據可以用來記錄每個機械臂關節的實時狀態,經過一定的數學解算,就可以將其作為運動規劃層的輸入,為複雜運動的規劃提供基本的保證。機械臂控制使用的是位置閉環演算法,具體這方面我了解的並不是很多,不過之前用起來還是很穩定的。

軟體

從軟體架構圖中可以很清楚的看到,機械臂的軟體層主要由三個部分組成,從下到上依次為:硬體介面層、運動規劃層和任務決策層。

硬體介面層

機械臂硬體介面層的設計理念來源於ROS Control。ROS Control是ROS提供的軟體與硬體之間進行數據通信的中間件,它對硬體進行了抽象,統一了數據通信的介面,並通過插件的形式封裝了一些常用的運動控制演算法,為建立機器人軟硬體模塊之間的數據通路提供了便捷。

ROS Control提供的硬體抽象層主要負責管理機器人的硬體資源,而控制器從抽象層請求資源即可,並不直接接觸硬體。這提高了代碼的復用率和可移植性。

首先,讓我們先看一下ROS Control官方提供的數據流圖是什麼樣子的:

細心的讀者可能會發現這兩個架構圖在硬體介面層部分有一些不一樣的地方。接下來我就講解一下硬體介面層部分各子模塊的功能,並解釋彼此不同的原因。

  • 實體機械臂:
    這一部分指的就是真實客觀存在的機械臂。STM32嵌入式控制器使用位置PID閉環演算法來計算由硬體抽象層通過串口通信方式發過來的關節數據,並將計算好的數據直接發送給電機對其進行控制。同時,電機的編碼器也將電機實時的位置數據經串口通信返回給上面的硬體抽象層。
  • 硬體抽象層:
    硬體抽象層和硬體直接打交道,通過writeread方法來完成對硬體的相關操作。硬體抽象層跟上面官方提供(紅色的部分)的有一些不太一樣的地方在於我並沒有使用ROS Control提供的Transmissions(數據轉換)和Joint Limits(關節限位)的API。原因的話,我在下面會講到。這首先簡要的介紹一下什麼是Transmissions和Joint Limits。
    • Transmissions:
      Transmissions就是機器人每個運動關節和電機之間的數學映射。因為機械臂關節結構的不同,會導致機器人上層規劃所使用的Joint與Actuator數據之間存在明顯的偏差。比如說有簡單齒輪和同步帶驅動的,有錐齒輪差動機構,四連桿機構等。Transmissions提供的介面中包含有解決上面這些結構進行數據轉換的映射公式。
    • Joint Limits:
      Joint Limits主要是維護了一個關節限位的數據結構,裡面可以包含的數據種類不僅僅是常用的關節位置、速度、力矩、加速度等方面的限位,還可以儲存具有安全作用的位置軟限位、位置邊界和速度邊界等。

至於我為什麼沒有使用以上兩個模塊的原因,主要是參考了西工大一小學生曾經在Exbot上發表的有關ROS Control的文章。下面就截取其中的一小部分:

以上兩個模塊是因為URDF中有相應的標籤,寫了一堆可以直接Load的,但是實際用處並不是很大。它的設計思想是想在URDF中表示更多的信息,這些信息在Gazebo中可以給出更多的細節。但是解析URDF的程序使得RobotHW體量很大,而且這些細節會因為機器人本體通訊暴露給ROS的細節量而不盡相同,而且還會顯著提高編程複雜度,所以這些信息顯得冗餘,而應用這些信息的庫也就顯得冗餘。

之前,我是有嘗試過在RobotHW中載入URDF中的相關標籤,不過用起來確實就如同小學生所說的那樣,比較麻煩,而且還很冗餘。因此,我根據機械組隊員提供的有關機械臂關節電機轉換的數學公式封裝了相應的函數,至於Joint Limits,我是在規劃層的地方進行了指定。

  • 控制器管理器:
    控制器管理器提供一種通用的介面來管理不同的ROS Controllers,它可以載入、開始運行、停止運行、卸載不同的Controller,並且提供了多種工具來完成這些操作。Controller Manager的輸入就是ROS上層應用的輸出。在這裡面,我用到了Joint Command Controller和Joint State Controller,它們分別可以完成對每個關節的控制以及讀取硬體介面中關節的狀態。

好的。前面講了很多新的概念,這裡我們還是找個案例來具體的分析一下。這裡,以我之前整理的源碼作為參考,分析一下機械臂分別在Gazebo模擬和物理物理環境中是如何體現上面那些概念的。

首先看一張來自Gazebo官網的ROS Control架構圖:

從圖中可以看到,SimulationHardware之上的Hardware Resource和Controller Manager是一樣的,這很清晰地體現了ROS Control的底層無關性,即無論使用的是抽象的模擬還是具體的硬體,只要程序能繼承RobotHW硬體抽象層的基類來做到數據介面的統一,Controller Manager就可以對相應的資源進行管理。

對於SimulationHardware來說,它們內部架構相似,但配置以及使用方式是不一樣的。Simulation的RobotHW部分,Gazebo官方已經將其實現,並且提供了相應的ROS Control插件來從機械臂的URDF文件中載入所需的數據。用戶只需寫好URDF和YAML文件,並使用ROS Launch將其整合到一起就萬事大吉了。

而對於Hardware這部分來說,除了上面說到的配置之外,我們還需要自己編寫C++代碼來繼承RobotHW基類,並在裡面分別使用命令和狀態硬體介面句柄對相應的關節數據進行註冊,然後再將不同的硬體介面註冊到RobotHW上。最後,我們還要自己編寫函數完成對關節和電機數據的相互轉換,並且根據指定的通信協議,實現readwrite函數。

  • 模擬部分:

在終端中輸入以下命令啟動Motion Control測試。

$&> roslaunch xm_arm_bringup xm_arm_bringup_gazebo_joint_control.launch
$&> rosrun xm_arm_teleop xm_arm_teleop_position_keyboard

你可以使用鍵盤上的按鍵來控制機械臂每個關節的移動位置。

  • 硬體部分:

(1)創建子類繼承RobotHW父類,並且聲明了一些函數和變數。

(2)初始化關節和電機數據,並使用Hardware Interface對相應的數據進行註冊,最後初始化與串口通信有關的Topic。

(3)根據機械臂公式,實現關節和電機數據之間的互相轉換。

(4)實現定製的read和write函數。

(5)載入關節名字到ROS的參數伺服器中。

以上就是硬體介面層的全部內容了。作為整個機械臂軟體架構最底層的部分,它的重要性不言而喻。根據我之前開發機械臂的經驗,只有編寫出穩定且魯棒的的硬體介面層,才能為之上的運動規劃提供強有力的保證。否則,等到機械臂出現暴走失控的情況的時候就麻煩了(我之前就曾入過這樣的坑!)。

運動規劃層

運動規劃層在機械臂的自主抓取中扮演了非常重要的角色。而對於運動規劃本身來說,裡面涉及了非常多的專業知識,比如運動學正逆解算、碰撞檢測演算法、3D環境感知、動作規劃演算法等,以上任何一個方面都需要我們長時間的積累才能理解清楚,而對於那些想立馬上手機械臂的初學者來說,這簡直就是一個災難。

而幸運的是,ROS提供了強大且易用的MoveIt!包,它可以讓你在較短的時間內實現模擬乃至實體機械臂的運動學規劃演示。

首先,簡要地介紹一下什麼是MoveIt!。以下是MoveIt官網給出的定義:

MoveIt! is state of the art software for mobile manipulation, incorporating the latest advances in motion planning, manipulation, 3D perception, kinematics, control and navigation. It provides an easy-to-use platform for developing advanced robotics applications, evaluating new robot designs and building integrated robotics products for industrial, commercial, RD and other domains.

概括來說,MoveIt!是ROS中與移動操作相關的組件包的集合。它包含了運動規劃、操作控制、3D感知,運動學,碰撞檢測等。當然,最重要的是MoveIt!提供了非常友好的配置和調試界面。

下圖是MoveIt的總體框架:

這張圖我在學習MoveIt!的時候看過很多遍,理解這個架構圖對於學習MoveIt!非常重要。從圖中可以看到,move_group是MoveIt!最核心的部分。它將其他獨立的組件集成到一起,為使用者提供了一系列可以使用的命令和服務。

  • 用戶介面:
    用戶可以使用C++、Python或者GUI來訪問move_group。一般對於初學者來說,GUI和Python的使用會更多一些。
  • 配置:
    move_group本質上還是一個ROS的節點,它需要使用ROS的參數伺服器來獲取以下三種信息。
    • URDF:
      move_group需要機械臂的URDF文件來進行運動規劃。
    • SRDF:
      move_group在啟動時會尋找機械臂的SRDF文件,它可以通過使用MoveIt! Setup Assistant自動生成。
    • MoveIt!配置:
      move_group在啟動時會載入機械臂的關節限位、動力學、運動規劃、感知以及其他相關信息。所有以上的配置信息都可以通過使用MoveIt! Setup Assistant自動生成。
  • 機器人介面:
    move_group使用ROS中的Topic和Action兩種機制來與機械臂進行數據通信。它可以獲取當前機械臂的位置信息,點雲數據以及其他感測器數據,並且發送命令給機械臂的Controller。
    • 關節狀態信息:
      move_group會監聽機械臂的/joint_states主題來獲取當前的狀態信息。注意:move_group只管監聽,你需要自己給機械臂配置好Joint State Controller。
    • 坐標轉換信息:
      move_group可以訂閱機械臂的TF主題來確定機械臂內部各關節之間的位置變換關係。跟上面一樣,你需要自己運行Robot State Publier節點來發布坐標轉換。
    • 控制器介面:
      move_group使用Follow Joint Trajectory類型的Action介面來與Controller進行數據通信。move_group自己是不帶Action介面的,它是使用了一個特殊的插件來發布上述Follow Joint Trajectory類型的Action,而對於機械臂來說,你依然需要自己配置上述類型的Controller來訂閱機械臂的數據。
    • 規劃場景:
      Planning Scene指的是機械臂本身以及其周圍環境的表示。
    • 擴展能力:
      move_group的所有組件都是以獨立插件的形式實現的,而且這些插件可以通過使用ROS的參數文件或插件庫來進行配置,這使得move_group擁有了強大的定製以及可擴展能力。

接下來,我們介紹一下Motion Planning

這裡我引用古月居前輩對運動規劃的解釋:

假設我們已知機器人的初始姿態和目標姿態,以及機器人和環境的模型參數,那麼我們就可以通過一定的演算法,在躲避環境障礙物和放置自身碰撞的同時,找到一條到達目標姿態的較優路徑,這種演算法就稱為機器人的運動規劃。機器人和環境的模型靜態參數由URDF文件提供,在默寫場景下還需要加入3D攝像頭、激光雷達來動態檢測環境變化,避免與動態障礙物發生碰撞。

在MoveIt!中,運動規劃演算法是由運動規劃器算出來的。當然,運動規劃演算法有很多,每一個運動規劃器都是MoveIt的一個插件,可以根據需求選用不同的規劃演算法。MoveIt!默認使用的是OMPL。OMPL(Open Motion Planning Library)是開源運動規劃庫的簡寫,它提供基於隨機化的運動規劃器。

  • 運動規劃請求:
    在讓運動規劃器進行運動規劃之前,我們要先發送一個運動規劃的請求。這個請求可以是新的機械臂或末端執行器的位置。為了讓運動規劃器規划出來的軌跡符合要求,我們需要指定一些約束條件:
    • 位置約束:
      約束機械臂Link的位置。
    • 方向約束:
      約束機械臂Link的方向。
    • 可見性約束:
      約束Link上的某點在某些區域的可見性。
    • 關節約束:
      約束Joint的運動範圍。
    • 自定義約束:
      使用自定義的回調函數來指定約束條件。
  • 運動規劃結果:
    move_group節點最終將會根據上面的運動規劃請求,生成一條運動軌跡。這條軌跡可以使機械臂移動到預想的目標位置。請注意:move_group輸出的是一條軌跡,而不是路徑。對於機械臂來說,路徑是使末端執行器移動到目標位置的過程中,中間所經歷的一系列獨立的位置點。而軌跡則是在路徑的基礎上,通過加入速度、加速度約束以及時間參數來使機械臂運動的更加平滑。
  • 規劃請求適配器:
    在運動規劃器的輸入輸出端分別有兩個規劃請求適配器。它們的作用分別是對規劃請求和規劃結果進行預處理和後期處理。MoveIt!提供了幾種默認的適配器來完成一些特定的功能。
    • FixStartStateBounds:
      當機械臂的一個或多個關節的初始狀態稍微超出了URDF文件中所定義的Joint Limits後,為了能讓運動規劃器可以運行,FixStartStateBounds適配器會通過將關節狀態移動到Joint Limits處來解決這個問題。不過,如果機械臂關節的偏差很大的話,這種靠軟體方式修正的方式就不適用了。
    • FixWorkspaceBounds:
      這個適配器會默認地生成一個10x10x10立方米的機械臂規劃空間。
    • FixStartStateCollision:
      如果已有的關節配置文件會導致碰撞,這個適配器可以採樣新的配置文件,並根據搖擺因子來修改已有的配置文件,從而保證新的機械臂不會發生碰撞。
    • FixStartStatePathConstraints:
      如果機械臂的初始姿態不滿足路徑約束,這個適配器可以找到附近滿足約束的姿態作為機械臂的初始姿態。
    • AddTimeParameterization:
      這個適配器非常重要。它把從運動規劃器中輸出的空間路徑按等距離進行劃分,並在其中添加加速度、加速度約束,以及時間戳等必要信息。

Planning Scene

Planning Scene用來表示機械臂周圍的外部世界並且保存機械臂自己本身的狀態。它通過監聽對應的Topic來獲取關節狀態信息、感測器信息。並可以根據感測器信息和用戶的輸入,生成機器人周圍3D世界空間的表示。

3D Perception

簡單來說,3D Perception使用插件來獲取點雲和深度圖像數據,並據此生成OctoMap,為之後機械臂的碰撞檢測提供基礎。

Kinematics

運動學演算法是機械臂各種演算法中的核心,尤其是反向運動學演算法IK(Inverse Kinematics)。MoveIt!使用插件的形式可以讓用戶靈活的選擇需要使用的反向運動學演算法,也可以選擇自己的演算法。

Collision Checking

MoveIt!使用CollisionWorld對象進行碰撞檢測,採用FCL(Flexible Collision Library)功能包。碰撞檢測是運動規劃中最耗時的運算,往往會佔用90%左右的時間,為了減少計算量,可以通過設置ACM(Allowed Collision Matrix)來進行優化。

好的,講了這麼多抽象的概念,就讓我們像上一節講ROS Control一樣,用具體的例子來實踐一下。

首先,你需要機械臂的URDF文件,而且保證裡面所包含的Link(連桿)、Joint(關節)、運動學參數、動力學參數、可視化和碰撞模型沒有問題。這裡要注意一下,通過SolidWorks插件導出的URDF文件,它默認使用的碰撞檢測模型和可視化模型是一樣的。為了提高運動規劃的執行速度,你可以使用MeshLab來簡化模型(.stl或.dae零件)的點和面。

之後,運行下面命令來啟動MoveIt! Setup Assistant。

$&> rosrun moveit_setup_assistant moveit_setup_assistant

之後你可以根據MoveIt! Setaup Assistant官網教程完成機械臂的配置。雖然這裡我沒有詳細講解配置的每一步(其實是我忘了截圖),但這一步是非常重要的。我之前就配置過很多次,但總有問題。所以說配置機械臂MoveIt!參數是需要一定經驗的。這裡,我主要講兩個我在配置過程中遇到的問題,希望對你有所幫助。

  • 互動式Marker沒有在末端執行器上生成:
    這個問題曾經困擾了我很久,後來我在Google上搜索了一段時間,終於找到問題的原因和解決辦法。出現這個問題的原因是我在配置末端執行器的時候,parent_link沒有選擇arm組中的link,而是選了gripper組中的。因此,解決辦法就是選擇arm組中的最頂端的link填入到parent_link中就沒問題了。
  • MoveIt!根據點雲數據生成的OctoMap在Rviz中的位置、方向與實際不符:
    這個問題的原因,你可以通過可視化Rviz中的TF插件來看到。每個Link都有自己的XYZ方向,如果你機器人的Camera Link的XYZ方向恰好與Rviz所使用的XYZ方向不符,就會出現上述問題。我的解決辦法是在URDF中再添加一個或兩個虛擬的Link來修正方向上的偏差。

接下來,讓我們運行兩個例子來測試一下MoveIt!。

首先,我們測試一下MoveIt!的Motion Planning。請在終端中輸入下列命令:

$&> roslaunch xm_arm_bringup xm_arm_bringup_moveit_and_gazebo.launch

在Rviz中,你可以使用末端執行器上的互動式Marker來移動機械臂到目標位置。接著,你可以在Planning Library的下拉式菜單中選擇OMPL庫中的某個特定規劃演算法。然後,點擊Plan按鈕,Rviz窗口中就會出現一條從初始位置到目標位置的運動軌跡並循環不斷地播放。最後,點擊Execute按鈕,MoveIt!會將上一步規划出來的機械臂關節軌跡通過FollowJointTrajectoryAction介面發送給Gazebo中對應類型的Controller,使得Gazebo中的機械臂可以移動到目標位置,以下是測試的截圖。注意:不同的規劃演算法所用的時間是不一樣的。請嘗試每一種演算法,並記住最優演算法的名字,這是為了之後方便在代碼中對其進行調用做準備。

第二個例子,我們來測試一下帶有Avoid Collision的Motion Planning。同樣的,請在終端中輸入下列命令:

$&> roslaunch xm_arm_bringup xm_arm_bringup_moveit_and_gazebo.launch

因為我在Gazebo中給機器人的頭部添加了深度感測器的插件,所以當你把桌子放到機器人前方的時候,MoveIt!可以立馬從點雲Topic中獲取物體的信息,並在Rviz中生成可視化的OctoMap。在下一次做運動規劃的時候,MoveIt!會將由正方體組成的OctoMap看成障礙物並考慮在內。圖中,機械臂的初始位置為伸直形態,我將其從桌子的下方移動到了桌子的正上方,規劃的效果如下圖所示。

當然,在使用MoveIt!對機械臂進行運動規劃的時候並不是每一次都能成功,有些時候會出現超時報錯的情況。遇到這種問題的時候,你可以嘗試嘗試其他OMPL演算法,因為不同的OMPL演算法可能對不同的情況有各自的優化。

最後,由於時間的緣故,我沒能將MoveIt!的C++和Python的使用代碼給整理出來,這對於我來說非常遺憾。不過,我相信隨著MoveIt!學習教程的越來越豐富,有關如何用代碼來做MoveIt!的運動規劃會更加容易。

任務決策層

任務決策層處於整個架構圖最頂端,是控制整個機械臂的大腦所在。首先,我要闡明的一點是:這一部分在我那一屆機械臂軟體代碼中並沒有實現,這是我後來總結機械臂開發經驗的時候重新設計的。

至於我為什麼要選擇重新設計新的任務決策層,原因其實很明顯,就是我們之前的那個存在著很多的不足的地方。我們之前的那個任務決策層架構比較鬆散,特別是機械臂的Action介面,我們定義了好幾種,但是其中有幾種的功能比較相近,顯得比較冗餘。而且狀態機可以直接發送Action的Goal到機械臂模塊中,換句話說就是沒有經過封裝的數據是一直暴露在整個任務決策的各個時間段,這會影響數據通信的穩定性,而且這樣的代碼也是不容易維護和重構的。

當然,除了上面存在的歷史問題,還有一個影響我做出改進的因素就是:中科大藍鷹隊可佳服務機器人早期的抓取視頻。視頻中,可佳機器人的機械臂可以非常精準地操作微波爐,並抓取桌子上三種不同的容器。其中最難的是那個盛有牛奶的碗,整個碗只有一個地方向外伸出了一個手柄,能讓機械臂末端手爪精準地抓住碗並且在移動其的過程中不讓碗中的牛奶灑出來,這是非常厲害的。當時看完視頻之後,我就被深深地震撼了,原來機械臂的自主抓取可以做到這樣的程度!後來,西工大一小學生跟我們講:

這個視頻里最厲害的還不是機械臂的抓取,而是可佳機器人的任務決策部分。可佳可以通過對人語義的理解來自動生成相應的任務序列,而且這個任務序列是能被實時的修改和更新的。

因此,我決定對之前的機械臂任務決策模塊進行封裝,把所有與機械臂相關的軟體細節都隱藏起來,最後暴露給外面的只有數據和任務介面。這樣可以大大降低模塊與模塊之間的耦合性,並減少了不必要的進程通信開銷,提高了程序運行時的效率。下面,我簡要地講解一下這個部分的原理。

任務決策層的核心簡單來說是在其內部定義了一個小型的狀態機,它可以根據不同的任務類型、物體位置以及物體的類型來選擇不同的數據發給下面的運動規劃層。這裡我舉一個具體的例子來說明其工作的整個流程:首先,機器人決策模塊給機械臂的任務決策層發送了一個抓取的狀態,任務決策層接收到之後就會在自己事先存儲好的狀態表中進行查找,如果匹配抓取狀態成功,就把表中的狀態鏈取出並放到狀態隊列中去。每次狀態控制器會根據當前狀態隊列中的子動作來分析其所需要的數據。比如說,抓取狀態可以拆分成很多子動作:初始、準備、抓取、手爪張開、手爪夾緊、手握物體等。此時,如果隊列中第一個動作是初始,那控制器便會從預先設定好的機械臂位置池中取出相應的位置,並從MoveIt!參數表中取出其所需要的數據,最後通過MoveIt!介面把初始動作發送給運動規劃層進行規範和執行。當機械臂完成這個動作後,任務決策層會比較機械臂實際運動的位置和預想位置之間的差值,如果誤差小於某個值,其便會返回執行成果給控制器,控制器則會繼續地執行下一個狀態,直到整個狀態隊列中的動作都被執行完。如果誤差過大,則報錯退出,以防止機械臂出現任何不可控的意外情況。

最後,鑒於這一部分只停留在我的設想階段,目前只供參考。至於最終能不能實現出來,還有待日後的驗證。

學習流程

基礎

開發規範

首先,我承認我對規範有一種近似瘋狂的恪守。很多人都覺得學習開發規範對項目開發沒有意義,簡直就是在浪費時間。可是我一直堅信著:只有好的開發規範,才能產生成功的項目。我把學習開發規範作為基礎中的基礎,是因為我曾經在項目開發的過程中吃過這樣的虧。因此,我希望每個開發者都能在為項目開始貢獻之前耐下心來好好學習本團隊的開發規範,並嚴格地執行規範中的內容。這裡,我推薦Google開發規範和ROS開發規範。當然,如果你感興趣的話,你可以看一下我曾經自己整理編寫的曉萌團隊開發規範。

版本管理

我認為掌握版本管理可以說是軟體開發的必備技能之一,也是提高代碼開發效率的絕對利器,希望大家好好地學習一下。版本管理主要涉及Git和GitHub的使用,這方面的學習資料很多,上網搜一下,花一段時間就能入門。

文檔寫作

這方面也有很多的開發者不是很重視。但個人認為如果你想成為真正的強者,只會編代碼是遠遠不夠的,你還需要優秀的文檔寫作能力。比如說你在開發的過程中遇到了一些問題,並成功地解決了。這個時候,你應該及時地將遇到的問題和解決辦法以項目日誌的形式記錄下來,這樣伴隨著項目開發進度的不斷向前,日誌的內容也會越來越多。我敢保證,若干年之後,你一定會擁有別人絕對沒有的寶貴財富!當然,除了開發日誌外,你也要學會如何使用Markdown來編寫項目文檔。Markdown是你與開源世界交流的最重要的工具,一定要學會,況且它也並不是很難學。

編程能力

這個我就不用講太多了,我相信如何學習編程,大家可能知道的比我還多。我這裡主要想強調一下,一定要重點理解、學習C++。畢竟編譯型語言要比解釋性語言Python在執行效率上要高,而且對於機械臂開發來說,MoveIt!中的C++ API也要比Python的要多。

ROS基礎

關於如何學習ROS,我推薦跟我曾經同在西工大舞蹈機器人基地的盛盛在易科上發表過的一篇文章:如何學習ROS——盛盛經驗談。這裡,我想補充一下,對於機械臂開發來說,除了盛盛在文章里講到的那些內容之外,各位還要重點理解以下幾個部分:

  • Action
  • ROS Control
  • Joint State Publisher
  • Robot State Publisher
  • Joint Trajectory Controller
  • URDF
  • Xacro
  • Launch XML
  • Gazebo Connect to ROS

進階

等你學習完以上的內容之後,我相信你已經打下了堅實的基礎。這個時候,你可以開始入門MoveIt!了。學習MoveIt!的時候,一定要多實踐,遇到問題多在ROS Answers上搜一搜,我相信大部分問題的解決辦法你都能找到。有關機械臂的URDF模型,我推薦剛開始入門的時候先從簡單的機械臂模型入手,不要一上來就整個PR2的,一是機械臂關節比較多,二是我估計你的電腦不一定能帶的動。

Gazebo

要熟練地掌握Gazebo模擬軟體,因為我覺得並不是每個人都有機械臂,機械臂的成本確實比較高,這個時候如果你學會了如何在模擬環境下搭建機械臂模型並將其與MoveIt!連接在一起,你就能在一定程度上節約時間、資金成本。當然,模擬是永遠無法替代實物的,這個我之前在開發機械臂的時候就深刻地體會過,不過,把Gazebo當做演算法的前期驗證平台還是非常好的。

MoveIt!

多看看別人的MoveIt!配置是什麼樣的,然後你自己再重新地配置幾遍,主要是熟悉其中的一些概念。最後,在Rviz里試著拖動機械臂到新的位置,點擊Plan按鈕看看MoveIt!是怎麼通過IK來輸出一條平滑的軌跡的。當然,如果你配置好了深度感測器介面的話,可以試一試MoveIt!是如何在有障礙物的情況下進行運動規劃的。

總之,想要開發好機械臂,MoveIt!+Gazebo是必不可少的。

高級

至此,如果你能按照我說的完成前兩步的話,你應該已經會用MoveIt!,並能用其做簡單的運動規划了。當然,如果你想成為機械臂開發大神的話,你還需要重點學習MoveIt!的代碼API。MoveIt!的API不少,你需要多嘗試,找到最適合你們機械臂使用的API(推薦C++的API)。

FCL

在MoveIt!中,碰撞檢測使用的是FCL庫。你需要了解和學習FCL的API,並將其融入到機械臂的運動規劃中去。

OMPL

MoveIt!默認使用OMPL庫來做運動規劃,你可以去OMPL的官網仔細地學習一下它的使用方法。如果你有時間的話,也可以研究一下其他幾種規劃器的效果如何,比如STOMP、SBPL、CHOMP等。

IK解算

如果你認為你已經對MoveIt!的使用了如指掌,你可以嘗試挑戰一下難度——根據你們自己機械臂的實際情況,手寫IK解算插件並將其集成到OMPL中去。

理論

完成以上之後,你如果發現自己還想在機械臂領域有更多的提升空間,那工程開發顯然已經不能滿足你的需求了,你需要閱讀機械臂方面的論文以及專業書籍。這裡我推薦《Robotics - Modelling, Planning and Control》這本書,裡面深入地講解了機器人的建模、軌跡規劃以及運動控制等相關內容。

資源

以下是我認為學習機械臂比較好的資源,推薦給大家。

網站

MoveIt!官方文檔

書籍

《Effective_Robotics_Programming_with_ROS_Third_Edition》
《Learning_ROS_for_Robotics_Programming_Second_Edition》
《Mastering_ROS_for_Robotics_Programming》
《Programming_Robots_with_ROS》
《Robot_Operating_System(ROS)_The_Complete_Reference》
《ROS_By_Example_2_Indigo》
《ROS_Robotics_By_Example》

博客

西工大一小學生:

ros_control攻略

古月居:

ROS探索總結(二十五)——MoveIt!基礎

ROS探索總結(二十六)——MoveIt!編程

ROS探索總結(三十一)——ros_control

redefine:

運動規劃 (Motion Planning): MoveIt! 與 OMPL

基於OMPL的採樣運動規劃演算法(Sampling-based Motion Planning)

yaked:

在qt下編寫基於KUKA youbot API的程序

用ROS控制KUKA youbot的5自由度機械臂和夾子

給KUKA youbot機械臂添加dynamic reconfig

Actionlib與KUKA youbot機械臂

利用rqt_plot與matlab分析KUKA youbot的joint_states信息

KUKA youbot機械臂與Moveit工具包(1)

KUKA youbot機械臂與Moveit工具包(2)

KUKA youbot機械臂與Moveit工具包(3)

Gazebo與ros_control(1):讓模型動起來

Gazebo與ros_control(2):七自由度機械臂和兩輪差速運動小車

Gazebo與ros_control(3):Moveit輸出規劃軌跡到Gazebo

Gazebo與ros_control(4):舉一反三,實戰youBot

邱博士:

使用MoveIt進行運動規劃

實例介紹機械臂運動規劃及前沿研究方向

邱博士知乎問題回答

創客智造:

MoveIt!入門教程系列

總結

我在大二的時候了加入西工大舞蹈機器人基地家政組,負責機械臂的軟體開發工作。那個時候ROS的版本還是Indigo,MoveIt!用的人還不是很多,RoboCup@Home比賽隊伍中用機械臂的還很少。如今接近兩年的時間過去了,當我再次打開MoveIt!官網的時候,教程的數量和質量已經不可同日而語了。我相信現在的機器人愛好者或研究者們要比我當初那會兒更容易地學習並掌握機械臂的開發,並能將其應用到解決當今人們所遇到的問題中去。我們正處在人工智慧的偉大時代,而機器人作為人工智慧技術最為重要的技術載體,需要我們為此付出努力並勇於探索前方未知的道路。最後,我希望這篇文章可以讓更多的開發者邁入機械臂開發的大門,並為機械臂的研究發展貢獻你們自己的一份力量!


剛來知乎,ROS低手關注一下這個問題。

ROS的話我覺得資料現在來講還是比較多的,不過基本沒有中文的......

所以想要學習ROS還的是直接看英語的。像A Gentle Introduction to Ros 或者是ROS By Example,還有一個以色列的大學叫Roi Yehoshua的人的PPT比較不錯,值得參考學習一下。

其實我覺得ROS還是比較簡單的,它只是一個平台。其實最重要的還是這個平台上應用的演算法。我在接觸ROS之前並沒有什麼機器人開發的經驗,所以大多數時間其實是花在這些演算法知識的學習上了。我是在做平面移動機器人的,所以我推薦你先從平面移動機器人入手,比較簡單,而且演算法比較成熟,像navigation,SLAM和mapping,localization用的EKF什麼的,如果比較懶,這些在網上都有現成的Package,設置一下launch file就可以直接用了。

計算機編程還是要有一些基礎的,C++和Python應用的比較多。如果這些不是很熟悉的話,也是可以用MATLAB的,用MATLAB ROS IO Package,在MATLAB官網上已經發布了,有一些簡單的例子,我們這邊做Image Processing的就一直在用MATLAB在做。

沒有實體機器人的話可以多做做Simulation。比較簡單的像Stage啊,再高級一點的gazebo,不過gazebo消耗CPU和顯卡資源很是高,最好是台式機用原生Ubuntu,我的2011年的Dell 14r用虛擬機根本帶不動......

我主要跑一些localization和SLAM演算法,所以以我的經驗,rviz是一個比較好的工具,提供可視化的環境。如果要做一些比較複雜的系統,可能會用到多台計算機,這時候ROS平台的優勢就顯現出來了,可以以輕鬆的設置網路環境,不過要有一些Ubuntu和計算機網路的知識,ROS也可以通過launch file自動設置通過SSH在其他machine上運行node。

最後,還是重複一下前面說過的。我用了快1年的ROS Hydro,能有9成的時間用在了學習機器人的相關演算法上。


最近稍微有一些閑暇的時間,準備堅持在知乎上寫一些機器人相關比較科普的文章,能讓更多年輕人,優秀的年輕人從事並從而推動機器人行業,是我一個大大的心愿~

本來想回答 如何學習Ros? - 機器人操作平台 (ROS) 這個問題,可是題目補充發現問問題是機器人小白,我的回答並不適合小白,所以希望在讀本文的你已經有一些ROS的概念,我不想再說消息通訊機制,ros spin什麼的,希望你至少會在Ubuntu下安裝ROS,知道你用的什麼版本,並且把Tutorial做過一遍吧。。。

從2015年開始創業後,不知道給公司的員工也好,實習生也好,還有高校合作的研究生,各種群里的水友,講過大大小小不知道多少ROS的東西。可是到現在,重新裝一次系統,重新建一個catkin_ws,做一次workspace的overlay,甚至新建一個package,都要去ROS的網站上看看流程。。

因此重中之重首先要強調, ROS Wiki是根本,雖然他寫的太零散,可是從我開始用ROS到現在,Wiki是在不斷進步的。ROS自己的介紹,tutorial, 還有一些package的功能介紹都在不斷變得翔實。所以記住,ROS wiki是永遠不會變得好朋友。可以說只要在開發中,ROS Wiki的頁面就應該打開著。畢竟ROS的版本不斷更迭,很多package也在不斷更迭,要麼自己更新了,要麼有了新的替代品。這些內容,往往看ROS Wiki就會有讓人驚喜的收穫。多說一句,有朋友私信問我用哪個版本ROS學習開發的問題,因為ubuntu我一般用長期支持版,以前在12.04的時候你可以用Fuerte, Hydro,Groovy等,但是14.04就只有用Indigo了, 16.04則要用Kinetic,所以現在可以用Indigo, 最好就上Kinetic。

第二點我想強調一下基礎。就像大學裡要學習專業課之前必須要完成基礎課的學習。ROS就是一門綜合性很強的專業課,之前同學們要學習的基礎課程需要包括Linux,C++(雖然ROS也支持Python,但是C++是根本),英語。這幾點是我覺得制約大多數ROS學習者的關鍵。再要多說些技能的話,要會翻牆用Google吧,ROS裡面的搜索就是Google引擎,不翻就無法在Wiki中搜索。Git要會用吧,以前還挺多庫在svn中,現在基本都要git,而且大多數庫都維護在github中。同時希望大家在享受拿來主義的時候,也盡量為開源社區貢獻力量。自己不搭伺服器也不想用github託管的話,國內http://coding.net也可以的。

第三說一下找資源和解決問題的事情。既然能翻牆就要多Google, 程序上的問題一般stackoverflow的答案都能解決,ubuntu的問題也有askubuntu,國內有一些活躍的ROS相關的qq群,還有一個ROS學習者常去的易科實驗室http://exbot.net。而關於ROS本身,肯定是ros answer最靠譜,不僅要了解怎麼樣找答案,還要學會如何在ros answer上面問問題。畢竟機器人學習開發不是閉卷考試,如何迅速找到答案才是最主要的。

最後,強調一下,就是一定要動手做!做機器人的老生常談就是get your hands dirty!不論你做什麼方向,拿一個項目來做。我就根據大家選擇ROS的目的,稍微給大家不同方向上的一點建議。如果是做研究工作,那麼Gazebo應該是要熟練掌握的,模擬環境可能是學計算機專業的朋友的最愛,所有的參數都可控,上帝視角研究機器人系統,能拿到所有機器人本體以及環境的數據。再加上Rosbag,大家可以輕鬆的重複實驗過程,科學最愛,發表論文容易很多~
但是如果需要基於實際的機器人平台開發,那麼模擬是沒什麼用處的(如果你要用很貴的機器人平台那另說,比如1.8米的人形機器人或者無人車)。這時需要有比較紮實的機器人系統知識和比較強的工科思維能力,比如運動學,坐標變換,一些感測器和執行機構的物理知識,簡單的電路(連接啊模擬數字啊什麼的),要保證機器人平台和軟體中的表達是一致的。這種錯誤往往不容易發現。在Debug的時候,要將物理世界和程序世界一一對應來檢查。
如果要做機器人產品開發(偏演算法),那麼ROS中的關鍵概念都會涉及,比如不常用的plugin,actionlib,nodelet,還包括常用到但是需要更熟悉的比如message,tf,catkin等等。這個問題比較複雜了,展開怕是要講太久。偏硬體的話,Arm版的ROS,各種嵌入式板子(樹莓派啊BeagleBone啊等),Arduino啊,(這個進入了我不擅長的話題),肯定是要都非常熟悉的。

要成為ROS的高手其實有點難度,即便我開發了這許多年,還有很多看了就頭大的問題,更有完全蒙圈不知所措的問題。機器人本來強交叉又多分支,ROS可能難有一個讓大家登堂入室的紅寶書,所以,還要大家堅持學習,循序漸進。


先把官網上的beginner tutorial過一遍. 一定要找台機子跑一下. 光看沒用. 理解了一些基本概念比如 rostopic, rosnode,publisher, subscriber, roslaunch之類的後可以自己做個小項目試試, 比如搭建一個跑ros的小車或者機械臂, 加些感測器用ros聯繫起來. 最後可以試試在gazebo里模擬一下, 做個motion planning什麼的.


低手來關注這個問題,順便談談自己的一些看法。
我感覺了解ROS作為一個工程技術,不把握「big picture」(全貌)的話很難理解進去。

按照我讀的教程http://courses.cs.washington.edu/courses/cse466/11au/calendar/ros_cc_1_intro-jrsedit.pdf來說,ROS不是一個操作系統,雖然他號稱操作系統……他只是一個通信的架構、一個代碼管理的框架。操作系統的功能:任務的時序規劃和CPU資源分配等等工作都是依靠linux來實現的,因此ROS不可能脫離linux,他們是一體的。

另一點可以幫助了解ROS的方法是,學習者必須有機器人應用方面的開發經驗。做過機器人,就會明白機器人的核心平台需要什麼——多感測器和處理器之間的通信、處理器和執行器之間的通信,這些通信必須有統一的時鐘,比如做感測器數據融合,如果從感測器抓回來的數據時間上都不同步,那融合根本沒法做。ROS的通信架構,主要解決的就是這個問題:讓設備之間的通信有一個統一的調度中樞(roscore),通過這個調度中樞不但可以讓信號傳遞更好控制,還能夠通過構建通信設備之間的關係來讓開發者明白自己的機器人內部在幹什麼。而ROS的另一個特點:代碼管理的框架,這個就不多說了,做軟體的都懂得……

以上的回答不能讓你成為ROS的高手,但是我覺得帶著這種"big picture"的理解再去學他應該會快很多。


低手來強答了(,,??.??,,)
利益相關:
大三在實驗室開始接觸ros,大四來機器人公司實習也一直在用ros。認真讀過amcl,nav2d, hector, open karto,tum ardrone等源碼。
先說結論:
學習ros的過程也是不斷理解機器人的過程,也是不斷有新的驚喜出現的過程。
歷程:
大三寫一個無人機光流避障的項目,覺得話題可以包打天下,學學怎麼寫話題。
大三下自己做了一個機器人底座參加馮如杯,開始接觸了tf,才發現這是多麼牛逼的玩意兒,沒tf的ros沒啥用啊。
大三暑假開始實習看navigation的源碼,咦?這個dynamic reconfigure好像很有用的樣子,可以在程序運行時用可視化工具調參數。
這個nodehandle初始化時加一個~原來可以自動加名空間啊。原來ros是單線程的啊。原來ros的話題中,選擇用msg和msgconstptr訂閱會有區別啊。
這個無人機的gazebo模擬好贊,但是上面沒有雷達,自己學一下urdf吧。
這個pluginlib又是幹啥的?好像可以很酷炫地完成不同類的動態載入工作。
這個actionlib又是幹啥的?哦哦原來是用在導航這種長時間不能返回機器人是否完成任務的服務上的。
看moveit,卧槽rviz還能改成這樣。
。。。
總之,學習ros的過程也是不斷理解機器人的過程。脫離實際環境想直接理解ros的某些設定是很困難的。因此建議在看完wiki擁有基本的話題,服務,參數的意識以後多看源碼。畢竟ros這種模塊化設計決定了每一個項目都不會很大,可能用幾天的時間就能看完,也會逐漸發現一些非常有用(裝逼)的東西。


低手用ROS的冒昧答一發,各位有興趣建個群組喵


回答問題

ROS的本質更像是通信庫和模塊的集合,如果你熟悉線程間通信和網路,會發現ROS的本質不過如此,其他的不過是建立在通信基礎上的模塊。


題主究竟問的是使用還是開發呢?題目和描述不大相符讓我糾結萬分。。 o(′益`)o

先從使用說起吧

答主不大喜歡用專業術語,所以。。。請諒解。。。(。?_?。)?

可以把ROS看作是一個大黑板(或者白的), 感測器,機器人或者一些演算法可以看作在底下坐著的同學們(node), 用戶看作是老師。簡單舉個例子:

老師先指定感測器同學,路徑規劃同學還有機器人同學盯緊黑板(⊙?⊙),並完成自己的工作。

感測器同學(node)的工作就是獲得測量數據,所以有時測到一些數據就跑到黑板上把測到的數據(topic)寫在黑板上
路徑規劃同學(node)看到感測器同學(node)寫在黑板上的信息(topic)就拿過來給機器人規劃一下路徑,然後跑到黑板上寫上機器人該走的路徑和速度什麼的(topic)
機器人同學(node)看到路徑規劃同學給的指示就按照指示讓機器人行走

這樣機器人就可以動起來了O(∩_∩)O~~

那什麼是launch呢? 有點像班長。比如路徑規劃同學可以規劃距離最短的路徑也可以規劃消耗能量最小的路徑,這時候提前讓launch君告訴一下要什麼樣的路徑規劃,否則路徑規劃同學就要按照自己的想法(默認)規划了。launch君有時候也可以完成老師的囑託,要讓哪幾個同學同時完成一件事,這樣老師就不用一直費心了(*^▽^*)

使用先到這,回頭有空再更


這是來自機器人公司打雜人員的回答
ROS本質是一個ROS的本質是一個開軟的軟體框架,並不是一個系統,也不是語言,它實質上統一通信介面
最大的好處就是可以調用滿足這個通信介面的開發結果。用戶機器人開發者之間的交流。避免大家的重複開發。由於機器人是一個複雜的系統,這樣使得大家可以集中自己的精力在自己的研究領域。
Node--節點--可執行的最基本單元,可以用C++和Python來編寫
Topics -主題---節點間傳輸數據的匯流排
Messages--消息--節點向特定主體發出的信息
Services--服務--用戶開發的,直接與節點通信
ROS
Master-管理器--節點之間通信的管理員,提供命名,註冊服務,跟蹤和記錄話題的發布和訂閱,提供參數伺服器
Packages--功能包--基本組織形式,可以包含節點和配置文件
Parameter Server--參數--通過網路提供變數字典,可供節點存儲和檢索運行時的參數
核心概念就這些了。


ROS的消息模式,註定了ROS只是一個玩具,給低年級的學生,或者業餘愛好者模擬一下;任何一個有經驗的開發人員,任何一個嚴肅的項目,都不會用ROS。

ROS最大的問題,它是偽消息隊列。就是它是不停的在while循環里詢問有沒有新消息,而不是系統非同步主動推送。當然ROS把while循環隱藏了,但是,每當你調用一次ros::spin(),其實後面還是在不停的while,間隔我沒記錯的話,默認是100ms。調快了空耗CPU,調慢了反應太慢。

至於消息template,實際項目也沒什麼意義。不同人開發的消息格式,哪裡有那麼巧正好對上的,總要寫各種轉換介面。

多進程同步?實際項目,一個機器就一個進程。要多機同步數據,同步的直接memcache,非同步的直接websocket。ROS是床上架床,畫蛇添足了。

靈活的介面?消息發布/訂閱模式方便動態配置?良好的代碼本身就有可擴展性,C++11里有callback;Qt裡面,也有signal模型啊。本身代碼就寫的不好,企圖通過進程直接用tcp互通消息,雖然能把代碼的混亂掩蓋在每個獨立進程裡面,犧牲的是效率,而且隨著系統的變大,雷峰塔終究是要倒掉的。

ROS會改進這些嗎?如果它改了,它也就變成了linux了,而這對業餘愛好者又太複雜。我們可以看到,ROS的本質,就是試圖掩蓋操作系統和程序設計的複雜性,註定是一個性能低下的玩具。

總結,好好設計代碼,直接從代碼級的復用,才是正道。


個人認為vrep比gazebo節省時間


上交大機器人五度空間ROS開發平台,專註百所高校學子學習交流,針對學生和愛好者開放平台,有興趣你可以加入


一定要看源碼 要不都白扯


從項目學,別無他法


推薦閱讀:

如果機器人知道自己是人造的,他會覺得屈辱嗎?
RoboMaster是一個什麼樣的機器人比賽?
剛剛開始做機器人,打算做SLAM,不知道機器人定位領域現在有哪些比較新的演算法?希望大家推薦推薦
個人職業如何更長遠發展?
浙大女生選控制系自動化還是電氣學院的自動化?

TAG:機器人 | 機器人操作平台ROS |