@@ -2701,13 +2701,35 @@ static int replanForward(TP_STRUCT *tp, double v0_override, double budget_sec)
27012701 applyBidirectionalReachability (scaled_v_entry, scaled_v_exit,
27022702 tc->target , max_acc, max_jrk);
27032703
2704+ // Fix: when predecessor is active and bidir reduced entry, restore it.
2705+ // RT delivers the active's profile exit regardless — a v0 gap at entry
2706+ // causes a spike, while overshooting the exit target shifts the mismatch
2707+ // downstream where the corridor chain absorbs it naturally.
2708+ if (pre_bidir_v_entry - scaled_v_entry > 0.1 && i > 0 ) {
2709+ TC_STRUCT *prev_tc_fix = tcqItem_user (queue, i - 1 );
2710+ if (prev_tc_fix && prev_tc_fix->active ) {
2711+ scaled_v_entry = pre_bidir_v_entry;
2712+ // Override exit with physics-based minimum from braking.
2713+ double min_exit = jerkLimitedMinExitVelocity (
2714+ scaled_v_entry, tc->target , max_acc, max_jrk);
2715+ scaled_v_exit = fmin (fmax (min_exit, scaled_v_exit), scaled_v_entry);
2716+ desired_fvel = scaled_v_exit;
2717+ }
2718+ }
2719+
27042720 // Backward propagation: if bidir reduced our entry, the predecessor's
27052721 // profile exit is too high. Rewrite it with the bidir-capped exit
27062722 // so RT sees a consistent junction velocity.
27072723 if (pre_bidir_v_entry - scaled_v_entry > 0.1 && i > 0 ) {
27082724 TC_STRUCT *prev_tc = tcqItem_user (queue, i - 1 );
2725+ // Skip rewriting the immediate successor of the active segment —
2726+ // its v0 was set to match the active's delivery velocity and must
2727+ // not be reduced by downstream bidir cascades.
2728+ TC_STRUCT *grandparent = (i >= 2 ) ? tcqItem_user (queue, i - 2 ) : NULL ;
2729+ bool prev_is_active_successor = grandparent && grandparent->active ;
27092730 if (prev_tc && prev_tc->term_cond == TC_TERM_COND_TANGENT &&
2710- prev_tc->shared_9d .profile .valid && !prev_tc->active ) {
2731+ prev_tc->shared_9d .profile .valid && !prev_tc->active &&
2732+ !prev_is_active_successor) {
27112733 double prev_feed = snap.forSegment (prev_tc);
27122734 double prev_vel_limit = getEffectiveVelLimit (tp, prev_tc);
27132735 double prev_max_vel = applyVLimit (tp, prev_tc, prev_vel_limit * prev_feed);
0 commit comments