Class McAbcCyclicPathSyntax
- Namespace
- Hi.NcParsers.LogicSyntaxs
- Assembly
- HiMech.dll
Resolve modular rotary axes to the shortest cyclic path relative to the previous node. Uses IsModularRotary(string) to determine which axes within MachineCoordinateState need cyclic resolution. Falls back to hardcoded A/B/C if no IMachineAxisConfig is available. Must be placed after ProgramXyzSyntax in NcSyntaxList.
Two stages, mirroring McXyzSyntax:
- Root
MachineCoordinateState— anchored at the previous block's modal rotary state. - CompoundMotion.ItemsKey[*]
— sequential walk through items, anchoring item 0 at the previous
block's modal state and item
i > 0at itemi-1's post-cycle value (per-axis chain). Items without a rotaryMachineCoordinateStateare skipped.
Per-word directional override: a block-root
PositioningOverride entry (stamped by
SiemensAcIcSyntax) valued
PositiveOnly (Siemens ACP()) or
NegativeOnly (ACN()) swaps that
axis's window for this block only: [anchor, anchor+360°) /
(anchor-360°, anchor] instead of the default ±180° — the approach
direction is forced even when it is the longer way around. A target
congruent with the anchor (within an ULP-scale epsilon) keeps the
anchor value verbatim — no move, never a spurious full turn, and no
deg→rad→deg drift. Shortest (DC())
is the default window and needs no special path here. The override
is read from the current block only (it is one-shot, never carried —
deliberately unlike the modal RotaryWrap gate's one-step
previous fallback) and applies to the root MC stage only, not to
CompoundMotion items (G28/G74/G75 expansions capture
their words in sub-objects the stamping syntax never sees, so an
override can only ever describe a root word). Directional/shortest
entries keyed by an axis outside the modular set are reported as
Coord-McAbc--003 — the promise cannot be honored there and
silence would mis-read the program's intent; an entry with no anchor
to resolve against (first rotary value in the stream) is reported as
Coord-McAbc--004 and adopted unwrapped, matching the default
path.
public class McAbcCyclicPathSyntax : ISituNcSyntax, INcSyntax, IMakeXmlSource
- Inheritance
-
McAbcCyclicPathSyntax
- Implements
- Inherited Members
- Extension Methods
Examples
Cases below run with no IMachineAxisConfig on the dep list, so the syntax uses the A/B/C fallback (a configuration warning is emitted but does not affect the JSON). The syntax is the tail-pass rotary-wrap centraliser — upstream rotary writers (McAbcSyntax, G28, G53.1, ...) store raw degrees and let this pass resolve to the shortest cyclic path.
Current B is within ±180° of the previous B — no wrap needed; the value is rewritten in place but equals the input:
#Previous:{ "MachineCoordinateState": { "B": 0 } }
#BeforeBuild:
{ "MachineCoordinateState": { "B": 10 } }
#AfterBuild:
{ "MachineCoordinateState": { "B": 10 } }
Current B is 270° but previous B is 0° — the shortest path is the
other way around, so the value is rewritten as -90° (mathematically
equivalent, geometrically the same orientation, but signalling the
shorter rotation to a downstream motion consumer). 270/0 round-trips
through ToRad→Cycle→ToDeg with no rounding
noise (1.5π → -0.5π → -90 exactly); other angle pairs (e.g.
350° → -10°) emit a trailing ULP-scale drift instead:
#Previous:
{ "MachineCoordinateState": { "B": 0 } }
#BeforeBuild:
{ "MachineCoordinateState": { "B": 270 } }
#AfterBuild:
{ "MachineCoordinateState": { "B": -90 } }
First block of the stream (no #Previous:) — no anchor to
resolve against, so the syntax early-returns and the raw value is
preserved verbatim:
#BeforeBuild:
{ "MachineCoordinateState": { "B": 350 } }
#AfterBuild:
{ "MachineCoordinateState": { "B": 350 } }
CompoundMotion.Items walk — two items chain: item 0 cycles
against the previous block's modal B = 0° (270° → -90°), and item 1
cycles against item 0's post-cycle -90° (170° → -190°, since the
shorter path from -90° to 170° wraps backward through -180°). If
item 1 had used the previous-block anchor instead of the chained
anchor, 170° would have stayed at 170° (already in the ±180° window
around 0°), so the test discriminates between chain and no-chain:
{ "MachineCoordinateState": { "B": 0 } }
#BeforeBuild:
{
"CompoundMotion": {
"Items": [
{ "MachineCoordinateState": { "B": 270 } },
{ "MachineCoordinateState": { "B": 170 } }
]
}
}
#AfterBuild:
{
"CompoundMotion": {
"Items": [
{ "MachineCoordinateState": { "B": -90 } },
{ "MachineCoordinateState": { "B": -190 } }
]
}
}
ACP (PositiveOnly) forces the positive swing even though the
shortest path from 0° to 270° is -90° (compare the default case
above — same numbers, opposite outcome). The override section stays
on the block (nothing consumes it away):
{ "MachineCoordinateState": { "B": 0 } }
#BeforeBuild:
{
"MachineCoordinateState": { "B": 270 },
"PositioningOverride": { "B": "PositiveOnly" }
}
#AfterBuild:
{
"MachineCoordinateState": { "B": 270 },
"PositioningOverride": { "B": "PositiveOnly" }
}
ACN (NegativeOnly) mirror — target 90° from anchor 0° swings
-270° instead of the shortest +90°:
#Previous:
{ "MachineCoordinateState": { "B": 0 } }
#BeforeBuild:
{
"MachineCoordinateState": { "B": 90 },
"PositioningOverride": { "B": "NegativeOnly" }
}
#AfterBuild:
{
"MachineCoordinateState": { "B": -270 },
"PositioningOverride": { "B": "NegativeOnly" }
}
Congruent target under a directional override — the raw anchor sits
at 370° (e.g. after an earlier ACP long-way swing) and the ACN
target 10° is the same physical position: no move, the anchor value
is kept verbatim (the epsilon snap; without it, radian ULP noise
would decide between "no move" and a spurious full -360° turn):
#Previous:
{ "MachineCoordinateState": { "B": 370 } }
#BeforeBuild:
{
"MachineCoordinateState": { "B": 10 },
"PositioningOverride": { "B": "NegativeOnly" }
}
#AfterBuild:
{
"MachineCoordinateState": { "B": 370 },
"PositioningOverride": { "B": "NegativeOnly" }
}
Constructors
McAbcCyclicPathSyntax()
Initializes a new instance with default settings.
public McAbcCyclicPathSyntax()
McAbcCyclicPathSyntax(XElement)
Initializes a new instance by deserializing from the given XML element.
public McAbcCyclicPathSyntax(XElement src)
Parameters
srcXElementSource XML element.
Properties
Name
Syntax kind name (typically the concrete type name).
public string Name { get; }
Property Value
XName
XML element name used to register this syntax with XFactory.
public static string XName { get; }
Property Value
Methods
Build(LazyLinkedListNode<SyntaxPiece>, List<INcDependency>, NcDiagnosticProgress)
Build syntax arrangement into the
syntaxPieceNode in-place.
public void Build(LazyLinkedListNode<SyntaxPiece> syntaxPieceNode, List<INcDependency> ncDependencyList, NcDiagnosticProgress ncDiagnosticProgress)
Parameters
syntaxPieceNodeLazyLinkedListNode<SyntaxPiece>ncDependencyListList<INcDependency>ncDiagnosticProgressNcDiagnosticProgress
MakeXmlSource(string, string, bool)
Creates an XML representation of the object. This method may also generate additional resources such as related files.
public XElement MakeXmlSource(string baseDirectory, string relFile, bool exhibitionOnly)
Parameters
baseDirectorystringThe base directory for resolving relative paths
relFilestringThe relative file path for the XML source
exhibitionOnlyboolif true, the extended file creation is suppressed.
Returns
- XElement
An XML element representing the object's state
Remarks
For the demand of easy moving source folder (especially project folder) without configuration file path corruption, the relative file path is applied.
The baseDirectory is typically the folder at the nearest configuration file folder.
Since the folder can be moving with the configuration file.
Reg(XFactory)
Registers this type's deserializer with the given XFactory
(or Default when factory is
null). Idempotent.
public static void Reg(XFactory factory = null)
Parameters
factoryXFactory