Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
8766d37
Phase 0: Tormach 9D Architecture Port
Jan 25, 2026
3b2533e
Phase 1: Move Kinematics to Userspace
Feb 1, 2026
fac868a
Phase 3: Feed Override and Motion Planning Optimization
Feb 13, 2026
9abe3bc
Force Kin in Uspace for Planner Type 2
Feb 13, 2026
2f7b532
Fix freezing in place
Feb 13, 2026
eeaabf7
small cleanup
Feb 13, 2026
dd3e39a
Derive feed override deferral timing from servo cycle and scale durat…
Feb 13, 2026
3817e20
Proper state reset for each run
Feb 13, 2026
12846cf
Chain-based downstream constraints and feed limiting for branch compu…
Feb 14, 2026
331092d
fix end spike
Feb 14, 2026
e1399ed
Fix Profile v0 Mismatch
Feb 15, 2026
cba4c4f
Fix Centripetal Acceleration Bound to kink_vel
Feb 15, 2026
e56db68
Fix velocity chain gaps at junctions and improve feed override stability
Feb 15, 2026
48bdb6a
lines get kink vel like arcs
Feb 15, 2026
3c4c2d4
Add alt-entry profiles and fix sub-cycle brake transitions
Feb 16, 2026
53132b2
Virtual arc for line-line junctions
Feb 16, 2026
243ac03
Eliminate stale feed-override profiles with one-shot cursor and v0-aw…
Feb 16, 2026
194e11f
Remove the hardcoded kinematics_type_id_t enum that prevented custom
Feb 17, 2026
de98ce9
G64 first draft
Feb 17, 2026
9be13ed
Refactor Kinematics one file per module
Feb 17, 2026
368c2e7
refined kins docs
Feb 17, 2026
36a81ea
Blending refinements
Feb 18, 2026
dc2fa79
Joint-space feedforward via finite differences for planner type 2
Feb 20, 2026
e39e68d
Reset canon length units on program open
Feb 20, 2026
82f01e3
C2 curvature matching and path deviation for Bezier blends
Feb 20, 2026
19b8b12
Curvature-matched blends and path deviation measurement
Feb 20, 2026
8439acf
G0/G1 blend guard, kink_vel fix, and tangential jerk budget
Feb 20, 2026
9328d60
Collinear segment consolidation for CAM toolpaths
Feb 20, 2026
c9b7079
Queue depth gate: eliminate velocity spike at segment activation
Feb 20, 2026
d622d09
Fix abort freeze: bypass handoff margin for stop requests in computeB…
Feb 21, 2026
08c2d26
Bidirectional reachability cap: eliminate Working profiles from fixup…
Feb 21, 2026
8733cb8
Fix split-cycle elapsed_time advance: prevent velocity dip on short s…
Feb 21, 2026
dc46a96
attempt at fixing arm build
Feb 21, 2026
d1640d9
Refactor blend projection calculations in tpSetupBlend9D to normalize…
Feb 21, 2026
6f7b530
Refactor bezier9PathDeviation to enforce distance to corner for stric…
Feb 21, 2026
e4a9fed
Fix feed override junction velocity mismatches in downstream profile …
Feb 22, 2026
7d48fac
Add near-active v0 reconciliation (Step 4) to fix stale-predecessor j…
Feb 23, 2026
5d7a8a0
Fix feed override crash/recovery spikes with alt-entry chain and clea…
Feb 23, 2026
6d69c3b
Harden split-cycle junction velocity: jerk-based v0 cap, physical cla…
Feb 23, 2026
d922494
Fix alt-entry flythrough bail blocking junction segments during feed …
Feb 23, 2026
ffd8cf4
Invalidate stale alt-entries at writeAltEntry convergence break
Feb 23, 2026
666da0b
Fix feed hold spill-over spikes with debounce exemption and branch-aw…
Feb 24, 2026
c532380
fix slowdown
Feb 24, 2026
a97b25c
Fix abort spill-over negative velocity with physics-based acceleratio…
Feb 24, 2026
38822f9
rolled back refactor of bezier9
Feb 24, 2026
3932eca
Fix Bezier 9D tangent weighting, arc-length parameterization, and G0↔…
Feb 25, 2026
f0e6e7b
Cubic Hermite arc-length interpolation for Bezier blends
Feb 25, 2026
24e0323
Reject stale-feed alt-entry profiles at RT junction handoff
Feb 25, 2026
e08dc2a
spike prediction
Feb 26, 2026
313ff51
defer
Feb 26, 2026
6179ab1
startup strategy
Feb 26, 2026
ebfe042
guard on less than 0.001
Feb 26, 2026
909efed
dynamic debounce
Feb 26, 2026
d82d3cd
accept closer vel
Feb 26, 2026
ef90839
fixed 183 pattern
Feb 26, 2026
0e5c3b5
before rearch
Feb 27, 2026
682f6eb
simplified
Feb 27, 2026
23177af
fixed feed-override seeding spike
Feb 27, 2026
a0b5df2
new helper fixupPass
Feb 27, 2026
55b288d
pause and stop unified
Feb 27, 2026
d7e1c0f
fix resume spikes: backward fixup end_idx covers full DS range
Feb 28, 2026
4756e8c
refactor
Feb 28, 2026
9f86da5
100% ok
Feb 28, 2026
0417aa6
200% ok
Feb 28, 2026
3e0228b
fix unable to start
Feb 28, 2026
ddf499b
feed override struct
Feb 28, 2026
0a9fa9f
fix backward/forward velocity inconsistency at v_f≈0 junctions
Feb 28, 2026
ca0cc99
fix abort rogue segment: reset compressor before stop branch
Mar 1, 2026
8ec2127
fix feed-override velocity oscillation: remove self-reinforcing min caps
Mar 1, 2026
e246544
remove backward pass depth limit: fix feed-change spikes on deep queues
Mar 1, 2026
935b203
gate-based feed coalescing: eliminate cross-feed frontier spikes
Mar 1, 2026
43143d6
better fail handling, better 10%
Mar 2, 2026
8aece55
drop feed to 10% ok
Mar 2, 2026
1903e07
90 and 100% ok
Mar 2, 2026
2549262
fix STOP/EXACT spike
Mar 3, 2026
ad732c4
cleanup some debug
Mar 3, 2026
f4f382b
fixed some spikes due to wrong capping
Mar 3, 2026
22163b9
fix bidir spikes
Mar 3, 2026
dc90c99
fixed corridor-kink pattern spikes
Mar 3, 2026
e624210
better 0%
Mar 3, 2026
e771d1e
removed debug
Mar 3, 2026
37d2836
fixed freezing up on non-tangent
Mar 3, 2026
0f5d15d
FINALIZED gate: prevent segment activation before boundaries known
Mar 4, 2026
56e0043
removed spike debug
Mar 4, 2026
a25664e
chain-split: fix short-segment lost-time jerk spikes
Mar 5, 2026
0b149b4
reinstated cubic for planner type 2
Mar 5, 2026
37ca561
fix C1 discontinuity from collinear consolidation after blend trim
Mar 5, 2026
2c53e4c
fix premature FINALIZED gate on G-code mode change
Mar 6, 2026
7d90087
fix include paths after upstream rebase (relative paths for non-INCLU…
Mar 6, 2026
b99685c
fix ARM build: remove spurious SRCHEADERS (tp/kinematics headers cove…
Mar 6, 2026
e36868e
fix initraj.cc: use qualified motion/motion.h path for ini/ directory
Mar 6, 2026
86cd415
fix include paths in motion_planning: use relative ../tp/ and motion/…
Mar 6, 2026
44e4e5e
fix remaining flat includes in motion_planning: blendmath.h and motio…
Mar 6, 2026
ebf69d5
convert all kinematics modules to nonrt_attach architecture
Mar 6, 2026
9c0ce1c
replace hal_priv.h/SHMOFF/self_offset with hal_struct_newf/attach API
Mar 7, 2026
74f0eb7
refactor hal_struct to use a dedicated namespace
Mar 7, 2026
abd2bc6
fix hal_struct: indentation, comp->ready check, duplicate/detach errors
Mar 8, 2026
84dfb00
hal_struct: add man3 pages and halcmd show/list struct support
Mar 8, 2026
27bff0a
hal_struct: fix man page: use AsciiDoc source, not hand-written troff
Mar 8, 2026
ecc6305
fix velocity spikes at segment junctions under feed override
Mar 8, 2026
95d616c
hal_struct man page: add volatile to example, ignore generated .3 files
Mar 8, 2026
b0147b6
Add comp_kins_uspace.h glue for .comp kinematics planner type 2 support
Mar 14, 2026
19e7ad2
Fix header-sanity: align with bertho's include isolation model
Mar 14, 2026
dc87197
fix blend jerk overshoot: partition tangential+centripetal budget per…
Apr 7, 2026
066f73b
port TP2 userspace planner from C++ Ruckig to cruckig
Apr 7, 2026
e5a8ebe
Build warning fix, and cruckig compatibility fix
Apr 7, 2026
86b4ea7
Register motion_planning public headers with HEADERS for make clean
Apr 12, 2026
a3951f1
Bezier tolerance to match TP0 distance from corners and not just enti…
Apr 7, 2026
1f24b10
Fast bezier init for blend optimizer + skip RT ack for planner type 2
Apr 9, 2026
3561764
Fix uninitialized read in bezier9MaxCurvature when called via bezier9…
Apr 10, 2026
fe0787a
TP2: short-segment blend guard fix + blend sizing improvements
Apr 12, 2026
0c1e98f
Move comp_kins_uspace.h from include/ to src/emc/kinematics/
Apr 12, 2026
4ed086c
Fix author signatures: aitekcnc → LinuxCNC
Apr 12, 2026
d429133
Fix backward pass using wrong kink_vel junction — tc exit kink leaked…
Apr 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/man/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ man3/hal_port_t.3
man3/hal_port.3
man3/hal_ready.3
man3/hal_s32_t.3
man3/hal_struct_attach.3
man3/hal_struct_detach.3
man3/hal_struct_newf.3
man3/hal_set_constructor.3
man3/hal_set_lock.3
man3/hal_signal_delete.3
Expand Down
1 change: 1 addition & 0 deletions docs/po4a.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@
[type: AsciiDoc_def] src/man/man3/hal_signal_new.3.adoc $lang:src/$lang/man/man3/hal_signal_new.3.adoc
[type: AsciiDoc_def] src/man/man3/hal_start_threads.3.adoc $lang:src/$lang/man/man3/hal_start_threads.3.adoc
[type: AsciiDoc_def] src/man/man3/hal_stream.3.adoc $lang:src/$lang/man/man3/hal_stream.3.adoc
[type: AsciiDoc_def] src/man/man3/hal_struct_newf.3.adoc $lang:src/$lang/man/man3/hal_struct_newf.3.adoc
[type: AsciiDoc_def] src/man/man3/hal_type_t.3.adoc $lang:src/$lang/man/man3/hal_type_t.3.adoc
[type: AsciiDoc_def] src/man/man3/hm2_allocate_bspi_tram.3.adoc $lang:src/$lang/man/man3/hm2_allocate_bspi_tram.3.adoc
[type: AsciiDoc_def] src/man/man3/hm2_bspi_set_read_function.3.adoc $lang:src/$lang/man/man3/hm2_bspi_set_read_function.3.adoc
Expand Down
104 changes: 102 additions & 2 deletions docs/src/config/ini-config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -861,8 +861,13 @@ Finally, no amount of tweaking will speed up a tool path with lots of small, tig
* `MAX_LINEAR_VELOCITY = 5.0` - (((MAX VELOCITY))) The maximum velocity for any axis or coordinated move, in 'machine units' per second.
The value shown equals 300 units per minute.
* `MAX_LINEAR_ACCELERATION = 20.0` - (((MAX ACCELERATION))) The maximum acceleration for any axis or coordinated axis move, in 'machine units' per second per second.
* `PLANNER_TYPE = 0` - (((PLANNER TYPE))) Selects the trajectory planner type: 0 = trapezoidal (default), 1 = S-curve with jerk limiting.
S-curve planning is only active when `PLANNER_TYPE = 1` AND `MAX_LINEAR_JERK > 0`.
* `PLANNER_TYPE = 0` - (((PLANNER TYPE))) Selects the trajectory planner type:
** 0 = trapezoidal velocity profile (default)
** 1 = S-curve with jerk limiting
** 2 = 9D jerk-limited planner with Ruckig library (see <<sub:ini:sec:traj:9d-planner,9D Planner>>)
+
S-curve planning (type 1) is only active when `PLANNER_TYPE = 1` AND `MAX_LINEAR_JERK > 0`.
The 9D planner (type 2) provides time-optimal jerk-limited trajectories with responsive feed override handling.
* `MAX_LINEAR_JERK = 10000.0` - (((MAX JERK))) The maximum jerk (rate of change of acceleration) for coordinated moves, in 'machine units' per second cubed.
Default is 1e9 (1 billion) if not specified, which effectively disables jerk limiting while avoiding numerical instability.
Values are clamped to a maximum of 1e9 to prevent numerical issues in S-curve calculations.
Expand Down Expand Up @@ -897,6 +902,101 @@ LinuxCNC will not know your joint travel limits when using `NO_FORCE_HOMING = 1`
* `NO_PROBE_JOG_ERROR = 0` - Allow to bypass probe tripped check when you jog manually.
* `NO_PROBE_HOME_ERROR = 0` - Allow to bypass probe tripped check when homing is in progress.

[[sub:ini:sec:traj:9d-planner]]
==== 9D Jerk-Limited Planner (PLANNER_TYPE = 2)

The 9D planner is an advanced trajectory planning system that uses the Ruckig library
for time-optimal, jerk-limited motion profiles. It features a dual-layer architecture
with userspace planning and real-time execution, providing responsive feed override
handling without motion discontinuities.

[NOTE]
====
The 9D planner is an experimental feature. Use `PLANNER_TYPE = 2` to enable it.
This planner is recommended for machines that require smooth motion with jerk limiting,
and responsive feed override changes during motion.
====

===== Basic 9D Planner Parameters

* `PLANNER_TYPE = 2` - Selects the 9D jerk-limited trajectory planner.
This enables the Ruckig-based motion planning with userspace optimization.
* `OPTIMIZATION_DEPTH = 8` - Number of segments to look ahead for velocity optimization (range: 4-200, default: 8).
Higher values allow the planner to achieve higher velocities on longer paths
by planning deceleration further in advance.
* `RAMP_FREQUENCY = 10.0` - Cutoff frequency in Hz for ramped velocity mode (range: 1.0-1000.0, default: 10.0).
Segments shorter than 1/RAMP_FREQUENCY seconds use constant acceleration instead
of trapezoidal profiles to reduce jerk on very short moves.
* `SMOOTHING_PASSES = 2` - Number of velocity smoothing passes (range: 1-10, default: 2).
Additional passes reduce velocity peaks but may slightly reduce maximum throughput.
* `TC_QUEUE_SIZE = 50` - Size of the trajectory queue (range: 32-400, default: 50).
Larger queues allow more look-ahead but use more memory.
===== Predictive Feed Override Handoff Parameters

These parameters control the branch/merge architecture for handling feed override changes.
When the operator adjusts the feed override, the planner computes a new trajectory
branch in userspace and hands it off to the real-time layer at a predicted future time.
This allows smooth velocity transitions without motion discontinuities.

* `HANDOFF_HORIZON_MS = 100` - How far ahead (in milliseconds) to predict the handoff point (range: 1-1000, default: 100).
This value must exceed the worst-case userspace latency to ensure the new trajectory
is ready before the real-time layer reaches the handoff point.
Typical values: 50-200ms depending on system load.
* `BRANCH_WINDOW_MS = 50` - Window size (in milliseconds) for RT to accept the branch (range: 10-500, default: 50).
The real-time layer must reach the handoff point within this window after HANDOFF_HORIZON_MS
to accept the new trajectory. If the window expires, the branch is discarded.
* `MIN_BUFFER_TIME_MS = 100` - Minimum buffered motion time before alarm (range: 10-1000, default: 100).
If the motion buffer drops below this value, a warning is generated.
Very short buffer times risk motion starvation.
* `TARGET_BUFFER_TIME_MS = 200` - Target buffered motion time (range: MIN_BUFFER_TIME_MS-2000, default: 200).
The optimizer aims to maintain at least this much motion in the buffer.
* `MAX_BUFFER_TIME_MS = 500` - Maximum buffered motion time (range: TARGET_BUFFER_TIME_MS-5000, default: 500).
The optimizer stops adding new segments when the buffer exceeds this value.
* `FEED_OVERRIDE_DEBOUNCE_MS = 50` - Minimum time between branch computations (range: 1-500, default: 50).
When the operator rapidly changes the feed override (e.g., with a rotary knob),
this debounce prevents excessive recomputation. After computing a branch,
the planner waits this long before computing another.

===== Example 9D Planner Configuration

[source,{ini}]
----
[TRAJ]
# Basic trajectory settings
LINEAR_UNITS = mm
ANGULAR_UNITS = degree
MAX_LINEAR_VELOCITY = 100.0
MAX_LINEAR_ACCELERATION = 2000.0
MAX_LINEAR_JERK = 50000.0

# Enable 9D planner
PLANNER_TYPE = 2

# 9D planner tuning
OPTIMIZATION_DEPTH = 16
RAMP_FREQUENCY = 20.0
SMOOTHING_PASSES = 2
TC_QUEUE_SIZE = 100

# Predictive handoff tuning (optional - defaults work well for most systems)
# HANDOFF_HORIZON_MS = 100
# BRANCH_WINDOW_MS = 50
# MIN_BUFFER_TIME_MS = 100
# TARGET_BUFFER_TIME_MS = 200
# MAX_BUFFER_TIME_MS = 500
# FEED_OVERRIDE_DEBOUNCE_MS = 50
----

[NOTE]
====
The 9D planner automatically uses the servo cycle time from `[EMCMOT]SERVO_PERIOD`
and jerk limits from `MAX_LINEAR_JERK`. If `MAX_LINEAR_JERK` is not specified,
a default of 50000 (units per second cubed) is used.

Per-joint jerk limits can also be specified in `[JOINT_N]MAX_JERK` sections.
The planner uses the most restrictive limit for each move.
====


[[sub:ini:sec:kins]]
=== [KINS] Section(((INI File,Sections,KINS Section)))
Expand Down
110 changes: 110 additions & 0 deletions docs/src/man/man3/hal_struct_newf.3.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
:manvolnum: 3

= hal_struct_newf(3)

== NAME

hal_struct_newf, hal_struct_attach, hal_struct_detach - named opaque blobs in HAL shared memory

== SYNTAX

int hal_struct_newf(int _comp_id_, long int _size_, const void *_defval_, const char *_fmt_, _..._)

int hal_struct_attach(const char *_name_, void **_memptr_)

int hal_struct_detach(const char *_name_)

== ARGUMENTS

_comp_id_::
A HAL component identifier returned by an earlier call to *hal_init*.

_size_::
The number of bytes to allocate in HAL shared memory for the data blob.

_defval_::
A pointer to an initialiser of _size_ bytes that is copied into the
newly allocated blob. If NULL the blob is zero-initialised.

_fmt, ..._::
A printf-style format string and arguments that form the name of the entry.
The resulting name must be no longer than HAL_NAME_LEN characters.

_name_::
The name of the struct entry to find, as passed to *hal_struct_newf*.

_memptr_::
Address of a pointer that will be set to point at the data blob on success.

== DESCRIPTION

HAL struct entries are named, reference-counted opaque blobs that live in HAL
shared memory. They occupy a separate namespace from pins, signals, and
parameters and are therefore not visible in *halcmd show pin* or
*halcmd show param* output. Use *halcmd show struct* to inspect them.

*hal_struct_newf* allocates _size_ bytes from HAL shared memory, optionally
initialises the region from _defval_ (or zeroes if NULL), and registers it
under the printf-formatted name. The function must be called before
*hal_ready(3)*. There is no corresponding delete function; the data lives for
the lifetime of the HAL shared memory block. The entry metadata is reclaimed
automatically when the owning component calls *hal_exit(3)*.

*hal_struct_attach* finds the entry by name, increments its reference count,
and stores a pointer to the data blob in _*memptr_. It may be called from
both realtime and userspace contexts after *hal_init(3)*.

*hal_struct_detach* decrements the reference count. Calling it when the
reference count is already zero is an error. The data is not freed.

== RETURN VALUE

All three functions return 0 on success. On failure they return a negative
HAL status code:

*-EINVAL*::
Bad argument, duplicate name (*hal_struct_newf*), component is already ready
(*hal_struct_newf*), or detach underflow (*hal_struct_detach*).

*-ENOMEM*::
Name too long, or HAL shared memory exhausted.

*-ENOENT*::
No entry with the given name found (*hal_struct_attach* or *hal_struct_detach*).

== EXAMPLE

RT side (in _rtapi_app_main_):

----
typedef struct { double value; int count; } my_params_t;
static volatile my_params_t *params;

my_params_t defaults = { 1.0, 0 };
if (hal_struct_newf(comp_id, sizeof(*params), &defaults,
"%s.params", prefix) < 0)
return -1;
if (hal_struct_attach(prefix ".params", (void **)&params) < 0)
return -1;
----

Userspace side:

----
volatile my_params_t *params;
if (hal_struct_attach("mycomp.params", (void **)&params) < 0)
return -1;
/* read params->value, params->count ... */
hal_struct_detach("mycomp.params");
----

The pointer should be declared `volatile` on both sides so the compiler does
not cache fields across accesses. Note that `volatile` alone does not
guarantee memory ordering between threads or processes. For fields that must
be read and written atomically (for example a sequence-lock head/tail pair),
use C11 `_Atomic` or explicit `__atomic_*` intrinsics with an appropriate
memory order.

== SEE ALSO

hal_init(3), hal_malloc(3), hal_exit(3), halcmd(1)
Loading
Loading