This commit is contained in:
2026-09-09 17:35:23 +08:00
parent 2a98ae7556
commit 161af68fe3
1271 changed files with 58251 additions and 98639 deletions
@@ -319,6 +319,18 @@ Modal carry to subsequent blocks is handled by
<a class="xref" href="Hi.NcParsers.PostLogicSyntaxs.ModalCarrySyntax.html">ModalCarrySyntax</a>, which already tracks the
<code>PathSmoothing</code> section key and deep-clones it forward.
</p>
<p>
Also consumes the bare <code>G05 P{n}</code> HPCC family (captured by
<a class="xref" href="Hi.NcParsers.Syntaxs.FanucSyntaxUtil.html#Hi_NcParsers_Syntaxs_FanucSyntaxUtil_G05Syntax">G05Syntax</a>) into the block-local
<a class="xref" href="Hi.NcParsers.Keywords.FanucHpcc.html">FanucHpcc</a> section — recognized, intentionally not
simulated (the <a class="xref" href="Hi.NcParsers.LogicSyntaxs.Siemens.SiemensStopreSyntax.html">SiemensStopreSyntax</a> pattern).
Ignoring P10000/P0 is safe offline; an ignored high-speed cycle
machining call (P10001–P10999) means the simulation misses that
machining, surfaced as a Warning. See <a class="xref" href="Hi.NcParsers.Keywords.IFanucHpccDef.html">IFanucHpccDef</a> for
the P function-selection semantics. The section is deliberately
separate from the modal <code>PathSmoothing</code> section and is not
modal-carried.
</p>
</dd>
</dl>
<dl class="jumplist">
@@ -430,7 +442,13 @@ by <a class="xref" href="Hi.NcParsers.LogicSyntaxs.PositioningSyntax.html">Posit
Per-word override: a block-root
<a class="xref" href="Hi.NcParsers.Keywords.PositioningOverride.html">PositioningOverride</a> section (written by
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensAcIcSyntax.html">SiemensAcIcSyntax</a> for the
Siemens per-word coordinate functions) beats the modal
Siemens per-word coordinate functions, and by the Heidenhain L / C /
CC / CYCL CALL POS parsers for the klartext I-prefixed words — see
<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Heidenhain.HeidenhainIncrementalAxisWordUtil.html">HeidenhainIncrementalAxisWordUtil</a>;
the CYCL CALL POS words never reach this syntax,
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainCannedCycleSyntax.html">HeidenhainCannedCycleSyntax</a> resolves them on
the spot ahead of it)
beats the modal
term for the listed axes on this block only: an
<a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_Incremental">Incremental</a> entry converts that word even
under G90, an <a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_Absolute">Absolute</a> entry skips it even
@@ -450,13 +468,18 @@ is rewritten to the resolved absolute coordinate, and the entry to
<a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_Absolute">Absolute</a>; a failed resolve reports an error
and holds the last program position. Axes without an entry follow the
modal term unchanged, so brands that never write the section
(Fanuc/Heidenhain/...) keep the exact legacy behavior.
(Fanuc/...) keep the exact legacy behavior.
</p>
<p>
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.IncrementalResolveSyntax.html#Hi_NcParsers_LogicSyntaxs_IncrementalResolveSyntax_WorkingPathList">WorkingPathList</a> specifies which JSON paths
contain axis values that need incremental-to-absolute conversion.
Default: <code>[["Parsing"], ["Parsing", "G28"]]</code>.
All matching paths are converted.
Default: <code>[["Parsing"], ["Parsing", "G28"]]</code>; the Heidenhain
bundle instead walks <code>["Parsing", "CC"]</code> for the klartext
circle-center record
(<a class="xref" href="Hi.NcParsers.Syntaxs.HeidenhainSyntaxUtil.html#Hi_NcParsers_Syntaxs_HeidenhainSyntaxUtil_CcAwareIncrementalResolveSyntax">CcAwareIncrementalResolveSyntax</a>).
All matching paths are converted against the same last program
position — a nested record's words are distances from where the
tool stands, exactly like the root's.
</p>
<p>
Canned cycle paths (Parsing.G81, G82, G83, …) are intentionally
@@ -478,13 +501,40 @@ incremental logic.
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.IsoCoordinateOffsetSyntax.html">IsoCoordinateOffsetSyntax</a></dt>
<dd><p>ISO/Fanuc/Mazak/Okuma/Syntec: resolves G54–G59.9 work coordinate offset.
Reads G54/G55/.../G59.9 from <a class="xref" href="Hi.NcParsers.Keywords.IFlagsDef.html#Hi_NcParsers_Keywords_IFlagsDef_Flags">Flags</a>,
looks up offset Vec3d via <a class="xref" href="Hi.NcParsers.Dependencys.IIsoCoordinateConfig.html">IIsoCoordinateConfig</a> dependencies
(e.g. brand parameter table or <a class="xref" href="Hi.NcParsers.Dependencys.Generic.IsoCoordinateTable.html">IsoCoordinateTable</a>),
composes into <a class="xref" href="Hi.NcParsers.Keywords.ITransformationDef.html#Hi_NcParsers_Keywords_ITransformationDef_ProgramToMcTransform">ProgramToMcTransform</a>.
Modal — active coordinate persists via backward lookback.
<dd><p>ISO/Fanuc/Mazak/Okuma/Syntec: resolves the G54–G59.9 work coordinate
offset and the Fanuc-family additional work coordinate systems
(<code>G54.1 Pn</code>, also spelled <code>G54 Pn</code>).
Reads G54/G55/.../G59.9 from <a class="xref" href="Hi.NcParsers.Keywords.IFlagsDef.html#Hi_NcParsers_Keywords_IFlagsDef_Flags">Flags</a> and the
captured <code>Parsing.G54.1 = {P: n}</code> object (written by
<a class="xref" href="Hi.NcParsers.Syntaxs.FanucSyntaxUtil.html#Hi_NcParsers_Syntaxs_FanucSyntaxUtil_G54p1Syntax">G54p1Syntax</a> for both spellings),
which resolves to the coordinate id <code>&quot;G54.1P{n}&quot;</code> that the brand
parameter tables map to <code>#7001+</code>
(<a class="xref" href="Hi.NcParsers.Dependencys.IsoCoordinateAddressMap.html">IsoCoordinateAddressMap</a>). Looks the offset Vec3d up via
the <a class="xref" href="Hi.NcParsers.Dependencys.IIsoCoordinateConfig.html">IIsoCoordinateConfig</a> dependencies (brand parameter
table or <a class="xref" href="Hi.NcParsers.Dependencys.Generic.IsoCoordinateTable.html">IsoCoordinateTable</a>) and composes it into
<a class="xref" href="Hi.NcParsers.Keywords.ITransformationDef.html#Hi_NcParsers_Keywords_ITransformationDef_ProgramToMcTransform">ProgramToMcTransform</a>.
Modal — the active coordinate persists via backward lookback.
Default coordinate ID is set by <a class="xref" href="Hi.NcParsers.Initializers.StaticInitializer.html">StaticInitializer</a>.</p>
<p>
A block that selects a work coordinate system nobody has configured is
reported on that block (never on the modal re-query of the following
blocks): <code>Coord-WorkOffset--AdditionalZero</code> when an additional
system (<code>G54.1 Pn</code>) resolves to no entry or to (0, 0, 0) — the
brand tables seed every P row with zero, hardware-faithfully, so a zero
there is the "never entered" state, whereas a zero row of the standard
series (G54–G59 and the G59.1–G59.9 extension alike) is a legitimate
authoring convention and stays silent;
<code>Coord-WorkOffset--NoTableEntry</code> when no provider resolves the id
at all (e.g. a <code>G59.x</code> on a runner carrying no brand-neutral table
beside its brand table); and
<code>Coord-WorkOffset--IndexUnresolved</code> when the P word is not a
positive integer (vacant variable, non-integer), in which case the
active system is kept. A bare <code>G54.1</code> without P is not this
syntax's business: the parameterized capture consumes nothing without
a parameter, the dotted number lands in <code>Parsing.Flags</code> where it
is not a G54-series member, so the active system is kept and the
unconsumed check reports the flag.
</p>
</dd>
</dl>
<dl class="jumplist">
@@ -590,7 +640,12 @@ Undeclared codes are untouched and keep falling through to
The axis values (X/Y/Z) in the block are interpreted as machine
coordinates, bypassing all work offsets, local coordinates,
tool height compensation, and coordinate rotations.
If G91 (incremental) is active, the code is ignored per ISO standard.</p>
If G91 (incremental) is active, the code is ignored per ISO standard.
A per-word incremental stamp on the block (block-root
<a class="xref" href="Hi.NcParsers.Keywords.PositioningOverride.html">PositioningOverride</a> entry <a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_Incremental">Incremental</a>
— Siemens <code>SUPA Y=IC(-10)</code>, klartext <code>L IY-10 M91</code>) is a
distance in the <b>machine</b> frame: the word is added to the
previous machine position of that axis.</p>
<p>
Defaults to ISO <code>G53</code>. Brands with additional one-shot
machine-coordinate codes widen <a class="xref" href="Hi.NcParsers.LogicSyntaxs.MachineCoordSelectSyntax.html#Hi_NcParsers_LogicSyntaxs_MachineCoordSelectSyntax_SupportedCodes">SupportedCodes</a> — the
@@ -605,12 +660,14 @@ Rotary words on the same block (e.g. <code>SUPA G0 B0</code>) are left to
axes flow through the normal rotary path.
</p>
<p>
Must be placed <b>before</b> <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzSyntax.html">ProgramXyzSyntax</a> in the
syntax chain. When a supported code is active, this syntax consumes
X/Y/Z from <a class="xref" href="Hi.NcParsers.Keywords.IParsingDef.html#Hi_NcParsers_Keywords_IParsingDef_Parsing">Parsing</a> and writes
Must be placed <b>before</b> <a class="xref" href="Hi.NcParsers.LogicSyntaxs.IncrementalResolveSyntax.html">IncrementalResolveSyntax</a>
and <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzSyntax.html">ProgramXyzSyntax</a> in the syntax chain. When a
supported code is active, this syntax consumes X/Y/Z from
<a class="xref" href="Hi.NcParsers.Keywords.IParsingDef.html#Hi_NcParsers_Keywords_IParsingDef_Parsing">Parsing</a> and writes
<a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateStateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateStateDef_MachineCoordinateState">MachineCoordinateState</a> directly,
preventing <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzSyntax.html">ProgramXyzSyntax</a> from processing them
as program coordinates.
preventing <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzSyntax.html">ProgramXyzSyntax</a> from processing them as
program coordinates — and, ahead of the resolve, reading a per-word
incremental word raw instead of re-based into the program frame.
</p>
</dd>
</dl>
@@ -659,6 +716,16 @@ to resolve against (first rotary value in the stream) is reported as
<code>Coord-McAbc--004</code> and adopted unwrapped, matching the default
path.
</p>
<p>
Per-word incremental override: an <a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_Incremental">Incremental</a>
entry (Siemens <code>IC()</code>, klartext <code>IC+270</code>) is a signed
traverse by definition — <a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a> already wrote
anchor + delta — so this pass keeps that value verbatim for the
axis instead of folding it into the ±180° window (a +270° chain
dimension must not become a -90° swing). Incremental entries on
non-modular axes need no warning: the literal value is what the
axis would do anyway.
</p>
</dd>
</dl>
<dl class="jumplist">
@@ -694,15 +761,18 @@ Values are stored in degrees (matching <a class="xref" href="Hi.NcParsers.LogicS
Per-word override: a block-root
<a class="xref" href="Hi.NcParsers.Keywords.PositioningOverride.html">PositioningOverride</a> section (written by
<a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensAcIcSyntax.html">SiemensAcIcSyntax</a> for the
Siemens <code>AC()</code>/<code>IC()</code> coordinate functions) marks a rotary
Siemens <code>AC()</code>/<code>IC()</code> coordinate functions, and by the
Heidenhain L / C parsers for the klartext <code>IA+</code>/<code>IB+</code>/<code>IC+</code>
words) marks a rotary
word <a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_Incremental">Incremental</a>: the parsed value is then
added to the previous modal value of that axis (previous
<code>MachineCoordinateState</code> lookback, falling back to a value
already present in the current section, then 0) instead of being
written as an absolute angle. The accumulated raw degrees stay
monotonic across iterations — each per-block step is well inside the
±180° window, so the <a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcCyclicPathSyntax.html">McAbcCyclicPathSyntax</a> tail-pass
keeps it as net rotation instead of re-normalizing it away. An
monotonic across iterations: the <a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcCyclicPathSyntax.html">McAbcCyclicPathSyntax</a>
tail-pass keeps an Incremental-stamped axis literal (a chain
dimension is a signed traverse, never re-shortened), so even a
+270° step survives as net rotation. An
<a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_Absolute">Absolute</a> entry (from <code>AC()</code>) matches
the default write and needs no special path — and so, deliberately,
do the rotary-family entries <a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_Shortest">Shortest</a>
@@ -797,6 +867,53 @@ Must be placed after syntaxes that write <code>ProgramXyz</code>
and before syntaxes that read <code>MachineCoordinate</code>
(e.g., <a class="xref" href="Hi.NcParsers.LogicSyntaxs.LinearMotionSyntax.html">LinearMotionSyntax</a>).
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.OrientationVectorResolveSyntax.html">OrientationVectorResolveSyntax</a></dt>
<dd><p>Shared vector-orientation resolve — the brand-independent half of
tool-axis-vector 5-axis programming (Heidenhain LN <code>TX/TY/TZ</code>;
the Fanuc/Syntec/Mazak <code>G43.5 I/J/K</code> and Siemens
<code>A3=/B3=/C3=</code> slots when their adapters land). Consumes the
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.OrientationVectorResolveSyntax.html#Hi_NcParsers_LogicSyntaxs_OrientationVectorResolveSyntax_ToolOrientationKey">ToolOrientationKey</a> section a brand adapter wrote —
<code>{ &ldquo;Vector&rdquo;: {X,Y,Z}, &ldquo;Term&rdquo;: &ldquo;&lt;brand word&gt;&rdquo; }</code>, unit
vector in program coordinates — and resolves it into rotary-axis
degrees on <a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateStateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateStateDef_MachineCoordinateState">MachineCoordinateState</a>
via <a class="xref" href="Hi.Numerical.Xyzabc.IMachineKinematics.html#Hi_Numerical_Xyzabc_IMachineKinematics_OrientationToMcAbc_Hi_Geom_Vec3d_Hi_Geom_Vec3d__">OrientationToMcAbc(Vec3d, out Vec3d)</a>
(axial-only: rotation about the tool axis is free). Everything
downstream is the existing RTCP pipeline untouched: the brand RTCP
syntax sees the endpoint ABC, marks the tool-height entry
<a class="xref" href="Hi.NcParsers.Syntaxs.TransformationUtil.html#Hi_NcParsers_Syntaxs_TransformationUtil_KindDynamic">KindDynamic</a> on a rotary change, and
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.LinearMotionSyntax.html">LinearMotionSyntax</a> routes the block to
<a class="xref" href="Hi.NcParsers.Keywords.Generic.MotionForm.html#Hi_NcParsers_Keywords_Generic_MotionForm_ClLinear">ClLinear</a> per-step IK.</p>
<p>
Branch continuity is seeded explicitly: before solving, the chain is
set to the previous block's rotary state
(<a class="xref" href="Hi.Numerical.Xyzabc.IMachineKinematics.html#Hi_Numerical_Xyzabc_IMachineKinematics_McAbcToMat_Hi_Geom_Vec3d_">McAbcToMat(Vec3d)</a> on the per-axis MC
lookback) so the solver follows the current solution branch
deterministically — the implicit chain state cannot be trusted under
lazy or out-of-order rebuilds — and the solved angles are unwrapped
to the nearest ±360° window of that anchor.
</p>
<p>
Must run <b>after</b> <a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a> (explicit rotary
words and lookback land first; a vector on the same block overrides
them) and <b>before</b> the brand RTCP syntax and
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McXyzSyntax.html">McXyzSyntax</a> (the section is created rotary-only, so
the XYZ derivation still runs — the <a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a>
rotary-only discipline). Registered per brand list by the brand that
has a vector adapter.
</p>
<p>
Degradation is diagnosed, never silent: no
<a class="xref" href="Hi.Numerical.Xyzabc.IMachineKinematics.html">IMachineKinematics</a> → <code>Orientation-Vector--NoKinematics</code>;
no rotary axes → <code>Orientation-Vector--NoRotaryAxes</code>; solver
failure → <code>Orientation-Vector--IkFailed</code>. In every case the
XYZ motion proceeds and the posture holds at its previous value
(deliberately unlike the CLSF path, which drops the motion on IK
failure — divergence recorded on the plan card). The section itself
stays on the block as the semantic record.
</p>
</dd>
</dl>
<dl class="jumplist">
@@ -954,7 +1071,12 @@ it is interpreted as a rotary machine axis.
to the block JSON.</p>
<p>
Fanuc/ISO: reads G90/G91 from <a class="xref" href="Hi.NcParsers.Keywords.IFlagsDef.html#Hi_NcParsers_Keywords_IFlagsDef_Flags">Flags</a> (global modal).
Heidenhain: would need a separate implementation reading I-prefix per axis.
Heidenhain: klartext has no modal word — the modal state stays at the
G90 default and the I-prefixed words (<code>IX+20</code>) ride on the same
per-word override as Siemens, stamped by the L / C / CC / CYCL CALL
POS parsers (see
<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Heidenhain.HeidenhainIncrementalAxisWordUtil.html">HeidenhainIncrementalAxisWordUtil</a>);
the DIN/ISO dialect on that brand uses G90/G91 like Fanuc.
Siemens: the AC()/IC() per-word override rides on top of this modal
state — <a class="xref" href="Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensAcIcSyntax.html">SiemensAcIcSyntax</a>
writes a <a class="xref" href="Hi.NcParsers.Keywords.PositioningOverride.html">PositioningOverride</a> section the
@@ -1278,6 +1400,16 @@ Writes resolved state to a <code>ToolChange</code> section:
when <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ToolChangeSyntax.html#Hi_NcParsers_LogicSyntaxs_ToolChangeSyntax_IsChangeKey">IsChangeKey</a> is true (i.e. the block actually carried
the tool-change M code); modal-only blocks omit it.</p>
<p>
Two more keys mirror HardNc's <code>T</code> / <code>PreparationT</code> split.
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ToolChangeSyntax.html#Hi_NcParsers_LogicSyntaxs_ToolChangeSyntax_PreparedToolIdKey">PreparedToolIdKey</a> holds the second T of a dual tool word
(<code>T10 T2 M06</code>: 10 is loaded, 2 is pre-selected) and is carried
until the next change loads it. <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ToolChangeSyntax.html#Hi_NcParsers_LogicSyntaxs_ToolChangeSyntax_EquippedToolIdKey">EquippedToolIdKey</a> is
written on non-change blocks and names the tool in the spindle — the
ToolId of the last change — because <code>ToolId</code> on such a block may
already be a pre-selection (<code>T2</code> alone). Consumers read it through
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ToolChangeSyntax.html#Hi_NcParsers_LogicSyntaxs_ToolChangeSyntax_ReadEquippedToolId_System_Text_Json_Nodes_JsonObject_">ReadEquippedToolId(JsonObject)</a>.
</p>
<p>
<code>ToolId</code> is an int for numeric calls (<code>T5</code>) and a string for
Siemens string tool calls (<code>T="D8R1"</code>, captured by
<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Siemens.SiemensToolCallSyntax.html">SiemensToolCallSyntax</a>); both
@@ -1327,10 +1459,14 @@ interpretation only, G700/G710 also switch feedrate interpretation —
a distinction preserved via the verbatim <a class="xref" href="Hi.NcParsers.Keywords.IUnitDef.html#Hi_NcParsers_Keywords_IUnitDef_Term">Term</a>
but irrelevant to this record-only syntax; both inch variants warn
identically). The first <a class="xref" href="Hi.NcParsers.LogicSyntaxs.UnitModeSyntax.html#Hi_NcParsers_LogicSyntaxs_UnitModeSyntax_MetricCodes">MetricCodes</a> entry doubles as the
program-start default <code>Term</code>. Note Siemens G70/G71 must never be
added to ISO/Fanuc presets — on Fanuc lathes the same codes are
finishing/roughing cycles (same collision family as the documented
Siemens G74 exclusion).
program-start default <code>Term</code>. RS-274-D, Syntec and Fanuc turning
G-code system C all spell the units G70 inch / G71 metric, and the
Fanuc milling dialects (RS-274-D descendants) read them the same way,
so the Fanuc/Syntec presets carry all four codes. The
finishing/roughing-cycle collision exists only on Fanuc turning
G-code systems A/B (system C moved those cycles to G72/G73) — a
future turning preset for those systems must not inherit this milling
preset's vocabulary.
</p>
<p>
The HiNC pipeline works exclusively in millimetres. When an inch code