ROS入門學習

self發表於2018-11-10

ROS學習筆記

ROS功能包/軟體包(Packages)

  • ROS軟體包是一組用於實現特定功能的相關檔案的集合,包括可執行檔案和其他支援檔案。
  • 所有的 ROS 軟體都是一個軟體包或其他軟體包的一部分。
  • 每個程式包由一個清單檔案(檔名為 package.xml)定義。
    • 該檔案定義關於包的一些細節,包括其名稱、版本、維護者和依賴關係。
    • 包含 package.xml 檔案的目錄被稱為軟體包目錄
    • 使用catkin編譯構建系統的功能包, 編譯產生的可執行檔案存放在一個單獨的標準化目錄層次結構中。
  • 功能包集(stack): 功能包集是緊密相關的功能包的集合,從groovy開始慢慢地被淘汰, 取而代之的是元功能包(metapackages)。

節點管理器(The Master)

  • 接單(node)是幾乎相對獨立的小程式,這些節點必須能夠通訊, 通訊的關鍵部分是ROS節點管理器
    • 啟動節點管理器的命令 -- roscore。
    • 大多數 ROS 節點在啟動時連線到節點管理器上,如果執行中連線中斷,則不會嘗試重新連線。
    • 因此,如果 roscore被終止,當前執行的其他節點將無法建立新的連線,即使稍後重啟 roscore 也無濟於事。
    • roslaunch 的工具,其目的是一次性啟動多個節點。

節點(Nodes)

  • 一旦啟動roscore後,便可以執行ROS程式了, ROS程式的執行例項被稱為節點(node)
  • “執行例項”(running instance)很重要。
    • 如果我們同時執行相同程式的多個副本——注意確保每個副本使用不同的節點名——則每個副本都被當做一個單獨的節點。
  • 啟動節點:
    • 利用命令rosrun: rosrun package-name executable-name;
    • rosrun 沒有什麼“神奇”的:它只不過是一個 shell 指令碼,能夠理解 ROS 的檔案組織結構,知道到哪裡能找到與給定包名稱對應的可執行檔案。
    • 通過節點管理器註冊成為 ROS 節點發生在程式的內部,而不是通過 rosrun 命令。
  • 檢視節點列表:
    • 利用命令: rosnode list;
    • rosout 節點是一個特殊的節點,通過 roscore 自動啟動,其作用類似於標準輸出(即std::cout)。
    • 節點名不一定與對應可執行檔名稱相同。
    • 獲得特定節點的資訊: rosmode info node-name;
    • 終止節點: rosnode kill node-name;
      • 終止和重啟節點通常不會對其他節點有較大影響。
      • 即使節點間正在相互交換訊息(message),這些連線也會在節點終止時斷開,在節點重啟時重新連線。
    • 將節點從列表中刪除: rosnode cleanup。

話題和訊息

  • ROS節點之間進行通訊所利用的最重要的機制就是訊息傳遞。
  • 在ROS中,訊息有組織地存放在話題裡。
  • 訊息傳遞的理念:
    • 當一個節點想要分享資訊時,它就會發布(publish)訊息到對應的一個或者多個話題;
    • 當一個節點想要接收資訊時, 它就會訂閱(subscribe)它所需要的一個或多個話題;
    • ROS節點管理器負責確保釋出節點和訂閱節點能找到對方;
    • 訊息是直接地從釋出節點傳遞到訂閱節點,中間並不經過節點管理器轉交;
  • 檢視節點構成的計算圖:
    • 檢視節點之間的釋出-訂閱關係的最簡單方式就是在終端輸入rqt_graph命令。
      • r代表ROS, qt指的是Qt圖形介面(GUI)工具包;
    • 在預設情況下,rqt_graph 隱藏了其認為只在除錯過程中使用的節點。
    • 的名稱/rosout 既指節點又指話題。但 ROS 並不會因這種重複的名字而混淆,因為 ROS 會根據上下文來推測我們討論的是/rosout 節點還是/rosout 話題。
  • ROS 節點通常設計成了只管釋出它們有用的資訊,而不需要擔心是否有其他節點來訂閱這些訊息。這樣有助於減少各個節點之間的耦合度。
  • ,/teleop_turtle 節點會以訊息的形式將這些運動控制命令釋出到 話 題 /turtle1/cmd_vel; 與此同時,因為turtlesim_node 訂閱了該話題,因此它會接收到這個些訊息,控制海龜按照該預定的速度移動。

話題列表

  • 通過rostopic list獲取當前活躍的話題;
  • 列印訊息內容rostopic echo topic-name;
  • 測試釋出頻率rostopic hz topic-name(每秒釋出訊息的數量) 和 rostopic bw topic-name(每秒釋出訊息所佔的頻寬);
  • Type在文字輸出中表示資料型別;
  • 檢視訊息型別: rosmsg show message-type-name。
  • 一個複合域是由簡單的一個或者多個子域組合而成,其中的每一個子域可能是另一個複合域或者獨立的域,而且它們一般也都由基本資料型別組成。

用命令列釋出訊息

  • 利用rostopic命令工具: rostopic pub -r rate-in-hz topic-name message-type message-content(按照指定的頻率給指定的話題釋出指定的訊息);
    • 該命令最後的引數 message-content 應該按順序提供訊息型別中所有域的引數值。
    • rostopic pub -r 1 /turtle1/cmd_vel geometry_msgs/Twist -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 3]'命令中利用了-r來指定話題以頻率模式釋出訊息;
      • 鎖存模式只是釋出一條訊息,但鎖存模式是預設的模式。
      • -f是從檔案中讀取,輸入應該 符合rostopic echo的輸出格式。
      • 編寫一種指令碼將 rostopic echo 和 rostopic pub 結合起來作為“記錄”和“回放”訊息的方式;rosbag工具。

理解訊息型別的命名

  • 每條訊息型別都屬於一個特定的包,訊息型別名總會包含一個斜杆,斜杆錢面的名字是包含它的包: package-name/type-name;
    • turtlesim/Color中的turtlesim是功能包名, Color是型別名稱;
  • ROS 節點管理器不允許多個節點擁有相同的名稱。

話題通訊的多對多機制

  • 基於話題和訊息的通訊機制是多對多的,即多個釋出者和多個訂閱者可以共享同一個話題。
  • 節點之間的鬆耦合關係:
    • 每個節點都不需要顯式知道其他節點的存在與否;它們的唯一互動方式是間接地發生在基於話題和訊息的通訊層。
    • 節點之間的獨立性,以及其支援的任務可分解特性(即複雜任務分解成可重用的小模組),是 ROS 最關鍵的設計特性之一。
    • “生產”訊息的程式(例如 turtle_teleop_key)只管釋出該訊息,而不用關心該訊息是如何被“消費”的。
    • “消費”訊息的程式(例如 turtlesim_node)只管訂閱該話題或者它所需要訊息的所有話題,而不用關心這些訊息資料是如何“生產”的。
  • ROS為更加直接的一對一通訊提供了一種稱為服務(services)的機制。
  • ROS 利用roswtf進行問題的查詢。
    • roswtf 將會檢測在安裝過程中 rosdep 初始化是否完成,任何節點是否出現了意外的掛起或者終止,以及活躍的節點是否正確地和其他節點相連線等。
    • roswtf 檢測的完整列表只能在 Python 原始碼中才能找到。

編寫ROS程式

  • 學習編寫能夠釋出和訂閱訊息的 ROS 程式。

