A new finite-jerk (S-curve) trajectory planner for testing.
- andypugh
-
Topic Author
- Offline
- Moderator
-
Less
More
- Posts: 19761
- Thank you received: 4589
08 Jan 2026 00:05 - 08 Jan 2026 00:09 #341147
by andypugh
A new finite-jerk (S-curve) trajectory planner for testing. was created by andypugh
With many thanks to Grandixximo and 杨阳 we now have an experimental
S-curve / finite-jerk trajectory planner for testing.
For those that build from source just look for the new v2.10.0-pre1 tag.
Others can download debs from github for the next 90 days:
x86 / bookworm
x86 / trixie
ARM64 / bookworm
ARM64 / trixie
Make no mistake, this is experimental, there are no guarantees that
these won't break your machines. The first user already hit the hard
stops when homing (too-low max jerk setting)
With the jerk setting it is probably best to start high and reduce, as
infinite jerk is closer to current behavior.
If you run these you are volunteering to be a guinea-pig.
The docs have been updated, but here is the README original pull-request.
================================================================================
LINUXCNC S-CURVE MOTION PLANNING - QUICK REFERENCE
================================================================================
OVERVIEW
S-curve motion planning provides smoother acceleration by limiting jerk
(the rate of change of acceleration). This can reduce machine vibration,
improve surface finish, and extend machine life.
STATUS: Optional feature, disabled by default for backward compatibility
ENABLING S-CURVE PLANNING
Add to [TRAJ] section of your INI file:
PLANNER_TYPE = 1 # 0=trapezoidal (default), 1=S-curve
MAX_LINEAR_JERK = 1000.0 # Units: machine-units/s^3
DEFAULT_LINEAR_JERK = 500.0 # Default jerk for moves
Add to [JOINT_n] sections:
MAX_JERK = 1000.0 # Per-joint jerk limit
Add to [AXIS_l] sections:
MAX_JERK = 1000.0 # Per-axis jerk limit
CONSTANTS DEFINED
File: src/emc/nml_intf/emccfg.h
DEFAULT_TRAJ_DEFAULT_JERK = 0.0 (disabled)
DEFAULT_TRAJ_MAX_JERK = 0.0 (disabled)
DEFAULT_TRAJ_PLANNER_TYPE = 0 (trapezoidal)
DEFAULT_JOINT_MAX_JERK = 0.0 (disabled)
DEFAULT_AXIS_MAX_JERK = 0.0 (disabled)
BEHAVIOR
S-curve planning is ACTIVE when:
- PLANNER_TYPE = 1, AND
- MAX_LINEAR_JERK > 0
Trapezoidal planning is used when:
- PLANNER_TYPE = 0, OR
- MAX_LINEAR_JERK = 0 (or not specified)
Note: Setting MAX_JERK=0 with PLANNER_TYPE=1 reverts to trapezoidal
for backward compatibility and easy testing.
HAL PINS ADDED
*** IMPORTANT: All trajectory-level HAL pins support RUNTIME changes! ***
You can switch between trapezoidal and S-curve planning on-the-fly
by connecting HAL signals to these pins.
Trajectory level (all support runtime modification):
- ini.traj_default_jerk (IN, float) - Can change while running
- ini.traj_max_jerk (IN, float) - Can change while running
- ini.traj_planner_type (IN, s32) - Can change while running (0 or 1)
Joint level (for each joint N):
- ini.N.jerk (IN, float) - Joint jerk limit
- joint.N.jerk-cmd (OUT, float) - Current commanded jerk
Axis level (for each axis L):
- ini.L.jerk (IN, float) - Axis jerk limit
TYPICAL VALUES
Units depend on your LINEAR_UNITS setting (mm or inch)
Light/rigid machines: 1,000 - 10,000 units/s^3
Medium machines: 100 - 1,000 units/s^3
Heavy/flexible machines: 100 - 500 units/s^3
Very rigid machines: 10,000 - 100,000 units/s^3
Rule of thumb: MAX_JERK ≈ 10-100 × MAX_ACCELERATION
TUNING PROCEDURE
1. Start with PLANNER_TYPE=0 (verify machine works normally)
2. Set PLANNER_TYPE=1, MAX_LINEAR_JERK=100 (very conservative)
3. Test simple moves (jog, MDI commands)
4. Gradually increase MAX_LINEAR_JERK by 2-3x steps
5. Monitor motor current, following errors, vibration
6. Find sweet spot: smooth motion without sluggishness
7. Test coordinated motion (G2/G3 arcs, 3D paths)
RUNTIME SWITCHING (Advanced Feature)
All trajectory jerk parameters can be changed while LinuxCNC is running!
This allows dynamic switching between planning modes.
EXAMPLE 1: Toggle button to switch planners
In your HAL file:
# Create a toggle button
net planner-toggle-btn pyvcp.scurve-enable => ini.traj_planner_type
# When button=0: Trapezoidal
# When button=1: S-curve
EXAMPLE 2: Automatic switching based on feedrate
In your HAL file:
# Use motion.current-vel to switch planners
# High speed = trapezoidal (faster), Low speed = S-curve (smoother)
loadrt comp names=vel-compare
addf vel-compare servo-thread
setp vel-compare.in0 150.0 # Switch threshold (units/sec)
net current-vel motion.current-vel => vel-compare.in1
net use-scurve vel-compare.out => ini.traj_planner_type
EXAMPLE 3: MDI commands to change jerk on-the-fly
You can use halcmd in MDI or scripts:
halcmd setp ini.traj_max_jerk 2000.0
halcmd setp ini.traj_planner_type 1
EXAMPLE 4: Material-specific jerk settings
In PyVCP or custom GUI:
<pyvcp>
<labelframe text="Motion Profile">
<radiobutton>
<choices>["Wood (500)", "Aluminum (1500)", "Steel (2500)"]</choices>
<halpin>"material-jerk"</halpin>
</radiobutton>
</labelframe>
</pyvcp>
# In HAL, use mux component to select jerk value
# and connect to ini.traj_max_jerk
NOTES:
- Changes take effect on the NEXT motion command
- Safe to change during idle or between moves
- Existing queued moves use old parameters
- Great for A/B testing different jerk values
TROUBLESHOOTING
Q: No difference between PLANNER_TYPE=0 and PLANNER_TYPE=1?
A: Verify MAX_LINEAR_JERK > 0 and all joint/axis MAX_JERK > 0
Q: Motion is slower with S-curve?
A: Increase MAX_LINEAR_JERK value
Q: Following errors increased?
A: Decrease MAX_LINEAR_JERK or tune PID parameters
Q: Want to disable S-curve temporarily?
A: Set PLANNER_TYPE=0 (no need to change jerk values)
FILES MODIFIED
Core implementation:
- src/emc/tp/sp_scurve.c (NEW - S-curve algorithm)
- src/emc/tp/sp_scurve.h (NEW - S-curve header)
- src/emc/motion/simple_tp.c (dispatch to S-curve planner)
- src/emc/motion/simple_tp.h (add jerk support)
Motion control:
- src/emc/motion/motion.h (add jerk commands/status)
- src/emc/motion/command.c (handle jerk commands)
- src/emc/motion/control.c (jerk limiting in motion loop)
- src/emc/motion/axis.c (axis jerk limits)
INI file parsing:
- src/emc/ini/initraj.cc (parse TRAJ jerk params)
- src/emc/ini/inijoint.cc (parse JOINT jerk params)
- src/emc/ini/iniaxis.cc (parse AXIS jerk params)
- src/emc/ini/inihal.cc (HAL pin creation & updates)
- src/emc/ini/inihal.hh (HAL data structures)
Configuration:
- src/emc/nml_intf/emccfg.h (default constants)
- lib/hallib/check_config.tcl (INI validation)
Build system:
- src/Makefile (add sp_scurve.o to build)
- src/emc/motion-logger/Submakefile
EXAMPLE CONFIGURATIONS
See: configs/scurve_example.ini for complete examples
TESTING RECOMMENDATIONS
1. Air cut test programs with known good results
2. Compare surface finish: trapezoidal vs S-curve
3. Monitor following errors during complex paths
4. Check motor temperature (shouldn't increase significantly)
5. Listen for unusual vibrations or resonances
6. Measure cycle time differences
FOR DEVELOPERS
S-curve algorithm location: src/emc/tp/sp_scurve.c
Key function: simple_scurve_tp_update()
- Called from simple_tp_update() when jerk > 0
- Implements 7-segment S-curve profile
- Updates position, velocity, acceleration, jerk
Integration points:
- simple_tp.c: Planner selection based on max_jerk
- axis.c: Apply axis jerk limits
- control.c: Apply joint jerk limits
- command.c: Process EMCMOT_SET_JERK commands
COMMUNITY TESTING
This feature is new and needs community testing. Please report:
- Machine configuration (type, size, rigidity)
- Jerk values that worked well
- Any issues or unexpected behavior
- Comparison to trapezoidal planning
Report to: LinuxCNC mailing list, forum or Discord
S-curve / finite-jerk trajectory planner for testing.
For those that build from source just look for the new v2.10.0-pre1 tag.
Others can download debs from github for the next 90 days:
x86 / bookworm
x86 / trixie
ARM64 / bookworm
ARM64 / trixie
Make no mistake, this is experimental, there are no guarantees that
these won't break your machines. The first user already hit the hard
stops when homing (too-low max jerk setting)
With the jerk setting it is probably best to start high and reduce, as
infinite jerk is closer to current behavior.
If you run these you are volunteering to be a guinea-pig.
The docs have been updated, but here is the README original pull-request.
================================================================================
LINUXCNC S-CURVE MOTION PLANNING - QUICK REFERENCE
================================================================================
OVERVIEW
S-curve motion planning provides smoother acceleration by limiting jerk
(the rate of change of acceleration). This can reduce machine vibration,
improve surface finish, and extend machine life.
STATUS: Optional feature, disabled by default for backward compatibility
ENABLING S-CURVE PLANNING
Add to [TRAJ] section of your INI file:
PLANNER_TYPE = 1 # 0=trapezoidal (default), 1=S-curve
MAX_LINEAR_JERK = 1000.0 # Units: machine-units/s^3
DEFAULT_LINEAR_JERK = 500.0 # Default jerk for moves
Add to [JOINT_n] sections:
MAX_JERK = 1000.0 # Per-joint jerk limit
Add to [AXIS_l] sections:
MAX_JERK = 1000.0 # Per-axis jerk limit
CONSTANTS DEFINED
File: src/emc/nml_intf/emccfg.h
DEFAULT_TRAJ_DEFAULT_JERK = 0.0 (disabled)
DEFAULT_TRAJ_MAX_JERK = 0.0 (disabled)
DEFAULT_TRAJ_PLANNER_TYPE = 0 (trapezoidal)
DEFAULT_JOINT_MAX_JERK = 0.0 (disabled)
DEFAULT_AXIS_MAX_JERK = 0.0 (disabled)
BEHAVIOR
S-curve planning is ACTIVE when:
- PLANNER_TYPE = 1, AND
- MAX_LINEAR_JERK > 0
Trapezoidal planning is used when:
- PLANNER_TYPE = 0, OR
- MAX_LINEAR_JERK = 0 (or not specified)
Note: Setting MAX_JERK=0 with PLANNER_TYPE=1 reverts to trapezoidal
for backward compatibility and easy testing.
HAL PINS ADDED
*** IMPORTANT: All trajectory-level HAL pins support RUNTIME changes! ***
You can switch between trapezoidal and S-curve planning on-the-fly
by connecting HAL signals to these pins.
Trajectory level (all support runtime modification):
- ini.traj_default_jerk (IN, float) - Can change while running
- ini.traj_max_jerk (IN, float) - Can change while running
- ini.traj_planner_type (IN, s32) - Can change while running (0 or 1)
Joint level (for each joint N):
- ini.N.jerk (IN, float) - Joint jerk limit
- joint.N.jerk-cmd (OUT, float) - Current commanded jerk
Axis level (for each axis L):
- ini.L.jerk (IN, float) - Axis jerk limit
TYPICAL VALUES
Units depend on your LINEAR_UNITS setting (mm or inch)
Light/rigid machines: 1,000 - 10,000 units/s^3
Medium machines: 100 - 1,000 units/s^3
Heavy/flexible machines: 100 - 500 units/s^3
Very rigid machines: 10,000 - 100,000 units/s^3
Rule of thumb: MAX_JERK ≈ 10-100 × MAX_ACCELERATION
TUNING PROCEDURE
1. Start with PLANNER_TYPE=0 (verify machine works normally)
2. Set PLANNER_TYPE=1, MAX_LINEAR_JERK=100 (very conservative)
3. Test simple moves (jog, MDI commands)
4. Gradually increase MAX_LINEAR_JERK by 2-3x steps
5. Monitor motor current, following errors, vibration
6. Find sweet spot: smooth motion without sluggishness
7. Test coordinated motion (G2/G3 arcs, 3D paths)
RUNTIME SWITCHING (Advanced Feature)
All trajectory jerk parameters can be changed while LinuxCNC is running!
This allows dynamic switching between planning modes.
EXAMPLE 1: Toggle button to switch planners
In your HAL file:
# Create a toggle button
net planner-toggle-btn pyvcp.scurve-enable => ini.traj_planner_type
# When button=0: Trapezoidal
# When button=1: S-curve
EXAMPLE 2: Automatic switching based on feedrate
In your HAL file:
# Use motion.current-vel to switch planners
# High speed = trapezoidal (faster), Low speed = S-curve (smoother)
loadrt comp names=vel-compare
addf vel-compare servo-thread
setp vel-compare.in0 150.0 # Switch threshold (units/sec)
net current-vel motion.current-vel => vel-compare.in1
net use-scurve vel-compare.out => ini.traj_planner_type
EXAMPLE 3: MDI commands to change jerk on-the-fly
You can use halcmd in MDI or scripts:
halcmd setp ini.traj_max_jerk 2000.0
halcmd setp ini.traj_planner_type 1
EXAMPLE 4: Material-specific jerk settings
In PyVCP or custom GUI:
<pyvcp>
<labelframe text="Motion Profile">
<radiobutton>
<choices>["Wood (500)", "Aluminum (1500)", "Steel (2500)"]</choices>
<halpin>"material-jerk"</halpin>
</radiobutton>
</labelframe>
</pyvcp>
# In HAL, use mux component to select jerk value
# and connect to ini.traj_max_jerk
NOTES:
- Changes take effect on the NEXT motion command
- Safe to change during idle or between moves
- Existing queued moves use old parameters
- Great for A/B testing different jerk values
TROUBLESHOOTING
Q: No difference between PLANNER_TYPE=0 and PLANNER_TYPE=1?
A: Verify MAX_LINEAR_JERK > 0 and all joint/axis MAX_JERK > 0
Q: Motion is slower with S-curve?
A: Increase MAX_LINEAR_JERK value
Q: Following errors increased?
A: Decrease MAX_LINEAR_JERK or tune PID parameters
Q: Want to disable S-curve temporarily?
A: Set PLANNER_TYPE=0 (no need to change jerk values)
FILES MODIFIED
Core implementation:
- src/emc/tp/sp_scurve.c (NEW - S-curve algorithm)
- src/emc/tp/sp_scurve.h (NEW - S-curve header)
- src/emc/motion/simple_tp.c (dispatch to S-curve planner)
- src/emc/motion/simple_tp.h (add jerk support)
Motion control:
- src/emc/motion/motion.h (add jerk commands/status)
- src/emc/motion/command.c (handle jerk commands)
- src/emc/motion/control.c (jerk limiting in motion loop)
- src/emc/motion/axis.c (axis jerk limits)
INI file parsing:
- src/emc/ini/initraj.cc (parse TRAJ jerk params)
- src/emc/ini/inijoint.cc (parse JOINT jerk params)
- src/emc/ini/iniaxis.cc (parse AXIS jerk params)
- src/emc/ini/inihal.cc (HAL pin creation & updates)
- src/emc/ini/inihal.hh (HAL data structures)
Configuration:
- src/emc/nml_intf/emccfg.h (default constants)
- lib/hallib/check_config.tcl (INI validation)
Build system:
- src/Makefile (add sp_scurve.o to build)
- src/emc/motion-logger/Submakefile
EXAMPLE CONFIGURATIONS
See: configs/scurve_example.ini for complete examples
TESTING RECOMMENDATIONS
1. Air cut test programs with known good results
2. Compare surface finish: trapezoidal vs S-curve
3. Monitor following errors during complex paths
4. Check motor temperature (shouldn't increase significantly)
5. Listen for unusual vibrations or resonances
6. Measure cycle time differences
FOR DEVELOPERS
S-curve algorithm location: src/emc/tp/sp_scurve.c
Key function: simple_scurve_tp_update()
- Called from simple_tp_update() when jerk > 0
- Implements 7-segment S-curve profile
- Updates position, velocity, acceleration, jerk
Integration points:
- simple_tp.c: Planner selection based on max_jerk
- axis.c: Apply axis jerk limits
- control.c: Apply joint jerk limits
- command.c: Process EMCMOT_SET_JERK commands
COMMUNITY TESTING
This feature is new and needs community testing. Please report:
- Machine configuration (type, size, rigidity)
- Jerk values that worked well
- Any issues or unexpected behavior
- Comparison to trapezoidal planning
Report to: LinuxCNC mailing list, forum or Discord
Last edit: 08 Jan 2026 00:09 by andypugh.
The following user(s) said Thank You: tommylight
Please Log in or Create an account to join the conversation.
- tommylight
-
- Away
- Moderator
-
Less
More
- Posts: 21131
- Thank you received: 7220
08 Jan 2026 00:26 #341148
by tommylight
Replied by tommylight on topic A new finite-jerk (S-curve) trajectory planner for testing.
404 on all links on GitHub and 403 on the guinea pig.
Please Log in or Create an account to join the conversation.
- andypugh
-
Topic Author
- Offline
- Moderator
-
Less
More
- Posts: 19761
- Thank you received: 4589
08 Jan 2026 01:41 #341149
by andypugh
Replied by andypugh on topic A new finite-jerk (S-curve) trajectory planner for testing.
They all work for me. I will have to try them at work tomorrow as the other-me to maybe see what is going on.
Can you see: github.com/LinuxCNC/linuxcnc/actions/run...1121/job/59737821393 ?
Can you see: github.com/LinuxCNC/linuxcnc/actions/run...1121/job/59737821393 ?
Please Log in or Create an account to join the conversation.
- tommylight
-
- Away
- Moderator
-
Less
More
- Posts: 21131
- Thank you received: 7220
08 Jan 2026 02:53 - 08 Jan 2026 02:55 #341151
by tommylight
Yes, this works.
-
Hovering over your links shows:
github.com/LinuxCNC/linuxcnc/actions/run...artifacts/5056097663
While opening them goes to
github.com/LinuxCNC/linuxcnc/suites/5379...artifacts/5056097663
None work, but removing some tailing does open correct sections for
github.com/LinuxCNC/linuxcnc/actions/runs/20798441121/
where the "artifacts" are listed but not clickable.
Edit
I am not logged in there, i do not have an account.
Replied by tommylight on topic A new finite-jerk (S-curve) trajectory planner for testing.
Can you see: github.com/LinuxCNC/linuxcnc/actions/run...1121/job/59737821393 ?
Yes, this works.
-
Hovering over your links shows:
github.com/LinuxCNC/linuxcnc/actions/run...artifacts/5056097663
While opening them goes to
github.com/LinuxCNC/linuxcnc/suites/5379...artifacts/5056097663
None work, but removing some tailing does open correct sections for
github.com/LinuxCNC/linuxcnc/actions/runs/20798441121/
where the "artifacts" are listed but not clickable.
Edit
I am not logged in there, i do not have an account.
Last edit: 08 Jan 2026 02:55 by tommylight. Reason: more info
Please Log in or Create an account to join the conversation.
Time to create page: 0.074 seconds