Ask Your Question
0

tf2 buffer lookupTransform fails, tf_echo and rostopic echo /tf_static work fine

asked 2018-04-04 14:51:48 -0500

patnolan33 gravatar image

I am having difficulties getting a transformation from a robot to the static world frame in a custom node I am writing. I am using Kinetic and I have a robot with a kinect sensor on board providing PointCloud2 data. I am using the robot_state_publisher node to take care of the tf transforms.

Here is a snippet of my launch file that calls the static_transform_publisher and robot_state_publisher:

<!-- send static transform -->
<node pkg="tf2_ros" type="static_transform_publisher" name="vehicle_broadcaster" args="0 0 0 0 0 0 $(arg world_frame) $(arg namespace)$(arg base_link_frame)" />

<!-- start robot state publisher -->
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" output="screen" >
  <param name="publish_frequency" type="double" value="50.0" />
  <param name="tf_prefix" type="string" value="$(arg namespace)" />
</node>

NOTE: the $(arg) values are passed in via command line to the launch file. They should be "world", "robot", "/base_link", and "robot", respectively

The reasoning for calling the static_transform_publisher was that I was not getting a base_link -> world transformation. In other words, I couldn't seem to get robot_state_publisher to output a transformation from the robot's frame to an inertial world frame. (I'd be happy to hear suggestions on this, although this is not the main intent of this question).

The node I have is running the following code:

tf2_ros::Buffer tfBuffer;
tf2_ros::TransformListener tfListener(tfBuffer);
geometry_msgs::TransformStamped transformStamped;

try {
    transformStamped = tfBuffer.lookupTransform("world", "robot/kinect_depth_optical_frame", ros::Time(0));
    std::cout << transformStamped << std::endl;
}
catch (tf2::TransformException &ex) {
    ROS_WARN("%s", ex.what());
}

All I am trying to do at this point is find the transformation between the kinect's optical frame and an inertial "world" frame. When I run this node from a launch file, I get the following exception:

[ WARN] [1522870890.897427898, 4.330000000]: "world" passed to lookupTransform argument target_frame does not exist.

This error persists when I use anything as the first argument, with "world" being replaced with whatever is passed in. When I run rosrun tf2_tools view_frames.py, I get a TF tree that looks exactly how I'd expect a working system to look. Unfortunately, since this is my first post, I don't have enough points to upload an image to this question. (Hopefully I can edit it soon to upload the image...)

When I run rosrun tf tf_echo robot/kinect_depth_optical_frame world in a terminal, I get the following output:

At time 0.000
- Translation: [-0.020, -0.060, -0.050]
- Rotation: in Quaternion [0.500, -0.500, 0.500, 0.500]
            in RPY (radian) [1.571, -1.571, 0.000]
            in RPY (degree) [90.000, -90.000, 0.000]

Regardless of whether or not the transformation is actually correct, the fact that I am getting a response means that this transformation is set up and I should be able to look it up using lookupTransform in my node. I also get an output from rostopic echo /tf_static that looks correct as well (I can add that if requested).

I apologize for the long winded explanation, but I am at a loss here ... (more)

edit retag flag offensive close merge delete

Comments

1

Buffers need time to be filled by their listeners. How much time are you giving your tf2_ros::TransformListener to fill the buffer you pass? If you don't give it any time, things won't work. All the other tools 'work', because they wait for transforms to become available.

gvdhoorn gravatar imagegvdhoorn ( 2018-04-04 15:47:15 -0500 )edit

That makes sense, but I'm not exactly sure how to answer your question. I have a ros::Rate loop_rate(10) defined in my node's main, but the above transform lookup is done in the callback for the kinect's point cloud topic. Is there a way to set that wait time for the tf2_ross::TransformListener?

patnolan33 gravatar imagepatnolan33 ( 2018-04-04 16:08:10 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted
1

answered 2018-04-05 01:51:52 -0500

gvdhoorn gravatar image

updated 2018-04-05 08:06:10 -0500

If you're using a class to wrap all this, just make the buffer and listener members and initialise them in your ctor. If not, put them in a scope other than this callback and do the same.

If that's impossible, use the timeout argument to lookupTransform(..) and set it to a non-zero value. That will make lookupTransform(..) wait for a maximum of timeout seconds before attempting the actual transformation.

See tf2_ros::Buffer::lookupTransform(..).

edit flag offensive delete link more

Comments

Alright great, that worked. Don't know how I missed that timeout argument to lookupTransform. I'd like to wrap it in a class as per your first comment, but the buffer was the issue. Thank you for your help! (Do I have to post an answer, or can I somehow mark your comment as the answer?)

patnolan33 gravatar imagepatnolan33 ( 2018-04-05 08:04:34 -0500 )edit

Check also canTransform(..) in the same class.

gvdhoorn gravatar imagegvdhoorn ( 2018-04-05 08:06:37 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2018-04-04 14:51:48 -0500

Seen: 810 times

Last updated: Apr 05 '18