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

controller_manager as component node #330

Open
tylerjw opened this issue Feb 12, 2021 · 4 comments
Open

controller_manager as component node #330

tylerjw opened this issue Feb 12, 2021 · 4 comments

Comments

@tylerjw
Copy link
Contributor

tylerjw commented Feb 12, 2021

Component nodes enable using intra-process communication which can greatly reduce latency in control systems that run on the same machine by running the nodes in the same process. Here is the official documentation on it.

If possible it would be nice if the controller_manager was a component node. This would not prevent running it in a stand-alone process as it is now. This could either be done by maintaining both the current standalone node implementation and a component node version or by changing existing launch files to load the controller_manager component node into it's own component_container with no other nodes.

In theory, this should be a simple change (and I'm happy to help make it happen) as the basic change is removing the main in favor of an entry-point function (most of the boilerplate is provided by macros) and building the controller_manager as a shared library. In practice, this might be more complex depending on how the current implementation interacts with ROS2 executors and spinning (there is some nuance in adapting code that uses some of these features).

I'm happy to help make this change. I've been working on moveit_servo recently which uses component nodes. Here is one of the launch files to show how it is launched: https://github.com/ros-planning/moveit2/blob/main/moveit_ros/moveit_servo/launch/servo_teleop.launch.py. Here is the teleop demo node that translates messages from the joystick package (xbox controller) and moveit_servo: https://github.com/ros-planning/moveit2/blob/main/moveit_ros/moveit_servo/src/teleop_demo/joystick_servo_example.cpp. You can look at the CMakeLists.txt in that package to see examples of the cmake needed to build component nodes.

This is all assuming that ros2_control is basically a single node controller_manager that loads various controllers via plubinlib. If my understanding is wrong I apologize, please point me to any architecture diagrams or launch-file examples on how to use ros2_control as that'd make it easier for me to understand (and therefore help with adapting ros2_control to use component nodes).

@bmagyar
Copy link
Member

bmagyar commented Feb 15, 2021

I think this'd be a much desired improvement and would fit well with our Foxy version.
Indeed, controller_manager is a single node, however controllers are their own nodes and multithreading really depends on the executor. I think it is worth giving a try to the component approach, it is partially why we opted to use nodes in the first place.
I'd say let's see a PR whenever you have a bit of time.

What about the executor/spinning-related issues you mentioned? Are there any common pitfalls one should be aware of?

@Karsten1987
Copy link
Contributor

Just a few things I'd like to have clarified before digging too deep into coding.

  • The controller manager is already a shared library. I am not sure I follow your sentence with "building the controller_manager as a shared library". https://github.com/ros-controls/ros2_control/blob/master/controller_manager/CMakeLists.txt#L22-L24
  • While the component manager gives us a nice CLI interface to start and stop nodes as we go, it hides quite a bit of details which might become important in terms of RT execution/spinning. The component manager adds every node to a common executor and calls spin on it. What we - within ros2_controls - however need, is to have a strict multi-threaded execution model in which non-RT callbacks are handled differently from RT-callbacks. Not sure we can easily achieve this with components. The component manager might leverage the new callback groups in the executor, but I am not aware of it exposing any API for it: Adding callback groups in executor ros2/rclcpp#1218, see an example for it here: Demo for callback-group-level executor concept. ros2/examples#302
  • What I could see happening is that we refactor the current ros2_control_node into a component. That is, the logic in here might be refactored as a node rather than using a node, however even then I am struggling to see how we can put that easily as a component. Note that we had the custom thread-logic within the node initially designed as a timer call, as which we could have realized it as a component. However, we saw that the multithreaded executor could not deliver the appropriate update rate and thus we opted for a explicit update thread.

All that is to say, I am a big fan of leveraging intra-process as much as possible. I just want to highlight that we might have to deal with some more details here and anticipated. A while ago, I started to write down some thoughts about it: https://github.com/ros-controls/roadmap/blob/master/design_drafts/controller_components.md
That design doc might be obsolete or at least outdated now, but captures the overall idea I had in mind back then.

@tylerjw
Copy link
Contributor Author

tylerjw commented Feb 16, 2021

Thank you for the detailed replies. My takeaway is that we generally need the issues with the executors to settle down and some support for RT execution/spinning before this becomes a real possibility.

I'm happy to help where I can if there are things I can do. When I said build as a shared library I meant the main node that loads the controllers, I didn't realize the overlap between it and the component manager node. I understand now why the current component container is not adequate for the current needs.

I'll close this issue if you'd like as further progress seems blocked by requirements upstream of this ros2_control and we can revisit it later. Thank you again for sharing all the details you've collected about this.

@destogl
Copy link
Member

destogl commented Feb 16, 2021

@tylerjw thanks for the initiative!

I would not close the issue, but just put it on low-priority for now since we need some other things to solve, e.g., #277.

Still, I think there it is worth investigating this and make a proof-of-concept implementation. So if you like to test it, please go for it and just ask what we can support you. The ContrtollerManager starts a node, but the executor is provided by ros2_control_node.cpp.

Considering everything above, maybe a custom component container is needed.

For starters, would be sufficient to rewrite ros2_control_node, or do you have to change the interface of the ControllerManager?

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

No branches or pull requests

4 participants