ROS入門(五)——Gazebo加載模型與ROS控制


ROS入門(五)——Gazebo加載模型與ROS控制
  iwehdio的博客園:https://www.cnblogs.com/iwehdio/

參考教程:Gazebo官方教程

1、將機器人添加到Gazebo環境中

  • 創建自己的Gazebo ROS包。在ROS工作空間下,所用與機器人模型和說明有關的都應放在/MYROBOT_description包中,所有與Gazebo有關的啟動文件和世界文件都應放在/MYROBOT_gazebo中。

    ~/catkin_ws/src
    	/MYROBOT_description
    		/urdf
    			MYROBOT.urdf
    		/meshes
    			mesh1.dae
    			...
    		/materials
    		/cad
    	/MYROBOT_gazebo
    		/launch
    			MYROBOT.launch
    		/worlds
    			MYROBOT.world
    		/models
    			world_object1.dae
    		/materials
    		/plugins
    
  • 創建自定義的世界文件和啟動世界文件的launch文件,在 smallcar_gazebo功能包下。station.launch文件放在launch文件夾下,station.world文件放在worlds文件夾下。

    station.launch文件
    <launch>
      <!-- We resume the logic in empty_world.launch, changing only the name of the world to be launched -->
      <include file="$(find gazebo_ros)/launch/empty_world.launch">
        <arg name="world_name" value="$(find smallcar_gazebo)/worlds/station.world"/>
        <!-- more default parameters can be changed here -->
      </include>
    </launch>
    
    station.world文件
    <?xml version="1.0" ?>
    <sdf version="1.4">
      <world name="default">
        <include>
          <uri>model://ground_plane</uri>
        </include>
        <include>
          <uri>model://sun</uri>
        </include>
        <include>
          <uri>model://gas_station</uri>
          <name>gas_station</name>
          <pose>-2.0 7.0 0 0 0 0</pose>
        </include>
      </world>
    </sdf>
    
  • 添加find smallcar_gazebo到環境變量后,使用指令:

    $ roslaunch smallcar_gazebo station.launch
    

    即可啟動加油站世界文件(如果啟動不了查看 .gazebo/.models下是否有 gas_station模型):

  • 使用 roslaunch 啟動 URDF描述的機器人。

    • 可以使用ROS服務調用的方法。該方法使用 python 腳本 spawn_modelgazebo_rosROS節點(在rostopic命名空間中簡稱為“ gazebo”)發出服務調用請求,以將自定義URDF添加到Gazebo中。主要考慮使用 URDF 的情況,使用XACRO 或模型數據庫方法可參考http://gazebosim.org/tutorials?tut=ros_roslaunch。

    • 運行腳本和查看所有可用參數的方法:

      $ rosrun gazebo_ros spawn_model -file `rospack find MYROBOT_description`/urdf/MYROBOT.urdf -urdf -x 0 -y 0 -z 1 -model MYROBOT
      $ rosrun gazebo_ros spawn_model -h
      
    • 如果沒有 URDF 實例,可以使用 baxter 實例。

      $ git clone https://github.com/RethinkRobotics/baxter_common.git
      $ rosrun gazebo_ros spawn_model -file `rospack find baxter_description`/urdf/baxter.urdf -urdf -z 1 -model baxter
      不想配置環境變量可以進入baxter_description/urdf輸入:
      $ rosrun gazebo_ros spawn_model -file baxter.urdf -urdf -z 1 -model baxter
      

      結果為將機器人添加到了環境中:

    • 將這個機器人集成到launch文件中,將以下的內容添加到launch文件中。效果與上相同

      <!-- Spawn a robot into Gazebo -->
      <node name="spawn_urdf" pkg="gazebo_ros" type="spawn_model" args="-file $(find baxter_description)/urdf/baxter.urdf -urdf -z 1 -model baxter" />
      

2、URDF 文件的使用。

  • 通用機器人描述格式(URDF)是ROS用於描述機器人的所有元素的XML文件格式。在后台,gazebo將自動將URDF轉換為SDF。

  • URDF 文件的總體要求:每個<link>標簽中都必須有一個<inertial>標簽;每個<link><joint><robot>標簽中都可以有一個<gazebo>標簽;如果想讓某組件固定到世界則指定<link name="world">

  • <gazebo>元素是URDF的擴展,用於指定在gazebo中進行仿真所需的其他屬性。它允許您指定以SDF格式找到的未包含在URDF格式中的屬性。三種不同的<gazebo>元素分別<link><joint><robot>標簽。

  • 獲取實例機器人RPBot,編譯並在Rviz中查看。

    $ git clone https://github.com/ros-simulation/gazebo_ros_demos.git 
    $ roslaunch rrbot_description rrbot_rviz.launch
    

    結果為:(還能夠使用“關節狀態發布者”窗口中的滑塊來移動兩個關節)

    在這里可能會報錯,解決方法見https://www.cnblogs.com/vtas-Yao/p/12376939.html。命令行里沒有警告了,但是 Camera 里還是有警告。

  • 在gazebo中查看:

    $ roslaunch rrbot_gazebo rrbot_world.launch
    
  • <gazebo>元素標簽沒有屬性,適用於整個機器人模型。<robot>中如果有該標簽則說明模型是不可移動的。更多該標簽的功能見http://gazebosim.org/tutorials/?tut=ros_urdf。

  • 剛性固定模型到世界。

    • 如果希望將URDF模型永久地附加到世界框架(地平面),則必須創建一個“世界”鏈接和一個將其固定到模型基礎的關節。RRBot通過以下步驟實現了這一目標:

        <!-- Used for fixing robot to Gazebo 'base_link' -->
        <link name="world"/>
      
        <joint name="fixed" type="fixed">
          <parent link="world"/>
          <child link="link1"/>
        </joint>
      
  • 鏈接(link)在RRBot中的示例:

    <!-- Base Link -->
      <link name="link1">
        <collision>
          <origin xyz="0 0 ${height1/2}" rpy="0 0 0"/>
          <geometry>
            <box size="${width} ${width} ${height1}"/>
          </geometry>
        </collision>
    
        <visual>
          <origin xyz="0 0 ${height1/2}" rpy="0 0 0"/>
          <geometry>
            <box size="${width} ${width} ${height1}"/>
          </geometry>
          <material name="orange"/>
        </visual>
    
        <inertial>
          <origin xyz="0 0 1" rpy="0 0 0"/>
          <mass value="1"/>
          <inertia
            ixx="1.0" ixy="0.0" ixz="0.0"
            iyy="1.0" iyz="0.0"
            izz="1.0"/>
        </inertial>
      </link>
    
    • gazebo中指定的單位為米和千克。

    • <collision>標簽中指定的是物理的碰撞模型,<visual>中指定的是可見的視覺模型。二者必須同時指定。

    • 開源工具Blender可以簡化碰撞模型,提高性能。

    • 標准 URDF 指定顏色:

      <material name="orange"/>
      或
      <material name="orange">
          <color rgba="${255/255} ${108/255} ${10/255} 1.0"/>
        </material>
      
      • 上述方法在gazebo中無效,gazebo中必須為每個鏈接指定材料標簽。

        <gazebo reference="link1">
            <material>Gazebo/Orange</material>
        </gazebo>
        
    • <inertial>在gazebo中為了使鏈接不被忽略,質量必須大於零。此外,在任何有限扭矩應用下,零主慣性矩(ixx,iyy,izz)的鏈接都可能導致無限加速。

      <inertial>
          <origin xyz="0 0 ${height1/2}" rpy="0 0 0"/>
          <mass value="1"/>
          <inertia
               ixx="1.0" ixy="0.0" ixz="0.0"
               iyy="1.0" iyz="0.0"
               izz="1.0"/>
      </inertial>
      

      <origin>標簽表示此鏈接的質心。通過將質心設置為RRBot矩形鏈接高度的一半,我們將質心居中。

    • 在RRBot中,指定了兩個非固定鏈接的摩擦系數,以便在發生碰撞時模擬更精確的接觸相互作用。

      <gazebo reference="link2">
          <mu1>0.2</mu1>
          <mu2>0.2</mu2>
          <material>Gazebo/Black</material>
        </gazebo>
      
  • 關節(joint)在RRBot中的示例:

    <joint name="joint2" type="continuous">
        <parent link="link2"/>
        <child link="link3"/>
        <origin xyz="0 ${width} ${height2 - axel_offset*2}" rpy="0 0 0"/>
        <axis xyz="0 1 0"/>
        <dynamics damping="0.7"/>
      </joint>
    
    • <origin><parent><child>標簽是必須的。
    • <limit>標簽中的所有屬性都是可選的。
  • 通過 gazebo 將 URDF 轉換為 SDF:

    $ gz sdf -p MODEL.urdf
    

