This chapter belongs to the multi-channel extension of linuxcncMulti. It documents what the trajectory planner of this fork offers beyond LinuxCNC 2.9, how to measure its behaviour on CAM-style programs, and the simulated 5-axis gantry used for that. The development concept (German) is docs/multichannel/bahnplaner.md.

Planner features present in this fork

  • Jerk-limited S-curve profiles. [TRAJ]PLANNER_TYPE = 1 selects the S-curve planner; it needs [TRAJ]MAX_LINEAR_JERK (machine units/s^3, at least 1.0). Every segment is planned with a jerk-limited velocity profile along the path, and the radius of blend arcs is limited so that the lateral jerk stays within the limit. Programs select the smooth planner with G64 R>0; [TRAJ]SMOOTH_PLANNER names the implementation.

  • Look-ahead bounds of the S-curve planner. The look-ahead limits each segment’s end velocity by what the following segment can brake away and by what the segment itself can reach from its start velocity. Earlier versions clamped both bounds to the peak of a rest-to-rest move over the segment, which held short CAM segments (0.2 to 2 mm) at a fraction of the programmed feed; the bounds are now the exact jerk-limited values.

  • Acceleration step at blend arcs. [TRAJ]MAX_ACCEL_OVL_FACTOR (0 to 1, default 1.0, HAL pin ini.traj_max_accel_ovl_factor) is the counterpart of Siemens MD32310: with the S-curve planner, the normal acceleration may jump at the ends of a blend arc up to this factor of the acceleration limit, so blend arcs are run at v = sqrt(f * a_n * R) like with the trapezoidal planner, while the motion along the arc stays jerk-limited. With 0 the planner keeps the strict model that limits every blend arc by the lateral jerk of its entry; on a 1 ms servo thread that holds blend arcs between 25 and 60 mm/s whatever the radius, and G64 P becomes slower than exact stop.

  • Per-axis jerk limits [AXIS_x]MAX_JERK and [JOINT_n]MAX_JERK are read and exported as HAL pins (ini.x.max_jerk, ini.N.max_jerk). Like velocity and acceleration, the jerk limit of every linear move is derived from the limits of the axes that move (the axis with the longest characteristic time sets the move’s jerk), so a move along the slowest axis never exceeds that axis' jerk; [TRAJ]MAX_LINEAR_JERK is the upper bound for the path. Blend arcs use the path limit. Under non-identity kinematics the joint limits are applied separately, see below.

  • Look-ahead. Each channel has a queue of 2000 segments. When a segment is queued, the planner walks back over [TRAJ]ARC_BLEND_OPTIMIZATION_DEPTH segments (default 50) and raises the end velocities of the queued segments as far as the following segments allow.

  • Blending. Tangent segments are joined directly, other transitions get a blend arc within the G64 P tolerance. Line-line transitions with rotary (ABC) or UVW motion are blended as well: the blend carries the rotary motion between its end points on a quintic Hermite curve that takes over the rate of each line at its end and has zero acceleration there, so the orientation rate and acceleration stay continuous, and the neighbouring lines are trimmed in all coordinates. The blend is limited by the rotary axes' velocity, acceleration and jerk limits and by the joint limits of the kinematics. Pure rotary segments and arcs with rotary motion still blend parabolically.

  • Curvature-continuous blends. [TRAJ]BLEND_TYPE = POLY (default ARC, HAL pin ini.traj_blend_type, 0 = ARC, 1 = POLY) replaces the blend arc between two lines by a polynomial of degree 7 whose tangent, curvature and change of curvature match the lines at both ends (G3), the counterpart of Siemens G642 with SOFT. The normal acceleration then ramps up and down inside the blend instead of jumping at the ends of an arc, the lateral jerk starts from zero at the junctions, so the joint jerk at corners stays within the limits and MAX_ACCEL_OVL_FACTOR has no effect on these transitions. The blend uses the whole G64 P tolerance; its speed is limited by the peak curvature (normal acceleration) and by the peak change of curvature (lateral jerk v^3 dk/ds), which makes a corner slower than the arc with its allowed acceleration step: the price of a jerk-limited corner. The jerk budget of the blend is split between the velocity profile (tangential, 0.5) and the curvature change (lateral, 0.866) so that their sum stays within the limit. Rotary and UVW motion is carried as with the arc. Transitions that involve a programmed arc, and corners sharper than 160 degrees, keep the blend arc. The sim configs/sim/multichannel/portal_bc runs with POLY.

  • Merging micro-segments with rotary motion. The naive CAM detector (G64 Q, the tolerance defaults to P) merges consecutive lines that stay within the tolerance of one straight line. In standard LinuxCNC any ABC or UVW motion ends the chain, so 5-axis CAM programs, which change the orientation in every block, were never merged. [RS274NGC]G64_DEFAULT_ORITOLERANCE (degrees, default 0 = standard behaviour) also chains such lines when the orientation of every merged point stays within that angle of the merged line’s linear orientation interpolation; UVW motion is held to the length tolerance. Merged lines give the blends room and halve the number of transitions.

  • Spline compressor. [RS274NGC]COMPRESSOR = OFF|LINE|SPLINE (default LINE, the naive CAM detector; OFF merges nothing). With SPLINE, the counterpart of Siemens COMPCAD with ORISON, the feed blocks of a G64 program are collected in groups of up to 256 and fitted with a cubic B-spline in all nine coordinates: every programmed point stays within the G64 Q tolerance (default P) of the curve, the orientation within G64_DEFAULT_ORITOLERANCE, and the curve stays within the tolerance of the polyline between the points plus the polyline’s own faceting there (the chord error of the CAM program). The planner gets the spline as cubic Bezier pieces (segment type TC_BEZIER) that are curvature-continuous across all junctions, also from group to group. A group ends at a corner (deflection above 15 degrees), at a block without XYZ motion, when the buffer is full, and at everything that interrupts the path (feed change, G61, G0, M-codes); where the path goes on smoothly the next group continues the spline, a corner leaves the ends free and the planner takes the kink. A group the fit cannot hold within the tolerances is sent as lines. Pieces with rotary motion need an orientation tolerance; a program whose orientation has kinks (rate limited by the CAM) forces the fit to nearly every point there.

Joint limits under a non-identity kinematics

The planner plans in world coordinates. With a swivel head (5axiskins) or a kinematic transformation (TRAORI) the joints move differently from the tool centre point: a change of the head orientation swings the pivot and adds to the linear joints. Before the fix the benchmark gantry ran its X joint at twice its acceleration limit and five times its jerk limit on a 5-axis surface program.

Every linear and circular segment is now sampled with the inverse kinematics when it is queued (motion.kins-limit-samples, s32 in, default 12 samples, at most 16; 0 switches the check off). From the joint displacement per unit of path and its first, second and third change, the segment’s velocity, acceleration and jerk limits are reduced so that every joint of the channel stays within its [JOINT_n] limits: the joint acceleration q'' v^2 + q' a and the joint jerk q''' v^3 + 3 q'' v a + q' j are evaluated at every sample with the segment’s limits. Blends are sampled too and the line before a blend keeps to the blend’s acceleration limit. This is the Siemens behaviour of limiting the path feed from the machine-axis limits under TRAORI. Identity kinematics are not sampled.

HAL pins for planner diagnostics

motion.tp-queue-depth (s32, out)

Number of segments in channel 0’s planner queue. motion.N.tp-queue-depth gives the same for channel N. A depth that keeps dropping to 0..2 while the program runs means the interpreter does not deliver segments as fast as the machine consumes them (short segments, slow task cycle); the planner then has to stop at the end of every segment.

Simulated 5-axis gantry with BC head

configs/sim/multichannel/portal_bc/portal_bc.ini is a gantry router with a BC swivel head on the 5axiskins kinematics (pivot length 250 mm, tool length from the tool table via G43). X runs at 60 m/min on a rack, Y at 50 m/min, Z at 25 m/min, 3 m/s^2 and 60 m/s^3; B tilts +/-120 degrees, C is continuous. The S-curve planner with arc blending and a look-ahead depth of 100 is enabled. portal_bc.ini starts AXIS with the vismach model, portal_bc_bench.ini is the headless variant for the benchmark.

Simulated 5-axis machining centre DMU 60

configs/sim/multichannel/dmu60/dmu60.ini is a vertical machining centre in the DMU 60 eVo layout: X/Y/Z in the column and head (600/500/500 mm, 50 m/min, 6 m/s^2, jerk 100 m/s^3), a swivel rotary table with B (-5 to +110 degrees about Y) and C (endless) in the bed, spindle 18000 rpm. The kinematics is xyzbc-trt-kins (table rotary tilting): the program is written in the workpiece frame and the controller turns it with the table (TCP; the tool length of G43 goes into the kinematics so that the table turns about the tool tip). Every path optimisation is enabled: PLANNER_TYPE = 1 with MAX_LINEAR_JERK, BLEND_TYPE = POLY, look-ahead 100, COMPRESSOR = SPLINE with G64_DEFAULT_ORITOLERANCE = 0.5 and motion.kins-limit-samples = 16 for the joint check of B and C at the tilted table. The window is mchmi with the 3D column (vismach model dmu60_model.py, the blank on the table with material removal in the workpiece frame, [WORKPIECE_0]FRAME = TCP); dmu60_bench.ini is the headless variant for the benchmark.

A second channel (WECHSLER, axes A and W on joints 5 and 6) is the automatic tool changer with a 30-place disc magazine and a double gripper: nc_files/wechsler.ngc is the channel’s event program (power-on, reset), which retracts from an interrupted change and then serves the prepare / change requests of iocontrol.0 (through HAL, dmu60.hal) in an endless loop (see the ASUP section of the configuration chapter and the tool management chapter), so T.. M6 in the machining channel waits for the magazine disc and the gripper. The tool management (WZ-Liste, mctooldb) belongs to the machining channel alone, with the magazine and the gripper places of [TOOLMAG_0] / [TOOLBUFFER_0]. In motion, channel 0 keeps the kinematics module (the TCP transformation) in the multi-channel loops as well.

nc_files/gen_impeller.py writes the programs: impeller.ngc (an impeller D120 with 7 backswept blades: contour roughing in Z layers with full circles, the channels roughed 5-axis with the ball mill leaning 25 degrees outward in arc strips from the outside in, the blade flanks finished along their ruling lines; 8000 moves), impeller_stl.ngc (the same on a preformed blank from impeller_rohteil.stl) and impeller_kurz.ngc (one layer, one channel, one blade; the test tests/multichannel/dmu60). The blank is defined in the program with the SINUMERIK statement WORKPIECE (G-code chapter). For a table-table machine a tool axis d = (sin b cos phi, sin b sin phi, cos b) in the workpiece frame is programmed as B = b, C = 180 - phi degrees; the generator writes C continuously.

Programs of the gantry

The sample programs in nc_files/ are generated by tests/trajectory-planner/bench/gen_programs.py:

freeform_5axis.ngc

Zig-zag finishing of a wavy surface with G1 segments of 0.2 to 2 mm, the tool axis follows the surface normal. B and C are derived from the normal in the 5axiskins convention (B polar angle from +Z, C azimuth, kept continuous, tilt limited to 25 degrees).

freeform_3axis.ngc

The same path with the head fixed.

corner_g64.ngc

Squares with 90 degree corners under G64 P0.05.

Planner benchmark

tests/trajectory-planner/bench/run_bench.py runs these programs headless on the gantry, records one sample per servo cycle with halsampler (path speed, tool centre point, joints, program line, queue depth, servo thread runtime) and evaluates them with analyze.py:

. scripts/rip-environment
python3 tests/trajectory-planner/bench/run_bench.py --out /tmp/bench-before

The result results.md lists per program the duration, the mean and minimum path speed, the share of time below 80 % and 50 % of the programmed feed, the maximum acceleration and jerk of every joint against the INI limits, the queue depth statistics and the servo thread load. Two revisions are compared by running the benchmark into two directories. The benchmark is not part of runtests.