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
Add controller manager services #139
Add controller manager services #139
Conversation
// TODO(v-lopez) this should only be done if controller_manager is configured. | ||
// Probably the whole load_controller part should fail if the controller_manager | ||
// is not configured, should it implement a LifecycleNodeInterface | ||
controller->get_lifecycle_node()->configure(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Karsten1987 Could I have your opinion regarding this? I do not fully understand why some classes inherit from Nodes
, others from LifeCycleNode
and others from LifeCycleNodeInterface
, but have a member LifeCycleNode
.
And to the best of my Google skills there's not much written about when to use what.
Codecov Report
@@ Coverage Diff @@
## master #139 +/- ##
==========================================
- Coverage 36.61% 33.97% -2.65%
==========================================
Files 42 44 +2
Lines 1726 2337 +611
Branches 1080 1524 +444
==========================================
+ Hits 632 794 +162
- Misses 100 174 +74
- Partials 994 1369 +375
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
945c3aa
to
064bdc3
Compare
5198371
to
ee4a1d5
Compare
for (auto loaded_controller : loaded_controllers_) { | ||
auto controller_state = loaded_controller->get_lifecycle_node()->activate(); | ||
for (auto loaded_controller : controllers_lists_[current_controllers_list_]) { | ||
auto controller_state = loaded_controller.c->get_lifecycle_node()->activate(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this code should be completely removed now.
When we activate the controller manager, we should not activate all loaded controllers, we should only activate controllers on the switch_controller
function.
But for deactivate, I believe we need to deactivate them.
This creates a unintuitive situation, you deactivate the controller manager, it deactivates the controllers, but you activate it, and it doesn't activate the controllers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
think of deactivating the controller manager as a last resort, something that an emergency stop would call for instance. I agree this part should be gone
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about activating previously active controllers?
Like you said, in the event of an emergency (which happen quite often with research robots) it's going to be a pain in the ass to reactivate controllers manually, it's something that is not needed in ROS1 right now.
Another alternative is not to deactivate the controllers themselves, just stop updating them because the controller manager is disabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this one is strongly about safety. A velocity controller will keep sending the same velocity (arm of robot base!) without an update, robot arms may be restarted with the old command but from a new joint position (if an arm doesn't know to hold position without sending command actively) and may overreact to reach the new target. I'd err on the side of caution and don't mind people writing one-liners to call the switch functionality every time they had to shut down controls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All right, removing the activation of controllers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be continued...
const std::string & controller_name) | ||
{ | ||
// get reference to controller list | ||
int free_controllers_list = (current_controllers_list_ + 1) % 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain the logic here a bit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be the same logic that was used on ROS1.
The idea is that the update loop is using the list A, so you do all your modifications on the list B.
At the end of the function, you change current_controllers_list_
so the index points to list B, on the next loop the B list will be used, and A is available to be cleared.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I think this could definitely do with more documentation. the logic here is similar to how some STL containers do memory management, moving things to the end of their allocated array and freeing stuff after the end index.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'll add it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be the same logic that was used on ROS1.
OK, this could be. I still do not understand this free_controllers_list
variable. I will contact you directly, maybe you could help me to grap it.
You can mark this as resolved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have refactored the whole thing here: 4c6a609
Hopefully it makes the original code easier to understand.
26ef14d
to
47b170f
Compare
controller_manager/include/controller_manager/controller_manager.hpp
Outdated
Show resolved
Hide resolved
controller_manager/include/controller_manager/controller_manager.hpp
Outdated
Show resolved
Hide resolved
@@ -0,0 +1,45 @@ | |||
// Copyright 2017 Open Source Robotics Foundation, Inc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems this license header is from the PoC ros2_control, if this is copied from ros1 I think you can re-own it with PAL under the new license. If you want to keep the ros1 license that'd be tricky mixing licenses
const std::string & controller_name) | ||
{ | ||
// get reference to controller list | ||
int free_controllers_list = (current_controllers_list_ + 1) % 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I think this could definitely do with more documentation. the logic here is similar to how some STL containers do memory management, moving things to the end of their allocated array and freeing stuff after the end index.
for (auto loaded_controller : loaded_controllers_) { | ||
auto controller_state = loaded_controller->get_lifecycle_node()->activate(); | ||
for (auto loaded_controller : controllers_lists_[current_controllers_list_]) { | ||
auto controller_state = loaded_controller.c->get_lifecycle_node()->activate(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
think of deactivating the controller manager as a last resort, something that an emergency stop would call for instance. I agree this part should be gone
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second part
controller_manager/include/controller_manager/controller_loader_interface.hpp
Outdated
Show resolved
Hide resolved
controller_manager/include/controller_manager/controller_loader_pluginlib.hpp
Outdated
Show resolved
Hide resolved
const std::string & controller_name) | ||
{ | ||
// get reference to controller list | ||
int free_controllers_list = (current_controllers_list_ + 1) % 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be the same logic that was used on ROS1.
OK, this could be. I still do not understand this free_controllers_list
variable. I will contact you directly, maybe you could help me to grap it.
You can mark this as resolved.
Co-authored-by: Denis Štogl <destogl@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few small comments.
It looks very good! Thank you for the great work!
controller_manager/include/controller_manager/controller_manager.hpp
Outdated
Show resolved
Hide resolved
controller_manager/include/controller_manager/controller_manager.hpp
Outdated
Show resolved
Hide resolved
controller_manager/include/controller_manager/controller_manager.hpp
Outdated
Show resolved
Hide resolved
|
||
int ControllerManager::RTControllerListWrapper::get_other_list(int index) const | ||
{ | ||
return (index + 1) % 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhhh, I got it now :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha no problem, I'm adding a short description for clarity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think this is overkill to simply flip-flop an index between 0 and 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well I believe it's better than having this random operation duplicated in a few places in the code, the function allows for giving the operation a name and some documentation. I could make it a free function so it's not even a private member of the class.
hardware_interface/include/hardware_interface/controller_info.hpp
Outdated
Show resolved
Hide resolved
Co-authored-by: Bence Magyar <bence.magyar.robotics@gmail.com> Co-authored-by: Denis Štogl <destogl@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There're quite some comments inline. I am requesting mainly changes for some of the ported ROS1 code which I think should be handled with a few calls to STL. Additionally, I would rethink the double buffered list to consider really only flip-flopping between an active and inactive list.
controller_manager/include/controller_manager/controller_loader_interface.hpp
Outdated
Show resolved
Hide resolved
controller_manager/include/controller_manager/controller_manager.hpp
Outdated
Show resolved
Hide resolved
controller_manager/include/controller_manager/controller_manager.hpp
Outdated
Show resolved
Hide resolved
Co-authored-by: Karsten Knese <Karsten1987@users.noreply.github.com>
controller_manager/include/controller_manager/controller_manager.hpp
Outdated
Show resolved
Hide resolved
controller_manager/include/controller_manager/controller_manager.hpp
Outdated
Show resolved
Hide resolved
controller_manager/include/controller_manager/controller_manager.hpp
Outdated
Show resolved
Hide resolved
return loaded_controllers_.back(); | ||
// Force a reload on all the PluginLoaders (internally, this recreates the plugin loaders) | ||
for (const auto & controller_loader : loaders_) { | ||
controller_loader->reload(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't the controller be re-configured
as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the old version it wasn't: https://github.com/ros-controls/ros_control/blob/noetic-devel/controller_manager/src/controller_manager.cpp#L663
We could discuss adding it, after reloading there are no loaded controllers. We may want to load (create + configure) them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd err on the side of caution here, we don't know what we are loading and whether the newly loaded ones will be compatible with each other.
get_controller_by_name was confusing as to in which list it might look into, and was returning a non const pointer to a controller that might be being used in the RT thread
Co-authored-by: Karsten Knese <Karsten1987@users.noreply.github.com>
As discussed in ros-controls#139 (review) Also removed a test that was redundant after these changes
fdb44d8
to
ae10741
Compare
e53f5cb
to
528d1c9
Compare
Thanks for following up on the remaining discussions. I'm merging this now, @Karsten1987 @destogl please refer to the issues to continue some of the design discussions. |
This PR introduced some regressions on clang.
|
Added services for:
To do that, besides adding all the respective code I've had to perform the following modifications to the existing code:
update()
only the active controllers, not all loaded controllers.The whole resource management implementation is not done yet, since that part is undergoing changes.
It is usually
#ifdef
'ed out with the tagTODO_IMPLEMENT_RESOURCE_CHECKING