Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
e547776
Phase 0: Tormach 9D Architecture Port
Jan 25, 2026
216cd2e
Phase 1: Move Kinematics to Userspace
Feb 1, 2026
0fcbbf6
Phase 3: Feed Override and Motion Planning Optimization
Feb 13, 2026
9b55e19
Force Kin in Uspace for Planner Type 2
Feb 13, 2026
85e76f2
Fix freezing in place
Feb 13, 2026
cfa4aff
small cleanup
Feb 13, 2026
9c752aa
Derive feed override deferral timing from servo cycle and scale durat…
Feb 13, 2026
3412a02
Proper state reset for each run
Feb 13, 2026
0444337
Chain-based downstream constraints and feed limiting for branch compu…
Feb 14, 2026
c2f77e0
fix end spike
Feb 14, 2026
6241e0f
Fix Profile v0 Mismatch
Feb 15, 2026
186219c
Fix Centripetal Acceleration Bound to kink_vel
Feb 15, 2026
8d465ec
Fix velocity chain gaps at junctions and improve feed override stability
Feb 15, 2026
c495140
lines get kink vel like arcs
Feb 15, 2026
d270ec3
Add alt-entry profiles and fix sub-cycle brake transitions
Feb 16, 2026
e4c5035
Virtual arc for line-line junctions
Feb 16, 2026
0b0d077
Eliminate stale feed-override profiles with one-shot cursor and v0-aw…
Feb 16, 2026
d8df326
Remove the hardcoded kinematics_type_id_t enum that prevented custom
Feb 17, 2026
7478ec7
G64 first draft
Feb 17, 2026
69049e4
Refactor Kinematics one file per module
Feb 17, 2026
d4f7c0d
refined kins docs
Feb 17, 2026
3af10f1
Blending refinements
Feb 18, 2026
26b3c54
Joint-space feedforward via finite differences for planner type 2
Feb 20, 2026
373d7a7
Reset canon length units on program open
Feb 20, 2026
99cbcf4
C2 curvature matching and path deviation for Bezier blends
Feb 20, 2026
24415b3
Curvature-matched blends and path deviation measurement
Feb 20, 2026
64c7837
G0/G1 blend guard, kink_vel fix, and tangential jerk budget
Feb 20, 2026
568a0de
Collinear segment consolidation for CAM toolpaths
Feb 20, 2026
7b1c7a0
Queue depth gate: eliminate velocity spike at segment activation
Feb 20, 2026
2eb3345
Fix abort freeze: bypass handoff margin for stop requests in computeB…
Feb 21, 2026
73b37d7
Bidirectional reachability cap: eliminate Working profiles from fixup…
Feb 21, 2026
a74d268
Fix split-cycle elapsed_time advance: prevent velocity dip on short s…
Feb 21, 2026
2a99353
attempt at fixing arm build
Feb 21, 2026
1a11aff
Refactor blend projection calculations in tpSetupBlend9D to normalize…
Feb 21, 2026
91949e8
Refactor bezier9PathDeviation to enforce distance to corner for stric…
Feb 21, 2026
688e5a0
Fix feed override junction velocity mismatches in downstream profile …
Feb 22, 2026
f20264b
Add near-active v0 reconciliation (Step 4) to fix stale-predecessor j…
Feb 23, 2026
fe2050a
Fix feed override crash/recovery spikes with alt-entry chain and clea…
Feb 23, 2026
c5005e9
Harden split-cycle junction velocity: jerk-based v0 cap, physical cla…
Feb 23, 2026
8f373db
Fix alt-entry flythrough bail blocking junction segments during feed …
Feb 23, 2026
713e70e
Invalidate stale alt-entries at writeAltEntry convergence break
Feb 23, 2026
981e051
Fix feed hold spill-over spikes with debounce exemption and branch-aw…
Feb 24, 2026
ee5d397
fix slowdown
Feb 24, 2026
8156b11
Fix abort spill-over negative velocity with physics-based acceleratio…
Feb 24, 2026
25454cd
rolled back refactor of bezier9
Feb 24, 2026
b186e01
Fix Bezier 9D tangent weighting, arc-length parameterization, and G0↔…
Feb 25, 2026
6af61da
Cubic Hermite arc-length interpolation for Bezier blends
Feb 25, 2026
0b30c5c
Reject stale-feed alt-entry profiles at RT junction handoff
Feb 25, 2026
6e205c1
spike prediction
Feb 26, 2026
6f8df7a
defer
Feb 26, 2026
0c4c68c
startup strategy
Feb 26, 2026
28dac44
guard on less than 0.001
Feb 26, 2026
5cf6b57
dynamic debounce
Feb 26, 2026
3cddfd1
accept closer vel
Feb 26, 2026
0726755
fixed 183 pattern
Feb 26, 2026
3ab6b62
before rearch
Feb 27, 2026
52f686f
simplified
Feb 27, 2026
0ab1c62
fixed feed-override seeding spike
Feb 27, 2026
6bac6c2
new helper fixupPass
Feb 27, 2026
5482259
pause and stop unified
Feb 27, 2026
55122cb
fix resume spikes: backward fixup end_idx covers full DS range
Feb 28, 2026
7659861
refactor
Feb 28, 2026
89b1747
100% ok
Feb 28, 2026
29731fe
200% ok
Feb 28, 2026
95d5102
fix unable to start
Feb 28, 2026
fbbf879
feed override struct
Feb 28, 2026
818d7b0
fix backward/forward velocity inconsistency at v_f≈0 junctions
Feb 28, 2026
1286e82
fix abort rogue segment: reset compressor before stop branch
Mar 1, 2026
e95a1c6
fix feed-override velocity oscillation: remove self-reinforcing min caps
Mar 1, 2026
67dfc84
remove backward pass depth limit: fix feed-change spikes on deep queues
Mar 1, 2026
86a903b
gate-based feed coalescing: eliminate cross-feed frontier spikes
Mar 1, 2026
a5955b0
better fail handling, better 10%
Mar 2, 2026
0873fdd
drop feed to 10% ok
Mar 2, 2026
77122c7
90 and 100% ok
Mar 2, 2026
49f0c72
fix STOP/EXACT spike
Mar 3, 2026
4433b35
cleanup some debug
Mar 3, 2026
1edb2f1
fixed some spikes due to wrong capping
Mar 3, 2026
faa95a1
fix bidir spikes
Mar 3, 2026
6b82b7d
fixed corridor-kink pattern spikes
Mar 3, 2026
3eca4dc
better 0%
Mar 3, 2026
fe375d8
removed debug
Mar 3, 2026
816e596
fixed freezing up on non-tangent
Mar 3, 2026
72e5e6b
FINALIZED gate: prevent segment activation before boundaries known
Mar 4, 2026
1d1fb0f
removed spike debug
Mar 4, 2026
0c0a609
chain-split: fix short-segment lost-time jerk spikes
Mar 5, 2026
82b0a6a
reinstated cubic for planner type 2
Mar 5, 2026
cce8e41
fix C1 discontinuity from collinear consolidation after blend trim
Mar 5, 2026
5f60d78
fix premature FINALIZED gate on G-code mode change
Mar 6, 2026
d8a51e1
fix include paths after upstream rebase (relative paths for non-INCLU…
Mar 6, 2026
a6511ab
fix ARM build: remove spurious SRCHEADERS (tp/kinematics headers cove…
Mar 6, 2026
969bded
fix initraj.cc: use qualified motion/motion.h path for ini/ directory
Mar 6, 2026
84a6c4e
fix include paths in motion_planning: use relative ../tp/ and motion/…
Mar 6, 2026
eba8e59
fix remaining flat includes in motion_planning: blendmath.h and motio…
Mar 6, 2026
f3fd553
convert all kinematics modules to nonrt_attach architecture
Mar 6, 2026
db1d070
replace hal_priv.h/SHMOFF/self_offset with hal_struct_newf/attach API
Mar 7, 2026
1af95ba
refactor hal_struct to use a dedicated namespace
Mar 7, 2026
cf54273
fix hal_struct: indentation, comp->ready check, duplicate/detach errors
Mar 8, 2026
8921ed0
hal_struct: add man3 pages and halcmd show/list struct support
Mar 8, 2026
330b993
hal_struct: fix man page: use AsciiDoc source, not hand-written troff
Mar 8, 2026
6e54e8a
fix velocity spikes at segment junctions under feed override
Mar 8, 2026
c8ffcb9
hal_struct man page: add volatile to example, ignore generated .3 files
Mar 8, 2026
5db5c73
Add comp_kins_uspace.h glue for .comp kinematics planner type 2 support
Mar 14, 2026
cb9e970
Fix header-sanity: align with bertho's include isolation model
Mar 14, 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