ROS 初級 - 解析 roslaunch 文件

1. roslaunch 命令

roslaunch 命令允許我們一次啓動 launch 文件中定義的多個 ROS 節點,啓動參數等在啓動文件(launch 文件)中配置,並且如果系統之前沒有啓動 roscore,則 roslaunch 會自動啓動它。

roslaunch 的命令行用法如下:

roslaunch [package] [filename.launch]

例如:

roslaunch beginner_tutorials turtlemimic.launch

其中 beginner_tutorials 是 turtlemimic.launch 文件中定義的一個節點,那 launch 文件是什麼呢?我們來看下。

2. 解析 launch 文件

簡單來說 launch 文件就是一堆節點和參數的集合,使用 launch 文件的目的是爲了一鍵啓動。因爲目前運行在機器人上的 ROS 系統一般都要同時運行多個節點,如果我們開機啓動時,一個一個的輸入命令來啓動每一個節點,想想就可怕,所以 ROS 系統就給我們提供了這麼一個 launch 文件,可以方便我們將要啓動的節點和對應的參數全部寫到這個文件中,然後使用 roslaunch 命令一鍵啓動!

一個 lanunch 文件例子:

<launch>
  <!-- local machine already has a definition by default.
       This tag overrides the default definition with
       specific ROS_ROOT and ROS_PACKAGE_PATH values -->
  <machine name="local_alt" address="localhost" default="true" ros-root="/u/user/ros/ros/" ros-package-path="/u/user/ros/ros-pkg" />
  <!-- a basic listener node -->
  <node name="listener-1" pkg="rospy_tutorials" type="listener" />
  <!-- pass args to the listener node -->
  <node name="listener-2" pkg="rospy_tutorials" type="listener" args="-foo arg2" />
  <!-- a respawn-able listener node -->
  <node name="listener-3" pkg="rospy_tutorials" type="listener" respawn="true" />
  <!-- start listener node in the 'wg1' namespace -->
  <node ns="wg1" name="listener-wg1" pkg="rospy_tutorials" type="listener" respawn="true" />
  <!-- start a group of nodes in the 'wg2' namespace -->
  <group ns="wg2">
    <!-- remap applies to all future statements in this scope. -->
    <remap from="chatter" to="hello"/>
    <node pkg="rospy_tutorials" type="listener" name="listener" args="--test" respawn="true" />
    <node pkg="rospy_tutorials" type="talker" name="talker">
      <!-- set a private parameter for the node -->
      <param name="talker_1_param" value="a value" />
      <!-- nodes can have their own remap args -->
      <remap from="chatter" to="hello-1"/>
      <!-- you can set environment variables for a node -->
      <env name="ENV_EXAMPLE" value="some value" />
    </node>
  </group>
</launch>

下面是一個簡單的 launch 文件格式,我帶你一步一步解析它的標籤用法:

<launch>
    <node .../>
    <rosparam .../>
    <param .../>
    <include .../>
    <env .../>
    <remap .../>
    <arg .../>
    <group>  </group>
</launch>

2.1 launch

launch 標籤是 launch 文件的根節點,它只作爲其他子標籤的容器,沒有其他功能。

<launch>
	...
</launch>

2.2 node

node 標籤指定一個將要運行的 ROS 節點,node 標籤可以說是 launch 文件中最重要的標籤,因爲我們配置 launch 文件的目的就是一次啓動多個 ROS node。

常見的用法如下:

<node name="bar1" pkg="foo_pkg" type="bar" args="--test" respawn="true" output="sceen">
  • name:節點名稱 bar1
  • pkg:節點所在的包 foo_pkg
  • type:節點類型是可執行文件(節點)的名稱,項目中必須要有一個相同名稱的可執行節點
  • args:命令行啓動參數 --test
  • respawn:是否自動重啓,true 表示如何節點未啓動,則自動重啓,false 則不重啓,默認 false
  • output:是否將節點信息輸出到屏幕,如果不設置該屬性,則節點信息會被寫入到日誌文件

在 node 標籤下頁可以嵌套使用以下標籤:

  • env:爲節點設置環境變量
  • remap:爲節點設置重映射參數
  • rosparam:爲節點加載 rosparam 文件
  • param:爲節點設置參數

2.3 param

在項目中某些參數需要經常改變,如果在程序中寫死了,以後我們每次修改參數都需要重新 build 一遍程序,非常麻煩,param 便籤給我們提供了一個傳遞參數的方法。

param 標籤定義一個將要被設置到參數服務器的參數,它的參數值可以通過文本文件、二進制文件或命令等屬性來設置,另外 param 標籤可以嵌入到 node 標籤中,以此來作爲該 node 的私有參數。

常見用法如下:

<param name="publish_frequency" type="double" value="10.0">
  • name:參數名稱 publish_frequency
  • type:參數類型 double,str,int,bool,yaml
  • value:參數值 10.0

param 標籤也可以爲一組 group 節點同時設置參數。

2.4 remap

remap 標籤提供了一種節點名稱的重映射方法,每個 remap 標籤包含一個元素名稱和一個新名稱,在系統運行後原始名稱會被替換爲新名稱。

常見用法如下:

<remap from="chatter" to="hello">
  • from:原始名稱
  • to:新名稱

