@@ -2543,6 +2543,16 @@ static int replanForward(TP_STRUCT *tp, double v0_override, double budget_sec)
25432543 prev_exit_vel = pu * tc->shared_9d .profile .computed_feed_scale ;
25442544 }
25452545 prev_exit_vel_known = true ;
2546+ if (FO_TRACE) {
2547+ int bv = __atomic_load_n (&tc->shared_9d .branch .valid , __ATOMIC_ACQUIRE);
2548+ rtapi_print_msg (RTAPI_MSG_ERR,
2549+ " FO_REPLAN_ACTIVE seg=%d bv=%d prev_exit=%.3f "
2550+ " prof_feed=%.3f prof_exit_unscaled=%.6f term=%d\n " ,
2551+ tc->id , bv, prev_exit_vel,
2552+ tc->shared_9d .profile .computed_feed_scale ,
2553+ profileExitVelUnscaled (&tc->shared_9d .profile ),
2554+ tc->term_cond );
2555+ }
25462556 }
25472557 continue ;
25482558 }
@@ -2565,11 +2575,25 @@ static int replanForward(TP_STRUCT *tp, double v0_override, double budget_sec)
25652575 // Skip when predecessor is active: RT delivers its old-feed profile
25662576 // exit velocity regardless of kink_vel. Capping here just creates a
25672577 // v0 mismatch (spike) while the junction jerk is unavoidable either way.
2568- // The corridor handles deceleration from the real entry velocity.
2578+ // Also skip when predecessor's profile exit already exceeds the kink:
2579+ // this happens in cross-feed corridor chains where the predecessor was
2580+ // profiled at high velocity (e.g. active→corridor→here). Capping entry
2581+ // by kink creates a gap (spike) since RT delivers the predecessor's
2582+ // profiled exit. The corridor handles deceleration downstream.
25692583 {
25702584 TC_STRUCT *prev_tc = (i > 0 ) ? tcqItem_user (queue, i - 1 ) : NULL ;
2571- if (prev_tc && prev_tc->kink_vel > 0 && !prev_tc->active )
2572- scaled_v_entry = fmin (scaled_v_entry, prev_tc->kink_vel );
2585+ if (prev_tc && prev_tc->kink_vel > 0 && !prev_tc->active ) {
2586+ bool prev_exit_exceeds_kink = false ;
2587+ if (prev_tc->shared_9d .profile .valid ) {
2588+ double prev_prof_exit =
2589+ profileExitVelUnscaled (&prev_tc->shared_9d .profile )
2590+ * prev_tc->shared_9d .profile .computed_feed_scale ;
2591+ prev_exit_exceeds_kink =
2592+ (prev_prof_exit > prev_tc->kink_vel * 1.01 );
2593+ }
2594+ if (!prev_exit_exceeds_kink)
2595+ scaled_v_entry = fmin (scaled_v_entry, prev_tc->kink_vel );
2596+ }
25732597 }
25742598
25752599 // Target exit velocity from backward pass
@@ -2700,6 +2724,7 @@ static int replanForward(TP_STRUCT *tp, double v0_override, double budget_sec)
27002724
27012725 applyBidirectionalReachability (scaled_v_entry, scaled_v_exit,
27022726 tc->target , max_acc, max_jrk);
2727+ double post_bidir_v_entry = scaled_v_entry; // capture before fix
27032728
27042729 // Fix: when predecessor is active and bidir reduced entry, restore it.
27052730 // RT delivers the active's profile exit regardless — a v0 gap at entry
@@ -2717,6 +2742,26 @@ static int replanForward(TP_STRUCT *tp, double v0_override, double budget_sec)
27172742 }
27182743 }
27192744
2745+ // Debug: trace active's successor pipeline during cross-feed replans
2746+ if (FO_TRACE && i <= 2 && i > 0 ) {
2747+ TC_STRUCT *dbg_prev = tcqItem_user (queue, i - 1 );
2748+ bool dbg_prev_active = dbg_prev && dbg_prev->active ;
2749+ rtapi_print_msg (RTAPI_MSG_ERR,
2750+ " FO_SUCC_DBG i=%d seg=%d prev_active=%d "
2751+ " prev_exit_in=%.3f max_vel=%.3f "
2752+ " pre_bidir=%.3f post_bidir=%.3f final_entry=%.3f "
2753+ " fix_fired=%d corridor=%d "
2754+ " v_exit=%.3f target=%.4f feed=%.3f kink=%.3f\n " ,
2755+ i, tc->id , dbg_prev_active ? 1 : 0 ,
2756+ prev_exit_vel, max_vel,
2757+ pre_bidir_v_entry, post_bidir_v_entry, scaled_v_entry,
2758+ (pre_bidir_v_entry - post_bidir_v_entry > 0.1 &&
2759+ dbg_prev_active) ? 1 : 0 ,
2760+ cross_feed_corridor ? 1 : 0 ,
2761+ scaled_v_exit, tc->target , feed_scale,
2762+ tc->kink_vel );
2763+ }
2764+
27202765 // Backward propagation: if bidir reduced our entry, the predecessor's
27212766 // profile exit is too high. Rewrite it with the bidir-capped exit
27222767 // so RT sees a consistent junction velocity.
@@ -2784,10 +2829,17 @@ static int replanForward(TP_STRUCT *tp, double v0_override, double budget_sec)
27842829 } else {
27852830 prev_exit_vel = 0.0 ;
27862831 }
2832+ if (FO_TRACE && i <= 2 && i > 0 ) {
2833+ rtapi_print_msg (RTAPI_MSG_ERR,
2834+ " FO_SUCC_RESULT i=%d seg=%d v0_stored=%.3f "
2835+ " v_exit_stored=%.3f prev_exit=%.3f feed=%.3f\n " ,
2836+ i, tc->id , tc->shared_9d .profile .v [0 ],
2837+ prev_exit_vel, prev_exit_vel, feed_scale);
2838+ }
27872839 } else {
2788- if (FO_TRACE && cross_feed_corridor) {
2840+ if (FO_TRACE && ( cross_feed_corridor || (i <= 2 && i > 0 )) ) {
27892841 rtapi_print_msg (RTAPI_MSG_ERR,
2790- " FO_CORRIDOR_FAIL i=%d seg=%d v_entry=%.3f v_exit=%.3f "
2842+ " FO_RUCKIG_FAIL_SUCC i=%d seg=%d v_entry=%.3f v_exit=%.3f "
27912843 " ruckig_max_vel=%.3f max_acc=%.3f max_jrk=%.1f "
27922844 " target=%.4f feed=%.3f corridor=%d\n " ,
27932845 i, tc->id , scaled_v_entry, scaled_v_exit,
0 commit comments