-
Notifications
You must be signed in to change notification settings - Fork 310
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
[HW Interface] Change creation, exportation and storing of Command-/StateInterface + Support for variant #1240
Conversation
923866c
to
e70f436
Compare
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 general, this looks good. I just see two bigger things to fix:
- abstract deprecated approach from new approach on the component level and not in the ResourceManager, then we don't need additional
on_export_*
methods inside components, but just interfaces. - I didn't see a test with the custom implementation fo a component that exports custom, not in URDF defined, interface manually. This functionality we want to keep and, therefore, should be tested. There is already a test with the current approach for exactly that case.
hardware_interface/include/hardware_interface/actuator_interface.hpp
Outdated
Show resolved
Hide resolved
hardware_interface/include/hardware_interface/actuator_interface.hpp
Outdated
Show resolved
Hide resolved
hardware_interface/include/hardware_interface/actuator_interface.hpp
Outdated
Show resolved
Hide resolved
hardware_interface/include/hardware_interface/hardware_info.hpp
Outdated
Show resolved
Hide resolved
ros2_control_test_assets/include/ros2_control_test_assets/components_urdfs.hpp
Outdated
Show resolved
Hide resolved
ros2_control_test_assets/include/ros2_control_test_assets/components_urdfs.hpp
Show resolved
Hide 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.
Here are some changes I think are necessary. I will review the rest of the code later
hardware_interface/include/hardware_interface/system_interface.hpp
Outdated
Show resolved
Hide resolved
hardware_interface/include/hardware_interface/system_interface.hpp
Outdated
Show resolved
Hide resolved
hardware_interface/include/hardware_interface/system_interface.hpp
Outdated
Show resolved
Hide resolved
hardware_interface/src/actuator.cpp
Outdated
@@ -192,12 +192,22 @@ std::vector<StateInterface> Actuator::export_state_interfaces() | |||
return impl_->export_state_interfaces(); | |||
} | |||
|
|||
std::vector<std::shared_ptr<StateInterface>> Actuator::on_export_state_interfaces() |
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.
std::vector<std::shared_ptr<StateInterface>> Actuator::on_export_state_interfaces() | |
std::vector<StateInterfaceSharedPtr> Actuator::on_export_state_interfaces() |
Think i changed everything.
@saikishor I didn't use unordered_map everywhere as for the name to interface description we want to keep the order in my understanding. O(log(n)) overhead should be ok in this case since its most of the time used to iterate over it. If you don't agree i can change it but then all test_component_interface tests need to be changed as well since they rely on implicit ordering of the interfaces... |
9c5396c
to
720e11f
Compare
Usually, the unoredered_map's are faster to access O(1), which is better to use in such a layer. For that reason, I recommended using if you have a different opinion on this, we can discuss |
Yes you are completely right about the performance thats why i now use unordered_map for the states and commands which is accessed a lot e.g. for SensorInterface:
But for the
and in my understanding it would be beneficial to have the same ordering of the Interfaces in this map as they are defined in the URDF. |
Thanks for the great work! These changes make it a lot easier to finish the asynchronous stuff, as currently any syhncronization can be bypassed due to the user having direct access to the double ptr. I only have one question, which is why shared ptrs are used here instead of unique ptrs. It's possible I missed something, but to me it looks like there's clear ownership (the hardware interface owns the states and commands). For the sensor_state interfaces example it's also possible to use a presorted vector of pairs instead of a map if it's accessed often and every nanosecond counts (if not, then it shouldn't matter), since the vector has better cache locality and usually performs better for a small number of elements, unless you're also inserting into and deleting elements from the middle. |
Hello @mamueluth! is there a specific reason to have the same ordering of the interfaces as in the URDF?. Moreover, |
@saikishor Manuel is changing this, he was using this a lot in the tests. He will finish their adjustment on friday. |
Sure. If it's being used a few times std::map should be fine. 🙌🏽🙌🏽🙌🏽 |
Now unorderd_map is used everywhere and tests are adjusted accordingly. |
a3ad478
to
b5f9b4d
Compare
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've added some minor comments and some questions at different parts to discuss
hardware_interface/include/hardware_interface/actuator_interface.hpp
Outdated
Show resolved
Hide resolved
hardware_interface/include/hardware_interface/actuator_interface.hpp
Outdated
Show resolved
Hide resolved
hardware_interface/include/hardware_interface/sensor_interface.hpp
Outdated
Show resolved
Hide resolved
hardware_interface/include/hardware_interface/system_interface.hpp
Outdated
Show resolved
Hide 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 like the approach, considering the cleaner code as demonstrated with example_1 and the (as by now, theoretical) support of other datatypes. I don't comment on the code as this has been done extensively by others already.
What is missing for my approval is an update to the documentation:
- A migration guide here.
- Update the Writing a Hardware Component section
7c07d0c
to
8dec983
Compare
* components check for export of interfaces * change intefaces to allow custom export and test
* Fix rst syntax and some typos * Fix rst syntax and small typos * Fix clang issue
b6a7819
to
1cea7f2
Compare
This pull request is in conflict. Could you fix it @mamueluth? |
Concluded. Thank you to everyone who took part! |
All separation-PRs are merged 🎉 |
Important from Aug. 12th 2024
This PR is split in multiple parts which can be merged step by step.
get_state
andset_state
Functions toget/set_lifecylce_state
(variant support) #1683Notes
The concept fully backward compatible, has been tested and works. In the demos repository the example_1 has been adapted to showcase the changes and test the approach.
Needs ros-controls/ros2_controllers#1103 to be mereged.
Idea
The idea is that the creation of the
Command-/StateInterface
is no longer handled by the HW (user) but instead by the Framework. The user doesn't need to know about creation ofCommand-/StateInterface
and creation and management of local memory. Instead, theCommand-/StateInterface
are defined in the urdf as before and then everything is handled automatically by the Framework. The HW only needs to set/get states or set/get commands via functions provided by the component interface.Additionally, the Handles are now prepared to support more than double as datatype (std::variant is used) and could in future provide functionality to check if the Handles has been updated since now the value is stored directly in the handle instead a pointer.
The export_command/state_interfaces_2() function is going to be renamed to export_command/state_interfaces() as soon as the deprecated version is removed. This step is necessary as no return type polymorphism is possible and we later want abase function the user can override to export custom unlisted interfaces.
Description
With this PR the exportation and creation of the
Command-/StateInterface
is now handled by the Framework withon_export_state_interface()
andon_export_command_interface()
instead of the HW-component exporting them via theexport_state_interface()
orexport_command_interface()
.The
Command-/StateInterface
are created based on anInterfaceDescription
which encapsulates all the information about an interface and is directly parsed from the urdf. This includes data_type, default_values, min and max.Command-/StateInterface
are stored in the component interface (Actuator-, Sensor- or SystemInterface). The resource manager gets shared_ptr to theCommand-/StateInterface
.The
Command-/StateInterface
are now store the value directly. There is no raw pointer to memory in the HW passed to theCommand-/StateInterface
. A component can then set/get values from theCommand-/StateInterface
viaset_state
/get_state
andset_commad
/get_command
functions provided by the component interface. In addition, the value is now of typstd::variant
Overview
export_state_interface()
orexport_command_interface()
withon_export_state_interface()
andon_export_command_interface()
in component interface -> Framework handles creation ofCommand-/StateInterface
set_state
/get_state
andset_commad
/get_command
functions to component interface -> since memory is moved to Handle, HW needs to be able to still set states/receive commands.Command-/StateInterface
are stored in (Actuator-, Sensor- or SystemInterface) in map. -> This was done because the memory is moved to the Handles. HW still needs to be able to set states/receive commands. Otherwise we would need to import "hw-loans" or ptr to theCommand-/StateInterface
. Map was used to make it explicit rather then implicit. e.g. HW can now set state withset_state("joint1/position", 1.0)