Use blocking read in controller manager (backport #1760) - #1920
Use blocking read in controller manager (backport #1760)#1920mergify[bot] wants to merge 4 commits into
Conversation
* Setup CM to not sleep and use blocking read * Change default value for blocking_read to true * Updated documentation for blocking read functionality. (cherry picked from commit c747f3e) # Conflicts: # ur_robot_driver/doc/migration/makoa.rst # ur_robot_driver/urdf/ur.urdf.xacro
|
Cherry-pick of c747f3e has failed: To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6ea8400. Configure here.
| trajectory_port="$(arg trajectory_port)" | ||
| ur_type="$(arg ur_type)" | ||
| verify_robot_model="$(arg verify_robot_model)" | ||
| non_blocking_read="${not blocking_read}" |
There was a problem hiding this comment.
Broken xacro boolean negation
High Severity
non_blocking_read="${not blocking_read}" does not invert the launch/xacro flag. blocking_read is the string "true"/"false" from the arg, and in ${} Python eval every non-empty string is truthy, so not always yields false. The hardware interface therefore always gets a blocking read, ignoring blocking_read and overriding the previous macro default of non-blocking.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 6ea8400. Configure here.


This PR is mainly a testing PR for implementing a non-sleeping ros2_control node that follows the hardware's pace.
It requires a non-sleeping controller manager, e.g. the one from ros-controls/ros2_control#3213.
Basically, this tries to solve the issue that the control loop on the ROS machine and the one on the robot can have a phase shift and might be slightly different. To illustrate things, I added a simple controller that moves a joint on a fixed sine wave pattern with fixed sampling times in between. This is for illustration purposes and will not get merged.
With a non-blocking read with a controller_manager running at a fixed 500Hz we can observe that every couple of minutes, the two loops (controller_manager and robot) come to a point, where it can happen that the robot didn't receive a new command since the last control cycle.
I've used a preempt-rt patched kernel for that test. The upper curve shows the total amount of control cycles without a new command coming in to the robot. For the test I used a position interface.
We can see that control runs quite stable up to a point where the two loops get "out of sync". There, the robot doesn't get a new package for the next control loop. In our case we do linear extrapolation in that case. In the next cycle, we get a new command correcting this extrapolation. This is especially visible on the acceleration domain. After a while, this stabilizes again only to reoccur a few minutes later.
With the controller manager not sleeping and the hardware interface doing a blocking read, the same plot looks exactly like the left half of the plot above, but for a very long time (tested for ~1h). The number of missed packages stays at 0 given a direct network connection without any disturbances.
Note
Medium Risk
Changes real-time control-loop synchronization defaults and depends on ros2_control hardware synchronization support; misconfiguration between launch and URDF defaults could affect timing in custom setups.
Overview
Adds a
blocking_readlaunch/configuration path so the ROS control loop can wait on incoming robot state instead of running on a fixed timer, reducing phase drift between the driver and the robot controller.ur_control.launch.pydefaultsblocking_readtotrueand passeshardware_synchronization.expect_blocking_read_writetoros2_control_node.ur_rsp.launch.pyandur.urdf.xacroexpose the same flag (URDF/xacro defaultfalsefor multi-robot setups) and map it to hardwarenon_blocking_read.Docs cover the new startup argument, a blocking read usage section, and Makoa migration notes (launch defaults vs URDF default).
Reviewed by Cursor Bugbot for commit eee3cd4. Bugbot is set up for automated code reviews on this repo. Configure here.
This is an automatic backport of pull request #1760 done by [Mergify](https://mergify.com).
Note
Medium Risk
Changes real-time control-loop synchronization wiring and depends on ros2_control hardware synchronization; launch vs URDF defaults both use
false, so custom setups must passblocking_readexplicitly to enable blocking mode.Overview
Adds a
blocking_readstartup path so the ROS control loop can pace itself on incoming robot state instead of only on a fixed timer, reducing phase drift between the driver and the robot controller.ur_control.launch.pypasseshardware_synchronization.expect_blocking_read_writefromblocking_readintoros2_control_node, and also setsoverruns.print_warningsfromheadless_mode.ur_rsp.launch.pyandur.urdf.xacroforward the same flag into the robot description, mappingblocking_readto hardwarenon_blocking_read(inverted).Docs add the
blocking_readlaunch argument and a Blocking read section explaining when to enable it and that unreliable communication should keep it off.Reviewed by Cursor Bugbot for commit 6ea8400. Bugbot is set up for automated code reviews on this repo. Configure here.