The robot that we are going to build in the following sections is a mobile robot with four wheels and an arm with a gripper.
To start with, we create the base of the robot with four wheels. Create a new file in the chapter4_tutorials/robot1_description/urdf
folder with the name robot1.urdf
, and enter the following code:
<?xml version="1.0"?> <robot name="Robot1"> <link name="base_link"> <visual> <geometry> <box size="0.2 .3 .1" /> </geometry> <origin rpy="0 0 0" xyz="0 0 0.05" /> <material name="white"> <color rgba="1 1 1 1" /> </material> </visual> </link> <link name="wheel_1"> <visual> <geometry> <cylinder length="0.05" radius="0.05" /> </geometry> <origin rpy="0 1.5 0" xyz="0.1 0.1 0" /> <material name="black"> <color rgba="0 0 0 1" /> </material> </visual> </link> <link name="wheel_2"> <visual> <geometry> <cylinder length="0.05" radius="0.05" /> </geometry> <origin rpy="0 1.5 0" xyz="-0.1 0.1 0" /> <material name="black" /> </visual> </link> <link name="wheel_3"> <visual> <geometry> <cylinder length="0.05" radius="0.05" /> </geometry> <origin rpy="0 1.5 0" xyz="0.1 -0.1 0" /> <material name="black" /> </visual> </link> <link name="wheel_4"> <visual> <geometry> <cylinder length="0.05" radius="0.05" /> </geometry> <origin rpy="0 1.5 0" xyz="-0.1 -0.1 0" /> <material name="black" /> </visual> </link> <joint name="base_to_wheel1" type="fixed"> <parent link="base_link" /> <child link="wheel_1" /> <origin xyz="0 0 0" /> </joint> <joint name="base_to_wheel2" type="fixed"> <parent link="base_link" /> <child link="wheel_2" /> <origin xyz="0 0 0" /> </joint> <joint name="base_to_wheel3" type="fixed"> <parent link="base_link" /> <child link="wheel_3" /> <origin xyz="0 0 0" /> </joint> <joint name="base_to_wheel4" type="fixed"> <parent link="base_link" /> <child link="wheel_4" /> <origin xyz="0 0 0" /> </joint> </robot>
This URDF code is based on XML, and the indentation is not mandatory but advisable. Use an editor that supports it or an adequate plugin or configuration (for example, an appropriate .vimrc
file in Vim).
As you can see in the code, there are two principal fields that describe the geometry of a robot: links
and joints
.
The first link has the name base_link
; this name must be unique to the file:
<link name="base_link"> <visual> <geometry> <box size="0.2 .3 .1" /> </geometry> <origin rpy="0 0 0" xyz="0 0 0.05" /> <material name="white"> <color rgba="1 1 1 1" /> </material> </visual> </link>
In order to define what we will see on the simulator, we use the visual field in the preceding code. Inside the code, you can define the geometry (cylinder, box, sphere, or mesh), the material (color or texture), and the origin. We then have the code for the joint, shown as follows:
<joint name="base_to_wheel1" type="fixed"> <parent link="base_link"/> <child link="wheel_1"/> <origin xyz="0 0 0"/> </joint>
In the joint
field, we define the name, which must be unique as well. Also, we define the type of joint (fixed
, revolute
, continuous
, floating
, or planar
), the parent, and the child. In our case, wheel_1
is a child of base_link
. It is fixed, but, as it is a wheel, we can set it to revolute
.
To check whether the syntax is fine or whether we have errors, we can use the check_urdf
command tool:
$ check_urdf robot1.urdf
The output of the command will be as follows:
If you want to see it graphically, you can use the urdf_to_graphiz
command tool:
$ urdf_to_graphiz robot1.urdf
This command generates two files: origins.pdf
and origins.gv
. You can open the file using evince
:
$ evince origins.pdf
The following image is what you will receive as an output:
Now that we have the model of our robot, we can use it on rviz
to watch it in 3D and see the movements of the joints.
We will create the display.launch
file in the robot1_description/launch
folder and put the following code in it:
<?xml version="1.0"?> <launch> <arg name="model" /> <arg name="gui" default="False" /> <param name="robot_description" textfile="$(arg model)" /> <param name="use_gui" value="$(arggui)" /> <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" /> <node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" /> </launch>
We will then launch it with the following command:
$ roslaunch robot1_description display.launch model:="'rospack find robot1_description'/urdf/robot1.urdf"
If everything is fine, you will see the following window with the 3D model on it:
Let's finish the design by adding some parts: A base arm, an articulatered arm, and a gripper. Try to finish the design yourself. You can find the final model in the chapter4_tutorials/robot1_description/urdf/robot1.urdf
file. You can see the final design in the following screenshot as well:
Sometimes, we want to give our model more realistic elements, or make a more elaborate design, rather than using basic geometric objects/blocks. It is possible to load meshes generated by us or to use meshes of other models. URDF models support .stl
and .dae
meshes. For our model, we used the PR2's gripper. In the following code, you can see an example of how to use it:
<link name="left_gripper"> <visual> <origin rpy="0 0 0" xyz="0 0 0" /> <geometry> <mesh filename="package://pr2_description/meshes/gripper_v0/ l_finger.dae" /> </geometry> </visual> </link>
This looks like the sample link that we used before, but in the geometry section we added the mesh that we are going to use. You can see the result in the following screenshot:
To convert the model into a robot that can actually move, the only thing you have to do is pay attention to the type of joints it uses. If you check the URDF model file, you will see the different types of joints used in this model.
The most used type of joint is the revolute joint. You can see it being used on arm_1_to_arm_base
in the following code:
<joint name="arm_1_to_arm_base" type="revolute"> <parent link="arm_base" /> <child link="arm_1" /> <axis xyz="1 0 0" /> <origin xyz="0 0 0.15" /> <limit effort="1000.0" lower="-1.0" upper="1.0" velocity="0.5" /> </joint>
This means that they rotate in the same way that the continuous joints do, but they have strict limits. The limits are fixed using the <limit effort ="1000.0" lower="-1.0" upper="1.0" velocity="0.5"/>
line, and you can select the axis to move with axis xyz="1 0 0"
. The <limit>
tag is used to set the following attributes: effort
(maximum force supported by the joint), lower
to assign the lower limit of a joint (radian per revolute joints, meters for prismatic joints), upper
for the upper limit, and velocity
for enforcing the maximum joint velocity.
A good way of testing whether or not the axis and limits of the joints are fine is by running rviz
with the Join_State_Publisher
GUI:
$ roslaunch robot1_description display.launch model:="'rospack find robot1_description'/urdf/robot1.urdf" gui:=true
You will see the rviz
interface in another window with some sliders, each one controlling a joint:
If you want to simulate the robot on Gazebo or any other simulation software, you have to add physical and collision properties. This means that we need to set the dimensions of the geometry to calculate the possible collisions; for example, we need to define the weight of an object in order to figure out its inertia.
It is vital that all links on the model file have these parameters; if not, the robot will not be simulated.
For the mesh models, it is easier to calculate collisions by using simplified geometry rather than the actual mesh. Calculating the collision between two meshes is more computationally complex than it is to calculate a simple geometry.
In the following code, you will see the new parameters added to the link with the name wheel_1
:
<link name="wheel_1"> ... <collision> <geometry> <cylinder length="0.05" radius="0.05" /> </geometry> </collision> <inertial> <mass value="10" /> <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0" /> </inertial> </link>
It is the same for the other links. Remember to put collision
and inertial
elements in all the links, because if you do not, Gazebo will not take the model.
You can find a complete file with all the parameters at robot1_description/urdf/robot1_physics.urdf
.