@@ -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