ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

Adding a namespace to robot frames

asked 2019-04-01 01:23:47 -0600

TharushiDeSilva gravatar image

updated 2019-04-01 01:45:54 -0600

jayess gravatar image

I am running multiple qbots in a multi-master network, and I have been able to successfully run individual robot topics under a given namespace. (eg: qbot1/mobile_base/commands/ .... , qbot2/mobile_base/commands/... etc). But my robots still run under the default frame names defined by the system, so every robot has the same frame names. For example, this is my TF tree for qbot0:

image description

My expectation is to remap these frames as,

    odom  -> qbot0/odom
    base_footprint -> qbot0/base_footprint 
    camera_link -> qbot0/camera_link
    base_link -> qbot0/base_link   etc.

So that, when I run two robots in the system, I can visualize two separate trees. (one tree per robot) I use the following launch file with the standard kobuki, and freenect drivers.

<group ns="qbot0">
    <!-- run kobuki base -->
    <include file="$(find kobuki_node)/launch/minimal.launch"/>

    <!-- tf config -->
    <param name="tf_prefix" value="qbot0" />
    <node pkg="tf" type="static_transform_publisher" name="camera_to_base" args="0 0 0.1 0 0.0 0 base_footprint camera_link 100"/>
    <node pkg="tf" type="static_transform_publisher" name="robot_state_publisher" args="0 0 0 0 0.0 0 base_footprint base_link 100"/>

    <!-- run kinect -->
    <include file="$(find freenect_launch)/launch/freenect.launch" />

I get the following results when I run tf_monitor command.

Frame: /camera_depth_frame published by unknown_publisher(static) Average Delay: 0 Max Delay: 0
Frame: /camera_depth_optical_frame published by unknown_publisher(static) Average Delay: 0 Max Delay: 0
Frame: /camera_rgb_frame published by unknown_publisher(static) Average Delay: 0 Max Delay: 0
Frame: /camera_rgb_optical_frame published by unknown_publisher(static) Average Delay: 0 Max Delay: 0
Frame: base_footprint published by unknown_publisher Average Delay: 0.000201064 Max Delay: 0.00149896
Frame: base_link published by unknown_publisher Average Delay: -0.0998057 Max Delay: 0
Frame: camera_link published by unknown_publisher Average Delay: -0.0998314 Max Delay: 0

I have no luck with the tf_prefix parameter. I wish to know a few thing if you are familiar with libraries like freenect and tf.

  1. What am I doing wrong with the tf_prefix parameter?
  2. Is there a way to debug the TF in more advanced manner s.t. I can find by whom the frames are actually being published?
  3. How can I accurately add the prefix in front of all the robot frames?
edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted

answered 2019-04-01 03:11:55 -0600

Reamees gravatar image

updated 2019-04-02 03:42:46 -0600

Points 1 and 3: You need to declare the tf_prefix parameter before you load anything that publishes TFs that should be in the namespace.

Move the line <param name="tf_prefix" value="qbot0" /> in your launch file before:

<!-- run kobuki base -->
<include file="$(find kobuki_node)/launch/minimal.launch"/>

Also the static_transform_publisher does not use the parameter I think, so you should either move those links to the URDF or use an argument for those transforms.

With the argument your launch file would look something like this:

<arg name="tf_prefix" default="qbot0"/>
<group ns="$(arg tf_prefix)">
    <param name="tf_prefix" value="$(arg tf_prefix)" />

    <!-- run kobuki base -->
    <include file="$(find kobuki_node)/launch/minimal.launch"/>

    <!-- tf config -->
    <node pkg="tf" type="static_transform_publisher" name="camera_to_base" args="0 0 0.1 0 0.0 0 $(arg tf_prefix)/base_footprint $(arg tf_prefix)/camera_link 100"/>
    <node pkg="tf" type="static_transform_publisher" name="robot_state_publisher" args="0 0 0 0 0.0 0 $(arg tf_prefix)/base_footprint $(arg tf_prefix)/base_link 100"/>

    <!-- run kinect -->
    <include file="$(find freenect_launch)/launch/freenect.launch" />

As for point 2. There are a range of tools that would help with debuging. The rosrun tf view_frames and rosrun rqt_tf_tree rqt_tf_tree both provide sources for the transform, there are other tools to work with tf like

$ rosrun tf     tf_change_notifier          tf_empty_listener           tf_remap
static_transform_publisher  tf_echo                     tf_monitor                  view_frames

And there are more, but it's too much for me to go into right now.

updated answer

I changed the arg tf_prefix I previously used in the launch file to robot_name to be less confusing. As @jaindu mentions it is possible to pass the tf_prefix to kinect_frames.launch from looking at the launch files you should include the freenect_tf_prefix.launch instead of freenect.launch for that, the relevant lines would look something like this:

<include file="$(find freenect_launch)/launch/freenect_tf_prefix.launch">
    <arg name="tf_prefix" default="$(arg robot_name)"/>

as for the kobuki_node stuff it is a bit harder to test without setting up quite a bit of stuff. As far as I can tell, setting the parameters in the kobuki_node minimal.launch should fix the problem. As I said it's not very easy to test without actual feedback but adding the params odom_frame and base_frame to minimal.launch, passing the robot_name arg and using it in the params might work. Here is my guess as to what might work:

kobuki_node minimal.launch

  Standalone launcher for running a default Kobuki
  <arg name="kobuki_publish_tf" default="true"/> <!-- Publish base_footprint - odom transforms (usually good thing to have for localisation) -->
  <arg name="tf_prefix" default=""/>

  <node pkg="nodelet" type="nodelet" name="mobile_base_nodelet_manager" args="manager"/>
  <node pkg="nodelet" type="nodelet" name="mobile_base" args="load kobuki_node/KobukiNodelet mobile_base_nodelet_manager">
    <rosparam file="$(find kobuki_node)/param/base.yaml" command="load"/>
    <param name="odom_frame" value="$(arg tf_prefix)/odom"/>
    <param name="base_frame" value="$(arg tf_prefix)/base_frame"/>
    <param name="publish_tf" value="$(arg kobuki_publish_tf)"/>
    <remap from="mobile_base/odom" to="odom"/>
    <remap from="mobile_base/joint_states" to="joint_states"/>

  <node pkg="diagnostic_aggregator" type="aggregator_node" name="diagnostic_aggregator" >
    <rosparam command="load" file="$(find kobuki_node)/param/diagnostics.yaml" />
  </node ...
edit flag offensive delete link more


@Reamees, I tried doing this, but still no luck. Now I can see that the TF tree is broken into parts with some frames with namespace, and some frames without namespace. This is the TF tree.

I tried adding the tf_prefix argument into kobuki udrf files. But it did not make any difference.

TharushiDeSilva gravatar image TharushiDeSilva  ( 2019-04-01 22:33:45 -0600 )edit
  1. To fix the odom->base_footprint transformation : The kobuki_node sets the frame names from the parameters ~odom_frame and ~base_frame. So you need to set them inside the launch file.
janindu gravatar image janindu  ( 2019-04-01 23:59:02 -0600 )edit

And if you take a look at the freenect.launch file you can see that it uses rgbd_camera kinect_frames.launch to launch tf. Going through that launch file, you can see that you can pass tf_prefix as an argument. You can use that to join the camera_link tree to qbot0/camera_link.

janindu gravatar image janindu  ( 2019-04-02 00:06:11 -0600 )edit

@Reamees, @janindu, Thank you both for the answers to solve my issue. I was able to set the odom frame and the base_footprint frame by considering the frame names as private parameters. (~odom_frame, ~base_frame as @janindu mentioned) Then I added the tf_prefix default parameter to rgbd_launch/launch/kinect_frames.launch file.

I was able to publish all the frames as I expected

But now I cannot visualize my camera output, which means the expected topics are not published and hence cannot be visualized by RViz. Looks like I'm going to enjoy solving that one. :D

TharushiDeSilva gravatar image TharushiDeSilva  ( 2019-04-02 23:07:56 -0600 )edit

if you launched the nodes in a namespace the topics will also most likely be in the same namespace.

Reamees gravatar image Reamees  ( 2019-04-03 00:47:04 -0600 )edit

Yes. I think my program is loading data via the sources in the /opt/ros/kinetic/share directory. They have all the old and default names. I have all the required sources within my workspace, and sourcing the workspace doesn't seem to work. I tried removing packages from /opt/ros/kinetic/share but it led to more errors. So I'm currently working on how to load drivers and other sources from my workspace.

TharushiDeSilva gravatar image TharushiDeSilva  ( 2019-04-03 01:19:17 -0600 )edit

In your sourced workspace, try rospack find package_name. It would tell you from where the packages are loaded.

janindu gravatar image janindu  ( 2019-04-03 18:07:41 -0600 )edit

The reason for this issue was; apart from installing the packages from the source, I had also installed them using command line. I did this when I was getting familiar with the devices and equipment because I wanted to play around. So as an example, I had freenect package installed in my /opt/ros/.. as well as in my workspace(cloned from git). I uninstalled the packages from the /opt/ros/.. directory and after that my parameter changes became effective. One lesson I learned was; it's troublesome to locate sources/drivers under common ROS installation space where I don't have control over it. I'm not sure whether it's a good practice, because there can be several workspaces in a machine.

TharushiDeSilva gravatar image TharushiDeSilva  ( 2019-04-04 23:56:36 -0600 )edit

Question Tools



Asked: 2019-04-01 01:23:47 -0600

Seen: 3,093 times

Last updated: Apr 02 '19