"right_arm_base_link" passed to lookupTransform argument target_frame does not exist.
ros kinetic, ubuntu 16.04, gazebo 7, intera 5.2 (for sawyer robot), kinect camera in simulation.
trying to transform pointcloud from kinect frame to base from of a sawyer robot. i've coded for this inside another void function that estimates the normals for each point in a point cloud.
trying to use transformPointCloud
from /tf
. code compiles properly, but i get the following error:
[ERROR] [1527657751.698135439, 3503.701000000]: Lookup would require extrapolation at time 3503.478000000, but only time 3503.692000000 is in the buffer, when looking up transform from frame [depth_link] to frame [right_arm_base_link]
when i "ctrl+c"
terminate called after throwing an instance of 'tf2::LookupException'
what(): "right_arm_base_link" passed to lookupTransform argument target_frame does not exist.
This is the code i'm using.
tf::TransformListener listener;
tf::StampedTransform transform;
// Perform point cloud transformation
ros::Time now = ros::Time(0);
listener.waitForTransform("/right_arm_base_link", "/depth_link", now, ros::Duration(5.0), ros::Duration(2));//, error_msg); // base on line 193 of /tf/tf.h
listener.lookupTransform("/right_arm_base_link", "/depth_link", now, transform); // based on line 129 /tf/tf.h
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr trans_cloud (new pcl::PointCloud<pcl::PointXYZRGBNormal>);
pcl_ros::transformPointCloud("/right_arm_base_link", *cloud_with_normals, *trans_cloud, listener); // based on line 131 /pcl_ros/transforms.h
// Publish transformed point cloud
sensor_msgs::PointCloud2 ros_trans_out;
pcl::toROSMsg( *trans_cloud, ros_trans_out);
tf_pub.publish (ros_trans_out);
*cloud_with_normals
is of type PointCloud2
and is my point cloud in. *trans_cloud
is my point cloud out, also PointCloud2
. the goal is to be able to publish the transformed point cloud to a rostopic (publisher has been omitted from the question). my concern is that right_arm_base_link
is not being recognised, but it appears in the transformation tree when i used $ rostopic echo /tf
.
I can also use the following to determine the actual transformation between right_arm_base_link
and depth_link
:
$ rosrun tf tf_echo right_arm_base_link depth_link
and it will yield:
At time 2358.846
- Translation: [0.547, 0.183, 0.017]
- Rotation: in Quaternion [-0.081, 0.701, 0.080, 0.704]
in RPY (radian) [-0.336, 1.567, -0.108]
in RPY (degree) [-19.257, 89.763, -6.202]
At time 2359.846
- Translation: [0.547, 0.183, 0.017]
- Rotation: in Quaternion [-0.081, 0.701, 0.080, 0.704]
in RPY (radian) [-0.335, 1.567, -0.107]
in RPY (degree) [-19.206, 89.763, -6.146]
can anyone suggest what i'm doing wrong or how to fix this issue? i will provide more detail if and when needed.
Thanks in advance!
~ Luke
EDIT
I've tried to use a try/catch. see code below.
try{
listener.waitForTransform("/right_arm_base_link", "/depth_link", now, ros::Duration(5.0), ros::Duration(2)); // base on line 193 of /tf/tf.h
listener.lookupTransform("/right_arm_base_link", "/depth_link", now, transform); // based on line 129 /tf/tf.h
}
catch(tf::LookupException){
std::cerr << "Transform lookup failed" << std::endl;
}
I still receive the error regarding extrapolating the transformation for a time other than the requested time. now
is still the same as the now
defined in the code above.
Just a guess, but: you're instantiating your
TransformListener
2 lines before you try to do a lookup. Assuming the code you show is your actual code, that most likely won't work.TF relies on a buffer. The
TransformListener
maintains that buffer and stores msgs coming in over/tf
in it. .... You need to give
TransformListener
some time to populate the buffer, otherwise it won't ever be able to lookup anything, as the things you're asking for are not in its buffer yet.how much time would you consider to be a sufficient buffer? I did see something like "waitforTransform"? not sure if that might be what you're talking about. I tried using it for a time, but if never compiled properly. i just ended up omitting it.
There is no exact answer to this, as it depends on your TF tree, the rate of publishing and which parts of the tree you want to lookup transforms in. A partial view of the tree is fine, as long as you stay inside it.
I would recommend to instantiate your
TransformListener
in .... the ctor of a class, or in the initialisation phase of your program if not using classes. Then always combine it with
waitForTransform(..)
: that way you can deterministically error-out if something is not found in the buffer. Either immediately, or after a configurable timeout.I think a good rule of thumb could be: if you're instantiating your
TransformListener
in the same scope as where you're callinglookupTransform(..)
(and you're not explicitly sleeping for some time and are not usingwaitForTransform(..)
) you're going to have a bad time (tm).I'm currently look at 2. Wait for Transform and trying to write the try/catch. What would be the exception to write for the catch?
tf2::LookupException
?I also edited my question to show the full error before it Aborts(core dump).