3、Gazebo插件與ROS

  • Gazebo主要支持三種插件:ModelPlugins 提供對物理模型的 API 訪問;SensorPlugins 提供對傳感器的 API 的訪問;VisualPlugins 提供對視覺的 API 的訪問。

  • 添加一個 ModelPlugins 。將ModelPlugins charity到<robot>標簽內部,且被<gazebo>標簽包裹着。

    <robot>
      ... robot description ...
      <gazebo>
        <plugin name="differential_drive_controller" filename="libdiffdrive_plugin.so">
          ... plugin parameters ...
        </plugin>
      </gazebo>
      ... robot description ...
    </robot>
    

    在Gazebo內加載機器人模型后,diffdrive_plugin代碼將獲得對模型本身的引用,從而可以對其進行操作。同樣,它將為自身的SDF元素供參考,以讀取傳遞給它的插件參數。

  • 添加一個 SensorPlugins 。指定傳感器插件略有不同,Gazebo中的傳感器應連接到鏈接,因此<gazebo>必須為描述該傳感器的元素提供對該鏈接的引用。

    <robot>
      ... robot description ...
      <link name="sensor_link">
        ... link description ...
      </link>
    
      <gazebo reference="sensor_link">
        <sensor type="camera" name="camera1">
          ... sensor parameters ...
          <plugin name="camera_controller" filename="libgazebo_ros_camera.so">
            ... plugin parameters ..
          </plugin>
        </sensor>
      </gazebo>
    
    </robot>
    

    在Gazebo內加載機器人模型后,camera_controller將為代碼提供對傳感器的引用,從而可以訪問其API。同樣,它將為自身的SDF元素提供參考,以讀取傳遞給它的插件參數。

  • gazebo_plugins中可用的插件:

    • Camera:提供ROS接口,用於通過發布CameraInfo和Image ROS消息來模擬wge100 攝像機之類的攝像機。

      • 以一個安裝在RRBot擺臂末端的簡單RGB相機為示例,在 rrbot.xacro 文件中。

        <xacro:property name="camera_link" value="0.05" /> <!-- Size of square 'camera' box -->
        
        <joint name="camera_joint" type="fixed">
            <axis xyz="0 1 0" />
            <origin xyz="${camera_link} 0 ${height3 - axel_offset*2}" rpy="0 0 0"/>
            <parent link="link3"/>
            <child link="camera_link"/>
          </joint>
        
          <!-- Camera -->
          <link name="camera_link">
            <collision>
              <origin xyz="0 0 0" rpy="0 0 0"/>
              <geometry>
            <box size="${camera_link} ${camera_link} ${camera_link}"/>
              </geometry>
            </collision>
        
            <visual>
              <origin xyz="0 0 0" rpy="0 0 0"/>
              <geometry>
            <box size="${camera_link} ${camera_link} ${camera_link}"/>
              </geometry>
              <material name="red"/>
            </visual>
        
            <inertial>
              <mass value="1e-5" />
              <origin xyz="0 0 0" rpy="0 0 0"/>
              <inertia ixx="1e-6" ixy="0" ixz="0" iyy="1e-6" iyz="0" izz="1e-6" />
            </inertial>
          </link>
        
      • 該插件為我們提供了攝像頭功能,並將圖像發布到ROS消息中。如前所示,在 rrbot.gazebo 文件中用<gazebo>標簽的引用指向鏈接。

        <!-- camera -->
        <gazebo reference="camera_link">
            <sensor type="camera" name="camera1">
                <update_rate>30.0</update_rate>
                <camera name="head">
                    <horizontal_fov>1.3962634</horizontal_fov>
                    <image>
                        <width>800</width>
                        <height>800</height>
                        <format>R8G8B8</format>
                    </image>
                    <clip>
                        <near>0.02</near>
                        <far>300</far>
                    </clip>
                    <noise>
                        <type>gaussian</type>
                        <!-- Noise is sampled independently per pixel on each frame.
                       That pixel's noise value is added to each of its color
                       channels, which at that point lie in the range [0,1]. -->
                        <mean>0.0</mean>
                        <stddev>0.007</stddev>
                    </noise>
                </camera>
                <plugin name="camera_controller" filename="libgazebo_ros_camera.so">
                    <alwaysOn>true</alwaysOn>
                    <updateRate>0.0</updateRate>
                    <cameraName>rrbot/camera1</cameraName>
                    <imageTopicName>image_raw</imageTopicName>
                    <cameraInfoTopicName>camera_info</cameraInfoTopicName>
                    <frameName>camera_link</frameName>
                    <hackBaseline>0.07</hackBaseline>
                    <distortionK1>0.0</distortionK1>
                    <distortionK2>0.0</distortionK2>
                    <distortionK3>0.0</distortionK3>
                    <distortionT1>0.0</distortionT1>
                    <distortionT2>0.0</distortionT2>
                </plugin>
            </sensor>
        </gazebo>
        

        其中:

        • <gazebo reference="camera_link">:鏈接名稱“ camera_link”必須與我們添加到 URDF 的鏈接的名稱匹配。

        • <sensor type="camera" name="camera1">:傳感器名稱“ camera1”必須與所有其他傳感器名稱唯一。

        • <update_rate>30.0</update_rate>:刷新率,Gazebo內每秒拍攝一次新相機圖像的次數。這是傳感器在仿真過程中將嘗試的最大更新速率,但是如果物理仿真的運行速度快於傳感器生成的速度,則它可能會落后於該目標速率。

        • 填寫以下這些值以匹配物理相機硬件上制造商的規格。假定為正方形。近片段和遠片段是特定於仿真的參數,為攝像機可以看到仿真對象的距離提供了上限和下限。在相機的驗光框中指定。

          <horizontal_fov>1.3962634</horizontal_fov>
          <image>
              <width>800</width>
              <height>800</height>
              <format>R8G8B8</format>
          </image>
          <clip>
              <near>0.02</near>
              <far>300</far>
          </clip>
          
        • <plugin name="camera_controller" filename="libgazebo_ros_camera.so">:這是與實際文件(gazebo_ros/gazebo_ros_camera.cpp) 鏈接。

        • 為圖像主題和照相機信息主題定義了照相機將發布到的rostopic。

          <cameraName>rrbot/camera1</cameraName>
          <imageTopicName>image_raw</imageTopicName>
          <cameraInfoTopicName>camera_info</cameraInfoTopicName>
          

          應當訂閱:/rrbot/camera1/image_raw 和 /rrbot/camera1/camera_info。

        • <frameName>camera_link</frameName>:圖像在tf樹中發布的坐標框架。

  • 運行 RRBot 相機示例:同時啟動gazebo和rviz。

    $ roslaunch rrbot_gazebo rrbot_world.launch
    $ roslaunch rrbot_description rrbot_rviz.launch
    

    在gazebo中在相機前放置之前的小車,在Rviz中可以看的相機的畫面(/rrbot/camera1/image_raw話題)。

    Gazebo中放置小車:

    Rviz中的相機畫面:

  • 多機位相機(同步多個相機,儀器發布圖像):

    <gazebo reference="left_camera_frame">
        <sensor type="multicamera" name="stereo_camera">
            <update_rate>30.0</update_rate>
            <camera name="left">
                <horizontal_fov>1.3962634</horizontal_fov>
                <image>
                    <width>800</width>
                    <height>800</height>
                    <format>R8G8B8</format>
                </image>
                <clip>
                    <near>0.02</near>
                    <far>300</far>
                </clip>
                <noise>
                    <type>gaussian</type>
                    <mean>0.0</mean>
                    <stddev>0.007</stddev>
                </noise>
            </camera>
            <camera name="right">
                <pose>0 -0.07 0 0 0 0</pose>
                <horizontal_fov>1.3962634</horizontal_fov>
                <image>
                    <width>800</width>
                    <height>800</height>
                    <format>R8G8B8</format>
                </image>
                <clip>
                    <near>0.02</near>
                    <far>300</far>
                </clip>
                <noise>
                    <type>gaussian</type>
                    <mean>0.0</mean>
                    <stddev>0.007</stddev>
                </noise>
            </camera>
            <plugin name="stereo_camera_controller" filename="libgazebo_ros_multicamera.so">
                <alwaysOn>true</alwaysOn>
                <updateRate>0.0</updateRate>
                <cameraName>multisense_sl/camera</cameraName>
                <imageTopicName>image_raw</imageTopicName>
                <cameraInfoTopicName>camera_info</cameraInfoTopicName>
                <frameName>left_camera_optical_frame</frameName>
                <!--<rightFrameName>right_camera_optical_frame</rightFrameName>-->
                <hackBaseline>0.07</hackBaseline>
                <distortionK1>0.0</distortionK1>
                <distortionK2>0.0</distortionK2>
                <distortionK3>0.0</distortionK3>
                <distortionT1>0.0</distortionT1>
                <distortionT2>0.0</distortionT2>
            </plugin>
        </sensor>
    </gazebo>
    
  • 深度相機:

    <gazebo reference="${link_name}">
      <sensor name="${link_name}_camera" type="depth">
        <update_rate>20</update_rate>
        <camera>
          <horizontal_fov>1.047198</horizontal_fov>
          <image>
            <width>640</width>
            <height>480</height>
            <format>R8G8B8</format>
          </image>
          <clip>
            <near>0.05</near>
            <far>3</far>
          </clip>
        </camera>
        <plugin name="${link_name}_controller" filename="libgazebo_ros_openni_kinect.so">
          <baseline>0.2</baseline>
          <alwaysOn>true</alwaysOn>
          <updateRate>1.0</updateRate>
          <cameraName>${camera_name}_ir</cameraName>
          <imageTopicName>/${camera_name}/color/image_raw</imageTopicName>
          <cameraInfoTopicName>/${camera_name}/color/camera_info</cameraInfoTopicName>
          <depthImageTopicName>/${camera_name}/depth/image_raw</depthImageTopicName>
          <depthImageInfoTopicName>/${camera_name}/depth/camera_info</depthImageInfoTopicName>
          <pointCloudTopicName>/${camera_name}/depth/points</pointCloudTopicName>
          <frameName>${frame_name}</frameName>
          <pointCloudCutoff>0.5</pointCloudCutoff>
          <pointCloudCutoffMax>3.0</pointCloudCutoffMax>
          <distortionK1>0.00000001</distortionK1>
          <distortionK2>0.00000001</distortionK2>
          <distortionK3>0.00000001</distortionK3>
          <distortionT1>0.00000001</distortionT1>
          <distortionT2>0.00000001</distortionT2>
          <CxPrime>0</CxPrime>
          <Cx>0</Cx>
          <Cy>0</Cy>
          <focalLength>0</focalLength>
          <hackBaseline>0</hackBaseline>
        </plugin>
      </sensor>
    </gazebo>
    
  • 激光雷達:

    與之前一樣,在 rrbot.xacro中指定鏈接和關節。

    <joint name="hokuyo_joint" type="fixed">
        <axis xyz="0 1 0" />
        <origin xyz="0 0 ${height3 - axel_offset/2}" rpy="0 0 0"/>
        <parent link="link3"/>
        <child link="hokuyo_link"/>
    </joint>
    
    <!-- Hokuyo Laser -->
    <link name="hokuyo_link">
        <collision>
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <geometry>
                <box size="0.1 0.1 0.1"/>
            </geometry>
        </collision>
    
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <geometry>
                <mesh filename="package://rrbot_description/meshes/hokuyo.dae"/>
            </geometry>
        </visual>
    
        <inertial>
            <mass value="1e-5" />
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <inertia ixx="1e-6" ixy="0" ixz="0" iyy="1e-6" iyz="0" izz="1e-6" />
        </inertial>
    </link>
    

    與之前一樣,在 rrbot.gazebo 文件中用<gazebo>標簽的引用指向鏈接。

    <!-- hokuyo -->
    <gazebo reference="hokuyo_link">
        <sensor type="gpu_ray" name="head_hokuyo_sensor">
            <pose>0 0 0 0 0 0</pose>
            <visualize>false</visualize>
            <update_rate>40</update_rate>
            <ray>
                <scan>
                    <horizontal>
                        <samples>720</samples>
                        <resolution>1</resolution>
                        <min_angle>-1.570796</min_angle>
                        <max_angle>1.570796</max_angle>
                    </horizontal>
                </scan>
                <range>
                    <min>0.10</min>
                    <max>30.0</max>
                    <resolution>0.01</resolution>
                </range>
                <noise>
                    <type>gaussian</type>
                    <!-- Noise parameters based on published spec for Hokuyo laser
                   achieving "+-30mm" accuracy at range < 10m.  A mean of 0.0m and
                   stddev of 0.01m will put 99.7% of samples within 0.03m of the true
                   reading. -->
                    <mean>0.0</mean>
                    <stddev>0.01</stddev>
                </noise>
            </ray>
            <plugin name="gazebo_ros_head_hokuyo_controller" filename="libgazebo_ros_gpu_laser.so">
                <topicName>/rrbot/laser/scan</topicName>
                <frameName>hokuyo_link</frameName>
            </plugin>
        </sensor>
    </gazebo>
    

    其中:

    • <visualize>false</visualize>:如果為true,則在gpu激光的掃描區域內可以看到半透明的激光射線。

    • 設置為將激光掃描發布到的ROS主題名稱,以及TF使用的轉換框架

      <topicName>/rrbot/laser/scan</topicName>
      <frameName>hokuyo_link</frameName>
      
  • 運行 RRBot 激光雷達實例:同時啟動gazebo和rviz。

    $ roslaunch rrbot_gazebo rrbot_world.launch
    $ roslaunch rrbot_description rrbot_rviz.launch
    
    • 在Rviz中,添加“ LaserScan”顯示,並在“主題”下將其設置為 /rrbot/laser/scan 。

      Gazebo中放置加油站:

      )

      Rviz中的激光雷達信息:

  • IMU 慣性運動傳感器(GazeboRosImu),計算在ROS中完成:

    <robot>
    :
      <gazebo>
        <plugin name="imu_plugin" filename="libgazebo_ros_imu.so">
          <alwaysOn>true</alwaysOn>
          <bodyName>base_footprint</bodyName>
          <topicName>imu</topicName>
          <serviceName>imu_service</serviceName>
          <gaussianNoise>0.0</gaussianNoise>
          <updateRate>20.0</updateRate>
        </plugin>
      </gazebo>
    </robot>
    
  • 差動驅動:

    <gazebo>
      <plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so">
        <alwaysOn>true</alwaysOn>
        <updateRate>${update_rate}</updateRate>
        <leftJoint>base_link_right_wheel_joint</leftJoint>
        <rightJoint>base_link_left_wheel_joint</rightJoint>
        <wheelSeparation>0.5380</wheelSeparation>
        <wheelDiameter>0.2410</wheelDiameter>
        <torque>20</torque>
        <commandTopic>cmd_vel</commandTopic>
        <odometryTopic>odom</odometryTopic>
        <odometryFrame>odom</odometryFrame>
        <robotBaseFrame>base_footprint</robotBaseFrame>
      </plugin>
    </gazebo>
    
  • 防滑轉向驅動:

    <gazebo>
      <plugin name="skid_steer_drive_controller" filename="libgazebo_ros_skid_steer_drive.so">
        <updateRate>100.0</updateRate>
        <robotNamespace>/</robotNamespace>
        <leftFrontJoint>front_left_wheel_joint</leftFrontJoint>
        <rightFrontJoint>front_right_wheel_joint</rightFrontJoint>
        <leftRearJoint>back_left_wheel_joint</leftRearJoint>
        <rightRearJoint>back_right_wheel_joint</rightRearJoint>
        <wheelSeparation>0.4</wheelSeparation>
        <wheelDiameter>0.215</wheelDiameter>
        <robotBaseFrame>base_link</robotBaseFrame>
        <torque>20</torque>
        <topicName>cmd_vel</topicName>
        <broadcastTF>false</broadcastTF>
      </plugin>
    </gazebo>
    
  • 平面移動:

    <robot name="test_model">
    
      <!-- root link, on the ground just below the model origin -->
      <link name="base_footprint">
       <visual>
          <origin xyz="0 0 0" rpy="0 0 0" />
          <geometry>
            <box size="0.001 0.001 0.001" />
          </geometry>
        </visual>
      </link>
    
      <joint name="base_link_joint" type="fixed">
        <origin xyz="0.0 0 1.25" rpy="0 0 0" />
        <parent link="base_footprint"/>
        <child link="base_link" />
      </joint>
    
      <!-- the model -->
      <link name="base_link">
        <inertial>
          <mass value="50" />
          <origin xyz="0 0 -1.25" />
          <inertia ixx="50.0" ixy="0.0" ixz="0.0"
            iyy="50.0" iyz="0.0"
            izz="50.0" />
        </inertial>
        <visual>
          <geometry>
            <box size="0.5 0.5 1.0" /> <!-- does not need to match collision -->
          </geometry>
        </visual>
        <collision>
          <origin xyz="0 0 -1.0" />
          <geometry>
            <cylinder length="0.5" radius="0.25" />
          </geometry>
        </collision>
      </link>
    
      <gazebo>
        <plugin name="object_controller" filename="libgazebo_ros_planar_move.so">
          <commandTopic>cmd_vel</commandTopic>
          <odometryTopic>odom</odometryTopic>
          <odometryFrame>odom</odometryFrame>
          <odometryRate>20.0</odometryRate>
          <robotBaseFrame>base_footprint</robotBaseFrame>
        </plugin>
      </gazebo>
    
    </robot>
    
  • 此外還包括:激光測距儀、地面力反饋、地面位置、關節姿態、Prosilica相機、投影儀、緩沖、視頻插件等,見http://gazebosim.org/tutorials?tut=ros_gzplugins。

4、用ROS控制Gazebo

  • 可以使用ros_control和簡單的Gazebo插件適配器在Gazebo中模擬機器人的控制。

  • 要將ros_control與機器人一起使用,需要向URDF添加一些其他元素。transmission>元素用於將執行器鏈接到關節。其中包括:

    • <joint name="">:URDF中關節的名字。
    • <type>:執行器的類型。
    • <hardwareInterface>:在 <actuator><joint>標簽中,用於告訴插件硬件層的位置、速度等參數。
  • 還需要將一個Gazebo插件添加到您的URDF中,該插件實際上會解析傳輸標簽並加載適當的硬件接口和控制器管理器。

    <gazebo>
      <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
        <robotNamespace>/MYROBOT</robotNamespace>
      </plugin>
    </gazebo>
    
    • <plugin>標簽還具有以下可選的子元素:
      • <robotNamespace>:用於此插件實例的ROS名稱空間,在URDF / SDF中默認為機器人名稱。
      • <controlPeriod>:控制器的更新周期(以秒為單位),默認為gazebo的周期。
      • <controlPeriod>:robot_description(URDF)在參數服務器上的位置,默認為'/ robot_description'。
      • <robotSimType>:要使用的自定義機器人sim接口的pluginlib名稱,默認為'DefaultRobotHWSim'。
    • gazebo_ros_control 默認行為提供的接口:
      • JointStateInterface。
      • EffortJointInterface。
      • VelocityJointInterface。
  • RRBot 中的示例:

    rrbot.xacro 中添加的<transmission>標簽。

    <transmission name="tran1">
        <type>transmission_interface/SimpleTransmission</type>
        <joint name="joint1">
            <hardwareInterface>EffortJointInterface</hardwareInterface>
        </joint>
        <actuator name="motor1">
            <hardwareInterface>EffortJointInterface</hardwareInterface>
            <mechanicalReduction>1</mechanicalReduction>
        </actuator>
    </transmission>
    
    <transmission name="tran2">
        <type>transmission_interface/SimpleTransmission</type>
        <joint name="joint2">
            <hardwareInterface>EffortJointInterface</hardwareInterface>
        </joint>
        <actuator name="motor2">
            <hardwareInterface>EffortJointInterface</hardwareInterface>
            <mechanicalReduction>1</mechanicalReduction>
        </actuator>
    </transmission>
    
    • <hardwareInterface>必須在<joint><actuator>標簽中都包含。

    rrbot.gazebo 中加載插件:

    <gazebo>
      <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
        <robotNamespace>/rrbot</robotNamespace>
      </plugin>
    </gazebo>
    
  • 創建一個 ros_controls 包。

    • 創建功能包。

      $ mkdir ~/catkin_ws
      $ cd ~/catkin_ws
      $ catkin_create_pkg smallcar_control controller_manager joint_state_controller robot_state_publisher_gui
      $ cd smallcar_control
      $ mkdir config
      $ mkdir launch
      
    • 創建一個 .yaml 配置文件,放置在 config 文件夾中。

      PID增益和控制器設置必須保存在yaml文件中,該文件通過roslaunch文件加載到參數服務器中。

      rrbot:
        # Publish all joint states -----------------------------------
        joint_state_controller:
          type: joint_state_controller/JointStateController
          publish_rate: 50  
      
        # Position Controllers ---------------------------------------
        joint1_position_controller:
          type: effort_controllers/JointPositionController
          joint: joint1
          pid: {p: 100.0, i: 0.01, d: 10.0}
        joint2_position_controller:
          type: effort_controllers/JointPositionController
          joint: joint2
          pid: {p: 100.0, i: 0.01, d: 10.0}
      
    • 創建一個 roslaunch 文件。

      創建用於啟動ros_control控制器的roslaunch文件。

      <launch>
      
        <!-- Load joint controller configurations from YAML file to parameter server -->
        <rosparam file="$(find rrbot_control)/config/rrbot_control.yaml" command="load"/>
      
        <!-- load the controllers -->
        <node name="controller_spawner" pkg="controller_manager" type="spawner" respawn="false"
          output="screen" ns="/rrbot" args="joint1_position_controller joint2_position_controller joint_state_controller"/>
      
        <!-- convert joint states to TF transforms for rviz, etc -->
        <node name="robot_state_publisher_gui" pkg="robot_state_publisherr_gui" type="robot_state_publisherr_gui
          respawn="false" output="screen">
          <remap from="/joint_states" to="/rrbot/joint_states" />
        </node>
      
      </launch>
      

      其中:

      • 第一行:“ rosparam”通過加載 yaml 配置文件將控制器設置加載到參數服務器。
      • 第二行:controller_spawner 節點通過運行 python 腳本啟動 RRBot 的兩個關節位置控制器,該腳本對ros_control控制器管理器進行服務調用。服務調用告訴控制器管理器您想要哪個控制器。它還加載了第三個控制器,該控制器使用 hardware_interfaces 發布所有關節的關節狀態,並在 / oint_states上發布話題。生成器只是用於roslaunch的幫助程序腳本。
      • 最后一行開始一個 robot_state_publisher_gui 節點,該節點僅偵聽來自 joint_state_controller 的 /joint_states消息,然后將轉換發布到 /tf。這使您可以在Rviz中查看模擬的機器人以及執行其他任務。
  • 使用 roslaunch 啟動控制器:

    $ roslaunch rrbot_gazebo rrbot_world.launch
    $ roslaunch rrbot_control rrbot_control.launch
    

    在此之前需要先安裝控制器插件:

    $ sudo apt-get install ros-melodic-effort-controllers
    
    • 也可以手動通過服務請求控制:

      # 加載控制器:
      $ rosservice call /rrbot/controller_manager/load_controller "name: 'joint1_position_controller'"
      $ rosservice call /rrbot/controller_manager/load_controller "name: 'joint2_position_controller'"
      # 啟動控制器:
      $ rosservice call /rrbot/controller_manager/switch_controller "{start_controllers: ['joint1_position_controller','joint2_position_controller'], stop_controllers: [], strictness: 2}"
      # 停止控制器:
      $ rosservice call /rrbot/controller_manager/switch_controller "{start_controllers: [], stop_controllers: ['joint1_position_controller','joint2_position_controller'], strictness: 2}"
      
  • 手動發送命令:

    $ rostopic pub -1 /rrbot/joint1_position_controller/command std_msgs/Float64 "data: 1.5"
    $ rostopic pub -1 /rrbot/joint2_position_controller/command std_msgs/Float64 "data: 1.0"
    
  • 使用 RQT 發送命令:

    啟動RQT:

    $ rosrun rqt_gui rqt_gui
    

    在RQT的“插件”菜單上,添加“主題->消息發布者”插件,添加命令發布者控制器 /rrbot/joint1_position_controller/command。調節話題發布速率和目標值。

    • 可視化控制器性能:將Plot插件添加到RQT,並添加與您在上面為主題發布者選擇的主題相同的主題:/rrbot/joint1_position_controller/command/data

    • 向Plot插件添加另一個主題,該主題可跟蹤被控制執行器的實際位置。您將需要通過調整PID增益來減少這兩個值之間的誤差,如下一步所示。對於RRBot:/rrbot/joint1_position_controller/state/process_value

    • 調節PID增益:將“動態重新配置”插件添加到RQT,然后單擊“全部擴展”以查看子選項。假設您的控制器使用PID,則應使用“ pid”選項。

    • 使用roslaunch 保存 rqt 配置。

      $ roslaunch rrbot_control rrbot_rqt.launch
      

iwehdio的博客園:https://www.cnblogs.com/iwehdio/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM