diff --git a/src/emc/tp/tc.c b/src/emc/tp/tc.c index 1acbd0e7072..19a30b779b0 100644 --- a/src/emc/tp/tc.c +++ b/src/emc/tp/tc.c @@ -750,6 +750,7 @@ int tcInit(TC_STRUCT * const tc, tc->ruckig_last_use_velocity_control = 0; tc->ruckig_last_req_pos = 0.0; tc->ruckig_last_feed_override = 0.0; + tc->ruckig_fail_logged = 0; return TP_ERR_OK; } diff --git a/src/emc/tp/tc_types.h b/src/emc/tp/tc_types.h index c1767d56132..e9d04aedc68 100644 --- a/src/emc/tp/tc_types.h +++ b/src/emc/tp/tc_types.h @@ -210,6 +210,10 @@ typedef struct { int ruckig_last_use_velocity_control; // control mode used in last planning (1=velocity, 0=position) double ruckig_last_req_pos; // last req_pos value from Ruckig (for velocity control incremental calc) double ruckig_last_feed_override; // feed override value at last planning (for debug and change detection) + int ruckig_fail_logged; // 1 once a plan failure has been logged for this + // segment, so a segment Ruckig can never solve + // logs ONCE instead of every servo cycle (1kHz) + // -> avoids a multi-GB log flood on long soak runs } TC_STRUCT; #endif /* TC_TYPES_H */ diff --git a/src/emc/tp/tp.c b/src/emc/tp/tp.c index 4d0d59d9091..443871939e5 100644 --- a/src/emc/tp/tp.c +++ b/src/emc/tp/tp.c @@ -2827,7 +2827,14 @@ int tpCalculateSCurveAccel(TP_STRUCT const * const tp, TC_STRUCT * const tc, TC_ // Borrow a Ruckig planner from the preallocated pool (no RT-cycle alloc) tc->ruckig_planner = ruckig_pool_acquire(tc->cycle_time); if (!tc->ruckig_planner) { - rtapi_print_msg(RTAPI_MSG_ERR, "tpCalculateSCurveAccel: failed to create Ruckig planner\n"); + // Same rate-limit as the plan-failure paths below: the pool is + // retried every servo cycle for as long as it stays exhausted. + if (!tc->ruckig_fail_logged) { + tc->ruckig_fail_logged = 1; + rtapi_print_msg(RTAPI_MSG_ERR, + "tpCalculateSCurveAccel: failed to acquire a Ruckig planner from the pool" + " (segment %d, reported once)\n", tc->id); + } return TP_SCURVE_ACCEL_ERROR; } tc->ruckig_planned = 0; @@ -2884,10 +2891,26 @@ int tpCalculateSCurveAccel(TP_STRUCT const * const tp, TC_STRUCT * const tc, TC_ maxjerk); // max jerk if (plan_result != 0) { + // Guarded exactly like the position-control paths below: both + // branches are re-entered every servo cycle while the segment + // keeps failing (the caller reverts to trapezoidal for that + // cycle only, then calls back in). The flag is cleared by + // tcInit on every new segment, so each distinct failure still + // logs once. if (tc->ruckig_planned) { - rtapi_print_msg(RTAPI_MSG_WARN, "tpCalculateSCurveAccel: Ruckig velocity control replanning failed, using previous trajectory\n"); + if (!tc->ruckig_fail_logged) { + tc->ruckig_fail_logged = 1; + rtapi_print_msg(RTAPI_MSG_WARN, + "tpCalculateSCurveAccel: Ruckig velocity control replanning failed," + " using previous trajectory (segment %d, reported once)\n", tc->id); + } } else { - rtapi_print_msg(RTAPI_MSG_WARN, "tpCalculateSCurveAccel: Ruckig velocity control planning failed, falling back to tp 0\n"); + if (!tc->ruckig_fail_logged) { + tc->ruckig_fail_logged = 1; + rtapi_print_msg(RTAPI_MSG_WARN, + "tpCalculateSCurveAccel: Ruckig velocity control planning failed," + " falling back to tp 0 (segment %d, reported once)\n", tc->id); + } return TP_SCURVE_ACCEL_ERROR; } } else { @@ -2950,25 +2973,36 @@ int tpCalculateSCurveAccel(TP_STRUCT const * const tp, TC_STRUCT * const tc, TC_ maxjerk); // max jerk if (plan_result != 0) { - rtapi_print_msg(RTAPI_MSG_INFO, "tpCalculateSCurveAccel: ruckig_plan_position failed with result %d\n", plan_result); if (tc->ruckig_planned) { // Keep using previous trajectory + if (!tc->ruckig_fail_logged) { + tc->ruckig_fail_logged = 1; + rtapi_print_msg(RTAPI_MSG_INFO, "tpCalculateSCurveAccel: ruckig_plan_position failed with result %d (segment %d, reported once)\n", plan_result, tc->id); + } } else { - // First planning attempt failed, fall back - rtapi_print_msg(RTAPI_MSG_ERR, - "Ruckig planning failed (first attempt), Back to tp 0\n" - " feed_override: %.6f \n" - " max_vel: %.6f\n" - " cpos: %.6f, tpos: %.6f, dx: %.6f\n" - " cvel: %.6f, tvel: %.6f\n" - " cacc: %.6f\n" - " maxa: %.6f, maxj: %.6f\n", - emcmotStatus->net_feed_scale, - effective_max_vel, - replan_pos, target_pos, dx, - replan_vel, effective_target_vel, - replan_acc, - maxaccel, maxjerk); + // First planning attempt failed, fall back to trapezoidal. + // Guarded so a segment Ruckig can never solve logs ONCE, not + // every servo cycle (the retry loop re-enters here each cycle + // until ruckig_planned flips). The flag is cleared by tcInit + // on every new segment, so each distinct failure still logs. + if (!tc->ruckig_fail_logged) { + tc->ruckig_fail_logged = 1; + rtapi_print_msg(RTAPI_MSG_ERR, + "Ruckig planning failed (first attempt), Back to tp 0 (segment %d, reported once)\n" + " feed_override: %.6f \n" + " max_vel: %.6f\n" + " cpos: %.6f, tpos: %.6f, dx: %.6f\n" + " cvel: %.6f, tvel: %.6f\n" + " cacc: %.6f\n" + " maxa: %.6f, maxj: %.6f\n", + tc->id, + emcmotStatus->net_feed_scale, + effective_max_vel, + replan_pos, target_pos, dx, + replan_vel, effective_target_vel, + replan_acc, + maxaccel, maxjerk); + } return TP_SCURVE_ACCEL_ERROR; } } else {