建立工作區和功能包

  • 建立工作區,我們建立的包,應該全部放到一個叫做工作區的目錄中。
    • 工作區就是包含自己所有包的一個工作區目錄。
  • ROS的catkin編譯系統試圖一次性編譯同一個工作區中的所有功能包,如果設計到幾個相互獨立的專案,則應該維護數個獨立的工作區。
  • 每個工作區必須建立一個src的子目錄,這個子目錄講用於存放功能包的原始碼。
  • catkin_create_pkg package-name是建立一個功能包。
    • 一個配置檔案 -- package.xml這是一個清單檔案。
    • CMakeLists.txt是一個Cmake的指令碼檔案, 其實catkin在內部使用了Cmake。
  • ROS 包的命名遵循一個命名規範,只允許使用小寫字母、數字和下劃線,而且首字元必須是一個小寫字母。一些 ROS工具,包括 catkin,不支援那些不遵循此命名規範的包。
  • 本著保持文件與實際功能同步的精神,至少在package.xml中填寫description 和 maintainer 兩部分可能是比較合理的
  • 包含訊息的宣告: 每一個話題都與一個訊息型別相關聯,每一個訊息型別都有一個相對應C++標頭檔案。
    • #include <package_name/type_name.h>標頭檔案, 像#include <geometry_msgs/Twist.h>表示名為 geometry_msgs 的包所擁有的型別為 Twist 的訊息。

編寫回撥函式

  • 釋出和訂閱訊息的一個重要的區別是訂閱者節點無法知道訊息什麼時候才能到達, 為了對應這一事實, 我們必須把響應收到訊息事件的程式碼放到回撥函式裡, ROS每接收到一個新的訊息將呼叫一次這個函式。

日誌訊息

  • 學習如何生成和檢視日誌訊息。
  • ROS中分為5個不同的嚴重級別,按嚴重性程度遞增為: DEBUG、INFO、WARN、ERROR、FATAL。
    • DEBUG: reading header from buffer.
    • INFO: Waiting for all connections to establish.
    • WARN: Less than 5GB of space free on disk.
    • ERROR: Publisher header did not have required element: type.
    • FATAL: You must call ros::init() before creating the first NodeHandle.
  • 為日誌系統本身就是面向行的, 沒有必要使用std::endl或者其他的行終止符。
  • 檢查和清除日誌檔案:
    • 這些日誌檔案將隨著時間積累;
    • rosrun和roslaunch執行時會檢查和檢測已經存在的日誌的大小,並會在日誌檔案大小超過1GB時提醒,但是不會採取任何措施來減小日誌檔案的大小。
    • 檢視當前使用者使用的日誌檔案的當前大小: rosclean check。
    • 刪除所有已經存在的日誌: rosclean purge。
    • 嘗試生成DEBUG級別的訊息將會被忽略。
    • 設定日誌級別類似於 rqt_consolt 中的日誌級別過濾選項。
    • ROS_INFO_STREAM 等構建方式是巨集而不是函式呼叫。這些巨集對應的展開程式碼會檢查訊息是否被啟用,並且只會評估那些被啟用訊息的表示式。
  • 通過命令列設定日誌級別:
    • rosservice call /node-name/set_logger_level ros.package-name level;
    • 這條命令呼叫 set_logger_level 服務,該服務由各個節點自動提供。
    • roservice 的引數 ros.package-name 是必需的,用來指明我們期望配置的日誌記錄器(logger)的名稱。
  • rqt_logger_level通過圖形介面設定日誌級別;
  • 通過C++程式碼設定日誌級別,最直接的方式是呼叫ROS來實現日誌功能的log4cxx提供的程式碼介面
#include <log4cxx/logger.h>
. . .
log4cxx::Logger::getLogger(ROSCONSOLE_DEFAULT_NAME)->setLevel(
ros::console::g_level_lookup[ros::console::levels::Debug]
);
ros::console::notifyLoggerLevelsChanged();
  • 呼叫 ros::console::notifyLoggerLevelsChanged()是有必要的,因為每個日誌的啟用或者禁用是快取了的。

計算圖源命名

  • ROS的計算圖資源(節點、話題、引數、和服務等)的命名和解析。

全域性名稱

  • 節點、話題、服務和引數統稱為計算圖源,而每個計算圖源由一個叫計算圖源名稱(graph resource name)的短字串標識。
  • 前斜杆"/"表明這個名稱為全域性名稱, 由斜杆分開的一系列名稱空間(namespace), 每個斜杆代表一級名稱空間。
  • 描述資源本身的基本名稱(base name)。

相對名稱

  • 一個主要替代方案是讓 ROS為計算圖源提供一個預設的名稱空間,具有此特徵的名稱叫做相對計算圖源名稱(ralative graph resource name),或簡稱為相對名稱(relative name)。
  • 設定預設名稱空間:
    • 預設的名稱空間是單獨地為每個節點設定的,而不是在系統範圍進行。
    • 大部分 ROS 程式,包括呼叫 ros::init 的所有 C++程式,接受叫做_ns 的命令列引數,此引數將為程式指定一個預設名稱空間。 _ns:=default-namespace;
    • 還可以利用環境變數為在 shell 內執行的 ROS 程式設定預設名稱空間。Export ROS_NAMESPACE=default-namespace

私有名稱

  • 私有名稱,以一個波浪字元(~)開始,是第三類也是最後一類計算圖源名稱。
  • 私有名稱並不能完全確定它們自身所在的名稱空間,而是需要 ROS 客戶端庫將這個名稱解析為一個全域性名稱。
  • 與相對名稱的主要差別在於,私有名稱不是用當前預設名稱空間,而是用的它們節點名稱作為名稱空間。

匿名名稱(Anonymous names)

  • 匿名名稱的目的是使節點的命名更容易遵守唯一性的規則。其思路是,當節點呼叫 ros::init 方法時可以請求一個自動分配的唯一名稱。
  • 為了請求一個匿名名稱,節點需要將ros::init_options::Anonymous-Name 作為第四個引數傳遞給ros::init 方法:ros::init(argc, argv, base_name, ros::init_options::AnonymousName);

啟動檔案

  • 利用啟動檔案一次性配置和執行多個節點,ROS提供了一個同時啟動節點管理器(master)和多個節點的途徑,即啟動檔案(launch file)
  • 啟動檔案需要roslaunch工具來進行啟動。

使用啟動檔案

  • roslaunch的基本思想是在一個XML格式的檔案內將需要同時啟動的一組節點羅列出來。

在名稱空間內啟動節點

  • 對一個節點設定預設名稱空間,這個過程通常叫做壓人(pushing down)名稱空間--的通常方法是使用一個啟動檔案,並對其節點元素配置名稱空間(ns,ns = namesapce)屬性。
  • 事實上 roslaunch 要求啟動檔案中的節點名稱是基名稱,即不涉及任何名稱空間的相對名稱。如果節點元素的名稱屬性中出現了全域性名稱,roslaunch 將會報錯。

名稱重對映(Remapping names)

  • 除了相對名稱和私有名稱, ROS節點還支援重對映(remapping), 它可以從更精細的層面控制對所用節點名稱的修改。
  • 重對映是基於替換的思想: 每個重對映包含一個原始名稱和一個新名稱。
  • 每當節點使用重對映中的原始名稱時, ROS客戶端庫就會將它默默地替換成其對應的名稱。

啟動引數(launch arguments)

  • 為了使啟動檔案便於配置, roslaunch還支援啟動引數,其功能有點像可執行程式中的區域性變數;
  • 這樣的有點是通過設定引數來描述節點在不同ROS會話中執行時可能需要改變.
  • 向包括的啟動檔案中傳送引數值,引數僅定義在對其進行宣告的啟動檔案中,而不能被包含的啟動檔案繼承;
  • 將arg元素作為一個包含元素的子元素。
<incluce file=”path–to-launch-file”>
    <arg name=”arg-name” value=”arg-value”/>
    …
</include>

建立組(Creating groups)

  • 組元素(group)是啟動檔案的最後一個特徵,它提供了一種在大型啟動檔案內管理節點的便捷方式。
  • 組可以把若干個節點放入同一個名稱空間內:
