Skip to content

Commit cc204f6

Browse files
committed
Refine joint saturation limiting with post-jerk checks
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>
1 parent 9653d5b commit cc204f6

1 file changed

Lines changed: 87 additions & 0 deletions

File tree

joint_limits/src/joint_saturation_limiter.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,93 @@ void JointSaturationLimiter<trajectory_msgs::msg::JointTrajectoryPoint>::clamp_j
363363
(current_joint_velocities[index] * dt_seconds) +
364364
(0.5 * desired_acc_[index] * dt_seconds * dt_seconds);
365365
}
366+
367+
// Post-jerk re-check: jerk-limited acceleration may cause velocity or
368+
// acceleration/deceleration to exceed their limits because jerk pulls
369+
// acceleration toward current_acc, which may itself exceed limits or
370+
// cause velocity to overshoot.
371+
372+
// Re-check velocity
373+
if (joint_limits_[index].has_velocity_limits)
374+
{
375+
if (std::fabs(desired_vel_[index]) > joint_limits_[index].max_velocity)
376+
{
377+
desired_vel_[index] =
378+
std::copysign(joint_limits_[index].max_velocity, desired_vel_[index]);
379+
vel_limit_hit_[index] = true;
380+
limits_enforced = true;
381+
382+
desired_acc_[index] =
383+
(desired_vel_[index] - current_joint_velocities[index]) / dt_seconds;
384+
385+
if (has_desired_position)
386+
{
387+
desired_pos_[index] =
388+
current_joint_states.positions[index] + desired_vel_[index] * dt_seconds;
389+
}
390+
}
391+
}
392+
393+
// Re-check acceleration and deceleration
394+
if (
395+
joint_limits_[index].has_acceleration_limits ||
396+
joint_limits_[index].has_deceleration_limits)
397+
{
398+
if (
399+
std::fabs(desired_acc_[index]) <= VALUE_CONSIDERED_ZERO ||
400+
std::isnan(desired_acc_[index]))
401+
{
402+
desired_acc_[index] =
403+
(desired_vel_[index] - current_joint_velocities[index]) / dt_seconds;
404+
}
405+
406+
bool deceleration_limit_applied = false;
407+
bool limit_applied = false;
408+
auto apply_recheck_limit =
409+
[&](const double limit, std::vector<double> & vec, std::vector<bool> & hit_flag) -> bool
410+
{
411+
if (std::fabs(vec[index]) > limit)
412+
{
413+
vec[index] = std::copysign(limit, vec[index]);
414+
hit_flag[index] = true;
415+
limits_enforced = true;
416+
return true;
417+
}
418+
return false;
419+
};
420+
421+
// Check deceleration (velocity changing toward zero)
422+
if (
423+
(desired_acc_[index] < 0 && current_joint_velocities[index] > 0) ||
424+
(desired_acc_[index] > 0 && current_joint_velocities[index] < 0))
425+
{
426+
if (joint_limits_[index].has_deceleration_limits)
427+
{
428+
limit_applied = apply_recheck_limit(
429+
joint_limits_[index].max_deceleration, desired_acc_, dec_limit_hit_);
430+
deceleration_limit_applied = true;
431+
}
432+
}
433+
434+
// Check acceleration (fallback to acceleration if no decel check applied)
435+
if (joint_limits_[index].has_acceleration_limits && !deceleration_limit_applied)
436+
{
437+
limit_applied = apply_recheck_limit(
438+
joint_limits_[index].max_acceleration, desired_acc_, acc_limit_hit_);
439+
}
440+
441+
if (limit_applied)
442+
{
443+
desired_vel_[index] =
444+
current_joint_velocities[index] + desired_acc_[index] * dt_seconds;
445+
if (has_desired_position)
446+
{
447+
desired_pos_[index] = current_joint_states.positions[index] +
448+
current_joint_velocities[index] * dt_seconds +
449+
0.5 * desired_acc_[index] * dt_seconds * dt_seconds;
450+
}
451+
}
452+
}
366453
}
367454
}
368455

0 commit comments

Comments
 (0)