0
$\begingroup$

Rosanswers logo

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.

<launch>
<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" />
</group>
</launch>

I get the following results when I run tf_monitor command.

Frames:
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?

Originally posted by TharushiDeSilva on ROS Answers with karma: 79 on 2019-04-01

Post score: 0

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

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:

<launch>
<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" />
</group>
</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 
bullet_migration_sed.py     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)"/>
</include>

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
 -->
<launch>
  <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>
  
  <node pkg="diagnostic_aggregator" type="aggregator_node" name="diagnostic_aggregator" >
    <rosparam command="load" file="$(find kobuki_node)/param/diagnostics.yaml" />
  </node>
</launch>

your launch file as the tf_prefix param does not have an effect in this file, I removed it.

<launch>
    <arg name="robot_name" default="qbot0"/>
    <group ns="$(arg robot_name)">

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

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

        <!-- run kinect -->
        <!-- <include file="$(find freenect_launch)/launch/freenect.launch" /> -->
        <include file="$(find freenect_launch)/launch/freenect_tf_prefix.launch">
            <arg name="tf_prefix" default="$(arg robot_name)"/>
        </include>
    </group>
</launch>

I guess I should add that neither of the packages use the tf_prefix as I think it was intended to be used. Kobuki does not use it based on the launch files I have seen so far (not many) and I have not looked at the code. And I guess not using it is OK. You can read more about it here tf_prefix deprecated


Originally posted by Reamees with karma: 591 on 2019-04-01

This answer was ACCEPTED on the original site

Post score: 4


Original comments

Comment by TharushiDeSilva on 2019-04-01:
@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.

Comment by janindu on 2019-04-01:\

  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.

Comment by janindu on 2019-04-02:
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.

Comment by TharushiDeSilva on 2019-04-02:
@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

Comment by Reamees on 2019-04-03:
if you launched the nodes in a namespace the topics will also most likely be in the same namespace.

Comment by TharushiDeSilva on 2019-04-03:
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.

Comment by janindu on 2019-04-03:
In your sourced workspace, try rospack find package_name. It would tell you from where the packages are loaded.

Comment by TharushiDeSilva on 2019-04-04:
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.

Comment by janindu on 2019-04-05:
The best practice is to install common ROS packages using apt. You should be able to configure the nodes using arguments / parameters specified in a launch file without having to worry about any code changes. The only reason to build from source IMO is when you do need a code change to configure a badly implemented node. I saw in a different problem you posted that octomap_server subscribes to a topic in global namespace (where you do need a code change if you want namespaces). However, a quick look at the kinetic devel and melodic devel branches show that it's fixed there.

Comment by janindu on 2019-04-05:
Careful use of source catkin_workspace_n/devel/setup.bash allows multiple ROS workspaces / ROS distributions to co-exist in a Linux environment.

Comment by Reamees on 2019-04-05:
What @janindu said. Also whether the package in your WS or the package installed with apt is used depends on which ever package appears first in your ROS_PACKAGE_PATH env variable. You can manipulate the variable manually, to test stuff out. What has been working for me so far is having the lines source /opt/ros/kinetic/setup.bash and source ~/catkin_ws/devel/setup.bash in .bashrc in that order. That way it has always used the package in my WS if there are two packages with the same name. You might not be using kinetic or your WS might not be called catkin_ws, so change that according to your setup.

Comment by TharushiDeSilva on 2019-04-05:
@janindu, @Reamees, Thank you both for the tips. I should try those things in the future.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.