Urdf
Urdf
Urdf
Peter Corke
November 2018
1 Introduction
The Universal Robot Data Format (URDF) is an increasingly common way to represent
the kinematic structure and visual appearance of robots. It is widely used in the ROS
software ecosystem. A URDF file is an XML format file and a number of specialized
tags.
I’ve not found a particularly helpful or readable tutorial hence I’m writing my own.
2 XML 101
URDF files are expressed in XML so it’s helpful to start with a refresher about XML.
2.1.1 Tags
A tag is a markup construct that begins with < and ends with >. Tags come in three
flavours:
where, in all cases, tag is the name of the tag and is given without quotes. For example
<foo> is a tag named foo. Tag names start with a letter, underscore or colon, followed
by alphanumeric, dot or underscore characters.
1
2.1 What’s in an XML file 2
2.1.2 Elements
An element is a logical document component that either begins with a start-tag and
ends with a matching end-tag or consists only of an empty-element tag. The characters
between the start-tag and end-tag, if any, are the element’s content, and may contain
markup, including other elements, which are called child elements.
An XML element has matching start and end tags like
<foo></foo>
<bar />
which is equivalent to
<bar></bar>
The body of the element can be an arbitrary mixture of plain text or other elements, ie.
elements can be nested within the body of other elements. This allows the creation of
hierarchies or trees, with the first or outermost element as the root. For example:
<bar>some text</bar>
<foo><bar>one</bar><bar>two</bar></foo>
The elements must not overlap. i.e., an end tag of an element must have the same name
as that of the most recent unmatched start tag.
2.1.3 Attributes
has two attributes. Their names are "src" and "alt", and their values are "madonna.jpg"
and "Madonna" respectively. An XML attribute can only have a single value and each
attribute can appear at most once on each element. Attribute names start with a letter,
underscore or colon, followed by alphanumeric, dot or underscore characters. Attribute
names in XML (unlike HTML) are case sensitive.
Special characters are introduced using XML references. References always begin with
the symbol "&" which is a reserved character and end with the symbol ";". XML has
two types of references
2.1 What’s in an XML file 3
Entity References contain a name between the start and the end delimiters. The name
refers to a predefined strings such as
& ampersand
' single quote
> greater than
< less than
" double quote
or a larger set defined for HTML which can be found in online lists, for example,
θ is the Greek letter θ .
Character References These specify a character by its Unicode code in either deci-
mal or hexadecimal format. For example the Roman character “A” can be speci-
fied as A in decimal or A in hexadecimal.
and the body of the comment can also span multiple lines
<!-- comment
more comment
still more comment -->
2.1.6 CDATA
A CDATA block refers to character data that is considered literally. The special char-
acters are interpreted as themselves, and not as markup. For example
<![CDATA[
characters with markup like 3<4;
]]>
This section may contain markup characters (<, >, and &). CDATA cannot contain the
string "]]>". This is somewhat analogous to a LaTeX verbatim block.
2.2 The DOM model 4
2.1.7 Document
XML documents may begin with an XML declaration that describes some information
about themselves. An example is
which is case-sensitive and must be the first statement in the document. An XML
document can have only one root element.
The document node is the root of the tree. If must have at most one (XML rule)
child node. That node may have multiple children of the types mentioned above. For
example the XML element <date type="year">2005</date> is represented
by an element node <date> with two child nodes: an attribute node with the name
"type" and value "year", and a child text node with the value "2005".
1 <?xml version="1.0"?>
2 <people>
3
4 <person employee_number="123" gender="female" >
5 <name>Alice</name>
6 <address>11 Alice St</address>
7 <commenced date="2016-01-01" />
8 </person>
9
10 < person employee_number = "237" gender = "male" status="on vacation" >
11 <name>Bob</name>
12 <commenced date="2015-07-07" />
13 <address>13 Bob St</address>
14 </person>
15
16 </people>
MATLAB provides a function to read and parse an XML file and return a DOM node-
tree
2.3 Reading XML with MATLAB 5
Table 1: Names and values for different node types. The symbolic value in column 3 is a
property of any node, ie. node.ATTRIBUTE NODE is the value 2.
which Table 1 indicates is a document node. The Table also shows the name and value
associated with different types of node. These are the display value of the variable,
shown when it is evaluated without a semicolon on the end of the line
>> root
root =
[#document: null]
which is an element node and the display value shows the tag name: people.
The syntax looks quite unMATLAB-like and that’s because the implementation is
based on the standard Java DOM processor and the objects are native Java objects.
Elements in the list are indexed starting at zero, and we use properties and methods of
the Java objects.
This node has a name, the tag name, but no value
2.3 Reading XML with MATLAB 6
>> node.getNodeName
ans =
people
>> node.getNodeValue
ans =
[]
which is somewhat surprising since the people node has only two children, the two
person nodes: Alice and Bob. We can list the child nodes
>> for i=0:node.getLength-1
persons.item(i)
end
ans =
[#text:
ans =
[person: null]
ans =
[#text:
ans =
[person: null]
ans =
[#text:
and what we’ve overlooked is the non-markup text in the XML file, the three blank
lines. Since we are only interested in the person nodes we can extract them specifi-
cally1
>> persons = node.getElementsByTagName(’person’);
>> persons.getLength
ans =
2
which has seven child nodes. Once again, we see that this is due to white space in the
file
ans =
[#text:
]
ans =
[name: null]
ans =
[#text:
]
ans =
[address: null]
ans =
[#text:
]
ans =
[commenced: null]
ans =
[#text:
]
but the index could vary depending on the formatting (white space) in the XML file. It
can be obtained more robustly by
The person node also has attributes. We can obtain a list of those by
2.3 Reading XML with MATLAB 8
>> person.hasAttributes
ans = logical
1
>> attributes = person.getAttributes;
>> attributes.getLength
ans =
2
has a display value that shows both its name and its value. We can get those strings by
>> att0.getNodeName
ans =
employee_number
>> att0.getNodeValue
ans =
123
>> person.getAttribute(’employee_number’)
ans =
123
This is all somewhat tedious to do manually but it lends itself to a programmatic solu-
tion.
9
3 URDF
A URDF file is an XML-format file that describes both the kinematic structure and the
visual appearance of a robot. We will deal with these separately, starting with kinematic
structure.
1 <?xml version="1.0"?>
2 <robot name="planar2">
3
4 <link name="base_link" />
5 <link name="link1" />
6 <link name="link2" />
7 <link name="end" />
8
9 <joint name="q1" type="continuous">
10 <parent link="base_link" />
11 <child link="link1" />
12 <axis xyz="0 0 1" />
13 </joint>
14
15 <joint name="q2" type="continuous">
16 <parent link="link1" />
17 <child link="link2" />
18 <origin xyz="1 0 0" />
19 <axis xyz="0 0 1" />
20 </joint>
21
22 <joint name="notajoint" type="fixed">
23 <parent link="link2" />
24 <child link="end" />
25 <origin xyz="1 0 0" />
26 </joint>
27
28 </robot>
Given our newfound knowledge about XML this file is quite easy to interpret. Line 2
is the top-level element in the file with the tag robot. Nested below this are elements
with the tags link and joint. The robot, the links and the joints all have names
which should be unique.
The links have no content and attributes are used to name them. The first link must be
named base link.
A joint connects a pair of links. The parent is the link closer to the base (or root) of the
mechanism, the child is closer to the tool tip. The first joint, lines 9–13, has attributes
that define its named, q1, and its type. In this case it is a continuous type which is
a revolute joint with no motion limits. Nested elements provide additional information
about the joint. Lines 10-11 indicate that it connects the base link to link1. Line 12
indicates that the rotation is about the z-axis, in the parent link’s coordinate frame.
Since no origin tag is given the joint connects to the parent link at the origin in
its coordinate frame. That point also defines the origin of the child coordinate frame
3.1 Kinematic structure 10
assuming a joint rotation angle of zero. The first part of the transformation chain for
this robot is therefore
R z (q1 )
The second joint, lines 15-20, is named q2 and similar except for the addition of an
origin element. This specifies that the second joint connects to the parent link,
link1 at the point [1, 0, 0] and that this point in the world is the origin of the child
link. This is shown graphically in Figure 1. The next part of the transformation chain
for this robot is therefore
Rz (q2 )
T x (1)R
We are interested in the motion of the end of the robot which is at the end of link 2, at a
fixed offset with respect to the link2 frame. To describe this we need to create another
link that is fixed to link 2 and this is described by lines 22–26. The next part of the
transformation chain for this robot is therefore
T x (1)
T x (1)R
R z (q1 )T Rz (q2 )T
T x (1)
θi di ai αi
q1 0 1 0
q2 0 1 0
For more complex URDF descriptions this transformation can be performed using the
RTB function DHFactor and the transform chain might result in Denavit-Hartenberg
parameters with joint angle offsets, and non-null base or tool transforms.
The origin tag can also contain an orientation. The translation is applied first, then
the rotation which is defined in terms of roll (about X), pitch (about Y) and yaw (about
Z) where all angles are expressed in radians. Explicitly this is the transform sequence
Ry (P)R
R z (Y )R Rx (R)
revolute a joint that rotates about the specified axis and has a limited range specified
by the upper and lower limits.
3.1 Kinematic structure 11
P
{J} <latexit sha1_base64="O9z3/4G9FbQ3qbk6EeilRyUzf7g=">AAACDHicbZDLSsNAFIYnXmu9NOrSTbAIbiyJFHRZcOOygr1AE8pketIOnUuYmRRK6Cv4Am71DdyJW9/BF/A5TNIstPWHgZ//P4c5fGHMqDau+2VtbG5t7+xW9qr7B4dHNfv4pKtlogh0iGRS9UOsgVEBHUMNg36sAPOQQS+c3uV9bwZKUykezTyGgOOxoBEl2GTR0K75MyCDdpD6ksMYL4Z23W24hZx145Wmjkq1h/a3P5Ik4SAMYVjrgefGJkixMpQwWFT9REOMyRSPYZBZgTnoIC0OXzgXWTJyIqmyJ4xTpL83Usy1nvMwm+TYTPRql4f/dYPERLdBSkWcGBBk+VGUMMdIJ6fgjKgCYtg8M5gomt3qkAlWmJiMVdUvFlM1I1dCmoJUDsZbxbBuutcNz214D816q1kiqqAzdI4ukYduUAvdozbqIIIS9Ixe0Kv1ZL1Z79bHcnTDKndO0R9Znz+u55wS</latexit>
!
P
⇠J {C}
Figure 1: Relationship between parent and child rigid bodies connected by a joint.
prismatic a joint that slides along the specified axis, and has a limited range specified
by the upper or lower limits.
fixed is not really a joint because it cannot move. All degrees of freedom are locked.
This type of joint does not require the axis.
calibration
For prismatic and revolute types the motion limits are specified by nested elements like
where the limits are given in units of radians or metres for revolute for prismatic joints
respectively. If either of the upper or lower limit is not specified, a limit, it defaults
to zero.
We will use the notation of [1] where XξY represents rigid-body motion from frame
{X} to {Y } and ⊕ represents rigid-body motion composition. For this problem we
consider three coordinates frames: {P} of the parent link, {C} of the child link and
{J} of the joint. The transformation from the link frame of the parent frame to the link
frame of the child is shown in Fig. 1 and given by
P
ξC = PξJ ⊕ JξC (q, Cω, σ )
The first transform is a constant set by theorigin tag of the joint element. The second
transform represents the action of the joint itself which is defined by a rotation about
(σ = 0), or translation along (σ = 1), the vector Pω by the joint variable q.
3.2 Visual appearance 12
1 <?xml version="1.0"?>
2 <robot name="myfirst">
3
4 <link name="base_link">
5 <visual>
6 <geometry>
7 <cylinder length="0.6" radius="0.2"/>
8 </geometry>
9 </visual>
10 </link>
11 </robot>
which defines a cylinder, with its axis parallel to the z-axis, of length 0.6 m and radius
of 0.2 m centred at the world origin. Substituting line 7 for
<box size="1 2 3"/>
would draw a box centred at the world origin of lengths 1, 2 and 3 m in the x-, y- and
z-directions respectively.
By default the cylinder or box is drawn centred at the origin of the link coordinate
frame. It can be repositioned by introducing an origin element. For example
<origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
after line 8 (within the visual element) will first translate the cylinder by -0.3 m in
the z-direction so its top is now at z = 0 and then rotate it by pi/2 about the y-axis.
The object is drawn with a default color3 but we can change that by altering the material
of the link. This can be done adding
<material rgba="0 0 0.8 1" />
below line 9. The four numbers are red, green, blue in the range 0 to 1 and alpha (0
transparent, 1 opaque). Alternatively
1 <?xml version="1.0"?>
2 <robot name="myfirst">
3
4 <material name="blue">
5 <color rgba="0 0 0.8 1"/>
6 </material>
7
8 <link name="link">
9 <visual>
10 <geometry>
11 <cylinder length="0.6" radius="0.2"/>
12 </geometry>
13 <material name="blue" />
14 </visual>
15 </link>
16 </robot>
we can create a named material, lines 4–6, and then specify it for the link in line 14.
3.3 Combining kinematics and appearance 13
1 <?xml version="1.0"?>
2 <robot name="planar2">
3
4 <material name="red">
5 <color rgba="1 0 0 0.8" />
6 </material>
7 <material name="green">
8 <color rgba="0 1 0 0.8" />
9 </material>
10
11 <link name="base_link" />
12 <link name="link1">
13 <visual>
14 <geometry>
15 <box size="1 0.1 0.1" />
16 </geometry>
17 <origin xyz="0.5 0 0" />
18 <material name="red" />
19 </visual>
20 </link>
21 <link name="link2">
22 <visual>
23 <geometry>
24 <box size="1 0.1 0.1" />
25 </geometry>
26 <origin xyz="0.5 0 0" />
27 <material name="green" />
28 </visual>
29 </link>
30 <link name="end">
31 <visual>
32 <geometry>
33 <cylinder radius = "0.05" length="0.2" />
34 </geometry>
35 </visual>
36 </link>
37
38 <joint name="q1" type="continuous">
39 <parent link="base_link" />
40 <child link="link1" />
41 <axis xyz="0 0 1" />
42 </joint>
43 <joint name="q2" type="continuous">
44 <parent link="link1" />
45 <child link="link2" />
46 <origin xyz="1 0 0" />
47 <axis xyz="0 0 1" />
48 </joint>
49 <joint name="notajoint" type="fixed">
50 <parent link="link2" />
51 <child link="end" />
52 <origin xyz="1 0 0" />
53 </joint>
54
55 </robot>
3.4 Displaying meshes 14
q1
q2
end-effector
Figure 2: Planar 2 robot with joint angles [0, π/4] parsed and plotted using the Robotic Systems
Toolbox
R
.
where lines 38–55 are as before. Lines 4–9 define two translucent materials called red
and green respectively. Link 1 now has a visual element defined in lines 13–19.
The geometry is a box of length 1 m in the x-direction and by default the reference
frame of the visual element is with respect to the reference frame of the link. One end
of the box should be at joint 1, at the origin, so we shift it by 0.5 m in the x-direction
using an origin element (line 17). Finally, we set the color to red using a material
element (line 18). Link 2 is similar.
The end of the robot is indicated by a small cylinder, in default color, which is centred
at the origin of the end link’s coordinate frame.
Using the Robotic Systems Toolbox
R
the file can be parsed and displayed very simply
by
>> r = importrobot(’/Users/corkep/pic3.urdf’)
>> r.DataFormat=’row’
>> show(r, [0 pi/4])
1 <visual>
2 <origin rpy="0 0 0" xyz="0 0 0"/>
3.5 xacro macros 15
3 <geometry>
4 <mesh filename="package://iiwa_description/meshes/iiwa14/visual/link_6.stl"/>
5 </geometry>
6 <material name="Orange"/>
7 </visual>
A mesh element, line 4, specifies a a filename, and an optional scale factor that scales
the mesh’s axis-aligned-bounding-box. The recommended format for best texture and
color support is Collada .dae files, though .stl files are also supported. The mesh
file is not part of the URDF file and must be provided along with the URDF file and
have the appropriate path. The <mesh> tag also supports a scale option with a list
of x-, y- and z-axis scale factors.
The Robotics System Toolbox includes a model of the Kuka iiwa14 arm and this can
be imported, along with its meshes defined in STL format, and displayed
expands to:
<pr2_upperarm suffix="left" reflect="1" parent="torso" />
<pr2_forearm suffix="left" reflect="1" parent="elbow_flex_left" />
<pr2_upperarm suffix="right" reflect="-1" parent="torso" />
<pr2_forearm suffix="right" reflect="-1" parent="elbow_flex_right" />
root = xmlread([’planar2b.urdf’]);
robot = root.getChildNodes.item(0);
materialNodes = robot.getElementsByTagName(’material’);
i = 1;
for j=1:materialNodes.getLength
node = materialNodes.item(j-1);
if isEqualNode(node.getParentNode, robot)
% only process material nodes at the top level
materials(i).name = string(node.getAttribute(’name’));
materials(i).rgba = str2num(node.getElementsByTagName(’color’).item(0).getAttribute(’rgba
materials(i).node = node;
i = i + 1;
end
end
try
materialNames = [materials.name];
end
materialNames
17
materialNames =
"red" "green"
materials(2)
ans =
name: "green"
rgba: [0 1 0 0.8000]
node: [1x1 org.apache.xerces.dom.DeferredElementImpl]
linkNodes = robot.getElementsByTagName(’link’);
for i=1:linkNodes.getLength
node = linkNodes.item(i-1);
links(i).name = string(node.getAttribute(’name’));
links(i).geometry = node.getElementsByTagName(’geometry’).item(0);
try
links(i).material = find(strcmp((node.getElementsByTagName(’material’).item(0).getAttribu
end
try
t = str2num( node.getElementsByTagName(’origin’).item(0).getAttribute(’xyz’));
rpy = str2num( node.getElementsByTagName(’origin’).item(0).getAttribute(’rpy’));
end
if isempty(t)
t = [0 0 0];
end
if isempty(rpy)
rpy = [0 0 0];
end
links(i).T = SE3(t) * SE3.rpy(rpy);
links(i).node = node;
end
linkNames = [links.name]
linkNames =
"base_link" "link1" "link2" "end"
links(2)
ans =
name: "link1"
geometry: [1x1 org.apache.xerces.dom.DeferredElementImpl]
T: [1x1 SE3]
node: [1x1 org.apache.xerces.dom.DeferredElementImpl]
material: 1
jointNodes = robot.getElementsByTagName(’joint’);
for i=1:jointNodes.getLength
node = jointNodes.item(i-1);
joints(i).name = string(node.getAttribute(’name’));
REFERENCES 18
joints(i).type = string(node.getAttribute(’type’));
try
joints(i).axis = node.getElementsByTagName(’axis’).item(0).getAttribute(’xyz’);
end
joints(i).parent = find(strcmp(node.getElementsByTagName(’parent’).item(0).getAttribute(’link
joints(i).child = find(strcmp(node.getElementsByTagName(’child’).item(0).getAttribute(’link’)
try
t = str2num( node.getElementsByTagName(’origin’).item(0).getAttribute(’xyz’));
rpy = str2num( node.getElementsByTagName(’origin’).item(0).getAttribute(’rpy’));
end
if isempty(t)
t = [0 0 0];
end
if isempty(rpy)
rpy = [0 0 0];
end
joints(i).T = SE3(t) * SE3.rpy(rpy);
joints(i).node = node;
end
joints(2)
ans =
name: "q2"
type: "continuous"
axis: [1x1 java.lang.String]
parent: 2
child: 3
T: [1x1 SE3]
node: [1x1 org.apache.xerces.dom.DeferredElementImpl]
References
[1] P. I. Corke, Robotics, Vision & Control: Fundamental Algorithms in MATLAB,
2nd ed. Springer, 2017, iSBN 978-3-319-54412-0.