<group ns=”namespace”/>
…
</group>
  • 組內的每個節點都從給定的預設名稱空間啟動。
  • 如果一個組元素內的某個節點有它自己的名稱空間屬性,並且其名稱是(原則上也應該是)相對名稱,那麼該節點將會在一個預設名稱空間內啟動,這個預設的名稱空間是將此節點名稱空間嵌入到組元素名稱空間的結果。這個規則和前面講到的名稱解析是相符的,並且這個規則也適用於組元素的巢狀。
  • 組可以有條件地使能或禁止一個節點:
<group if=”0 or 1”/>
</group>
  • 只有 0 和 1 才是 if 和 unless 屬性的合法取值。特別需要提醒的是,讀者熟悉的布林型運算子 AND 和 OR 在這裡不能直接使用。
  • 使用組可以減少程式碼重複——名稱空間和條件設定僅出現一次——並且使啟動檔案的結構更加清晰。

引數

  • ROS還提供另一種參 數(parameters)機制用於獲取節點的資訊。
  • 使用集中引數伺服器(parameter server)維護一個變數集的值, 包括整數,浮點數,字串以及其他資料型別,每個變數用一個較短的字串標識。

通過命令列獲取引數

  • 檢視引數列表: rosparam list。
  • 引數伺服器是節點管理器的一部分,因此,它總是通過 roscore 或者 roslaunch 自動啟動。
  • 需要銘記的是,所有的引數都屬於引數伺服器而不是任何特定的節點。
  • 查詢引數:
    • rosparam get parameter_name, 查詢某個引數的值。
    • rosparam get namespace, 通過查詢全域性名稱空間,我們可以一次性看到所有引數的值。
  • 設定引數:
    • rosparam set parameter_name parameter_value, 修改一個已有引數或者建立一個新的參。
    • 以YAML字典的形式表示引數和對應值的對映關係。
    • 冒號後的空格是非常重要的,以確保 rosparam 將其作為一個/duck_colors 名稱空間內的引數集,而不是全域性名稱空間中的單個字串引數 duck_colors。
  • 建立和載入引數檔案:
    • rosparam dump filename namespace, 了以 YAML 檔案的形式儲存名稱空間中的所有引數。
    • rosparam load filename namespace, 從一個檔案中讀取引數,並將它們新增到引數伺服器。
  • 一個好的策略是演示真正的ROS節點如何工作得更好案例,是turtle首先測試這些引數是否存在,當且僅當這些引數不存在時, 才至指定預設的藍色。
  • rosparam get 命令是獲取背景引數的值。
  • 如果節點關心它的一些或者所有引數是否改變,必須明確向引數伺服器請求這些引數的值。

使用C++獲取引數

  • ROS引數的C++介面是相當簡單的: void ros::param::set(parameter_name, input_value);和bool ros::param::get(parameter_name, output_value);

在啟動檔案中設定引數

  • 設定引數:
    • 可以使用param元素請求roslaunch設定引數值,
  • 設定私有引數:
    • 作為節點元素的子集時,param元素中給出的引數名總是被當做私有名稱解析,無論它們是否以~或者/開始。
    <node . . . >
    <param name="param-name" value="param-value" />
     . . .
    </node>
    // 啟動檔案中設定
    <launch>
      <node
          pkg="turtlesim "
          type="turtlesim_node"
          name="turtlesim "
      />
      <node
          pkg="agitr "
          type="pubvel_with_max"
          name="publish_velocity "
      >
      <param name="max_vel" value="3" />
      </node>
      <node
          pkg="agitr "
          type="set_bg_color"
          name="set_bg_color"
      />
    </launch>
  • 在檔案中讀取引數: 啟動檔案也支援與rosparam load等價的命令, 可以一次性從檔案中載入多個引數: <rosparam command="load" file="path-to-param-file" />
    • 這裡的引數檔案通常是通過rosparam dump命令建立的。
    <rosparam
        command="load"
        file="$(find package-name)/param-file"
    />
  • 引數的思想雖然簡單, 但是可以大大提高ROS節點的靈活性和可配置性。

