Ask Your Question
0

Proper use of ros_control's RealtimeBuffer

asked 2015-01-19 14:44:22 -0500

Daniel L gravatar image

updated 2015-01-19 14:46:49 -0500

I am new to real-time programming, and I am trying to learn how to properly use realtime_tools::RealtimeBuffer in my ros_control controller by looking at source code from related packages. After looking at the source code of RealtimeBuffer, effort_controllers::JointPositionController, and forward_command_controller::ForwardJointGroupCommandController, I am still confused about three things.

First, JointPositionController uses the buffer to share command data between the RT and non-RT threads, but command_struct_, the member variable used to set the buffer, is also accessed by both threads. Is it safe to access command_struct_ in this way? If it is safe, why is this the case?

Second, in ForwardJointGroupCommandController, why is RealtimeBuffer not used at all? My controller has several joints and I was thinking on using RealtimeBuffer to protect a vector. In order to pre-allocate the buffer internally, I was thinking on passing a vector with dummy values to RealtimeBuffer::initRT() in the init() method of the controller (I don't know the size of the vector until this point). Then call initRT() again in starting() with appropriate values.

Third, why doesn't RealtimeBuffer::initRT() check the lock of the mutex? Under the context of the JointPositionController , I can imagine messages published to the command topic even before the controller is started. Would this be safe?

Source code: RealtimeBuffer, JointPositionController, ForwardJointGroupCommandController.

edit retag flag offensive close merge delete

1 Answer

Sort by » oldest newest most voted
1

answered 2015-01-22 08:55:21 -0500

Adolfo Rodriguez T gravatar image

For your first question, the RealtimeBuffer is intended for synchronization of data shared by one non-rt and one rt thread, where the non-rt thread writes into the shared data, and the rt thread reads it. When writing, the non-rt thread is subject to waiting for the shared resource to become free, while the rt thread never waits for reading. Internally, RealtimeBuffer keeps two versions of the shared resource, one which can always be read, and another one which can be safely written into.

For your second question, the implementation of both ForwardCommandController and ForwardJointGroupCommandController is missing proper synchronization between the non-rt thread that executes the subscriber callback and the rt thread that runs the controller update method. Good catch!, I just opened a ticket to track this issue. effort_controllers::JointPositionController, on the other hand, handles concurrency correctly.

Finally, for the third question. The RealtimeBuffer::initRT() is likely assuming that it can only be called in circumstances in which there is no active writer to the shared resource. This is of course undocumented, and I'm judging from the implementation. The fact is, RealtimeBuffer is not well suited for usecases in which the rt-thread writes into the shared resource. For such cases, you could try using a regular lock, possibly around a lightweight object like a pointer. realtime_tools::RealtimeBox is a trivial implementation of this (in fact, there is nothing rt-specific in the implementation).

It has been on my mind for ros_control to leverage better synchronization primitives, but so far the resources have not been there to properly take on the task.

i hope to have answered your questions.

edit flag offensive delete link more

Comments

Thank you for taking the time to answer. I think I was not clear with my first question. In JointPositionController, command_struct_, which is not the RealtimeBuffer, is used in both threads: ROS message handling (setCommand) and the control loop (starting and update). Is this ok?

Daniel L gravatar image Daniel L  ( 2015-01-24 16:44:18 -0500 )edit

I have added the realtime buffers for the forward controllers: https://github.com/ros-controls/ros_c... It fixes some other problems as well.

You are right, the use of command_struct_ is not thread-safe! It must not be used in update. The copy could be replaced by a local reference.

Mathias Lüdtke gravatar image Mathias Lüdtke  ( 2015-01-28 11:02:15 -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

3 followers

Stats

Asked: 2015-01-19 14:44:22 -0500

Seen: 824 times

Last updated: Jan 22 '15