Skip to content

Commit 1e2e75d

Browse files
author
Luca Toniolo
committed
Add validation for planner type and improve S-curve deceleration logic
This commit: Validates PLANNER_TYPE in INI files and motion commands to only accept 0 (trapezoidal) or 1 (S-curve), defaulting to 0 for invalid values Improves S-curve lookahead calculation in tpComputeOptimalVelocity() to use proper S-curve kinematics instead of trapezoidal formulas Adds named constants for tpCalculateSCurveAccel() return values for better code clarity Removes incorrect position error correction logic in tcUpdateDistFromSCurveAccel() Clarifies deceleration condition comments and logic flow The changes fix edge cases in S-curve mode and make the planner type handling more robust.
1 parent 267ac38 commit 1e2e75d

5 files changed

Lines changed: 59 additions & 29 deletions

File tree

src/emc/ini/inihal.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,12 @@ int check_ini_hal_items(int numjoints)
297297
if (CHANGED(traj_planner_type)) {
298298
if (debug) SHOW_CHANGE_INT(traj_planner_type)
299299
UPDATE(traj_planner_type);
300-
if (0 != emcTrajPlannerType(NEW(traj_planner_type))) {
300+
// Only 0 and 1 are supported, set to 0 if invalid
301+
int planner_type = NEW(traj_planner_type);
302+
if (planner_type != 0 && planner_type != 1) {
303+
planner_type = 0;
304+
}
305+
if (0 != emcTrajPlannerType(planner_type)) {
301306
if (emc_debug & EMC_DEBUG_CONFIG) {
302307
rcs_print("check_ini_hal_items:bad return value from emcTrajPlannerType\n");
303308
}

src/emc/ini/initraj.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,10 @@ static int loadTraj(EmcIniFile *trajInifile)
225225
old_inihal_data.traj_default_jerk = jerk;
226226
planner_type = 0; // Default: 0 = trapezoidal, 1 = S-curve
227227
trajInifile->Find(&planner_type, "PLANNER_TYPE", "TRAJ");
228+
// Only 0 and 1 are supported, set to 0 if invalid
229+
if (planner_type != 0 && planner_type != 1) {
230+
planner_type = 0;
231+
}
228232
if (0 != emcTrajPlannerType(planner_type)) {
229233
if (emc_debug & EMC_DEBUG_CONFIG) {
230234
rcs_print("bad return value from emcTrajPlannerType\n");

src/emc/motion/command.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1194,7 +1194,12 @@ void emcmotCommandHandler_locked(void *arg, long servo_period)
11941194
/* set the type of planner: 0 = trapezoidal, 1 = S-curve */
11951195
/* can do it at any time */
11961196
rtapi_print_msg(RTAPI_MSG_DBG, "SET_PLANNER_TYPE, type(%d)", emcmotCommand->planner_type);
1197-
emcmotStatus->planner_type = emcmotCommand->planner_type;
1197+
// Only 0 and 1 are supported, set to 0 if invalid
1198+
if (emcmotCommand->planner_type != 0 && emcmotCommand->planner_type != 1) {
1199+
emcmotStatus->planner_type = 0;
1200+
} else {
1201+
emcmotStatus->planner_type = emcmotCommand->planner_type;
1202+
}
11981203
break;
11991204

12001205
case EMCMOT_PAUSE:

src/emc/tp/sp_scurve.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,15 @@ int findSCurveVSpeedConservative(double distance, double Ve, double maxA, double
4747
double calcDecelerateTimes(double v, double amax, double jerk, double* t1, double* t2);
4848
double calcSCurveSpeedWithT(double amax, double jerk, double T);
4949

50+
/**
51+
* tpCalculateSCurveAccel return value definitions
52+
*
53+
* TP_SCURVE_ACCEL_ERROR - calculation failed (maxjerk invalid or less than/equal to 1)
54+
* TP_SCURVE_ACCEL_ACCEL - acceleration or normal state (no deceleration needed)
55+
* TP_SCURVE_ACCEL_DECEL - deceleration needed
56+
*/
57+
#define TP_SCURVE_ACCEL_ERROR -5
58+
#define TP_SCURVE_ACCEL_ACCEL 0
59+
#define TP_SCURVE_ACCEL_DECEL 1
60+
5061
#endif

src/emc/tp/tp.c

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1764,13 +1764,20 @@ STATIC int tpComputeOptimalVelocity(TP_STRUCT const * const tp, TC_STRUCT * cons
17641764
double acc_this = tcGetTangentialMaxAccel(tc);
17651765

17661766
// Find the reachable velocity of tc, moving backwards in time
1767-
double vs_back = pmSqrt(pmSq(tc->finalvel) + 2.0 * acc_this * tc->target);
1767+
double vs_back;
17681768
if(GET_TRAJ_PLANNER_TYPE() == 1){
1769-
double vs_back2;
1770-
// Use clamped jerk to match execution phase behavior
1769+
// S-curve mode: use S-curve kinematics calculations
1770+
// Starting from finalvel, maximum starting speed achievable within distance tc->target
1771+
// During actual execution, tpCalculateSCurveAccel will adjust dynamically based on current state (including current acceleration)
1772+
// Use minimum of segment's max jerk and system max jerk to ensure limits are not exceeded
17711773
double maxjerk = fmin(tc->maxjerk, emcmotStatus->jerk);
1772-
if(findSCurveVSpeedWithEndSpeed(tc->target * 2.0 , tc->finalvel, acc_this, maxjerk, &vs_back2) == 1)
1773-
vs_back = vs_back2;
1774+
if(findSCurveVSpeedWithEndSpeed(tc->target, tc->finalvel, acc_this, maxjerk, &vs_back) != 1){
1775+
// S-curve calculation failed, use conservative estimate (at least maintain finalvel)
1776+
vs_back = tc->finalvel;
1777+
}
1778+
} else {
1779+
// Trapezoidal acceleration/deceleration mode: use trapezoidal kinematics formula
1780+
vs_back = pmSqrt(pmSq(tc->finalvel) + 2.0 * acc_this * tc->target);
17741781
}
17751782
// Find the reachable velocity of prev1_tc, moving forwards in time
17761783

@@ -2713,7 +2720,7 @@ STATIC int tpCalculateRampAccel(TP_STRUCT const * const tp,
27132720
/**
27142721
* Calculate distance update from velocity and acceleration.
27152722
*/
2716-
STATIC int tcUpdateDistFromSCurveAccel(TC_STRUCT *const tc, double acc, double jerk, double vel_desired, double perror, int reverse_run, int dec)
2723+
STATIC int tcUpdateDistFromSCurveAccel(TC_STRUCT *const tc, double acc, double jerk, double vel_desired, double perror __attribute__((unused)), int reverse_run, int dec)
27172724
{
27182725
// If the resulting velocity is less than zero, than we're done. This
27192726
// causes a small overshoot, but in practice it is very small.
@@ -2733,24 +2740,20 @@ STATIC int tcUpdateDistFromSCurveAccel(TC_STRUCT *const tc, double acc, double j
27332740
tc->progress = tcGetTarget(tc,reverse_run);
27342741
}
27352742
} else {
2736-
if(dx < 1e-6){
2743+
if(dx < TP_POS_EPSILON){
27372744
tc->progress = tcGetTarget(tc,reverse_run);
27382745
}else{
27392746
// sc_distance(double t, double v, double a, double j);
2740-
double displacement = sc_distance(tc->cycle_time, tc->currentvel, tc->currentacc, jerk);
2747+
double displacement = sc_distance(tc->cycle_time, tc->currentvel, tc->currentacc, jerk);
27412748
// Account for reverse run (flip sign if need be)
27422749
double disp_sign = reverse_run ? -1 : 1;
27432750

2744-
if(perror > 0 && tc->last_move_length >= perror && displacement <= perror){
2745-
tc->progress += (disp_sign * perror);
2746-
tc->last_move_length = perror;
2747-
//printf("TRY TO FIX ERROR: %.15f \n", perror);
2748-
return TP_ERR_OK;
2749-
}
2751+
// Update position using calculated displacement
2752+
// Note: perror is actually margin (dx - dlen1), not position error,
2753+
// so it should not be used for position correction
27502754
tc->last_move_length = displacement;
2751-
27522755
tc->progress += (disp_sign * displacement);
2753-
2756+
27542757
//Progress has to be within the allowable range
27552758
tc->progress = bisaturate(tc->progress, tcGetTarget(tc, TC_DIR_FORWARD), tcGetTarget(tc, TC_DIR_REVERSE));
27562759
}
@@ -2791,7 +2794,7 @@ int tpCalculateSCurveAccel(TP_STRUCT const * const tp, TC_STRUCT * const tc, TC_
27912794
maxjerk = 1;
27922795
//rtapi_print_msg(RTAPI_MSG_ERR,
27932796
// "ERROR!!! maxjerk Is less than 1\n");
2794-
return -5;
2797+
return TP_SCURVE_ACCEL_ERROR;
27952798
}
27962799

27972800
// Find maximum allowed velocity from feed and machine limits
@@ -2810,9 +2813,9 @@ int tpCalculateSCurveAccel(TP_STRUCT const * const tp, TC_STRUCT * const tc, TC_
28102813
*acc = tc->currentacc;
28112814
*vel_desired = tc->currentvel;
28122815
*jerk =0;//(maxnewaccel - tc->currentacc) / dt;
2813-
return 0;
2816+
return TP_SCURVE_ACCEL_ACCEL;
28142817
}
2815-
int res = 1;
2818+
int res = TP_SCURVE_ACCEL_DECEL;
28162819

28172820

28182821
nextSpeed(tc->currentvel, tc->currentacc, tc->cycle_time, tc_target_vel, maxaccel, maxjerk, &req_v, &req_a, &req_j);
@@ -2837,23 +2840,24 @@ int tpCalculateSCurveAccel(TP_STRUCT const * const tp, TC_STRUCT * const tc, TC_
28372840

28382841
// Handle special case: position overshoot or reached endpoint
28392842
if (dx <= TP_POS_EPSILON) {
2843+
// Already reached or exceeded endpoint, must decelerate/stop
28402844
nextSpeed(tc->currentvel, tc->currentacc, tc->cycle_time, tc_finalvel, maxaccel, maxjerk, &req_v, &req_a, &req_j);
2841-
res = 1;
2845+
res = TP_SCURVE_ACCEL_DECEL;
28422846
}
2843-
else if(tc->currentvel < 1e-6 && dx > TP_POS_EPSILON && dx < 1e-4){
2847+
else if(tc->currentvel < TP_VEL_EPSILON && dx > TP_POS_EPSILON && dx < 1e-4){
28442848
// Very low velocity and close to target
2845-
res = 1;
2849+
res = TP_SCURVE_ACCEL_DECEL;
28462850
}else{
28472851
// Decel conditions:
2848-
// 1. margin <= 0: decel distance >= remaining distance
2849-
// 2. dx - moveL <= dlen2: if we continue accel, next cycle remaining <= decel dist
2852+
// Condition 1: margin <= 0 - decel distance already >= remaining distance, must decelerate
2853+
// Condition 2: dx - moveL <= dlen2 - if we continue accel, next cycle remaining <= decel dist
28502854
int need_decel = (margin <= TP_POS_EPSILON) || (dx - moveL <= dlen2);
28512855

28522856
if (need_decel){
28532857
nextSpeed(tc->currentvel, tc->currentacc, tc->cycle_time, tc_finalvel, maxaccel, maxjerk, &req_v, &req_a, &req_j);
28542858
}else{
28552859
if(tc_finalvel > TP_VEL_EPSILON || tc_target_vel > TP_VEL_EPSILON)
2856-
res = 0;
2860+
res = TP_SCURVE_ACCEL_ACCEL;
28572861
}
28582862
}
28592863

@@ -3510,7 +3514,8 @@ STATIC int tpUpdateCycle(TP_STRUCT * const tp,
35103514
if(*mode == 1){
35113515
tc->cycle_time = tp->cycleTime;
35123516
int is_dec = tpCalculateSCurveAccel(tp, tc, nexttc, &acc, &jerk, &vel_desired, &perror, 1);
3513-
if(is_dec == -5){ //If the calculation fails, revert to T-shaped acceleration/deceleration.
3517+
3518+
if(is_dec == TP_SCURVE_ACCEL_ERROR){ //If the calculation fails, revert to T-shaped acceleration/deceleration.
35143519
*mode = -5;
35153520
res_accel = 1;
35163521
acc=0, vel_desired=0;
@@ -3527,7 +3532,7 @@ STATIC int tpUpdateCycle(TP_STRUCT * const tp,
35273532
}
35283533
}else{
35293534
int is_dec = tpCalculateSCurveAccel(tp, tc, nexttc, &acc, &jerk, &vel_desired, &perror, 0);
3530-
if(is_dec == -5){ //If the calculation fails, revert to T-shaped acceleration/deceleration.
3535+
if(is_dec == TP_SCURVE_ACCEL_ERROR){ //If the calculation fails, revert to T-shaped acceleration/deceleration.
35313536
*mode = -5;
35323537
res_accel = 1;
35333538
acc=0, vel_desired=0;

0 commit comments

Comments
 (0)