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