@@ -307,25 +307,34 @@ void JointSaturationLimiter<trajectory_msgs::msg::JointTrajectoryPoint>::clamp_j
307307 // else we cannot compute acc, so not limiting it
308308 }
309309
310- // Re-clamp velocity after acceleration limiting (can overshoot max_velocity
311- // when max_acceleration * dt > max_velocity, since acceleration limiting
312- // recomputes velocity from clamped acceleration without re-checking velocity)
313- if (joint_limits_[index].has_velocity_limits )
310+ // Re-clamp velocity if it exceeds the max velocity
311+ auto post_velocity_check_and_clamp = [&](size_t joint_index) -> bool
314312 {
315- if (std::fabs (desired_vel_[index]) > joint_limits_[index].max_velocity )
316- {
317- desired_vel_[index] = std::copysign (joint_limits_[index].max_velocity , desired_vel_[index]);
318- vel_limit_hit_[index] = true ;
319- limits_enforced = true ;
313+ // Clamp velocity to max allowed
314+ desired_vel_[joint_index] =
315+ std::copysign (joint_limits_[joint_index].max_velocity , desired_vel_[joint_index]);
316+ vel_limit_hit_[joint_index] = true ;
320317
321- desired_acc_[index] = (desired_vel_[index] - current_joint_velocities[index]) / dt_seconds;
318+ // Recalculate acceleration based on clamped velocity
319+ desired_acc_[joint_index] =
320+ (desired_vel_[joint_index] - current_joint_velocities[joint_index]) / dt_seconds;
322321
323- if (has_desired_position)
324- {
325- desired_pos_[index] =
326- current_joint_states. positions [index] + desired_vel_[index] * dt_seconds;
327- }
322+ // Update position if needed
323+ if (has_desired_position)
324+ {
325+ desired_pos_[joint_index] =
326+ current_joint_states. positions [joint_index] + desired_vel_[joint_index] * dt_seconds;
328327 }
328+
329+ return true ; // Indicates a limit was enforced
330+ };
331+
332+ // Check if joint velocity exceeds max velocity
333+ if (
334+ joint_limits_[index].has_velocity_limits &&
335+ std::fabs (desired_vel_[index]) > joint_limits_[index].max_velocity )
336+ {
337+ limits_enforced = post_velocity_check_and_clamp (index);
329338 }
330339
331340 // Limit jerk
@@ -364,30 +373,12 @@ void JointSaturationLimiter<trajectory_msgs::msg::JointTrajectoryPoint>::clamp_j
364373 (0.5 * desired_acc_[index] * dt_seconds * dt_seconds);
365374 }
366375
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 )
376+ // Re-check velocity exceeds max velocity and clamp it
377+ if (
378+ joint_limits_[index].has_velocity_limits &&
379+ std::fabs (desired_vel_[index]) > joint_limits_[index].max_velocity )
374380 {
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- }
381+ limits_enforced = post_velocity_check_and_clamp (index);
391382 }
392383
393384 // Re-check acceleration and deceleration
0 commit comments