The Modifications to the robot URDF section in Chapter 2, Creating Your First Two-Wheeled ROS Robot (in Simulation), describes changes that need to be made to the URDF model so that Gazebo recognizes it as an SDF. The next section identifies the changes needed for our robot arm, rrbot
.
Specific elements unique to the Gazebo simulation environment are grouped into the following areas:
<material>
tags are used to specify the Gazebo color or texture for each link<mu1>
and <mu2>
tags are used to define the friction coefficients for the contact surfaces of four of the robot's linksrrbot
(included here, but described in the Adding a Gazebo ROS control plugin section)These specific Gazebo XML elements needed for simulation are split into a separate file labeled rrbot.gazebo
, and an Xacro <include>
statement is used in the main rrbot4.xacro
file:
<xacro:include filename="$(find ros_robotics)/urdf/rrbot.gazebo" />
Using this <include>
statement, the rrbot.gazebo
file must be located in the ros_robotics/urdf
directory.
To create the rrbot.gazebo
file, use the following code:
<?xml version="1.0"?> <robot> <!-- Base Link --> <gazebo reference="base_link"> <material>Gazebo/Red</material> </gazebo> <!-- Middle Link --> <gazebo reference="mid_link"> <mu1>0.2</mu1> <mu2>0.2</mu2> <material>Gazebo/Green</material> </gazebo> <!-- Top Link --> <gazebo reference="top_link"> <mu1>0.2</mu1> <mu2>0.2</mu2> <material>Gazebo/Blue</material> </gazebo> <!-- Gripper Elements --> <gazebo reference="left_gripper"> <mu1>0.2</mu1> <mu2>0.2</mu2> </gazebo> <gazebo reference="right_gripper"> <mu1>0.2</mu1> <mu2>0.2</mu2> </gazebo> <gazebo reference="left_tip" /> <gazebo reference="right_tip" /> <!-- ros_control plugin --> <gazebo> <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so"> <robotNamespace>/rrbot</robotNamespace> <robotSimType> gazebo_ros_control/DefaultRobotHWSim </robotSimType> </plugin> </gazebo> </robot>
Since Gazebo simulates the physics of the real world, a robot arm, as we have defined it, will not stand up for long as the force of gravity will cause it to topple. Therefore, we need to attach our robot arm model to Gazebo's world frame. In the rrbot4.xacro
version of our code, a world
link has been added and a fixed joint attaching the robot's base_link
to the world
link:
<link name="world"/> <joint name="fixed" type="fixed"> <parent link="world"/> <child link="base_link"/> </joint>
With the base_link
of the arm fixed to the world
link, the mid_link
and top_link
will still succumb to the force of gravity. Although the robot arm appears to be standing straight up when the arm is launched in Gazebo, you will see that these top two links of the arm fall. The arm will swing and slow down due to the <dynamics damping>
element defined for the joint, until it comes to a complete stop. We encourage you to play with the <dynamics damping>
value in order to understand its property in relation to the Gazebo simulation.
Before we continue to add control elements to our URDF, we need to launch the rrbot4.xacro
file in Gazebo. This launch file is similar to the ddrobot_gazebo.launch
file in Chapter 2, Creating Your First Two-Wheeled ROS Robot (in Simulation). This launch file can be downloaded from the book's website, or created as rrbot_gazebo.launch
from the following XML code:
<launch> <!-- We resume the logic in gazebo_ros packageempty_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 ros_robotics)/worlds/rrbot.world"/> <arg name="paused" default="false"/> <arg name="use_sim_time" default="true"/> <arg name="gui" default="true"/> <arg name="headless" default="false"/> <arg name="debug" default="false"/> </include> <!-- Load the URDF into the ROS Parameter Server --> <param name="robot_description" command="$(find xacro)/xacro--inorder '$(find ros_robotics)/urdf/rrbot4.xacro'" /> <!-- Spawn rrbot into Gazebo --> <node name="spawn_urdf" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen" args="-param robot_description -urdf -model rrbot" /> </launch>
The rrbot.world
file from this book's website can be downloaded and used, or you can use the ddrobot.world
file created in Chapter 2, Creating Your First Two-Wheeled ROS Robot (in Simulation). You can even just omit the argument for world_name
in the include
statement and use empty_world
from the gazebo_ros
package.
The command to launch the robot arm in Gazebo is as follows:
$ roslaunch ros_robotics rrbot_gazebo.launch
The Gazebo screen should look similar to the following screenshot after the top two links of the arm have fallen and slowed to a stop:
After verifying the model in Gazebo, additional control elements should be added to the robot arm URDF.
The following are the steps used to set up controls for this robot arm in the Gazebo simulation:
rrbot
and gripper Xacro files.gazebo_ros_control
plugin to our file of Gazebo-specific elements.To begin with, we need to install four packages: gazebo_ros_pkgs
, gazebo_ros_control
, ros_control
, and ros_controllers
. gazebo_ros_pkgs
is a set of ROS packages (metapackage) that provides the interface and control for a robot in Gazebo. ros_control
and ros_controllers
provide generic controllers for ROS robots. For ROS Kinetic, the Debian packages should be installed with the following command:
$ sudo apt-get install ros-kinetic-gazebo-ros-pkgs ros-kinetic-gazebo-ros-control ros-kinetic-ros-control ros-kinetic-ros-controllers
The gazebo_ros_control
package integrates the ros_contol
controller software with the Gazebo simulator. The gazebo_ros_control
package instantiates the ros_control
metapackage controller_manager
package to provide simulation of the robot's controllers. The controller manager will be used by our control launch file to spawn controllers for the joint_state_controller
and controllers for all four of the robot arm's revolute joints.
More details on the ROS controllers and the ros_control
packages can be found at http://wiki.ros.org/ros_control.
Specific elements must be added to the URDF/SDF in order for a model to be controlled in the Gazebo simulation environment. The <transmission>
element is used to define the relationship between the robot joint and the actuator. This <transmission>
element encapsulates the details of the mechanical coupling with specific gear ratios and parallel linkages defined. For the rrbot
robot, we have simple mechanical joints and do not require complex transmission element definitions.
The rrbot
robot arm requires a <transmission>
element for each of the rrbot
revolute joints (joint_base_mid
, joint_mid_top
, left_gripper
, and right_gripper
). Each <transmission>
element has a unique <name>
and is associated with one of the <joint names>
for the revolute joints. The <type>
is transmission_interface/SimpleTransmission
. In the <joint>
, the <hardwareInterface>
is hardware_interface/EffortJointInterface
because we will be using simulated ros_control hardware_interface::RobotHW
. This interface corresponds to the control plugin selected in the next section, Adding a Gazebo ROS control plugin. Each of the four <transmission>
elements will look similar to the following code:
<transmission name="transmission1"> <type>transmission_interface/SimpleTransmission</type> <joint name="joint_base_mid"> <hardwareInterface>hardware_interface/EffortJointInterface </hardwareInterface> </joint> <actuator name="motor1"> <mechanicalReduction>1</mechanicalReduction> </actuator> </transmission>
This code should be duplicated twice and added to the joint_base_mid
joint and joint_mid_top
joint in the rrbot4.xacro
file. It should also be duplicated twice and added to the left_gripper
joint and right_gripper
joint in the gripper.xacro
file.
More details on the <transmission>
elements can be found at http://wiki.ros.org/urdf/XML/Transmission.
The gazebo_ros_control
plugin defined previously in the Adding Gazebo-specific elements section is as follows:
<!-- ros_control plugin --> <gazebo> <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so"> <robotNamespace>/rrbot</robotNamespace> <robotSimType> gazebo_ros_control/DefaultRobotHWSim </robotSimType> </plugin> </gazebo>
This plugin will parse the <transmission>
elements in the rrbot4.xacro
and gripper.xacro
files and load the identified hardware interfaces and controller managers. The preceding control plugin is a custom simulation plugin that should already be in the rrbot.gazebo
file.
YAML is a markup language commonly used for ROS parameters. It is convenient to use YAML-encoded files to set ROS parameters on the Parameter Server. For rrbot
, a YAML file is created to hold the joint controller configurations, and this YAML file is loaded via the control launch file. The controller type is defined for the joint_state_controller
, as well as for all the four rrbot
joint controllers. The four rrbot
controllers also have proportional–integral–derivative (pid) gains defined. These pid gains have been tuned to the control of the rrbot
arm and gripper. The rrbot_control.yaml
file contains the following code:
rrbot: # Publish all joint states joint_state_controller: type: joint_state_controller/JointStateController publish_rate: 50 # Position Controllers joint_base_mid_position_controller: type: effort_controllers/JointPositionController joint: joint_base_mid pid: {p: 100.0, i: 0.01, d: 10.0} joint_mid_top_position_controller: type: effort_controllers/JointPositionController joint: joint_mid_top pid: {p: 100.0, i: 0.01, d: 10.0} left_gripper_joint_position_controller: type: effort_controllers/JointPositionController joint: left_gripper_joint pid: {p: 1.0, i: 0.00, d: 0.0} right_gripper_joint_position_controller: type: effort_controllers/JointPositionController joint: right_gripper_joint pid: {p: 1.0, i: 0.00, d: 0.0}
The rrbot_control.yaml
file should be saved to a /config
directory under the ros_robotics
package directory.
The best way to initiate control of our rrbot
robot arm is to create a launch file to load the parameters into the Parameter Server and start all the ros_control
controllers. The rosparam
statement loads the controller settings to the Parameter Server from the YAML configuration file. Next, the control_spawner
node creates the five controllers for rrbot
using the controller_manager
package. Another node is started for the robot_state_publisher
. This rrbot_control.launch
control file contains the following code, and is stored in the /launch
directory of the ros_robotics
package directory:
<launch> <!-- Load joint controller configurations from YAML file to parameter server --> <rosparam file="$(find ros_robotics)/config/rrbot_control.yaml" command="load"/> <!-- load the controllers --> <node name="control_spawner" pkg="controller_manager" type="spawner" respawn="false" output="screen" ns="/rrbot" args="joint_state_controller joint_base_mid_position_controller joint_mid_top_position_controller left_gripper_joint_position_controller right_gripper_joint_position_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"> <remap from="/joint_states" to="/rrbot/joint_states" /> </node> </launch>
After the nodes are started, the joint_state_controller
begins publishing all the (nonfixed) joint states of rrbot
on the JointState
topic. The robot_state_publisher
node subscribes to the JointState
messages and publishes the robot's transforms to the tf
transform library. Each of the other joint position controllers manages the control for its particular revolute joint.
To start the rrbot
simulation, launch rrbot
in Gazebo using the following command:
$ roslaunch ros_robotics rrbot_gazebo.launch
When rrbot
is visible in the Gazebo window, open a second terminal window and launch the controllers using the following command:
$ roslaunch ros_robotics rrbot_control.launch
In the previously created control launch file, both the controller_manager
and robot_state_publisher
packages are used. If you plan to reuse this code or share it, it is recommended that you add these dependencies to your package.xml
file for the ros_robotics
package. The following statements should be added under the dependencies:
<exec_depend>controller_manager</exec_depend> <exec_depend>robot_state_publisher</exec_depend>
Now, we are able to send commands via a third terminal window to control our rrbot
robot arm. The rostopic pub
command is used to publish our command data to a specific joint position controller.
To command the top link of the arm to move to a 1.57radian (90degree) position, relative to the middle link, type the following command:
$ rostopic pub -1 /rrbot/joint_mid_top_position_controller/command std_msgs/Float64 "data: 1.57"
On the terminal, the following screen message is displayed:
publishing and latching message for 3.0 seconds
On the Gazebo screen, the rrbot
arm should look similar to the following screenshot. The view has been rotated to make the arm more visible to the reader:
Note that the top link of the arm may not be at a true 90 degree angle to the middle link because of the gravitational effects of the environment and the action of the controller. The proportional gain of the pid controls can be increased to improve these results. This can be done by changing the rrbot
controller gains in the YAML file or in real-time using the Dynamic Reconfigure tool described in the upcoming section.
To open the gripper, two commands can be sent consecutively to move the right gripper and then the left gripper -0.5 radians from their center position:
$ rostopic pub -1 /rrbot/right_gripper_joint_position_controller/command std_msgs/Float64 "data: -0.5"; rostopic pub -1 /rrbot/left_gripper_joint_position_controller/command std_msgs/Float64 "data: -0.5"
On the Gazebo screen, the rrbot
gripper should look similar to the following screenshot. Joint axes and rotation are shown in the Gazebo view:
Another tool that we can use to control our rrbot
arm is rqt, the ROS plugin-based user interface described in the Introducing rqt tools section of Chapter 3, Driving Around with TurtleBot. The command to start rqt is as follows:
$ rosrun rqt_gui rqt_gui
Or simply:
$ rqt
Under the Plugins menu in the rqt main window menu bar, select the Topics | Message Publisher plugin. From the Topics drop-down box, at the top of the Message Publisher plugin, select the command for the particular controller that you want to publish to and add it to the Message Publisher main screen. The green plus sign button at the top-right corner of the window will add the command to the main screen. In the following screenshot, the /rrbot/joint_base_mid_position_controller/command
and/rrbot/joint_mid_top_position_controller/command
topics have been added to the Message Publisher main screen:
To change the position of the rrbot
arm, expand the topic by clicking on the triangle symbol on the left side. Next, select and change the expression field of one of the topics and check the checkbox on the left of the topic to publish the message. In the following screenshot, the value of the /rrbot/joint_base_mid_position_controller/command
topic has been changed to -1.57 radians. In addition to this, the plugin for Topic Monitor has been displayed so that the change in the published state of the /rrbot/joint_base_mid_position_controller/state
topic set_point
field can be verified:
The following screenshot shows both rqt and Gazebo with the rrbot
arm positioned with its joint_base_mid
at -1.57 radians. The joint_mid_top
is set at 0.0 radians:
The following suggestions are additional starting points for using rqt with your rrbot
arm:
joint_xxx_position_controller/command/data
to the screen or even joint_xxx_position_controler/state/error
. The error plot will visually display how well the pid control eliminates the error on the joint.Moving the robot arm with a Python script is also possible, but this is left as an exercise for the reader.