Skip to content

Fix spline point velocity and acceleration precision - #559

Open
s4lmon wants to merge 9 commits into
UniversalRobots:masterfrom
s4lmon:precision_vel_acc
Open

Fix spline point velocity and acceleration precision#559
s4lmon wants to merge 9 commits into
UniversalRobots:masterfrom
s4lmon:precision_vel_acc

Conversation

@s4lmon

@s4lmon s4lmon commented Aug 26, 2026

Copy link
Copy Markdown

The spline vel/acc are quantised at 1e-6 by MULT_JOINTSTATE, so near-zero accelerations reconstruct as jagged profiles. On our UR15 we notice many current compensation errors, that make the arm unusable with the ROS 2 driver.

We have this fix that is working, implementing the same strategy as #482.

We implement a finer dedicated multiplier (MULT_VEL_ACC = 1e8) and an explicit range guard (~21.47 rad/s(²)), analagous to max goal time check.

This is backwards compatible. We achieve this by only setting the range guard if the modern encoding is used. UrDriver detects whether the control script defines the new multiplier via {{VEL_ACC_REPLACE}}. If undefined, we fall back to legacy MULT_JOINTSTATE encoding with a warning.

Credit to Toni Divic for discovering this bug.


Note

Medium Risk
Changes real-time trajectory wire encoding and robot script decoding for splines; mismatch between library and custom scripts without {{VEL_ACC_REPLACE}} keeps legacy behavior but with reduced precision.

Overview
Spline trajectory points now encode per-sample velocities and accelerations with a dedicated MULT_VEL_ACC (1e8) instead of MULT_JOINTSTATE (1e6), so near-zero values survive the int32 wire format and acceleration profiles stay smooth. external_control.urscript decodes those fields with MULT_velacc from a new {{VEL_ACC_REPLACE}} placeholder; docs describe limits (~21.47 rad/s²) and rejection of out-of-range values.

TrajectoryPointInterface applies the finer multiplier only for SPLINE points (positions still use joint-state scaling), exposes setVelAccMultiplier, and validates spline vel/acc magnitude against the active multiplier. ScriptReader records which placeholders were substituted (isVariableRegistered) so UrDriver picks modern vs legacy encoding after loading the control script—warning and falling back to MULT_JOINTSTATE when the placeholder is missing. Tests cover near-zero roundtrip, range checks, legacy multiplier, and variable registry behavior.

Reviewed by Cursor Bugbot for commit 892841f. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread src/control/trajectory_point_interface.cpp
Comment thread doc/architecture/trajectory_point_interface.rst
@urrsk

urrsk commented Aug 27, 2026

Copy link
Copy Markdown
Member

Hi @s4lmon
Thanks for pointing this out and your proposal.

@urrsk
urrsk requested review from urfeex and a balanced review from Copilot August 27, 2026 08:33

Copilot AI 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.

Pull request overview

Improves spline velocity/acceleration wire precision to prevent quantization-induced controller faults.

Changes:

  • Adds MULT_VEL_ACC = 1e8 with range validation.
  • Updates URScript decoding and driver templating.
  • Expands protocol documentation and tests.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
include/ur_client_library/control/trajectory_point_interface.h Defines the multiplier and range limit.
src/control/trajectory_point_interface.cpp Validates and encodes spline velocity/acceleration.
src/ur/ur_driver.cpp Injects the multiplier into scripts.
resources/external_control.urscript Decodes spline fields using the new scale.
doc/architecture/trajectory_point_interface.rst Documents scaling and limits.
tests/test_trajectory_point_interface.cpp Tests precision, encoding, and range validation.
tests/test_script_reader.cpp Updates script-template test data.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/ur/ur_driver.cpp
Comment on lines +528 to +533
EXPECT_EQ(send_vel[0], ((double)received_velocities[0]) / traj_point_interface_->MULT_VEL_ACC);
EXPECT_EQ(send_vel[1], ((double)received_velocities[1]) / traj_point_interface_->MULT_VEL_ACC);
EXPECT_EQ(send_vel[2], ((double)received_velocities[2]) / traj_point_interface_->MULT_VEL_ACC);
EXPECT_EQ(send_vel[3], ((double)received_velocities[3]) / traj_point_interface_->MULT_VEL_ACC);
EXPECT_EQ(send_vel[4], ((double)received_velocities[4]) / traj_point_interface_->MULT_VEL_ACC);
EXPECT_EQ(send_vel[5], ((double)received_velocities[5]) / traj_point_interface_->MULT_VEL_ACC);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed.

@urrsk urrsk added the bugfix label Aug 27, 2026
@urrsk
urrsk requested a balanced review from Copilot August 31, 2026 11:23
@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.87879% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.20%. Comparing base (dde4869) to head (892841f).

