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

Add class for thread management of async hw interfaces #981

Merged
merged 14 commits into from
May 17, 2023

Conversation

VX792
Copy link
Contributor

@VX792 VX792 commented Apr 2, 2023

This PR is about making the async components fit into the framework structurally. I didn't have the opportunity to test the lifecycle changes extensively. I think it should be safe enough, since the only change is that we're destroying the map elements on shutdown, plus storing the components in a separate vector so we don't have to check for is_async everytime in the control loop.

The threads are created and started at the end of the init_resource_manager class, but I'll put it into the activate function to be consistent with the async controllers' solution. Also, now the resource manager owns all async components and their thread wrapper classes

@codecov-commenter
Copy link

codecov-commenter commented Apr 5, 2023

Codecov Report

Merging #981 (38b4ef6) into master (925f5f3) will decrease coverage by 2.14%.
The diff coverage is 35.26%.

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

@@            Coverage Diff             @@
##           master     #981      +/-   ##
==========================================
- Coverage   34.61%   32.48%   -2.14%     
==========================================
  Files          52       92      +40     
  Lines        2981     9647    +6666     
  Branches     1855     6484    +4629     
==========================================
+ Hits         1032     3134    +2102     
- Misses        310      766     +456     
- Partials     1639     5747    +4108     
Flag Coverage Δ
unittests 32.48% <35.26%> (-2.14%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
controller_manager/src/controller_manager.cpp 38.03% <ø> (-1.68%) ⬇️
controller_manager/src/ros2_control_node.cpp 0.00% <0.00%> (ø)
..._interface/include/hardware_interface/actuator.hpp 100.00% <ø> (ø)
...ce/include/hardware_interface/async_components.hpp 0.00% <0.00%> (ø)
...re_interface/include/hardware_interface/sensor.hpp 100.00% <ø> (ø)
...re_interface/include/hardware_interface/system.hpp 100.00% <ø> (ø)
hardware_interface/src/resource_manager.cpp 47.16% <ø> (-6.47%) ⬇️
hardware_interface/src/sensor.cpp 50.52% <ø> (ø)
hardware_interface/src/system.cpp 55.45% <ø> (ø)
...rface/test/mock_components/test_generic_system.cpp 9.02% <ø> (ø)
... and 68 more

... and 20 files with indirect coverage changes

Copy link
Member

@destogl destogl left a comment

Choose a reason for hiding this comment

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

Generally fine, few small comments to make simpler interfaces and proposal for the better code-reuse in the follow-up.

Comment on lines 38 to 40
std::is_same<hardware_interface::Actuator, HardwareT>::value ||
std::is_same<hardware_interface::System, HardwareT>::value ||
std::is_same<hardware_interface::Sensor, HardwareT>::value,
Copy link
Member

Choose a reason for hiding this comment

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

Does this means if someone extends a component type, they will not be able to use this async implementation?

Can we enable this to all types that have mentioned types as base class?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually that wouldn't work since all component type classes are final. Maybe I don't understand the use case here.

@bmagyar bmagyar added the iron label Apr 14, 2023
bmagyar
bmagyar previously approved these changes May 3, 2023
@bmagyar bmagyar merged commit 51e6aa9 into ros-controls:master May 17, 2023
1 check passed
Comment on lines +36 to +55
explicit AsyncComponentThread(
Actuator * component, unsigned int update_rate,
rclcpp::node_interfaces::NodeClockInterface::SharedPtr clock_interface)
: hardware_component_(component), cm_update_rate_(update_rate), clock_interface_(clock_interface)
{
}

explicit AsyncComponentThread(
System * component, unsigned int update_rate,
rclcpp::node_interfaces::NodeClockInterface::SharedPtr clock_interface)
: hardware_component_(component), cm_update_rate_(update_rate), clock_interface_(clock_interface)
{
}

explicit AsyncComponentThread(
Sensor * component, unsigned int update_rate,
rclcpp::node_interfaces::NodeClockInterface::SharedPtr clock_interface)
: hardware_component_(component), cm_update_rate_(update_rate), clock_interface_(clock_interface)
{
}
Copy link
Member

Choose a reason for hiding this comment

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

Can we template this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the constructor sadly no, but I think I can provide a templated setup function or something similar instead

@@ -46,7 +49,9 @@ class HARDWARE_INTERFACE_PUBLIC ResourceManager
{
public:
/// Default constructor for the Resource Manager.
ResourceManager();
ResourceManager(
unsigned int update_rate = 100,
Copy link
Member

Choose a reason for hiding this comment

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

Why default value? I would avoid it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because this is the default update rate of the ControllerManager too, and this way you don't have to provide one when creating a ResourceManager object. Also, this is passed to the ResourceStorage and only used for async components. But it might be misleading for the reader of the code though.

@@ -73,10 +76,16 @@ class ResourceStorage
static constexpr const char * system_interface_name = "hardware_interface::SystemInterface";

public:
ResourceStorage()
// TODO(VX792): Change this when HW ifs get their own update rate,
Copy link
Member

Choose a reason for hiding this comment

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

How do you want to do this? I don't understand. Resource Storage will easier know the update rate then component. Or do you mean that for async HW has this in parameters?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, the async HW itself. Since when HW ifs get their own update rate, then this could be parsed from the config file directly to the HardwareInfo struct of the component.

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

Successfully merging this pull request may close these issues.

4 participants