ros / geometry

Packages for common geometric calculations including the ROS transform library, "tf". Also includes ROS bindings for "bullet" physics engine and "kdl" kinematics/dynamics package.
173 stars 275 forks source link

tf2_ros::threading_error screen flood #188

Closed rmerriam closed 5 years ago

rmerriam commented 5 years ago

This morning at 3 am I watched my computer screen get flooded with this error message. There is no documentation about what this really means or the actual solution. More importantly it is not an appropriate response to just flood the message on the output.

` tf2_ros::threading_error = "Do not call canTransform or lookupTransform with a timeout unless you are using another thread for populating data. Without a dedicated thread it will always timeout. If you have a seperate thread servicing tf messages, call setUsingDedicatedThread(true) on your Buffer instance."

` Been working on this code for weeks (Ariac competition) to control UR10 arms. Only worked with one arm up until this morning when I added the ability to work with both arms. I don't need threading since the code runs much faster than the arms handle the movement. I can send a command to one arm, calculate what needs doing on the other one to send it command, and then wait. Never saw this message until I started calling the code alternating between the arms. The code is not reentrant since each arm has its own instance of the C++ objects.

Why a separate thread? I thought that was what ros::spinner is supposed to handle.

What is the solution? Create a thread with just tf2_ros::Buffer and tf2_ros::TransformListener? Then use that buffer instance when calling transforms?

Got just over 24 hours to figure this out and a lot more to do for the competition so don't have time to experiment.

tfoote commented 5 years ago

Please ask questions on http://answers.ros.org according to our support policy: http://wiki.ros.org/Support We try to keep the issue tracker reserved for bugs and feature developments.

I found similar questions at: https://answers.ros.org/question/205117/tf2-thread-setusingdedicatedthread-timeout/ However it's likely related to how you're setting up the system since both default constructors for TransformListener have spin_thread=true http://docs.ros.org/melodic/api/tf2_ros/html/c++/classtf2__ros_1_1TransformListener.html which would take care of this. If you're not using a listener that's spinning and receiving the data you will need to make sure that the buffer is being populated by another thread. Otherwise this error is correct that you will always timeout, this is thrown instead of waiting for the timeout to give the developer more information. If you're still having an issue please ask your question on answers.ros.org with a minimal example able to reproduce your problem.

rmerriam commented 5 years ago

I posted this as an issue because the way the 'error' is handled is inappropriate. I found the answers' message you referred to and it did not help my situation.

Why would I look at the constructors for a solution? The scrolling message doesn't reference them.

saikishor commented 3 years ago

@rmerriam The issue could also happen if you have added an instance of tf2 Buffer after TransformListener in your class members, in this case, even if you properly pass the buffer member at the constructor time. The Buffer has not been completely instantiated and hence, the Transform Listener fails to spawn the thread, and thereby causing this issue.

Belal111125 commented 1 year ago

@saikishor what do you suggest as workaround of using two instances?

saikishor commented 1 year ago

Hello @Belal111125

@saikishor what do you suggest as workaround of using two instances?

  std::shared_ptr<tf2_ros::TransformListener> tf_listener_;
  std::unique_ptr<tf2_ros::Buffer> tf_buffer_;

   tf_buffer_ = std::make_unique<tf2_ros::Buffer>(this->get_clock());
   tf_listener_ = std::make_shared<tf2_ros::TransformListener>(*tf_buffer_);

This is what I meant that the instance by having tf_buffer after the transform listener in your class members list and then the listener properly uses it and spawns a thread.

Belal111125 commented 1 year ago

I am having two buffers for two different transforms and i am still getting the same error above for the second buffer, keep in mind that i have declared them as class members as you have highlighted. The first:
tf2_ros::Buffer tfBuffer; const auto transformed_pose = tfBuffer.transform(waypoint, "base_link", ros::Duration{0.1}); The second: tf2_ros::Buffer tfBuffer2; const auto transformed_pose_2 = tfBuffer2.transform(waypoint,"map",ros::Duration{0.1});

saikishor commented 1 year ago

I am having two buffers for two different transforms and i am still getting the same error above for the second buffer, keep in mind that i have declared them as class members as you have highlighted.

You can reuse the buffer rather than creating a new one for every new transform

saikishor commented 1 year ago

I am having two buffers for two different transforms and i am still getting the same error above for the second buffer, keep in mind that i have declared them as class members as you have highlighted.

I'm apologise for my previous code message, I sent you something of ROS2 but yes in ROS1 you need to declare them in order and pass the buffer as a construction argument to the listener and then start using it

Belal111125 commented 1 year ago

i took note that you are using ros2, however the issue is still persisting