服務

  • 訊息傳遞是ROS中節點通訊的主要方法, 但確實受到了一定的限制,服務呼叫(service calls)是另一種通訊的方法。
  • 服務呼叫和訊息的區別在兩個方面:
    • 服務呼叫是雙向的, 一個節點給另一個節點傳送資訊並等待響應,因此資訊流是雙向的。訊息釋出後並沒有響應的概念,甚至不能保證系統內有節點訂閱了這些訊息。
    • 服務呼叫實現的是一對一通訊, 每一個服務有一個節點發起,這對這個服務的響應返回同一個節點。另一方面,每一個訊息都和一個話題相關,這個話題可能有很多的釋出者和訂閱者。
    • 訊息和服務十分相似。

服務的專用術語

  • 一個客戶端(client)節點傳送一些稱為請求(request)的資料到一個伺服器(server)節點,並等待迴應。
  • 伺服器節點接收到請求後, 採取一些行動(計算、配置軟體和硬體、改變自身行為等),然後傳送一些稱為響應(response)的資料給客戶端節點。
  • 請求和響應資料攜帶的特定內容由服務資料型別(service data type)來決定,它與決定訊息內容的訊息型別是類似的,服務資料型別也是由一系列域構成;
    • 唯一區別是,服務資料型別分為兩部分,分別表示請求(客戶端節點提供伺服器節點)和響應(服務其節點反饋給客戶端節點)。

從命令列檢視和呼叫服務

  • 服務通常由節點內部的程式碼呼叫;
  • 列出所有服務: ros service list; 服務名是計算圖源名稱,同其他資源名稱一樣,可以劃分為全域性的、相對的或者私有的名稱。rosservice list命令的輸出是所有服務的全域性名稱。
  • 服務通常將節點名用作名稱空間來防止命名衝突,並且允許節點通過私有名稱來提供服務。
  • 檢視某個節點的服務型別,檢視一個特定節點提供的服務,使用rosnode info命令。
  • 查詢提供服務的節點: rosservice node service-name;
  • 檢視服務資料型別: 當服務的資料型別已知時, 我們可以使用rossrv指令來獲得此服務資料型別的詳情 -- rossrv show service-data-type-name。
  • 服務資料型別中的請求或響應欄位可以為空,甚至兩個欄位可以同時為空。
  • 從命令列呼叫服務: rosservice call service-name request-content

客戶端程式

  • 宣告請求和響應的型別,必須包含相關的標頭檔案: #include <package_name/type_name.h>
  • 建立一個客戶端物件, ros::ServiceClient client = node_handle.serviceClient<service_type>(service_name);
    • service_name是一個字串,應當是一個相對名稱。
    • 與建立類似的 ros::Publisher 物件相比,建立 ros::ServiceClient 物件不需要佇列大小。
  • 呼叫服務: 一旦擁有了一個ServiceClient, 一個完整的Request以及Response, 我們就可以呼叫服務了: bool success = service_client.call(request, reponse);
    • 這個方法實際上完成了定位伺服器節點、傳輸請求資料、等待響應和儲存響應資料等一系列工作。
  • 宣告依賴: 需要編輯CMakeLists.txt和清單檔案packag.xml。
    • 必須保證CMakeLists.txt中的find_package行涉及了turtlesim功能包: find_package(catkin REQUIRED COMPONENTS roscpp turtlesim)。
    • 在package.xml中, 我們應當確保build_depend和run_depend元素中存在相同名稱的包,turtlesimturtlesimturtlesim