Files with missing lines Patch % Lines
src/ur/ur_driver.cpp 40.00% 2 Missing and 1 partial ⚠️
src/control/trajectory_point_interface.cpp 95.45% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #559      +/-   ##
==========================================
- Coverage   80.51%   80.20%   -0.32%     
==========================================
  Files         116      116              
  Lines        6976     6995      +19     
  Branches     3083     3095      +12     
==========================================
- Hits         5617     5610       -7     
- Misses        980     1002      +22     
- Partials      379      383       +4     
Flag Coverage Δ
check_version_ur10-3.15.8 11.60% <0.00%> (-1.47%) ⬇️
check_version_ur10e-10.11.0 11.47% <0.00%> (-0.09%) ⬇️
check_version_ur10e-5.15.2 11.47% <0.00%> (-0.66%) ⬇️
check_version_ur12e-10.12.1 11.47% <0.00%> (-0.09%) ⬇️
check_version_ur12e-5.25.1 12.22% <0.00%> (+0.25%) ⬆️
check_version_ur15-10.12.1 11.47% <0.00%> (-0.13%) ⬇️
check_version_ur15-5.25.1 11.47% <0.00%> (-0.28%) ⬇️
check_version_ur16e-10.12.1 11.47% <0.00%> (-0.13%) ⬇️
check_version_ur16e-5.25.1 11.47% <0.00%> (-0.56%) ⬇️
check_version_ur18-10.12.1 11.47% <0.00%> (-0.09%) ⬇️
check_version_ur18-5.25.1 11.47% <0.00%> (-0.56%) ⬇️
check_version_ur20-10.12.1 11.47% <0.00%> (-0.09%) ⬇️
check_version_ur20-5.25.1 11.47% <0.00%> (-0.28%) ⬇️
check_version_ur3-3.14.3 11.51% <0.00%> (-1.91%) ⬇️
check_version_ur30-10.12.1 11.47% <0.00%> (-0.13%) ⬇️
check_version_ur30-5.25.1 11.47% <0.00%> (-0.28%) ⬇️
check_version_ur3e-10.11.0 11.51% <0.00%> (-0.04%) ⬇️
check_version_ur3e-5.9.4 11.47% <0.00%> (-0.28%) ⬇️
check_version_ur5-3.15.8 11.66% <0.00%> (-1.65%) ⬇️
check_version_ur5e-10.11.0 11.47% <0.00%> (-0.13%) ⬇️
check_version_ur5e-5.12.8 11.47% <0.00%> (-0.33%) ⬇️
check_version_ur7e-10.11.0 11.47% <0.00%> (-0.09%) ⬇️
check_version_ur7e-5.22.2 11.47% <0.00%> (-0.71%) ⬇️
check_version_ur8long-10.12.1 11.47% <0.00%> (-0.13%) ⬇️
check_version_ur8long-5.25.1 11.66% <0.00%> (-0.13%) ⬇️
python_scripts 75.90% <ø> (ø)
start_ursim 83.93% <ø> (-2.67%) ⬇️
ur20-latest 75.51% <87.87%> (-0.25%) ⬇️
ur5-3.14.3 75.42% <87.87%> (-0.13%) ⬇️
ur5e-10.11.0 70.06% <87.87%> (-0.26%) ⬇️
ur5e-10.12.0 71.18% <87.87%> (-0.19%) ⬇️
ur5e-10.7.0 69.39% <87.87%> (-0.31%) ⬇️
ur5e-5.9.4 75.81% <87.87%> (-0.13%) ⬇️
ur7e-10.13.0 71.86% <87.87%> (-0.21%) ⬇️

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

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

Copilot AI 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.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comment thread src/control/script_reader.cpp
Comment on lines +345 to +348
void TrajectoryPointInterface::setVelAccMultiplier(const int32_t multiplier)
{
mult_vel_acc_ = multiplier;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would agree with that.

@urfeex urfeex left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you please add a test for a legacy script that it falls back to using MULT_JOINTSTATE?

Comment thread doc/architecture/trajectory_point_interface.rst
Comment thread src/control/script_reader.cpp
(spline_primitive->target_accelerations.has_value() &&
!within_range(spline_primitive->target_accelerations.value())))
{
URCL_LOG_ERROR("Spline point velocity or acceleration out of range. Maximum allowed magnitude is %f.",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Printing the actual value might be helpful to narrow it down.

Comment thread src/control/trajectory_point_interface.cpp
Comment on lines +345 to +348
void TrajectoryPointInterface::setVelAccMultiplier(const int32_t multiplier)
{
mult_vel_acc_ = multiplier;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would agree with that.

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.

4 participants