Note: This tutorial assumes you are familiar with the xml markup language.
(!) Please ask about problems and questions regarding this tutorial on Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags.

Using urdf with robot_state_publisher

Description: This tutorial gives a full example of a robot model with URDF that uses robot_state_publisher. First, we create the URDF model with all the necessary parts. Then we write a node which publishes the JointState and transforms. Finally, we run all the parts together.

Keywords: robot_state_publisher urdf

Tutorial Level: INTERMEDIATE

tf is deprecated in favor of tf2. tf2 provides a superset of the functionality of tf and is actually now the implementation under the hood. If you're just learning now it's strongly recommended to use the tf2/Tutorials instead.

Create the URDF File

Here is the URDF file for a 7-link model roughly approximating R2-D2. Save the following link to your computer: model.xml

Publishing the State

Now we need a method for specifying what state the robot is in. To do this, we must specify all three joints and the overall odometry. Start by creating a package:

catkin_create_pkg r2d2 roscpp rospy tf sensor_msgs std_msgs

Then fire up your favorite editor and paste the following code into the src/state_publisher.cpp file:

   1 #include <string>
   2 #include <ros/ros.h>
   3 #include <sensor_msgs/JointState.h>
   4 #include <tf/transform_broadcaster.h>
   6 int main(int argc, char** argv) {
   7     ros::init(argc, argv, "state_publisher");
   8     ros::NodeHandle n;
   9     ros::Publisher joint_pub = n.advertise<sensor_msgs::JointState>("joint_states", 1);
  10     tf::TransformBroadcaster broadcaster;
  11     ros::Rate loop_rate(30);
  13     const double degree = M_PI/180;
  15     // robot state
  16     double tilt = 0, tinc = degree, swivel=0, angle=0, height=0, hinc=0.005;
  18     // message declarations
  19     geometry_msgs::TransformStamped odom_trans;
  20     sensor_msgs::JointState joint_state;
  21     odom_trans.header.frame_id = "odom";
  22     odom_trans.child_frame_id = "axis";
  24     while (ros::ok()) {
  25         //update joint_state
  26         joint_state.header.stamp = ros::Time::now();
  28         joint_state.position.resize(3);
  29[0] ="swivel";
  30         joint_state.position[0] = swivel;
  31[1] ="tilt";
  32         joint_state.position[1] = tilt;
  33[2] ="periscope";
  34         joint_state.position[2] = height;
  37         // update transform
  38         // (moving in a circle with radius=2)
  39         odom_trans.header.stamp = ros::Time::now();
  40         odom_trans.transform.translation.x = cos(angle)*2;
  41         odom_trans.transform.translation.y = sin(angle)*2;
  42         odom_trans.transform.translation.z = .7;
  43         odom_trans.transform.rotation = tf::createQuaternionMsgFromYaw(angle+M_PI/2);
  45         //send the joint state and transform
  46         joint_pub.publish(joint_state);
  47         broadcaster.sendTransform(odom_trans);
  49         // Create new robot state
  50         tilt += tinc;
  51         if (tilt<-.5 || tilt>0) tinc *= -1;
  52         height += hinc;
  53         if (height>.2 || height<0) hinc *= -1;
  54         swivel += degree;
  55         angle += degree/4;
  57         // This will adjust as needed per iteration
  58         loop_rate.sleep();
  59     }
  62     return 0;
  63 }

Launch File

This launch file assumes you are using the package name "r2d2" and node name "state_publisher" and you have saved this urdf to the "r2d2" package.

   1 <launch>
   2         <param name="robot_description" command="cat $(find r2d2)/model.xml" />
   3         <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
   4         <node name="state_publisher" pkg="r2d2" type="state_publisher" />
   5 </launch>

Viewing the Results

First we have to edit the CMakeLists.txt in the package where we saved the above source code. Make sure to add the tf dependency in addition to the other dependencies:

find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs tf)

Notice that roscpp is used to parse the code that we wrote and generate the state_publisher node. We also have to add the following to the end of the CMakelists.txt in order to generate the state_publisher node:

include_directories(include ${catkin_INCLUDE_DIRS})
add_executable(state_publisher src/state_publisher.cpp)
target_link_libraries(state_publisher ${catkin_LIBRARIES})

Now we should go to the directory of the workspace and build it using:

$ catkin_make

Now launch the package (assuming that our launch file is named display.launch):

$ roslaunch r2d2 display.launch

Run rviz in a new terminal using:

$ rosrun rviz rviz

Choose odom as your fixed frame (under Global Options). Then choose "Add Display" and add a Robot Model Display and a TF Display (see

Wiki: urdf/Tutorials/Using urdf with robot_state_publisher (last edited 2021-04-01 04:37:13 by FelixvonDrigalski)