Skip to content

Commit 4acaeb6

Browse files
committed
fix STOP/EXACT spike
1 parent 44a99b0 commit 4acaeb6

1 file changed

Lines changed: 32 additions & 2 deletions

File tree

src/emc/motion_planning/motion_planning_9d.cc

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,9 +1174,24 @@ static double computeChainExitCap(TP_STRUCT *tp, TC_STRUCT *active_tc,
11741174
double seg_jrk = seg->maxjerk > 0 ? seg->maxjerk : default_jerk;
11751175
double seg_fv = readFinalVelCapped(seg);
11761176
double seg_exit = fmin(seg_fv * seg_feed, seg_max_vel);
1177-
1177+
11781178
if (seg->kink_vel > 0) seg_exit = fmin(seg_exit, seg->kink_vel);
11791179

1180+
// When the next segment is STOP/EXACT (v_f≈0), the backward pass
1181+
// uses trapezoidal formula sqrt(2*a*d) which ignores jerk limits.
1182+
// This inflates final_vel beyond what Ruckig can achieve. Cap to
1183+
// profile exit so the chain propagates physically consistent limits.
1184+
TC_STRUCT *next_in_chain = tcqItem_user(&tp->queue, i + 1);
1185+
if (next_in_chain &&
1186+
(next_in_chain->term_cond == TC_TERM_COND_STOP ||
1187+
next_in_chain->term_cond == TC_TERM_COND_EXACT) &&
1188+
seg->shared_9d.profile.valid &&
1189+
seg->term_cond == TC_TERM_COND_TANGENT) {
1190+
double prof_exit = profileExitVelUnscaled(&seg->shared_9d.profile)
1191+
* seg->shared_9d.profile.computed_feed_scale;
1192+
seg_exit = fmin(seg_exit, prof_exit);
1193+
}
1194+
11801195
double seg_acc = tcGetTangentialMaxAccel_9D_user(seg);
11811196
double brake_dist = jerkLimitedBrakingDistance(
11821197
seg_max_vel, seg_exit, seg_acc, seg_jrk);
@@ -1204,9 +1219,24 @@ static double computeChainExitCap(TP_STRUCT *tp, TC_STRUCT *active_tc,
12041219
double seg_fv = readFinalVelCapped(seg);
12051220
double seg_exit = (seg->term_cond == TC_TERM_COND_TANGENT)
12061221
? fmin(seg_fv * seg_feed, seg_max_vel) : 0.0;
1207-
1222+
12081223
if (seg->kink_vel > 0) seg_exit = fmin(seg_exit, seg->kink_vel);
12091224

1225+
// When the next segment is STOP/EXACT (v_f≈0), the backward pass
1226+
// uses trapezoidal formula sqrt(2*a*d) which ignores jerk limits.
1227+
// This inflates final_vel beyond what Ruckig can achieve. Cap to
1228+
// profile exit so the chain propagates physically consistent limits.
1229+
TC_STRUCT *next_in_chain_p2 = tcqItem_user(&tp->queue, i + 1);
1230+
if (next_in_chain_p2 &&
1231+
(next_in_chain_p2->term_cond == TC_TERM_COND_STOP ||
1232+
next_in_chain_p2->term_cond == TC_TERM_COND_EXACT) &&
1233+
seg->shared_9d.profile.valid &&
1234+
seg->term_cond == TC_TERM_COND_TANGENT) {
1235+
double prof_exit = profileExitVelUnscaled(&seg->shared_9d.profile)
1236+
* seg->shared_9d.profile.computed_feed_scale;
1237+
seg_exit = fmin(seg_exit, prof_exit);
1238+
}
1239+
12101240
// Cap exit by what next segment can accept (cascading backward)
12111241
seg_exit = fmin(seg_exit, next_entry_cap);
12121242

0 commit comments

Comments
 (0)