伺服器程式

  • 必須建立一個ros::ServiceServer來代替ros::Subscriber, 唯一的區別在於服務端可以通過一個響應物件和一個表明成功與否的不二比昂兩給客戶端回傳資料。
  • 節點每次接收到一個服務請求,ROS就執行一次回撥函式,引數Request中包含了來自客戶端的資料,回撥函式的工作是給Response物件的資料成員賦值。
  • 建立伺服器物件: ros::ServiceServer server = node_handle.advertiseService(service_name,pointer_to_callback_function);
    • 私有名稱以~開始。
  • 可以使用兩個分開的執行緒:一個釋出訊息,一個處理服務回撥。 儘管 ROS沒有明確指出程式要使用多個執行緒,但如果可以的話,這是非常便於合作的。
  • 可以用ros::spin來代替sleep/ros::spinOnce迴圈,並且利用計數器回撥函式(timer callback)來發布訊息。

訊息錄製與回放

  • ROS 系統的一個重要特徵便是系統中資訊的消費者不應該關心資訊的生產者。
    • 這種體系架構最明顯的體現是ROS主要使用的訊息釋出-訂閱模型。
    • 不論什麼時刻,只要有訊息被髮布,其訂閱節點就應該正常工作,而不管是哪個或是那些節點正在釋出這些訊息。
  • rosbag工具,能夠釋出在一個或這多個話題上的訊息錄製到一個包檔案中,然後可以回放這些訊息,重現像是的執行過程。

錄製與回放包檔案

  • 術語包檔案(bag files)是指用於儲存帶時間戳的ROS訊息的特殊格式檔案,rosbag命令列工具可以用來錄製和回放包檔案。
  • 錄製包檔案: rosbag record -O filename.bag topic-names。
    • 如果不指定檔名,rosbag 將基於當前的日期和時間自動生成一個。
    • 用rosbag record -a 記錄當前釋出的所有話題的訊息。
    • 用 rosbag record -j 啟用包檔案的壓縮。
  • 回放包檔案: rosbag info filename.bag。
  • 持續時間、訊息計數以及話題列表三個欄位似乎很有趣。
  • 錄製正方形軌跡的包檔案,rosbag record -O square.bag /turtle1/cmd_vel /turtle1/pose

啟動檔案裡面的包檔案

  • 通過這兩個可執行檔案可以很容易地將包檔案作為啟動檔案的一部分,方法是包含適當的節點元素。
// 錄製節點
<node
    pkg="rosbag"
    name="record"
    type="record"
    args="-O filename.bag topic-names"
/>
// 回放節點
<node
    pkg="rosbag"
    name="play"
    type="play"
    args="filename.bag"
/>
  • 在網路環境中執行ROS, ROS的一大優勢是支援分散式機器人控制模式,即諸多程式執行在不同的計算機上,通過互相互動來完成指定任務。
    • 需要在網路層和ROS層進行配置,網路層確保計算機之間能夠互相通訊, 而ROS層的配置是確保所有節點都能與節點管理器通訊。
  • 編寫更規範的程式, 程式一定要注重可擴充套件性和可維護性;
    • 用ros::Timer的回撥函式來替代ros::Rate物件。
  • 使用rviz使資料視覺化,機器人感測器獲得的資料不僅複雜而且通常帶有噪聲, ROS提供了一個叫做rviz的非常強大的圖形介面工具,它可以通過訂閱使用者選擇的話題來顯示機器人內部的各種資訊,便於機器人的開發和除錯。
  • 建立訊息和服務型別
  • 使用tf工具來管理多個座標系,用不同的座標系來描述機器人不同部件的位置,包括機器人要避開或互動的目標。
  • 需要知道將某個座標從一個座標系到另一個座標系的變換矩陣(Transforation),ROS提供了一個標準功能包,來幫助節點來完成座標轉換。
    • tf具有很強的魯棒性,既能夠處理來自不同節點的資料,也能應對座標系的實時變換。
  • 使用Gazebo模擬, ROS系統最大的優勢之一就是能夠實現軟體的模組化設計,基於這個框架可以輕易地替換系統中的各種軟體模組,從而節約系統的開發時間,也使得測試變得簡單方便。
    • Gazebo是一個高保真的機器人模擬器。
    • 在Gazebo中,我們可以建立機器人和相應場景的模擬模型,然後為模擬機器人定義與實體機器人相同的通訊介面。