Difference between URDF and SDF and how to convert
Last updated
Last updated
In this article, we discuss the differences betwee URFD and SDF, focusing on their syntax and transformation representation. Additionally, we demonstrate how to implement the conversion from SDF to URDF and provide a customizable sample code.
The primary distinction between URDF and SDF lies in their syntax. You can find more details in the official format specifications online. Here, we illustrate with examples to showcase the apparent differences. In URDF, attributes are typically embedded within a tag as fields, such as <inertia ixx="..."/>
. Conversely, SDF expresses the same information through nested tags, like <inertia><ixx>...</ixx></inertia>
.
Example of URDF
Example of SDF
A key difference between URDF and SDF lies in how transformations are represented. In URDF, transformations are specified with in the joint
element, whereas in SDF, they are defined separated in the parent and child link elements. For instance:
It's important to note that during the conversion from SDF to URDF, values for the pose
tag in the child link are not directly transferred. This is because the representation of transformations differ significantly between the two formats, making the process more complex than a straightforward copy of tag values.
(optional: defaults to identity if not specified)
This is the transform from the parent link to the child link. The joint is located at the origin of the child link, as shown in the figure above.
xyz (optional: defaults to zero vector): Represents the x, y, z offset. All positions are specified in metres.
rpy (optional: defaults to zero vector): Represents the rotation around fixed axis: first roll around x, then pitch around y and finally yaw around z. All angles are specified in radians.
Element Required: 0 Type: pose Default: 0 0 0 0 0 0 Description: A pose (translation, rotation) expressed in the frame named by @relative_to. The first three components (x, y, z) represent the position of the element's origin (in the @relative_to frame). The rotation component represents the orientation of the element as either a sequence of Euler rotations (r, p, y), see http://sdformat.org/tutorials?tut=specify_pose, or as a quaternion (x, y, z, w), where w is the real component.
relative_to Attribute Required: 0 Type: string Default: Description:If specified, this pose is expressed in the named frame. The named frame must be declared within the same scope (world/model) as the element that has its pose specified by this tag. If missing, the pose is expressed in the frame of the parent XML element of the element that contains the pose. For exceptions to this rule and more details on the default behavior, see http://sdformat.org/tutorials?tut=pose_frame_semantics. Note that @relative_to merely affects an element's initial pose and does not affect the element's dynamic movement thereafter. New in v1.8: @relative_to may use frames of nested scopes. In this case, the frame is specified using
::
as delimiter to define the scope of the frame, e.g.nested_model_A::nested_model_B::awesome_frame
.
This implies that the transformation described in the pose
tag of the child link may be based on the world frame (by default) or a frame specified in the relative_to
attribute, which differ from the parent frame.
When you download an SDF file, it often uses the default mode of the pose
tag, where link transformations are expressed in the world frame. Directly copying the the child link's pose value from an SDF file to the origin
tag of a URDF joint
element may lead to unexpected results. The below screenshot illustrates this effect. We also replicate this in Three.js, using the Group
concept to verify the behavior.
Another tag that has similar nuance is axis. For simplicity, we will not dive into the details in this article.
Since Gazebo can use URDF files directly, conversion from URDF to SDF is typically unnecessary. However, when downloading the robot models from the internet, which are often in the SDF format, converting them to URDF becomes essential. This section will outline the steps in this conversion process.
The first step is to parse the SDF file and create an in-memory representation. An XML parser library such as ElementTree in python can do the job.
Follow the URDF specification and convert the in-memory representation into the URDF format. This step is a standard serialization process.
For SDF files that use mesh files, it's often necessary to modify the model path. This is because ROS2 and Gazebo locate model files differently. In URDF, mesh file locations are specified as follows:
where as in SDF, we use the following form:
The key distinction between the two formats lies in their path references: URDF uses an absolute path, whereas SDF employs a relative path that depends on an environment variable that configure the model search directory. To standardize the path, we can set this environment variable to the directory of the package that contains the model resources. In Gazebo Fortress, the relevant variable is IGN_GAZEBO_RESOURCE_PATH
. This adjustment can be implemented in the python launch file. For instance,
As discussed earlier, converting transformation of child links from the world frame to the parent frame may be necessary. The pose
element in SDF takes the form x y z r p y
and in both pose
and origin
tags, the xyz
represents to the translation part of the transformation and the rpy
attribute denote rotation. Recall that the homogeneous transformation is represented as follows:
Suppose the pose
of link
represents the transformation in the world frame. Consider a joint with parent link and the child link. This scenario involves three frames:
world frame
parent frame
child frame
and three transformations:
: transformation of parent frame expressed in the world frame
: transformation of child frame expressed in the world frame
: transformation of the child frame expressed in the parent frame
The first two transformation are inputs as they are given in the SDF file; the third transformation is the output because that's the information we need to put in the joint
tag in the URDF file.
The conversion is given the formula below:
and the inverse of the homogeneous transformations is given as:
The python code below implements the conversion using scipy
:
©2023 - 2024 all rights reserved
The specification of the transformation in URDF is straightforward. According to the :
It's important to note that the transformations in URDF are always relative (i.e. from the parent link frame to the child link frame), whereas in SDF, they are more nuanced. According to the :
We created a that illustrates the steps mentioned in this article, which is not suitable for production usage.