Gazebo筆記(六)

Chien-lin.Tseng
My learning note
Published in
22 min readAug 7, 2019

2019年8月7日(三)

目錄:

一、參考的網站

二、在 urdf 中,link 和 joint 的建立方法 (有 rpy )

三、在gazebo建出手掌的model

四、讓 joint 動起來 (延續上一篇跳過的部份)

一、參考的網站

(1) urdf_tutorial (上一篇有提過)

(2)

二、在 urdf 中,link 和 joint 的建立方法 (有 rpy )

(1) 使用 rviz

借用前面 urdf_tutorial 的環境,來實際測測看 link、joint、xyz、rpy,彼此間的關係。

會使用 rviz 而不直接用 gazebo 來測的原因:
因為 gazebo 會把 fixed joint 的圖示給直接忽略,要看到 joint 必須要把 type 改成 非fixed ,不太好觀察。
而在 rviz 中,每一個 fixed 或 非fixed 的 joint 都會清楚的顯示出來。

rviz、gazebo的註解:
在rviz,按著shift再按滑鼠左鍵,可以平移整個畫面。
在gazebo,按著shift再按滑鼠左鍵,可以旋轉畫面。(很好用)

(2) 使用修改後的 03-origins.urdf

對位於 /catkin_ws/src/urdf_tutorial/urdf 的 03-origins.urdf 進行修改:

在 /catkin_ws/src/urdf_tutorial 執行 roslaunch (開啟 rviz):

roslaunch urdf_tutorial display.launch model:=urdf/03-origins.urdf

結果圖:

基本上,可以把那些小座標軸當成 joint 。
那些小座標軸指明了 xyz的方向 (往上是z,剩下兩個可用右手定則判斷)。

分析程式:

(a) 固定 robot 在某個地方

  <!-- for fixing the robot -->
<link name="world"/>
<joint name="fixed" type="fixed">
<parent link="world"/>
<child link="base_link"/>
</joint>
<link name="base_link">
<visual>
<geometry>
<cylinder length="0.6" radius="0.2"/>
</geometry>
</visual>
</link>

world 的用途是固定 robot 在某個地方。

<joint name>那部份是在宣告一個關節,並且指定前一個 link 和下一個 link。

<link name> 中,照理來說會有<visual>、<collision>、<inertial>三個東西。但這裡為求簡便只寫了最重要的 <visual>,剛好 rviz 的環境也允許我只寫<visual> (在 gazebo 會多要求 <inertial>)。

在 <link name=”base_link”>中,有<visual>,裡面有<geometry>,更裡面有<cylinder>,這裡表示它宣告了一個圓柱體,高0.6公尺,半徑0.2公尺。第一個 link 因為沒有特別註明 origin (後面其他 link 有),所以他的圓柱中心在(0 0 0),可以看到圓柱一半在 xy 平面上方,一半在 xy 平面下方。

(b)

  <joint name="base_to_right_leg" type="fixed">
<parent link="base_link"/>
<child link="right_leg"/>
<origin xyz="0 -0.22 0.25" rpy="0 0 0"/>
<!-- change rpy here -->
</joint>
<link name="right_leg">
<visual>
<geometry>
<box size="0.6 0.1 0.2"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 -0.3"/>
</visual>
</link>

<joint name=”base_to_right_leg” type=”fixed”> 宣告一個名為 base_to_right_leg 的固定 joint (就是姿勢固定的意思)。
這個 joint 連接了base_link 和 right_leg。
<origin xyz>表示這個 joint 的位置和前一個 joint位置的相對座標,像是這邊的例子,前一個 joint位置在(0 0 0),
那麼這個 joint 的位置會在 (0 -0.22 0.25),可以對照 rviz圖看(那個小座標軸)
,如下圖。

<link name=”right_leg”>的 <visual>中,有<box size=” ”>,這宣告了一個長方體,它的 x有0.6公尺,y有0.1公尺,z有0.2公尺。
這個長方體的位置:我們可以看到

<origin rpy="0 0 0" xyz="0 0 -0.3"/>

預設 rpy 都是0,可以忽略。
<origin xyz >代表著長方體的中心位置和 joint位置的相對座標
joint 的位置在( 0 -0.22 0.25),所以長方體的中心位置在( 0 -0.22 -0.05),
可以觀察 rviz,發現長方體中心稍稍的低於 xy 平面。

(c)

  <joint name="right_leg_to_my_leg" type="fixed">
<parent link="right_leg"/>
<child link="my_leg"/>
<origin xyz="0 -0.5 0"/>
</joint>
<link name="my_leg">
<visual>
<geometry>
<box size="0.6 0.1 0.2"/>
</geometry>
<origin xyz="0 0 -0.1"/>
</visual>
</link>

<joint name>宣告一個叫做 right_leg_to_my_leg 的固定 joint 。
<origin xyz>表示這個 joint 的位置和前一個 joint位置的相對座標。

<link name>宣告一個叫做 my_leg 的 link。
它是長方體。
<origin xyz >代表著長方體的中心位置和 joint位置的相對座標

(3) 如果改變 rpy 的值

在 urdf 中,有兩個地方會有rpy的參數,一個在<joint>,一個在<link>,這邊測試看看在不同地方改rpy會有什麼效果。

(a) 更改 joint 的 rpy

這邊更改 base_to_right_leg 的 rpy。把 rpy 設定成 (0 1.57 0)。

這樣會使 joint 繞著 y 軸轉 1.57 rad (1圈是6.28 rad)。

同時可發現,後面的物件會連帶的動。

註解:y 軸方向需要自己看那些小座標軸指到哪裡
(他們會隨著轉動而變化)。

<joint name="base_to_right_leg" type="fixed">
<parent link="base_link"/>
<child link="right_leg"/>
<origin xyz="0 -0.22 0.25" rpy="0 1.57 0"/>
<!-- change rpy here -->
</joint>

原圖:

結果圖(更改完 rpy):

仔細觀察可以發現,joint的小座標軸改變方向了:

如果把rpy改成 (0 1.57 1.57):

這個地方很特別。我們想要它繞著z軸轉,雖然它也真的是繞z軸轉,
但它認定的z軸是 rpy 都是0的z軸。

註解:如果 rpy 三個參數都有值,那麼它會依序r p y的順序轉動
(我之前試出來的結果)

(b) 更改 link 的 rpy

先把程式碼回復到最原本的樣子。( 03-origins.urdf )

這邊更改名叫 right_leg 的 link。將 rpy 改成 (0 1.57 0)。

  <link name="right_leg">
<visual>
<geometry>
<box size="0.6 0.1 0.2"/>
</geometry>
<origin rpy="0 1.57 0" xyz="0 0 -0.3"/>
</visual>
</link>

這會使長方體繞著自己的中心旋轉,
且這裡我們特別指定繞 y 軸旋轉 1.57 rad。

原圖:

更改rpy後的圖:

註解:

旋轉 link 的rpy不會影響到後面的物件,只會改變自己的姿勢。

同時可以發現,那些小座標軸都沒改變。

三、在gazebo建出手掌的model

(1) 使用gazebo

這裡我是借用之前rrbot教學的環境,來進行手掌的建模。
所以可能會有一些多餘未刪的程式碼。

之前的 rrbot tutorial:

(2) 更改位於rrbot_gazebo內的 rrbot_world.lauch

位址在 /catkin_ws/src/gazebo_ros_demos/rrbot_gazebo/launch

只要更改第20行~第23行就好,這裡會指定gazebo去畫出哪一個urdf,

inorder '$(find rrbot_description)/urdf/my_hand_version3.xacro'" />註:$(find rrbot_description)會自己去尋找rrbot_description package的路徑
註:預設是/urdf/rrbot.xacro,這裡我更改為/urdf/my_hand_version3.xacro,
這樣它就會去畫出我指定的urdf了

第29行~第31行先不用管他,這個是為了解決pid error所加上去的,之後要讓手掌動時會提到。

(3) 建立 my_hand_version3.xacro
(這個檔案還沒完成,可能會不定時更新)

在/catkin_ws/src/gazebo_ros_demos/rrbot_description/urdf
建立 my_hand_version3.xacro :(因為有點長,所以就用付網址的方式)

https://gist.github.com/pythongo1/c64868cdd316077eb80abbd9be247ab9

my_hand_version3.xacro 會引用到位於同個資料夾的 rrbot.gazebo 和 materials.xacro 。

rrbot.gazebo: (是拿教學的直接改,所以有些用不到)

https://gist.github.com/pythongo1/5474275f82006b3b4527424cbf5a033e

materials.xacro :(教學的,沒改過。)

https://gist.github.com/pythongo1/39f66a31f6cc5974a13b9e0521f97546

(4) 分析 my_hand_version3.xacro

(a) 宣告這個檔案是 xacro檔

xmlns:xacro="http://www.ros.org/wiki/xacro"

(b) 引入位於同個資料夾的 rrbot.gazebo、materials.xacro

在 rrbot.gazebo中,

有 gazebo_plugin (這個很重要,要記得加):

註:我把<robotNamespace>的裡面設成/。 (原本是 rrbot )
(原因待補)

更改顏色的方法:

  <gazebo reference="hand_base">
<material>Gazebo/Yellow</material>
</gazebo>

註:顏色的英文(如 Yellow) 記得第一個字要大寫,不然它不會error,也不會改顏色

註:原本以為在 my_hand_version3.xacro中,改<link>內的<material>,就可以改顏色,但試了很久顏色都沒變化。最後才發現這個改顏色方法。

(c) 中間很多的 joint、link

就是手掌的參數,把手掌建立出來。

一開始建手掌的話,建議是把所有 joint 的type都是設成fixed,這樣比較好弄。建完固定姿勢的手掌後,再慢慢把他們改成continuous或其他非fixed型態(改成非fixed型態,其實要改不少東西或加一些東西,所以從fixed比較好)

如果所有joint都是fixed,那麼假如rrbot.gazebo和materials.xacro都有寫好,就可以直接執行

roslaunch rrbot_gazebo rrbot_world.launch

來觀察手掌的樣子。
(但因為上面付的檔案,裡面的joint很多都是 non-fixed的,所以這種體驗的感覺可能會不一樣)

(d) 最底下的transmission

每一個非fixed type (如 continuous)的joint,都要有一個transmission。

transmission 和控制關節的轉動有關,使用方法一併在下面一起講。

四、讓 joint 動起來 (延續上一篇跳過的部份)

(1) 參考的網站

這個網站函蓋了大部分要做的事,不過還是有一些東西沒提到,要自己加。

(2) 記得加上 gazebo plugin

我是加在 rrbot.gazebo,可以看自己要加在哪裡,記得引用就好。

<robotNamespace>裡面塡 / 。如果填其他名字,執行controller相關指令時,會有一些 error,如:

[WARN] [1565680912.734540, 196.867000]: Controller Spawner couldn’t find the expected controller_manager ROS interface

照理來說應該有辦法解決,只是我目前還找不到QQ。

以下是我試著找解決辦法時,發現的一些頗有用的文章:

(a)

(b)

(3) Spawning Controllers (產生 控制器)

(a) 建立 joint.yaml

在某個config資料夾中(我是在 /catkin_ws/src/urdf_sim_tutorial/config,當然也可以自己建一個config資料夾),建立 joint.yaml

joint.yaml :

joint.yaml 會指定我們的第一個 controller。

這個 controller 會發布各個joint的state情況,到 /joint_state topic 。

(b) 建立 my_hand_control.launch

在 /catkin_ws/src/gazebo_ros_demos/rrbot_control/launch 建立
my_hand_control.launch :

在<rosparam>中,file 填入 .yaml 檔的所在位置,ns 填入你想用的代稱。

在<node name>那邊,args 填入你所命名的代稱ns。

(c) 執行 roslaunch

執行 roslaunch,開啟 controller ,發布消息到 /joint_state:

roslaunch rrbot_control my_hand_control.launch

可以執行 rostopic echo /joint_state ,來得到這個話題上的消息:

rostopic echo /joint_state
---------------------------------------------------------
header:
seq: 652
stamp:
secs: 13
nsecs: 331000000
frame_id: ''
name: []
position: []
velocity: []
effort: []

大概會是像上面那樣,name以下都沒東西。name以下東西,在加了 transmission 後會出現。

(4) Transmissions

在 /catkin_ws/src/gazebo_ros_demos/rrbot_description/urdf 資料夾中,有我們的 my_hand_version3.xacro ,在這裡加入 transmission:

  <!-- transmission finger5 -->
