Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Synchronous updates #1475

Open
wants to merge 2 commits into
base: noetic-devel
Choose a base branch
from

Conversation

simonschmeisser
Copy link
Contributor

The api documentation of rviz::Display claims to provide a ros::NodeHandle whose associated callback queue is processed synchronously from the gui thread. Following this promise most subclasses of Display ignore thread-safety in their callback-functions. This promise however breaks if an AsyncSpinner is used in an application using the rviz::RenderPanel (or ros::spinOnce gets called in different threads)

This PR therefore adds a separate CallbackQueue for synchronous processing of message callbacks such that the promise continues to hold. Since not all Display subclasses are expected to use the designated NodeHandles [1], a second commit adds a periodic ros::spinOnce in rviz::VisualizerApp that processes the global ros callback queue.

Note that the second commit requires Qt5, I can rewrite it using a member function if desired

1: https://github.com/ros-planning/moveit/blob/e8a4072727abe4c704d009f05baa764bcf106b33/moveit_ros/visualization/robot_state_rviz_plugin/src/robot_state_display.cpp#L300

Copy link
Contributor

@rhaschke rhaschke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is the right way to go, because of the following reasoning:
As you discovered yourself, we cannot ensure that all custom plugins use update_nh_ and its queue.
Thus, to be on the safe side, you should modify your application in such a fashion that the global queue is handled by the main thread. If you want to handle other messages asynchronously, you should configure a separate queue and process it from your threads. This way you have full control.

@@ -344,7 +345,7 @@ void VisualizationManager::onUpdate()
resetTime();
}

ros::spinOnce();
private_->update_queue_.callAvailable(ros::WallDuration(0.01));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private_->update_queue_.callAvailable(ros::WallDuration(0.01));
private_->update_queue_.callAvailable(ros::WallDuration());
ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration());

@@ -221,6 +221,13 @@ bool VisualizerApp::init( int argc, char** argv )
ros::NodeHandle private_nh("~");
reload_shaders_service_ = private_nh.advertiseService("reload_shaders", reloadShaders);

//process any callbacks that don't use the designated callback queues of VisualizationManager
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you want to handle the global queue differently?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VisualizerApp is used by the rviz binary but not by library users. Handling the global queue here will make sure that plugins that rely on it won't see any difference. For library users it allows not handling the global queue in the main thread.

@rhaschke
Copy link
Contributor

@simonschmeisser, what is your feeling about this PR? Did you find an alternative solution?

@simonschmeisser
Copy link
Contributor Author

I have to admit that I haven't worked on this the last three weeks. The issue is still open and I understand your point about there potentially being too many non-conformant plugins. This approach would allow fixing the set of plugins we use while not changing anything for others.

I will however also check the alternative you mentioned of using the AsyncSpinner for non-gui data handling and the global queue for GUI stuff only.

while the documentation suggests this, getUpdateQueue returns the global
callback queue which might be processed in different threads if
AsyncSpinner is used or other threads call ros::spinOnce
@simonschmeisser simonschmeisser changed the base branch from melodic-devel to noetic-devel April 5, 2021 19:53
@rhaschke
Copy link
Contributor

rhaschke commented Jan 3, 2023

@simonschmeisser, can we close this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants