@@ -60,14 +60,6 @@ static unsigned long last_period = 0;
6060/* servo cycle time */
6161static double servo_period ;
6262
63- /* Planner type 2: joint-space velocity feedforward via finite differences.
64- * Correct for ALL kinematics (trivkins, tilting pivot, etc.) unlike the
65- * previous direction-vector decomposition which assumed joints = XYZ axes. */
66- static double p2_prev_pos [EMCMOT_MAX_JOINTS ];
67- static double p2_prev_vel [EMCMOT_MAX_JOINTS ];
68- static double p2_prev_acc [EMCMOT_MAX_JOINTS ];
69- static int p2_ff_init = 0 ;
70-
7163extern struct emcmot_status_t * emcmotStatus ;
7264
7365// *pcmd_p[0] is shorthand for emcmotStatus->carte_pos_cmd.tran.x
@@ -1215,7 +1207,6 @@ static void get_pos_cmds(long period)
12151207 /* run traj planner code depending on the state */
12161208 switch ( emcmotStatus -> motion_state ) {
12171209 case EMCMOT_MOTION_FREE :
1218- p2_ff_init = 0 ; /* Reset feedforward state when leaving coord mode */
12191210 /* in free mode, each joint is planned independently */
12201211 /* initial value for flag, if needed it will be cleared below */
12211212 SET_MOTION_INPOS_FLAG (1 );
@@ -1365,61 +1356,44 @@ static void get_pos_cmds(long period)
13651356 }
13661357
13671358 if (emcmotStatus -> planner_type == 2 ) {
1368- /* Planner type 2 (Ruckig): bypass cubic interpolator.
1369- * Joint velocity/acceleration/jerk feedforward computed from
1370- * finite differences of IK output — correct for ALL kinematics. */
1359+ /* Planner type 2 (Ruckig): use cubic interpolation to smooth
1360+ * directional discontinuities at bezier-to-line split boundaries.
1361+ * The cubic [1,4,1]/6 waypoint filter spreads single-sample
1362+ * direction jumps over 3 samples, eliminating jerk spikes. */
13711363 EmcPose current_pos = emcmotStatus -> carte_pos_cmd ;
13721364
13731365 result = kinematicsInverse (& current_pos , positions , & iflags , & fflags );
13741366 if (result == 0 ) {
1375- double inv_dt = 1.0 / servo_period ;
1376-
13771367 for (joint_num = 0 ; joint_num < NO_OF_KINS_JOINTS ; joint_num ++ ) {
13781368 if (!isfinite (positions [joint_num ])) {
13791369 reportError (_ ("kinematicsInverse gave non-finite joint location on joint %d" ),
13801370 joint_num );
13811371 SET_MOTION_ERROR_FLAG (1 );
13821372 emcmotInternal -> enabling = 0 ;
1383- p2_ff_init = 0 ;
13841373 break ;
13851374 }
13861375 joint = & joints [joint_num ];
13871376 joint -> coarse_pos = positions [joint_num ];
1388- joint -> pos_cmd = positions [joint_num ];
1389-
1390- if (p2_ff_init ) {
1391- double vel = (positions [joint_num ] - p2_prev_pos [joint_num ]) * inv_dt ;
1392- double acc = (vel - p2_prev_vel [joint_num ]) * inv_dt ;
1393- joint -> vel_cmd = vel ;
1394- joint -> acc_cmd = acc ;
1395- joint -> jerk_cmd = (acc - p2_prev_acc [joint_num ]) * inv_dt ;
1396- p2_prev_vel [joint_num ] = vel ;
1397- p2_prev_acc [joint_num ] = acc ;
1398- } else {
1399- joint -> vel_cmd = 0.0 ;
1400- joint -> acc_cmd = 0.0 ;
1401- joint -> jerk_cmd = 0.0 ;
1402- p2_prev_vel [joint_num ] = 0.0 ;
1403- p2_prev_acc [joint_num ] = 0.0 ;
1404- }
1405- p2_prev_pos [joint_num ] = positions [joint_num ];
14061377 }
1407- p2_ff_init = 1 ;
14081378
1409- /* Still feed the cubic so it stays primed if we switch planner types */
1379+ /* Feed cubic interpolator */
14101380 while (cubicNeedNextPoint (& (joints [0 ].cubic ))) {
14111381 for (joint_num = 0 ; joint_num < NO_OF_KINS_JOINTS ; joint_num ++ ) {
14121382 cubicAddPoint (& (joints [joint_num ].cubic ), positions [joint_num ]);
14131383 }
14141384 }
1385+ /* Get smoothed position with analytical vel/acc/jerk */
1386+ for (joint_num = 0 ; joint_num < NO_OF_KINS_JOINTS ; joint_num ++ ) {
1387+ joint = & joints [joint_num ];
1388+ joint -> pos_cmd = cubicInterpolate (& (joint -> cubic ), 0 ,
1389+ & (joint -> vel_cmd ), & (joint -> acc_cmd ), & (joint -> jerk_cmd ));
1390+ }
14151391 } else {
14161392 reportError (_ ("kinematicsInverse failed" ));
14171393 SET_MOTION_ERROR_FLAG (1 );
14181394 emcmotInternal -> enabling = 0 ;
1419- p2_ff_init = 0 ;
14201395 }
14211396 } else {
1422- p2_ff_init = 0 ;
14231397 /* Planner type 0 and 1: use cubic interpolator as before */
14241398
14251399 /* Fill cubic buffer if needed (may need multiple points per cycle) */
@@ -1495,7 +1469,6 @@ static void get_pos_cmds(long period)
14951469 break ;
14961470
14971471 case EMCMOT_MOTION_TELEOP :
1498- p2_ff_init = 0 ; /* Reset feedforward state when leaving coord mode */
14991472 ext_offset_teleop_limit = axis_calc_motion (servo_period );
15001473 if (!ext_offset_teleop_limit ) {
15011474 ext_offset_coord_limit = 0 ; //in case was set in prior coord motion
0 commit comments