<transmission name="finger5_trans">
<type>transmission_interface/SimpleTransmission</type>
<actuator name="finger5_motor">
<mechanicalReduction>1</mechanicalReduction>
</actuator>
<joint name="hand_base_to_finger5">
<hardwareInterface>PositionJointInterface</hardwareInterface>
</joint>
</transmission>

這個transmission是為了某個non-fixed joint (hand_base_to_finger5) 而寫的。

<transmission name>、<actuator name>都填入自己想填的名字即可。
<joint name>則一定要填對。

每一個 非fixed (non-fixed) joint 都要加上transmission。

這時候再一次執行(3)_(c),會發現下方有東西了。

(5) joint control

(a) finger5_0.yaml

在 /catkin_ws/src/gazebo_ros_demos/rrbot_control/config 中(之後很多.yaml 檔都會放這裡),建立 finger5_0.yaml 。

finger5_0.yaml :

type: "position_controllers/JointPositionController"
joint: hand_base_to_finger5

joint 一定要填對,對應到 transmission 內的 joint。

(b) 之後在 my_hand_control.launch 加入 <rosparam>

在/catkin_ws/src/gazebo_ros_demos/rrbot_control/launch,my_hand_control.launch:

多load了一個 .yaml 檔,file 填入 .yaml檔的位置。

<node name>那邊,在 args 加入新的代稱。

my_hand_control.launch 最後的樣子:

(c) 建立 gazebo_ros_control_params.yaml (教學沒有)

為了解決掉這個error :

No p gain specified for pid. Namespace: /gazebo_ros_control/pid_gains/hand_base_to_finger5

這個 error 一直指出缺少pid,最後找到了以下方法解決。

在 /catkin_ws/src/gazebo_ros_demos/rrbot_control/config
建立 gazebo_ros_control_params.yaml :

把 joint 名稱寫上去,之後加上pid。

經過不斷的增加joint後,最後會長的樣子:

在 /catkin_ws/src/gazebo_ros_demos/rrbot_gazebo/launch 的 rrbot_world.launch中,加入:

load 這個 gazebo_ros_control_params.yaml。

rrbot_world.launch 最後的樣子:

(d) 更改 joint limit

在 my_hand_version3.xacro。

因為 type 設定成 continuous,所以可以增加以下兩個東西。

加入 axis,指定旋轉軸(會依據當時的 joint 的座標軸來判斷方向)。

加入 limit,限制力的大小,限制速度的大小。

(e)

重複(4)transmission~(5)joint control,直到把所有non-fixed joint 加完。

下一步就可以執行他們,並且讓 joint 轉動。

這裡統整一下要做的事(一直重複做的部份):

把 joint type 改成 continuous
先加 transmission
加上各別對應 yaml
更改 my_hand_control.launch ( load )
更改 gazebo_ros_control_params.yaml (為了pid)
更改 joint limit

(6) 讓 joint 動起來

執行:

// 在一個新終端機
roslaunch rrbot_gazebo rrbot_world.launch
//在一個新終端機
roslaunch rrbot_control my_hand_control.launch

註:可用shift+左鍵,來旋轉畫面。

看一下所有 topic :

rostopic list

可以藉由發布消息到以下 topic 來控制 joint 的動作:

/finger1_controller/command      (finger1是大拇指比較特別,動動看就知道了)
/finger1_rotate_axis_controller/command
/finger2_0_controller/command (食指和掌心的關節)
/finger2_1_controller/command (食指的第一關節)
/finger3_0_controller/command (中指和掌心的關節)
/finger3_1_controller/command (中指的第一關節)
/finger4_0_controller/command (無名指和掌心的關節)
/finger4_1_controller/command (無名指的第一關節)
/finger5_0_controller/command (小拇指和掌心的關節)
/finger5_1_controller/command (小拇指的第一關節)

發布消息,轉動小拇指:

rostopic pub /finger5_0_controller/command std_msgs/Float64 "data: 1"
rostopic pub /finger5_1_controller/command std_msgs/Float64 "data: 0.5"

發布消息,轉動大拇指:

rostopic pub /finger1_rotate_axis_controller/command std_msgs/Float64 "data: -1.3"
rostopic pub /finger1_controller/command std_msgs/Float64 "data: 1"

--

--