Feature "async" - "slave" controller getting synchronized with a hardware#478
Feature "async" - "slave" controller getting synchronized with a hardware#478Nibanovic wants to merge 11 commits intoros-controls:masterfrom
Conversation
|
@Nibanovic, all pull requests must be targeted towards the |
|
This PR is stale because it has been open for 45 days with no activity. Please tag a maintainer for help on completing this PR, or close it if you think it has become obsolete. |
|
@Nibanovic can you give us an update on the status of this PR, is it ready for review? |
* now this hardware's update loop is synchronized by the blocking read() of a robot it is targeting
|
It is not ready for review, as it relies on #473 getting merged, along with any changes that might be required there. |
|
Ok, I was not sure if this replaces the other PR or is on top of it. |
merge with detached_callback
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## jazzy #478 +/- ##
==========================================
- Coverage 84.86% 82.91% -1.96%
==========================================
Files 19 19
Lines 1520 1557 +37
Branches 142 153 +11
==========================================
+ Hits 1290 1291 +1
- Misses 136 168 +32
- Partials 94 98 +4
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Co-authored-by: Felix Exner (fexner) <git@fexner.de>
…erface * Monitor pattern
abbd88c to
71eaaf0
Compare
|
This pull request is in conflict. Could you fix it @Nibanovic? |
* add docs for functions * const correctness * add std::optional<> to catch timeouts when waiting for signal, to starndardize usage * pre-commit
|
Closed with explanation here: ros-controls/ros2_control#2971 (comment) |
This PR extends the basic functionality of async slave hardware interface found in #473, and has a parallel
ros2_controlPR: ros-controls/ros2_control#2971The basic functionality ensures the async hardware interface with blocking
read()schedules the control cycle. The robot waits for a heartbeat signal (usuallyrecvon UDP socket) to continue towrite().This PR implements a solution for the issue described in the original PR discussion:
Setup
Main idea:
So, we have an async slave hardware interface and one or more async controllers. We expect:
read()read()to finishread()is complete, executeupdate()on async controllers, signal completionupdate_finishedsignals, and after all are done, proceeds withwrite()Fail states:
0.9 * read_write_periodtimeout and throw a warning if updates don't complete in timeon_error,on_shutdown,on_cleanupandon_deactivatede-register the controller so the hardware does not hand on dead controllersValidation
In this setup, we have
TestSystemComponent+joint_state_broadcasterrunning in regular sync mode, 500Hzkassowrobot with blockingread()250Hza.
joint_state_broadcaster_asyncslave tokassowhardwareb.
joint_state_broadcaster_async_2, also slave tokassowadditionally, I've added a
500ussleep after controllerupdate(), so we can more clearly see the effect a "long" update would have on this setupWe have 2 new introspection members:
sync_latency_us: Time between when last "I'm finished" signal was sent out and the component woke up as a consequence. For example:read_finishedsignal, after each of them wakes up, it notes the time from when the signal was emmitted to when the controller thread actually woke up to process itupdate_finished. This measures the time from last update signal which causes the hw interface to wake up forwrite(), and the time the hardware interface thread actually woke up towrite()sync_triggers: number of triggers forupdate()of the async slave controllers, as triggered by the hardware interface.controllers.yamlSync triggers
We see that the regular
joint_state_broadcasterat 500Hz has about 40k triggers, while the async ones, slave to hardware at 250hz, have about half as much, meaning they are woken up correctly (even though they are configured to be at 500Hz incontrollers.yaml!)Plots
In this graph we can see actual measurements for:
sync_latencyfor kassow and two async slave JSBskassow read execution_time: (purple), showing the portion of the 4000us loop spent waiting (as measured from the controller manager)deactivating one of the async
joint_state_broadcasterupdate()to completedeactivating both async
joint_state_broadcastersConclusion
I believe this PR showcases the basic functionality of using the Monitor pattern to "pin" async controllers to async hardware that is slave to an external clock of the robot, as propagated by its blocking
read().The
read()signals completion, andwrite()waits until all pinned controllers signal theirupdate()is complete.Open questions
read_execution_timefor async slave components have to be reviewed, as currently, we're measuring the "total blocking time" of the read/update (i.e. time the thread spends sleeping in read/update) from the perspective of the controller manager. From this we can deduce the time spent processing, but the measurement is not immediatelly obvious.