ROS筆記,絕對乾貨之 .launch檔案內容,詳細解析!
.launch檔案是ROS中用於同時啟動多個節點的重要檔案,在大型的ROS專案中使用頻繁,所以掌握其主要元素與屬性對ROS系統的應用至關重要:
- launch標籤(元素)說明
- launch拓展說明
- parameter說明
1. 標籤(元素)說明
- 以launch標籤開頭以表明是launch檔案.
- group標籤定義名稱空間.
<group ns="turtlesim1">
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
</group>
<group ns="turtlesim2" >
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
</group>
- 1
- 2
- 3
- 4
- 5
- 6
在這裡我們建立了兩個節點分組並以’名稱空間(namespace)’標籤來區分,其中一個名為turtulesim1,另一個名為turtlesim2,兩個組裡面都使用相同的turtlesim節點並命名為’sim’。 這樣可以讓我們同時啟動兩個turtlesim模擬器而不會產生命名衝突。(當然如果直接用不同的命名也是可以的,比如一個叫sim_1,一個叫sim_2,這樣也可以同時多次啟動同一節點).
1. if 或unless 屬性
組(groups)可以通過 判別條件 來啟用或禁用節點(nodes):
<group if="0-or-1" />
. . .
</group>
如果 if 屬性的值是 1 , 標籤內封閉的元素(elements)會被包含。如果 if 屬性 值是 0 ,則 標籤內包含的元素會被忽略。 unless 屬性的工作方式類似 if 屬性,但是含義顛倒:
<group unless="1-or-0" />
. . .
</group>
當然了,通常我們不會給這些屬性使用簡單的 0 或 1 這樣的賦值。建議:結合 arg 的 $() 技術,它們會將你的launch檔案的配置變得非常的強大。
- node標籤
任何一個launch檔案的重點都是:節點(node)元素的集合。啟動的每一個節點(node)都要有自己獨一無二的名字(name)。如果node(節點)元素有children,就需要顯式標籤來定義,children比如是:remap 元素或者 param 元素。
顯式關閉標籤的形式:
<node pkg="" type="" name=""></node>
- 1
pkg 和 type 它們分別是:程式包名字和可執行檔案的名字。 ros::init() 函式 提供的 name 資訊將會全面的覆蓋命名資訊(launch檔案中node標籤裡面的name 屬性)
拓展屬性:
- output = “screen”
Q: 如何將標準輸出資訊顯示在終端(console)上?
A: 在 node 元素中使用 output 屬性:
output=”screen” - respawn=”true”
啟動完所有請求啟動的節點之後,roslaunch 監測每一個節點,讓它們保持正常的執行狀態。對於每一個節點,當它終止時,我們可以要求 roslaunch 重新啟動它. - required=”true”
當一個必需的節點終止時,roslaunch會做出響應,終止其他所有的節點並退出它自己。
注意: 由於 required 屬性和 respawn 屬性的含義,所以如果你給單個的一個節點同時設定了這2個屬性,roslaunch 命令會抱怨。所以不要這樣設定。 - launch-prefix = “command-prefix”
roslaunch 命令 的一個潛在的缺點:相比我們原來對每個節點在單獨的終端使用 rosrun 命令啟動的做法,roslaunch 則是讓所有的節點共享同一個終端。 那些只需要生產簡單的日誌訊息檔案而不需要終端(console)輸入的節點是容易管理的,而那些依賴終端輸入的節點,比如 turtle_teleop_key 節點,它可能要優先的保留在獨立的終端上。
在例子launch檔案中,我們給 teleoperation 節點使用了這個屬性:launch-prefix=”xterm -e”.因為這個屬性,啟動這個 node 元素的 rosrun 命令大致相當於:xterm -e rosrun turtlesim turtle_teleop_key.
xterm 命令會開一個新的終端視窗。 -e 引數告訴 xterm :執行其命令列剩餘部分(rosrun turtlesim turtle_teleop_key)。 - ns = “namespace”
在例子launch檔案中,使用這個屬性建立了兩個無關的 turtlesim 模擬器。
turtlesim 話題名字(turtle1/cmd_vel、turtle1/color_sensor 和 turtle1/pose )被從全域性名稱空間移動 到 /sim1 和 /sim2 的單獨名稱空間裡。 - args屬性
傳遞引數到節點. 個人理解,arg引數只在launch檔案中合法(相當於區域性變數),不直接傳給節點,所以需 要通過node中的args屬性進行傳遞.
- remap標籤
在launch檔案中重新命名:使用 remap 元素:
<remap from="original-name" to="new-name" />
- 1
如果這個 remap 是 launch 元素的一個child(子類),與 node 元素同一層級, 並在 launch 元素內的最頂層。那麼這個 remapping 將會作用於後續所有的節點。
- include標籤
- file屬性
<include file="path-to-launch-file" />
包含其他檔案.這個 file屬性期望我們新增想要包含的檔案的完整路徑。但是大多數時候,include 元素使用一個 find 命令來搜尋一個程式包,代替一個明確的完整路徑:
<include file="$(find package-name)/launch-file-name" />
這樣做是正確的:
<include file = "find learning_tutrols"/launch/start_demo.launch" / >
這樣做是錯誤的:
<include file = "find learning_tutrols"/start_demo.launch" /> - ns屬性
include 元素也支援 ns 屬性,可以讓這個檔案裡的內容推送到一個名稱空間裡面:
<include file=". . . " ns="namespace" />
一般我們都會給 include 元素設定一個 ns 屬性。
- arg標籤
在launch檔案中,要宣告一個引數的存在,我們使用arg元素:
<arg name="arg-name" />
- 1
聲明裡面只有一個 name 是起不上什麼作用的,這就像是你在程式中定義了一個 int 型別的變數,但 是你並沒有使用它一樣。(你至少還需要給 arg 元素分配 default 屬性或 value 屬性)
- 給arg賦值
在launch檔案中使用的每一個argument必須給它分配一個 value(賦值)。有以下兩種實現方法:
在命令列中你可以這樣做:給 roslaunch 提供一個 value :
roslaunch package-name launch-file-name arg-name:=arg-value
另外,在launch檔案中,你可以提供一個 value(賦值) 作為 arg 宣告的一部分,使用下面的兩種語法之一就可以:
<arg name="arg-name" default="arg-value" />
<arg name="arg-name" value="arg-value" />
這兩種語法的唯一不同是:命令列可以覆蓋default的值,但是不能覆蓋 value 。在例子launch檔案 中,use_sim3 節點的 default 值為 0,所以它可以通過命令列改變值,就像下面這樣:
$ roslaunch agitr triplesim.launch use_sim3:=1
如果我們修改了這個例子launch檔案:使用value替換default。那麼上面這個命令執行的時候會出 現錯誤,因為使用 value屬性 配置的argument的值是不允許改變的。 - 獲取argument的數值
$(arg arg-name)
$() 這個符號出現的任何地方,roslaunch命令都將會把它替換成給定argument 的值(value)。 - 關於argument的繼承
在argument的傳遞上有一個限制,就是argument不能傳遞給 include 元素裡包含的子launch檔案 使用。這個問題非常重要,因為這個 argument 就像是一個區域性變數,它不能被包含的launch檔案 所 “繼承” 。
解決這個問題的方法:在 include 元素中插入 arg 元素作為 include 元素的子類(children),就像是這樣:
<include file="path-to-launch-file">
<arg name="arg-name" value="arg-value"/>
. . .
</include>
注意,這裡的 arg 元素不同於我們已經知道的 arg 宣告,在 inchude 標籤內的arguments是給包含 (included) 的launch檔案提供的arguments,不是為本launch檔案提供的。
一種常見的情況是,被包含(included)的launch檔案和本launch檔案會有共同的引數。在這種情況下,我們希望這些值(values)永遠不變。像這樣的元素,在這兩個地方使用相同的argument name (引數名),要這樣做:
<arg name="arg-name" value="$(arg arg-name)" />
在這種情況下,第一個 arg-name 和往常一樣。第二個 arg-name 是launch檔案中提供的。結果是,這兩個launch檔案中給定的argument具有相同的值(value)。
拓展說明
- 使用 roslaunch 命令 和 使用 rosrun 命令 單獨執行每個節點之間的重要區別
預設情況下,roslaunch 命令 從啟動節點開始,標準輸出資訊會重定向到一個日誌檔案中,而不會像 rosrun 命令那樣,將 log 資訊顯示在終端(console)上.
日誌檔案所在路徑: ∼/.ros/log/run_id/node_name-number-stdout.log
Q: 如何將標準輸出資訊顯示在終端(console)上?
A: 在 node 元素中使用 output 屬性:
output=”screen”
帶這個屬性啟動的節點會將標準輸出資訊顯示在終端的視窗中,而不會儲存在日誌檔案中。這也 解釋 了為什麼這個帶有output=”screen”的節點(node) 的日誌檔案在上面日誌檔案列表中丟失的原因。
擴充套件: node 元素的 output 屬性只能影響這個節點自己。除了 output 屬性,我們可以使用 roslaunch命令列工具的 –screen 命令列選項強制性的在終端的視窗中顯示所有節點的輸出資訊。
$ roslaunch --screen package-name launch-file-name
- 1
- 重對映名字
在啟動一個節點的時候,有兩種方法建立重對映:
在終端命令列中啟動一個節點時,要重新給這個節點命名:給出一個節點原來的名字和新的名字, 中間用:=分開。 original-name:=new-name
例如,在執行turtlesim例項時,我們現在想把釋出姿態資料的話題/turtle1/pose名稱改 為:/tim,那麼命令就 是這樣的:$ rosrun turtlesim turtlesim_node turtle1/pose:=tim
在launch檔案中重新命名:使用 remap 元素:
<remap from="original-name" to="new-name" />
如果這個 remap 是 launch 元素的一個child(子類),與 node 元素同一層級, 並在launch 元素內的最頂 層。 那麼這個 remapping 將會作用於後續所有的節點。
這個 remap 元素也可以作為 node 元素的一個child(子類)出現。下面這個就是使用模板:
<node node-attributes >
<remap from="original-name" to="new-name" />
. . .
</node>
例如:上面命令列命令如果在launch檔案中,就是下面這個樣子的:
<node pkg="turtlesim" type="turtlesim_node"
name="turtlesim" >
<remap from="turtle1/pose" to="tim" />
</node> - argument和parameter有區別
儘管術語argument和parameter在許多計算機環境中稍微可以互換使用,它們的含義在ROS中有很大的不同。Parameters(引數)在一個執行的ROS系統中是變數(values),它被儲存在parameter伺服器中,活動(或者叫:執行)的節點通過ros::param::get()函式訪問它,並且使用者可以通過 rosparam 命令列工具使用它。相比之下,arguments只有在launch檔案裡合法,它們的值不是直接提供給節點。
parameter說明
All parameters are “owned” by the parameter server rather than by any particular node. This means that parameters—even those created with private names—will continue to exist even after the node they’re intended for has terminated.
在C++檔案中,set或者get處理parameter引數
r o s : : param : : s e t ( ” background_r ” , 2 5 5 ) ;
b o o l ok = r o s : : param : : g e t (PARAM_NAME, maxVel ) ;
在launch檔案中設定parameter,使用param標籤:
<param name="param-name" value="param-value" />
- 1
group標籤中的param標籤的作用等同於rosparam set命令.
node標籤中的param標籤設定為該節點的子元素.
Parameter names given in param elements that are children of node elements are always resolved as private names, regardless of whether they begin with ∼ or even / .
在launch檔案中也支援等同與rosparam load 功能的rosparam標籤
用於一次性載入大量的引數
<rosparam command="load" file="path-to-param-file" />
- 1
這裡的file是.yaml型別.