可以這樣理解這個替換標籤:你有一個節點訂閱了「chatter」主題,但是你只有一個節點發布「hello」主題,而「hello」和「chatter」的類型相同,所以我們可以將「chatter」簡單地替換爲「hello」,從而實現訂閱「hello」主題。

2.5 machine

machine 標籤定義了節點所運行的機器信息,如果只是在本地運行節點則不需要配置這個標籤,它主要使用在 SSH 和遠程機器,不過也可以用來配置本地機器的相關信息。

常見用法如下:

<launch>
	<machine name="foo" address="foo-address" env-loader="/opt/ros/kinetic/env.sh" user="someone">
	<node machine="foo" name="footalker" pkg="test_ros" type="talker.py">
</launch>
  • name:機器名稱
  • address:機器的網絡地址
  • env-loader:設置機器的環境變量,必須是一個設置了所有要求變量的 shell 腳本
  • user:用戶名稱

2.6 rosparam

rosparam 標籤允許節點從參數服務器上 load、dump 和 delete YAML 文件,也可以使用在遠程機器上,需要注意的是 delete 必須在 load 或者 dump 之後進行。

常見用法如下:

# 參數較多使用 yaml 文件
<rosparam command="load" file="$(find rosparam)/example.yaml">
<rosparam command="delete" param="my/param">

# 傳遞數組
<rosparam param="a_list">[1, 2, 3, 4]</rosparam>

<rosparam>
	a: 1
	b: 2
</rosparam>
  
<arg name="whitelist" default="[3, 2]"/>
<rosparam param="whitelist" subt_value="True">$(arg whitelist)</rosparam>
  • command:load,dump,delete
  • file:參數文件的路徑
  • param:參數名稱
  • subt_value:是否允許在 YAML 中替換參數

補充下 yaml 文件基本用法,yaml 文件就是單純的來存儲啓動參數,格式如下:

a: 1
str: hello
c: 2.0

其中不需要指定變量類型,yaml 文件會自動確定類型。使用 yaml 文件的目的就是方便配置參數,如果有很多參數需要配置,不需要寫很多 rosparam 命令。

yaml 文件還有挺多複雜的寫法,後續項目中用到再總結出來。

2.7 include

include 類似編程語言中的 include 預處理,它可以導入其他 roslaunch 的啓動文件到當前 include 標籤所在的位置。

常見用法如下:

<include file="$(find package_name)/launch_file_name">

項目中使用絕對路徑不太方便,可以使用 find 來查找。

2.8 env

env 標籤可以在啓動的節點上設置環境變量,這個標籤基本只會使用在 launch、include、node、machine 這 4 個標籤內部,當使用在 launch 內部時,env 設置的環境標量會應用到內部定義的節點。

常見用法如下:

<env name="ENV_EXAMPLE" value="some value" />
  • name:環境變量名稱
  • value:環境變量值

2.9 test

test 標籤在語法上類似 node 標籤,但在功能上只表示當前的節點作爲測試節點去運行。

常見用法如下:

<test test-name="test_1" pkg="my_pkg" type="test_1.py" time-limit="10.0" args="--test1">
  • test-name:測試節點名稱
  • pkg:測試節點所在的包
  • type:測試節點類型
  • time-limit:超時時間
  • arg:測試節點啓動的命令參數

2.10 arg

arg 標籤表示啓動參數,該標籤允許創建更多可重用和可配置的啓動文件,其可以通過命令行、include 標籤、定義在高級別的文件這 3 種方式配置值。

arg 標籤聲明的參數不是全局的,只能在聲明的單個啓動文件中使用,可以當成函數的局部參數來理解。

常見用法如下:

# 1. 命令行傳遞啓動參數
roslaunch my_file.launch my_arg:=my_value
# 2. 定義時賦值
<arg name="arg_name" default="arg_name">
<arg name="arg_name" value="arg_name">

這兩者有點區別,命令行傳遞的 arg 參數可以覆蓋 default,但不能覆蓋 value。

# 3. 通過 launch 文件傳遞,兩個 launch 文件中的 arg 參數值必須相同!

# my_file.launch
<include file="include.launch">
	<arg name="hoge" value="fuga">
</include>

# include.launch
<launch>
	<arg name="hoge" value="fuga">
</launch>

注意 arg 和 param 標籤的區別:

  • arg:啓動時參數,只在啓動文件 launch 中有意義
  • param:運行時參數,存儲在參數服務器中

2.11 group

group 標籤可以方便的將一組配置應用到組內的所有節點,它也具有命名空間 ns 特點,可以將不同的節點放入不同的 namespace。

常見用法如下:

<group ns="namespace">
	<node pkg="pkg_name1" .../>
	<node pkg="pkg_name2" .../>
	...
</group>

配合 if 和 unless 使用:

  • if=value:value 爲 true 則包含內部信息
  • unless=value:value 爲 false 則包含內部信息
<group if="$(arg foo1)">
	<node pkg="pkg_name1" .../>
</group>

<group unless="$(arg foo2)">
	<node pkg="pkg_name2" .../>
</group>
  • 當 foo1 == true 時包含其標籤內部
  • 當 foo2 == false 時包含其標籤內部

本文原創首發於 同名微信公號「登龍」,微信搜索關注回覆「1024」你懂的!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章