接下來我們就要來把模型匯入到 Gazebo 裡面了!
前天的內容提到,我們要使用 ROS 指令來啟動 Gazebo ,並且要做到以下事情:
.launch
)、模型檔(.sdf
)、世界檔(.world
)既然要做的事情這麼多,我們就需要按照 Day 5 的方式建立套件來達成目的。
在 src
目錄中建立一個套件,我先命名為 my_simulations
,相依套件先用預設的幾個就好。
$ cd ~/catkin_ws/src
$ source devel/setup.bash
$ catkin_create_pkg my_simulation std_msgs rospy roscpp
$ cd ~/catkin_ws
$ catkin_make
$ cd ~/catkin_ws/scr/my_simulation
接著建立需要用到的目錄:
$ mkdir launch world models
啟動檔 .launch
是利用 XML 格式寫的配置文件,用來啟動多個節點、設定參數、載入環境變數,如此一來就不需要手忙腳亂地又要啟動主節點、啟動 Gazebo ,又要執行其他 ROS 的程序。
XML 格式大致上是使用一對三角括號的標籤(Tags,如:
<launch></launch>
或<arg … />
)將區塊包起組成的結構,每個標籤區塊內都可以包含多個標籤區塊。
在區塊內可以設定該標籤的屬性(Attributes,如:arg name="debug"
)。而用<!-- -->
包起的部分則是註解的內容。
.launch
的基本結構首先在 launch
目錄建立一個啟動檔 my_launch.launch
:
$ touch launch/my_launch.launch
在 my_launch.launch
中加入內容如下,這裡面包含了啟動檔的基本結構:
<?xml version="1.0" encoding="UTF-8" ?>
<launch>
<!-- 設定引數 -->
<arg name="debug" default="false" />
<arg name="gui" default="true" />
<arg name="pause" default="false" />
<arg name="world" default="$(find my_simulations)/world/my_world.world" />
<!-- 設定 inclue 並提供引數 -->
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="world_name" value="$(arg world)" />
<arg name="debug" value="$(arg debug)" />
<arg name="gui" value="$(arg gui)" />
<arg name="paused" value="$(arg pause)" />
<arg name="use_sim_time" value="true" />
</include>
</launch>
XML 宣告和 <launch>
標籤:
<?xml version="1.0" encoding="UTF-8" ?>
這一行是 XML 格式宣告,這一條其實可有可無,但是加上這行後系統就能自動解析這個檔案的格式,對於撰寫文件會更方便。
<launch>
標籤是整個啟動檔的根基,用來包住所有的內容。
<arg>
引數設置區塊:
在 <arg>
這個區塊中用來指派引數(Argument)的值,和寫 Python 程式時需要指派變數值的概念類似。在匯入其他啟動檔或是定義節點時可以傳遞進去供其使用。
格式:
<arg name="[arg_name]" default="[defalut_value]" />
<arg name="[arg_name]" value="[fixed_value]" />
name="[arg_name]”
:宣告引數名稱。default="[defalut_value]"
:定義引數具有預設值,但是可以被覆蓋。value="[fixed_value]"
:定義引數具有特定的值,不可以被覆蓋。在 my_launch.launch
中,我設置了 debug
為 false
(不要啟動 Gazebo 除錯模式), gui
為 true
(開啟 Gazebo 圖形介面), pause
為 false
( 如果設定為 true
則模型將支援動態表現,如起降、飛行等), world
指定來自 my_simulations
套件路徑下的世界檔 my_world.world
。
<include>
匯入其他啟動檔:
在 <include>
這個區塊中,可以將多個啟動檔匯入這個啟動檔之中,這可以讓專案更加模組化。比如說,我可以在 main.launch
中匯入 spawn_robot.launch
負責生成機器人,再匯入 start_world.launch
負責載入模擬環境設定和啟動 Gazebo 。透過匯入已存在的啟動檔,我們就可以沿用它的啟動邏輯,而不用在其他專案裡重新寫一遍。
格式:
<include file="$(find [pkg-name])/path/filename.launch">
<arg name="arg_name" value="arg_value"/>
</include>
$(find pkg_name)
:這裡使用替換引數(substitution args)的做法,也就是在執行時, roslaunch
會先解析 $( )
內的指令。在這裡 find pkg_name
代表先找到套件的路徑,並將路徑替代上去後再組合得到完整路徑。類似的用法還有 $(arg arg_name)
替代引數的值。在 my_launch.launch
中,我設置匯入 gazebo_ros
這個套件的啟動檔,直接使用 Gazebo 官方設置的啟動環境,並且將開頭設定的引數傳進去。
<node>
節點宣告區塊
因為在這個範例中直接匯入 gazebo_ros
套件的啟動檔,所以沒有真的用到節點宣告。這裡拿 gazebo_ros
的原始碼片段說明,有興趣的人可以前往套件的 GitHub 儲存庫看看:
<!-- ...前面省略 -->
<!-- start gazebo server-->
<node name="gazebo" pkg="gazebo_ros"
type="$(arg script_type)" respawn="$(arg respawn_gazebo)" output="$(arg output)"
args="$(arg command_arg1) $(arg command_arg2) $(arg command_arg3) -e $(arg physics) $(arg extra_gazebo_args) $(arg world_name)"
required="$(arg server_required)" />
<!-- start gazebo client -->
<node name="gazebo_gui" pkg="gazebo_ros"
type="gzclient" respawn="false" output="$(arg output)" args="$(arg command_arg3)"
required="$(arg gui_required)"/>
節點宣告的區塊使用 <node>
標籤包起來,用來定義要啟動或關閉的 ROS 節點。
格式:
<node name="node_name" pkg="pkg_name" type="filename" args="arg1 arg2 arg3" output="screen"/>
name="node_name"
:節點名稱。pkg="pkg_name"
:節點所在的套件名稱。type="filename"
:節點的可執行檔名稱。args="arg1 arg2 arg3”
:提供給節點的引數。output="screen"
:輸出位置,設定 screen
可以在終端機看到節點的輸出訊息,設置 log
則會儲存在 ROS 的日誌檔案。光是啟動檔的部分就可以寫了這麼多有點出乎我意料,這個範例甚至只有設定環境參數和指定世界檔而已!為了避免篇幅過長,明天再繼續寫設定模型和世界的部分吧。