當前位置: 華文問答 > 數位

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

2013-11-04數位

前言

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

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

曉萌機器人

技術介紹

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

機械

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

電子

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

軟體

曉萌機械臂軟體架構圖

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

硬體介面層

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

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

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

ROS Control數據流程圖

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

  • 實體機械臂:
    這一部份指的就是真實客觀存在的機械臂。STM32嵌入式控制器使用位置PID閉環演算法來計算由硬體抽象層透過串口通訊方式發過來的關節數據,並將計算好的數據直接發送給電機對其進行控制。同時,電機的編碼器也將電機即時的位置數據經串口通訊返回給上面的硬體抽象層。
  • 硬體抽象層:
    硬體抽象層和硬體直接打交道,透過 write read 方法來完成對硬體的相關操作。硬體抽象層跟上面官方提供(紅色的部份)的有一些不太一樣的地方在於我並沒有使用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架構圖:

    ROS Control架構圖

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

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

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

  • 仿真部份:
  • 在終端中輸入以下命令啟動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, R&D and other domains.

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

    下圖是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)是開源運動規劃庫的簡寫,它提供基於隨機化的運動規劃器。

    Motion Planner執行流程圖
  • 運動規劃請求:
    在讓運動規劃器進行運動規劃之前,我們要先發送一個運動規劃的請求。這個請求可以是新的機械臂或末端執行器的位置。為了讓運動規劃器規劃出來的軌跡符合要求,我們需要指定一些約束條件:
  • 位置約束:
    約束機械臂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架構圖

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

    3D Perception

    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! 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中的機械臂可以移動到目標位置,以下是測試的截圖。註意:不同的規劃演算法所用的時間是不一樣的。請嘗試每一種演算法,並記住最優演算法的名字,這是為了之後方便在程式碼中對其進行呼叫做準備。

    機械臂運動規劃測試(MoveIt!界面)
    機械臂運動規劃測試(Gazebo界面)

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

    $> roslaunch xm_arm_bringup xm_arm_bringup_moveit_and_gazebo.launch

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

    帶碰撞檢測的機械臂運動規劃測試(MoveIt!界面)
    帶碰撞檢測的機械臂運動規劃測試(Gazebo界面)

    當然,在使用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!官網的時候,教程的數量和品質已經不可同日而語了。我相信現在的機器人愛好者或研究者們要比我當初那會兒更容易地學習並掌握機械臂的開發,並能將其套用到解決當今人們所遇到的問題中去。我們正處在人工智慧的偉大時代,而機器人作為人工智慧技術最為重要的技術載體,需要我們為此付出努力並勇於探索前方未知的道路。最後,我希望這篇文章可以讓更多的開發者邁入機械臂開發的大門,並為機械臂的研究發展貢獻你們自己的一份力量!