Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/emc/tp/tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
4 changes: 4 additions & 0 deletions src/emc/tp/tc_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
72 changes: 53 additions & 19 deletions src/emc/tp/tp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down