Skip to content

Use blocking read in controller manager (backport #1760) - #1920

Open
mergify[bot] wants to merge 4 commits into
jazzyfrom
mergify/bp/jazzy/pr-1760
Open

Use blocking read in controller manager (backport #1760)#1920
mergify[bot] wants to merge 4 commits into
jazzyfrom
mergify/bp/jazzy/pr-1760

Conversation

@mergify

@mergify mergify Bot commented Aug 3, 2026

Copy link
Copy Markdown

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.

preempt_rt_non_blocking_read_fixed_dt

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_read launch/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.py defaults blocking_read to true and passes hardware_synchronization.expect_blocking_read_write to ros2_control_node. ur_rsp.launch.py and ur.urdf.xacro expose the same flag (URDF/xacro default false for multi-robot setups) and map it to hardware non_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 pass blocking_read explicitly to enable blocking mode.

Overview
Adds a blocking_read startup 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.py passes hardware_synchronization.expect_blocking_read_write from blocking_read into ros2_control_node, and also sets overruns.print_warnings from headless_mode. ur_rsp.launch.py and ur.urdf.xacro forward the same flag into the robot description, mapping blocking_read to hardware non_blocking_read (inverted).

Docs add the blocking_read launch 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.

* 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
@mergify

mergify Bot commented Aug 3, 2026

Copy link
Copy Markdown
Author

Cherry-pick of c747f3e has failed:

On branch mergify/bp/jazzy/pr-1760
Your branch is up to date with 'origin/jazzy'.

You are currently cherry-picking commit c747f3e.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --skip" to skip this patch)
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Changes to be committed:
	modified:   ur_robot_driver/doc/usage/startup.rst
	modified:   ur_robot_driver/launch/ur_control.launch.py
	modified:   ur_robot_driver/launch/ur_rsp.launch.py

Unmerged paths:
  (use "git add/rm <file>..." as appropriate to mark resolution)
	deleted by us:   ur_robot_driver/doc/migration/makoa.rst
	both modified:   ur_robot_driver/urdf/ur.urdf.xacro

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

Comment thread ur_robot_driver/urdf/ur.urdf.xacro Outdated
@urfeex urfeex removed the conflicts label Aug 3, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ 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}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6ea8400. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant