Skip to content

FTM: constant jerk planner#28349

Draft
dbuezas wants to merge 12 commits intoMarlinFirmware:bugfix-2.1.xfrom
dbuezas:dbuezas/ftm-constant-jerk-planner
Draft

FTM: constant jerk planner#28349
dbuezas wants to merge 12 commits intoMarlinFirmware:bugfix-2.1.xfrom
dbuezas:dbuezas/ftm-constant-jerk-planner

Conversation

@dbuezas
Copy link
Contributor

@dbuezas dbuezas commented Feb 22, 2026

Description

Adds a constant-jerk trajectory planner and generator to FT Motion as a new trajectory type alongside Trapezoidal, Poly5, and Poly6.

Marlin's standard trapezoidal motion profile changes acceleration instantaneously, causing mechanical stress and resonance. This PR introduces 7-phase S-curve trajectories where jerk (the rate of change of acceleration) is bounded, so acceleration ramps up and down gradually. This is unrelated to Marlin's "classic jerk" (which is an axial delta-v threshold).

How it works

image

The system has two layers:

1. Trajectory generator (trajectory_constant_jerk.h) — Plans the S-curve for a single junction-speed-optimized block:

[+jerk → cruise accel → −jerk → cruise velocity → −jerk → cruise decel → +jerk]

Uses binary search to find the highest feasible peak velocity given entry/exit speeds, distance, acceleration limit, and jerk limit. All phase boundaries have zero acceleration (smooth transitions).

2. Block planner (constant_jerk_planner.h) — Sits between Marlin's planner and the trajectory generator. It:

  • Ignores Marlin's entry_speed/exit_speed (computed with trapezoidal v²=v₀²+2ad, not valid under jerk constraints)
  • Uses max_entry_speed_sqr as junction speed ceiling (geometric, valid for any motion profile)
  • Runs its own jerk-aware reverse/forward pass across up to 16 look-ahead blocks using maxReachableSpeed() (binary search with S-curve distance instead of v²=v₀²+2ad)
  • Merges compatible consecutive blocks into a single S-curve trajectory, eliminating unnecessary decel/accel at intermediate junctions.

Block merging algorithm

Compatible blocks (same nominal speed, acceleration within 10%) are merged using a left/right superblock approach:

  1. Find left-compatible group and right-compatible group
  2. Treat the right group as a superblock — its larger distance allows a higher entry speed, which improves the left group's exit speed
  3. Compute v_peak of the left group; if it exceeds any interior junction limit, binary-split the group and retry
  4. Same check for the right group
  5. The validated left group becomes a single merged S-curve trajectory

This allows eliminating a variable during planning (when optimising junction speed at junctions). Acceleration is constrained to zero at junctions so the backwards and forward passes don't output complex vel+accel envelopes that are hard to compute and intersect. The trajectory merging algorithm then reduces the need for unnecessary slowdowns. The full generalised optimal planner would be prohibitively complex.

As far as I know this is a novel approach.

Although a single 7 phase trajectory now can cover multiple blocks, original block boundaries are tracked by distance so ft_motion.cpp can release consumed planner blocks and update axis ratios.

Configuration

// Configuration_adv.h
#define FTM_CONSTANT_JERK                     // Enable constant-jerk trajectory
#if ENABLED(FTM_CONSTANT_JERK)
  #define FTM_DEFAULT_JERK_MAX 500'000.0f     // (mm/s³) Default maximum jerk
#endif

G-code

M494 J<value> — Set maximum jerk (mm/s³). Higher values print faster at the cost of increased resonance. The J parameter follows the same set_jerkMax() pattern as set_smoothing_time(): it calls prep_for_shaper_change() to synchronize motion before updating.

Trajectory type selection: M494 T3 (CONSTANT_JERK).

LCD menu

Adds jerk max editing to the FT Motion settings menu and CONSTANT_JERK to the trajectory type selector. The unit in the menu is not mm/s3, but is m/s3 because the numbers are otherwise too large to show in the LCD (that's why I added the unit to the lcd string).

Files changed

File Description
ft_motion/trajectory_constant_jerk.h New. 7-phase S-curve generator with phase simulation, ramp planning, and time-domain sampling
ft_motion/constant_jerk_planner.h New. Block planner with jerk-aware reverse/forward pass and superblock merge algorithm
Configuration_adv.h FTM_CONSTANT_JERK enable flag and FTM_DEFAULT_JERK_MAX default
Conditionals-4-adv.h Derived flag HAS_FTM_TRAJECTORY_SELECTION, default FTM_TRAJECTORY_TYPE
ft_motion.h cfg.jerk_max, cfg.set_jerkMax(), cjPlanner member
ft_motion.cpp CJ branch in plan_next_block() and block boundary tracking in fill_stepper_plan_buffer()
M494.cpp J parameter parsing, jerk reporting
trajectory_generator.h CONSTANT_JERK enum value
menu_motion.cpp Jerk max editor, trajectory type menu entry
language_en.h MSG_FTM_CONSTANT_JERK, MSG_FTM_JERK_MAX strings

Requirements

This uses considerably more cycles so probably requires an FPU, just try it out! :)
And it is available only in FTMotion.

Benefits

  • Smoother acceleration profiles - bounded jerk reduces mechanical stress on frames, belts, and extruders compared to trapezoidal profiles
  • Reduced ringing - gradual acceleration changes excite fewer resonant frequencies
  • More accurate linear advance - no discontinuities in acceleration translate to no discontinuities in the LA term of extrusion rate, and since extrusion is proportinal to tangential speed and not axial speed, there shouldn't be many discontinuities coming from junction deviation/classic jerk either. This reduces the need for extruder smoothing in post processing making effective extrusion better following the ideal.

Configurations

Tested with STM32H723VG_btt environment (SKR3 EZ). Enable FTM_CONSTANT_JERK in Configuration_adv.h.

Related Issues

@dbuezas dbuezas marked this pull request as draft February 23, 2026 19:40
@dbuezas
Copy link
Contributor Author

dbuezas commented Feb 23, 2026

On longer tests i found some bugs, please hold until i fix them.

fix discontinuity bug

use full BLOCK_BUFFER_SIZE

remove 50% left/right cap

cap left side by at most half full buffer

left min size is old right (with bug)

exit speed fix but over complicated

wip

remove left min size (works but risky?)

fix with min size

fmt

move out

cleanup (tested working in printer)

cleanup

(cherry picked from commit 8f5de41)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant