Skip to content

Enhance JointSaturationLimiter with Jerk limits - #3417

Open
sachinkum0009 wants to merge 30 commits into
ros-controls:masterfrom
sachinkum0009:feat/jtc-jerk-limits
Open

Enhance JointSaturationLimiter with Jerk limits #3417
sachinkum0009 wants to merge 30 commits into
ros-controls:masterfrom
sachinkum0009:feat/jtc-jerk-limits

Conversation

@sachinkum0009

@sachinkum0009 sachinkum0009 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Description

This PR added the Jerk Limits to JointSaturationLimiter.

Summary of changes

  • Refactor code to functions for readability
  • Pre-allocate vector to avoid malloc when calling enforce fn
  • Implemented Jerk Limiter to check limitation and backward recalculate safe acc, vel and pos
  • Tests added for pos only, vel only, acc only, pos + vel, vel + acc, pos + vel + acc.
  • Warn users when implicit vel exceed max velocity and then reclamp velocity to max velocity
  • Post Jerk limit recalculate acc, vel, pos

Fixes # (ros-controls/ros2_controllers#2434)

Is this user-facing behavior change?

Did you use Generative AI?

Used Opencode to understand the code and implement tests.

Additional Information

TODOs

To send us a pull request, please:

  • Fork the repository.
  • Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
  • Ensure local tests pass. (colcon test and pre-commit run (requires you to install pre-commit by pip3 install pre-commit)
  • Commit to your fork using clear commit messages.
  • Send a pull request, answering any default questions in the pull request interface.
  • Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.

… expected states

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
… to JointSaturationLimiter

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
…re by reorganizing conditional checks for desired position, velocity, and acceleration

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
… by using boolean flags for position, velocity, acceleration, and deceleration limits, and streamline the clamp_joint_limits method.

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
…position_limit methods with detailed step-by-step explanations

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
…state tracking

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
…onLimiter tests

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
@codecov

codecov Bot commented Jun 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.23171% with 55 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.47%. Comparing base (4bcce09) to head (b2c4751).

Files with missing lines Patch % Lines
joint_limits/src/joint_saturation_limiter.cpp 78.03% 35 Missing and 12 partials ⚠️
...oint_limits/test/test_joint_saturation_limiter.cpp 92.23% 0 Missing and 8 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3417      +/-   ##
==========================================
- Coverage   89.51%   89.47%   -0.05%     
==========================================
  Files         164      164              
  Lines       21265    21479     +214     
  Branches     1658     1687      +29     
==========================================
+ Hits        19036    19218     +182     
- Misses       1530     1555      +25     
- Partials      699      706       +7     
Flag Coverage Δ
unittests 89.47% <83.23%> (-0.05%) ⬇️

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

Files with missing lines Coverage Δ
...nt_limits/include/joint_limits/data_structures.hpp 80.55% <ø> (ø)
.../include/joint_limits/joint_saturation_limiter.hpp 100.00% <100.00%> (ø)
...oint_limits/test/test_joint_saturation_limiter.cpp 91.49% <92.23%> (+0.25%) ⬆️
joint_limits/src/joint_saturation_limiter.cpp 81.09% <78.03%> (-4.29%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…reference in JointSaturationLimiter methods

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
…ter acceleration limiting in JointSaturationLimiter

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
@mergify

mergify Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

This pull request is in conflict. Could you fix it @sachinkum0009?

Added a re-check mechanism after calculating desired acceleration based
on jerk-limited values. This ensures that velocity and acceleration
do not violate joint limits due to the influence of jerk-limited
acceleration or deceleration calculations.

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
Adjusts the logic for calculating safe target velocities when a
joint limit is hit to ensure smoother deceleration towards the limit.
This replaces the placeholder calculation with physics-based limits
considering deceleration and time constraints.

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
Removes detailed, multi-step comments from the documentation of the
`clamp_joint_limits` and `handle_braking_near_position_limit` methods.
These functions' internal workings are complex enough that the previous
verbose description became overly long and hard to parse.

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
Updates the joint saturation limiter to refactor redundant and complex
code blocks related to re-clamping velocity after acceleration limiting.

Introduces a local lambda, `post_velocity_check_and_clamp`, to
centralize the logic for clamping velocity, recalculating derived values
(acceleration and position), and ensuring consistency when multiple
limits are hit sequentially.

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
Updates `clamp_joint_limits` in both header and source files to
accept and use the availability of current joint velocities for
more accurate trajectory limiting. The warning message when
acceleration limits are configured but current velocity is absent
is also updated accordingly.

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>
@sachinkum0009

Copy link
Copy Markdown
Contributor Author

Hi @saikishor @christophfroehlich

Sorry to ping you.
I wanted to request if you can review this PR and give your suggestions. This PR integrates the jerk limit checks to JointSaturationLimiter and backward calculate the acceleration, velocity and position.
I have refactored the code a little bit and updated the test for pos, vel, acc, pos+vel, vel+acc, pos+vel+acc limits crossed.

I have self reviewed it couple of times. I know that you are busy, it would really help me learn and contribute to ros2 control and become a maintainer in future.
Thanks

Ensure position limits are only applied when configured and re-clamp
velocity limits after acceleration and jerk computations to maintain
validity.

Signed-off-by: Sachin Kumar <sachinkum123567@gmail.com>

@destogl destogl 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.

As general comments.

Let's move the following in a separate PR:

  • Refactor code to functions for readability
  • Pre-allocate vector to avoid malloc when calling enforce fn

Also separate:

  • Warn users when implicit vel exceed max velocity and then reclamp velocity to max velocity

And then rebase this PR on those changes it will make them more readable and simpler to merge.

I find this maybe too simple implementation. Are you sure there are no more cases when we have jerk limits. Can you make the tests of all possible cases in robot trajectory where jerk limits will be important?

prev_command_ = current_joint_states;
const size_t num_joints = this->number_of_joints_;

desired_pos_.assign(num_joints, 0.0);

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.

This is a very good catch! I would like to see this in a separate PR, as this seems to be merged very fast.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Separate PR created for this.

std::mutex mutex_;

private:
// Cached vectors to eliminate dynamic memory allocation (malloc) in the real-time execution loop

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.

@saikishor is this true that we had the memory allocations previously? Can this be?

*/
void clamp_joint_limits(
const bool has_desired_position, const bool has_desired_velocity,
const bool has_desired_acceleration, const bool has_current_velocity,

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.

This seems to be part of the restructuring. I would like to see this in a separate PR. This is hard to figure out what is important and why.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Separate PR created for restructuring.

* Handles the braking near position limit
*/
void handle_braking_near_position_limit(
const std::vector<double> & current_joint_velocities, double dt_seconds,

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.

why only "position" and "velocity" input?

const std::vector<double> & current_joint_velocities,
bool & braking_near_position_limit_triggered, const double dt_seconds);

template <>

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.

this is template for what exactly?

}

// Re-clamp desired velocity after acceleration/jerk may have recomputed it
if (

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.

this will be done always, why do we then have it above?

{
clamp_vel_limit();
}
// Re-clamp desired position after acceleration/jerk may have recomputed it

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.

Also this one.

double stopping_distance =
std::fabs((-desired_vel[index] * desired_vel[index]) / (2 * stopping_deccel));
std::fabs((-desired_vel_[index] * desired_vel_[index]) / (2 * stopping_deccel));
// compute stopping duration at stopping_deccel

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.

OK, but what happens with jerk in that case?

// this setup requires 0.15 distance to stop, and 0.2 seconds (so 4 cycles at 0.05)
std::vector expected_ret = {true, true, true, false};
for (auto i = 0u; i < 4; ++i)
// cycles 0-3 apply limits (braking + jerk), cycles 4-5 settle at stop

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 what to see a new test with jerk. Current test should stay the same, as we should test also when no jerk limits are defined.


rclcpp::Duration period(0, 50000000);

current_joint_states_.velocities[0] = 1.0;

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.

give here more explanation on the numbers in a comment of the test. For all tests.

@github-project-automation github-project-automation Bot moved this from Needs review to WIP in Review triage Jul 8, 2026
@sachinkum0009

Copy link
Copy Markdown
Contributor Author

@sachinkum0009
sachinkum0009 force-pushed the feat/jtc-jerk-limits branch from 6a56d11 to b6442a6 Compare July 17, 2026 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: WIP

Development

Successfully merging this pull request may close these issues.

3 participants