gazebo入门测试

First step with gazebo and ros

• setup a ROS workspace
• create projects for your simulated robot
• create a Gazebo world
• create your own robot model
• connect your robot model to ROS
• use a teleoperation node to control your robot
• add a camera to your robot
• use Rviz to vizualize all the robot information

Setup a new workspace

mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace
cd ..
catkin_make
source ~/catkin_ws/devel/setup.bash

Create projects for your simulated robot

cd ~/catkin_ws/src
catkin_create_pkg mybot_gazebo gazebo_ros
catkin_create_pkg mybot_description
catkin_create_pkg mybot_control

Creating your own World

roscd mybot_gazebo 
mkdir launch worlds
cd worlds
vim mybot.world

A basic world file defines at least a name:

world是我们调用所有model的接口,包括机器人也是一个model,在此处调用。

<?xml version="1.0"?>
<sdf version="1.4">
<world name="myworld">
</world>
</sdf>

At first we just want to add some basic  , like a ground and a basic illumination source inside the world tag. include标签包含的是model,我们在这里引入了三个model。

<include>
    <uri>model://sun</uri>
</include>

<include>
    <uri>model://ground_plane</uri>
</include>

<include>
    <uri>model://turtlebot</uri>
</include>
roscd mybot_gazebo/launch
vim mybot_world.launch

mybot_world.launch

launch文件的主要作用是调用其他文件。其中,arg是参数的意思。就这样,我们通过launch调用了一个world文件——mybot.world,然后world调用了其他的model。

<launch>      
    <include file="$(find gazebo_ros)/launch/empty_world.launch">       
        <arg name="world_name" value="$(find mybot_gazebo)/worlds/mybot.world"/>        
        <arg name="gui" value="true"/>    
    </include>  
</launch>

make a test

roslaunch mybot_gazebo mybot_world.launch

Creating your own Model

roscd mybot_description
mkdir urdf
cd urdf
gedit mybot.xacro
XACRO CONCEPTS

• xacro:include: Import the content from other file. We can divide the content in different xacros and merge them using xacro:include.
• property: Useful to define constant values. Use it later using ${property_name}
• xacro:macro: Macro with variable values. Later, we can use this macro from another xacro file, and we specify the required value for the variables. To use a macro, you have to include the file where the macro is, and call it using the macro’s name and filling
the required values.

mybot.xacro

This file will be the main description of our robot. Let’s put some xacro basic structure:

<?xml version="1.0"?>
<robot name="mybot" xmlns:xacro="http://www.ros.org/wiki/xacro">
        <!-- Put here the robot description -->
</robot>

Let’s define some physical properties for our robot, mainly the dimensions of the chassis, the caster wheel, the wheels and the camera:

<xacro:property name="PI" value="3.1415926535897931"/>

<xacro:property name="chassisHeight" value="0.1"/>
<xacro:property name="chassisLength" value="0.4"/>
<xacro:property name="chassisWidth" value="0.2"/>
<xacro:property name="chassisMass" value="50"/>

<xacro:property name="casterRadius" value="0.05"/>
<xacro:property name="casterMass" value="5"/>

<xacro:property name="wheelWidth" value="0.05"/>
<xacro:property name="wheelRadius" value="0.1"/>
<xacro:property name="wheelPos" value="0.2"/>
<xacro:property name="wheelMass" value="5"/>

<xacro:property name="cameraSize" value="0.05"/>
<xacro:property name="cameraMass" value="0.1"/>

We will also include three files :

 <xacro:include filename="$(find mybot_description)/urdf/mybot.gazebo" />
 <xacro:include filename="$(find mybot_description)/urdf/materials.xacro" />
 <xacro:include filename="$(find mybot_description)/urdf/macros.xacro" />

These three correspond respectively to:

• all the gazebo-specific aspects of our robot
• definition of the materials used (mostly colors)
• definitions of some macros for easier description of the robot

Add it to mybot.xacro

其中,collision代表碰撞标签,用于仿真过程中的碰撞体积计算。visual代表可视化,如果不定义,那么laser或者camera就看不到。inertial代表物体的惯性,如果不设置,那么当驱动它时候,默认密度为0,加速度会无穷大。

<link name='chassis'>
  <collision> 
    <origin xyz="0 0 ${wheelRadius}" rpy="0 0 0"/> 
    <geometry> 
      <box size="${chassisLength} ${chassisWidth} ${chassisHeight}"/> 
    </geometry> 
  </collision>
  <visual> 
    <origin xyz="0 0 ${wheelRadius}" rpy="0 0 0"/> 
    <geometry> 
      <box size="${chassisLength} ${chassisWidth} ${chassisHeight}"/> 
    </geometry> 
    <material name="orange"/>
  </visual>
  <inertial> 
    <origin xyz="0 0 ${wheelRadius}" rpy="0 0 0"/> 
    <mass value="${chassisMass}"/> 
    <box_inertia m="${chassisMass}" x="${chassisLength}" y="${chassisWidth}" z="${chassisHeight}"/>
  </inertial>
</link>

Add it to mybot.gazebo

在gazebo的显示中,chassis显示为橙色。

<gazebo reference="chassis">
  <material>Gazebo/Orange</material>
</gazebo>

Add this in the “materials.xacro” :

定义材料颜色。

<?xml version="1.0"?>
<robot>
<material name="black">
  <color rgba="0.0 0.0 0.0 1.0"/>
</material>

<material name="blue">
  <color rgba="0.0 0.0 0.8 1.0"/>
</material>

<material name="green">
  <color rgba="0.0 0.8 0.0 1.0"/>
</material>

<material name="grey">
  <color rgba="0.2 0.2 0.2 1.0"/>
</material>

<material name="orange">
  <color rgba="${255/255} ${108/255} ${10/255} 1.0"/>
</material>

<material name="brown">
  <color rgba="${222/255} ${207/255} ${195/255} 1.0"/>
</material>

<material name="red">
  <color rgba="0.8 0.0 0.0 1.0"/>
</material>

<material name="white">
  <color rgba="1.0 1.0 1.0 1.0"/>
</material>
</robot>

Add this in the macros.xacro file, within the robot tag

定义各种宏,下面包括气缸,方盒子和球的物理惯性定义。

<?xml version="1.0" ?>
<robot name="mybot" xmlns:xacro="http://www.ros.org/wiki/xacro">

<macro name="cylinder_inertia" params="m r h">
  <inertia  ixx="${m*(3*r*r+h*h)/12}" ixy = "0" ixz = "0"
    iyy="${m*(3*r*r+h*h)/12}" iyz = "0"
    izz="${m*r*r/2}"
  />
</macro>

<macro name="box_inertia" params="m x y z">
  <inertia  ixx="${m*(y*y+z*z)/12}" ixy = "0" ixz = "0"
    iyy="${m*(x*x+z*z)/12}" iyz = "0"
    izz="${m*(x*x+z*z)/12}"
  />
</macro>

<macro name="sphere_inertia" params="m r">
  <inertia  ixx="${2*m*r*r/5}" ixy = "0" ixz = "0"
    iyy="${2*m*r*r/5}" iyz = "0"
    izz="${2*m*r*r/5}"
  />
</macro>

</robot>

Add this before the chassis link in the mybot.xacro file :

<link name="footprint" />

<joint name="base_joint" type="fixed">
  <parent link="footprint"/>
  <child link="chassis"/>
</joint>

mybot_world.launch by adding the following two tags in the launch tag:

将.xacro文件转换成urdf文件,xacro文件的优势在于可以include,所以设计中更方便,但是gazebo调用时必须使用urdf文件。第二段时将的description量产成gazebo中的节点。

<!-- urdf xml robot description loaded on the Parameter Server, converting the xacro into a proper urdf file-->
<param name="robot_description" command="$(find xacro)/xacro.py '$(find mybot_description)/urdf/mybot.xacro'" />

<!-- push robot_description to factory and spawn robot in gazebo -->
<node name="mybot_spawn" pkg="gazebo_ros" type="spawn_model" output="screen"
 args="-urdf -param robot_description -model mybot" />

make a test

 roslaunch mybot_gazebo mybot_world.launch 

mybot.xacro As a next step we add a caster wheel to the robot. This is the simplest wheel as we have no axis and no friction

万向轮的添加。

<joint name="fixed" type="fixed">
  <parent link="chassis"/>
  <child link="caster_wheel"/>
</joint>

<link name="caster_wheel">
  <collision>
    <origin xyz="${casterRadius-chassisLength/2} 0 ${casterRadius-chassisHeight+wheelRadius}" rpy="0 0 0"/>
    <geometry>
      <sphere radius="${casterRadius}"/>
    </geometry>
  </collision>
  
  <visual>
    <origin xyz="${casterRadius-chassisLength/2} 0 ${casterRadius-chassisHeight+wheelRadius}" rpy="0 0 0"/>
    <geometry>
      <sphere radius="${casterRadius}"/>
    </geometry>
    <material name="red"/>
  </visual>

  <inertial>
    <origin xyz="${casterRadius-chassisLength/2} 0 ${casterRadius-chassisHeight+wheelRadius}" rpy="0 0 0"/>
    <mass value="${casterMass}"/>
    <sphere_inertia m="${casterMass}" r="${casterRadius}"/>
  </inertial>
</link>

mybot.gazebo Add a gazebo tag in the gazebo file for this link :

material 材料,gravity重力,damping factor阻尼因素(即震荡因素) ,mu1,mu2摩擦因子

<gazebo reference="caster_wheel">
  <mu1>0.0</mu1>
  <mu2>0.0</mu2>
  <material>Gazebo/Red</material>
</gazebo>

As usual, we specify the color used in material. We also added mu1 and mu2, with value 0 to remove the friction.

macros.xacro .We could add the two links in the main file, but let’s make one macro to make it simple.

这是一个轮子的函数,变量是lr和tY,这里面的变量都是类似于宏定义的替换。

<macro name="wheel" params="lr tY">

<link name="${lr}_wheel">
  <collision>
    <origin xyz="0 0 0" rpy="0 ${PI/2} ${PI/2}" />
    <geometry>
      <cylinder length="${wheelWidth}" radius="${wheelRadius}"/>
    </geometry>
  </collision>

  <visual>
    <origin xyz="0 0 0" rpy="0 ${PI/2} ${PI/2}" />
    <geometry>
      <cylinder length="${wheelWidth}" radius="${wheelRadius}"/>
    </geometry>
    <material name="black"/>
  </visual>

  <inertial>
    <origin xyz="0 0 0" rpy="0 ${PI/2} ${PI/2}" />
    <mass value="${wheelMass}"/>
    <cylinder_inertia m="${wheelMass}" r="${wheelRadius}" h="${wheelWidth}"/>
  </inertial>
</link>

<gazebo reference="${lr}_wheel">
  <mu1 value="1.0"/>
  <mu2 value="1.0"/>
  <kp  value="10000000.0" />
  <kd  value="1.0" />
  <fdir1 value="1 0 0"/>
  <material>Gazebo/Black</material>
</gazebo>


<joint name="${lr}_wheel_hinge" type="continuous">
  <parent link="chassis"/>
  <child link="${lr}_wheel"/>
<origin xyz="${-wheelPos+chassisLength/2} ${tY*wheelWidth/2+tY*chassisWidth/2} ${wheelRadius}" rpy="0 0 0" />
  <axis xyz="0 1 0" rpy="0 0 0" />
  <limit effort="100" velocity="100"/>
  <joint_properties damping="0.0" friction="0.0"/>
</joint>


<transmission name="${lr}_trans">
  <type>transmission_interface/SimpleTransmission</type>
   <joint name="${lr}_wheel_hinge">
    <hardwareInterface>EffortJointInterface</hardwareInterface>
  </joint>
  <actuator name="${lr}Motor">
    <hardwareInterface>EffortJointInterface</hardwareInterface>
    <mechanicalReduction>10</mechanicalReduction>
  </actuator>
</transmission>

</macro>

mybot.xacro

<wheel lr="left" tY="1"/>
<wheel lr="right" tY="-1"/>

Connect your robot to ROS

Alright, our robot is all nice and has this new car smell, but we can’t do anything with it yet as it has no connection with
ROS In order to add this connection we need to add gazebeo plugins to our model. There are different kinds of plugins:

  • World: Dynamic changes to the world, e.g. Physics, like illumination or gravity, inserting models
  • Model: Manipulation of models (robots), e.g. move the robots
  • Sensor: Feedback from virtual sensor, like camera, laser scanner
  • System: Plugins that are loaded by the GUI, like saving images

First of all we’ll use a plugin to provide access to the joints of the wheels. The transmission tags in our URDF will be used by this plugin the define how to link the joints to controllers. To activate the plugin, add the following to mybot.gazebo:

<gazebo>
  <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
    <robotNamespace>/mybot</robotNamespace>
  </plugin>
</gazebo>

With this plugin, we will be able to control the joints, however we need to provide some extra configuration and explicitely
start controllers for the joints. In order to do so, we’ll use the package mybot_control that we have defined before. Let’s first create the configuration file:

roscd mybot_control
mkdir config
cd config
vim mybot_control.yaml

This file will define three controllers: one for each wheel, connections to the joint by the transmission tag, one for
publishing the joint states. It also defined the PID gains to use for this controller:

mybot:
  # Publish all joint states -----------------------------------
  joint_state_controller:
    type: joint_state_controller/JointStateController
    publish_rate: 50  
  

  # Effort Controllers ---------------------------------------
  leftWheel_effort_controller:
    type: effort_controllers/JointEffortController
    joint: left_wheel_hinge
    pid: {p: 100.0, i: 0.1, d: 10.0}
  rightWheel_effort_controller:
    type: effort_controllers/JointEffortController
    joint: right_wheel_hinge
    pid: {p: 100.0, i: 0.1, d: 10.0}

Now we need to create a launch file to start the controllers. For this let’s do:

roscd mybot_control
mkdir launch
cd launch
vim mybot_control.launch

In this file we’ll put two things. First we’ll load the configuration and the controllers, and we’ll also start a node that will
provide 3D transforms (tf) of our robot. This is not mandatory but that makes the simulation more complete

<launch>

  <!-- Load joint controller configurations from YAML file to parameter server -->
  <rosparam file="$(find mybot_control)/config/mybot_control.yaml" command="load"/>

  <!-- load the controllers -->
  <node name="controller_spawner"
    pkg="controller_manager"
    type="spawner" respawn="false"
    output="screen" ns="/mybot"
    args="joint_state_controller
      rightWheel_effort_controller
      leftWheel_effort_controller"/>


  <!-- convert joint states to TF transforms for rviz, etc -->
  <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" respawn="false" output="screen">
    <param name="robot_description" command="$(find xacro)/xacro.py '$(find mybot_description)/urdf/mybot.xacro'" />
    <remap from="/joint_states" to="/mybot/joint_states" />
  </node>

</launch>

make a test

roslaunch mybot_gazebo mybot_world.launch 
roslaunch mybot_control mybot.launch 
rostopic list

We could launch our model on gazebo and then launch the controller, but to save some time (and terminals), we’ll start the controllers automatically by adding a line to the mybot_world.launch in the mybot_gazebo package :

<!-- ros_control mybot launch file -->
<include file="$(find mybot_control)/launch/mybot_control.launch" />
rostopic pub -1 /mybot/leftWheel_effort_controller/command std_msgs/Float64 "data: 1.5"
rostopic pub -1 /mybot/rightWheel_effort_controller/command std_msgs/Float64 "data: 1.0"
rostopic echo /mybot/joint_states

Teleoperation of your robot

Adding a camera

    <joint name="camera_joint" type="fixed">
        <axis xyz="0 1 0" />
        <origin xyz="0 0 0.2" rpy="0 0 0"/>
      <parent link="footprint"/>
      <child link="camera"/>
    </joint>


    <link name="camera">
      <collision>
        <origin xyz="0 0 0" rpy="0 0 0"/>
        <geometry>
          <box size="${cameraSize} ${cameraSize} ${cameraSize}"/>
        </geometry>
      </collision>

      <visual>
        <origin xyz="0 0 0" rpy="0 0 0"/>
        <geometry>
          <box size="${cameraSize} ${cameraSize} ${cameraSize}"/>
        </geometry>
        <material name="blue"/>
      </visual>

      <inertial>
        <mass value="${cameraMass}" />
        <origin xyz="0 0 0" rpy="0 0 0"/>
        <box_inertia m="${cameraMass}" x="${cameraSize}" y="${cameraSize}" z="${cameraSize}" />
      </inertial>
    </link>

Add the plugin to gazebo file

<gazebo reference="camera">
  <material>Gazebo/Blue</material>
  <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>
    </camera>
    <plugin name="camera_controller" filename="libgazebo_ros_camera.so">
      <alwaysOn>true</alwaysOn>
      <updateRate>0.0</updateRate>
      <cameraName>mybot/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>
rosrun image_view image_view image:=/mybot/camera1/image_raw

Visualisation with RViz

rosrun rviz rviz

整个代码框架如下:

发布者

harifun

小学的时候,说自己要当一名科学家!那时候,看到新闻联播在宣传“四化”,立志要为现代化作出贡献!高中立志要做机器人,本科和硕士学的自动化!毕业进入华为,因为是测试岗位而离开,然后进入创业公司做工业扫地机器人和服务式机器人!A轮完成数千万级融资后因家庭原因离开上海,回武汉进入一家上市公司从事激光雷达设计工作!机器人是我一直以来的追求,希望有一天我能实现我的理想!

发表评论

电子邮件地址不会被公开。 必填项已用*标注