Table of Contents

Namespace Hi.NcParsers.LogicSyntaxs.Siemens

Classes

SiemensCircularMotionSyntax

Siemens variant of CircularMotionSyntax (replaces it in the Siemens preset — do not run both): writes McArc motion for G02/G03 blocks from I/J/K center offsets or the Siemens signed radius CR= (captured as Parsing.CR by an equals-form FloatTagValueSyntax), with the helix turn count from TURN= (Parsing.TURN).

Differences from the Fanuc/ISO parent, per the corpus-driven plan:

  • CR replaces R — same math (ResolveCenterFromSignedRadius(Vec3d, Vec3d, int, bool, double); negative CR selects the >180° arc), but a CR full circle (start ≈ end on the plane) is invalid on Sinumerik and the chord collapse would produce a NaN center — rejected with Arc-CR--ClosedChord, params left visible.
  • TURN=N means N additional full circles: AdditionalCircleNum = TURN + (closed ? 1 : 0)no −1 (the legacy HardNc path treated TURN like Fanuc L and silently undercounted Siemens helices by one turn; deliberately not ported). The closed-loop +1 stacks on the same closure heuristic used when TURN is absent, because the downstream angle wrap yields 0 rad for closed arcs and the whole loop count must come from AdditionalCircleNum.
  • No L and no K-as-pitch reading — Siemens L{n} is a subprogram call and helix travel is endpoint + TURN driven.

Must be placed before LinearMotionSyntax (shared Group 01 motion slot).

SiemensCoordinateOffsetSyntax

Siemens Sinumerik: resolves work coordinate offset from G54–G57 (ISO-compatible), G505–G599 (extended Siemens), and G500 (cancel — machine coordinate mode). Reads from Flags, looks up IsoCoordinateTable dependency, composes into ProgramToMcTransform.

SiemensCycle800TiltSyntax

Siemens CYCLE800 (swivel cycle): resolves the tilted work plane from the positional arguments captured by SiemensCycleCallSyntax and composes it into ProgramToMcTransform as the shared TransformSource entry — the Siemens sibling of IsoG68p2TiltSyntax its XmlDoc promises. Unlike Fanuc G68.2 (plane only), CYCLE800 also positions the rotary axes implicitly (the G53.1 half): with IMachineKinematics wired, the tilt normal is solved to machine ABC and written into MachineCoordinateState, and the block gets a non-modal rapid MotionEvent with Term = “CYCLE800” (mirroring G53p1RotaryPositionSyntax).

Argument layout (HardNc reference NcArgCycle800): CYCLE800(FR, TC, ST, MODE, X0, Y0, Z0, A, B, C, X1, Y1, Z1, DIR [, FR_I, DMODE]) — 15- and 16-arg post variants both occur in the corpus. MODE is bit-coded: bits 7-6 select the swivel mode (00 axis-by-axis, 01 solid angle, 10 projection angle, 11 direct rotary), bit pairs 1-0/3-2/5-4 select each angle's axis (01=X, 10=Y, 11=Z). The motion-convention matrix is T(X1,Y1,Z1) · R · T(X0,Y0,Z0) (row-vector; the post-rotation zero offset applies innermost). ST units digit 1 composes additively onto the current programmable frame; FR/FR_I retraction and DIR solution preference are recorded in the section but not simulated (DIR = 0 suppresses the rotary positioning, per the control's frame-only variant).

Cancel forms — bare CYCLE800, empty parentheses, the single-argument CYCLE800(0), or swivel-data-record name TC = "0" — reset the tilt to the shared inactive sentinel (Term = "G69" + identity entry, HardNc's convention). An in-between argument count (1–9 with a live TC) is treated as a truncated/unmodeled capture, not a cancel — warning + visible residue, so a mis-parsed call can never silently drop an active swivel. The rotary axes are not re-positioned on cancel: the retract/re-orient behavior depends on the machine's swivel data record, which does not exist offline; corpus programs follow the cancel with explicit G0 A.. C.. moves anyway.

Fail-soft: a non-numeric argument (machine-runtime variable) leaves the Parsing.CYCLE800 residue visible and applies no transform (Coord-Tilt--003); an IK failure keeps the euler tilt and skips positioning (Coord-Tilt--004); a rotating CYCLE800 on a machine without kinematics/rotary axes keeps the tilt and warns (Coord-Tilt--005).

Must run before SiemensProgrammableFrameSyntax (which owns the once-per-block TiltTransform modal carry and composes additive AROT/ATRANS onto this cycle's fresh matrix) and before G53p1RotaryPositionSyntax / the coordinate-offset syntaxes (chain order: frame entry ahead of CoordinateOffset).

SiemensModalCycleSyntax

Maps Siemens MCALL CYCLE8x(…) modal drilling calls onto the shared canned-cycle machinery — the “setup half” of the Fanuc G66-style modal pattern; the “expansion half” needs no new code because CannedCycleResolveSyntax's previous-block modal lookback already re-triggers the armed cycle at every subsequent block carrying X/Y words, exactly Sinumerik's MCALL semantic.

  • MCALL CYCLE81/82(RTP,RFP,SDIS,DP,DPR[,DTB]) → an armed CannedCycle section (Term G81/G82) with Params.R = RFP + |SDIS|, Params.Z = DP (or RFP − DPR), dwell P = DTB for G82.
  • MCALL CYCLE83(…,FDEP,FDPR,DAM,DTB,DTS,FRF,VARI,…) → G83 (VARI≠0, full retract) or G73 (VARI=0, chip-break) with Q = |RFP − FDEP| or |FDPR|. The FDEP/DAM decreasing peck chain is approximated by that constant first-peck depth.
  • MCALL CYCLE85(…,DTB,FFR,RFF) → G89 (DTB>0, dwell) or G85, feed-in F = FFR; the separate retract feed RFF has no slot in the shared expansion (retract reuses F).
  • bare MCALL → the G80 cancel sentinel (WriteCannedCycleCancel(JsonObject, string)).

The MCALL block itself must NOT execute the cycle (Sinumerik arms only), so no Parsing.G8x section is written here — the armed section rides the ModalCarrySyntax CannedCycle tracked key to the following motion blocks. Return plane: ReturnMode = G98 (previous-block Z); RTP has no slot in the shared expansion — programs that park at RTP before the first trigger get exactly RTP back, the corpus shape. Fail-soft paths (consume + structured warning + no arm): non-literal arguments (R-parameter args — cycle args bypass the P2 evaluator), missing RFP / depth / peck values, and any callee outside the CYCLE8x map (MCALL L123 modal subprogram calls are not simulated). Pipeline placement: before CannedCycleResolveSyntax in the Siemens Logic bundle.

SiemensPathSmoothingSyntax

Records the Siemens path-control / smoothing modal registers into the brand-invariant PathSmoothing section (fields per ISiemensPathSmoothingDef): the G-code groups G60/G64/G641/G642 (path control) and G601/G602 (exact-stop criterion) from Flags, the bare modal words FNORM / SOFT / BRISK / FFWON / FFWOF / COMPCAD / COMPON / COMPOF / UPATH / SPATH (captured by the preset's FlagSyntax word list), and the Parsing.CYCLE832 call sub-object (captured by SiemensCycleCallSyntax) whose first argument arms the high-speed tolerance (0 / empty parentheses cancel it).

Record-only — simulation does not alter the tool path (same contract as the Fanuc G05.1 sibling FanucPathSmoothingSyntax, which this class replaces in the Siemens preset: that one reads only the Parsing["G05.1"] sub-object no Siemens capture produces). IsEnabled is derived — true while a CYCLE832 tolerance is armed or the path-control group sits on a continuous-path mode (G64/G641/G642).

Modal behavior: a block touching any group starts from a clone of the previous block's section, applies the touched groups and rewrites the section; untouched blocks write nothing and ModalCarrySyntax (whose TrackedKeys already contain PathSmoothing) carries the previous section forward. The stream's first block stamps a conservative { IsEnabled: false } default — the actual delivered state of a real control is machine-data dependent, so no term is invented for it.

SiemensPivotTransformationSyntax

Siemens pivot gate over the shared engine (PivotTransformUtil): writes the PivotTransformSource entry on blocks where commanded XYZ needs the Pn→MC kinematic rigid transform — active TRAORI RTCP (SiemensTraoriSyntax's ToolHeightCompensation.Term), an active swivel/tilt (CYCLE800, or a mixed-dialect G68/G68.2 term), or a Dynamic chain entry. The Siemens-specific exclusion: a plain geometric frame (TRANS/ATRANS/ROT/AROT, IsPlainGeometryFrame(string)) transforms coordinates only and implies no physically positioned rotaries, so it must not open the gate — a corpus TRANS X0 Y0 Z0 reset would otherwise leave the modal term folding the pivot on every later plain-mode block.

The ISO/Fanuc sibling gate is PivotTransformationSyntax; both write the identical JSON vocabulary through the shared engine, and only one of them is registered per brand pipeline. Same chain-position contract: after all Pn-frame writers, so the PivotTransform entry lands last.

SiemensProgrammableFrameSyntax

Siemens programmable frame (TRANS/ATRANS/ROT/AROT incl. RPL=): consumes the structured Parsing.<keyword> sub-objects captured by SiemensFrameStatementSyntax, accumulates the programmable-frame matrix across blocks, and composes it into ProgramToMcTransform as the shared TransformSource entry — the same Source CYCLE800 writes, so the two stay mutually exclusive via AddOrReplaceTransform's in-place replacement (on a real Sinumerik, CYCLE800 itself writes the programmable frame chain, so single ownership mirrors the control).

Semantics follow the Sinumerik programmable-frame rules (HardNc reference: HardNcLine.ParseSiemensFrameTransform + NcArgSiemensFrame): the absolute forms TRANS/ROT reset the whole programmable frame and set only their own component; the additive forms ATRANS/AROT compose onto the current frame with the new operation applied first (M = M_op · M_prev, row-vector convention — an AROT after a TRANS rotates inside the translated frame). A bare keyword (any of the four) resets the programmable frame entirely — written as the shared inactive sentinel Term = "G69" plus an identity chain entry (the same convention HardNc's CYCLE800 reset uses). Multi-axis rotation in one statement applies the Sinumerik RPY order (intrinsic Z → Y′ → X″, i.e. row-vector Rx·Ry·Rz); RPL rotates about the active G17/G18/G19 plane normal and composes after the axis angles.

ROTS/AROTS/SCALE/ASCALE/MIRROR/AMIRROR (zero corpus occurrences; SCALE/MIRROR would inject non-rigid matrices that downstream consumers have never been audited for) are consumed recognized-but-not-simulated with a SiemensFrame--Unsupported warning and zero transform effect. A structured keyword whose capture fell back to the verbatim Statement shape, or whose value is an unevaluated variable expression, is left in Parsing — the VariableExpression--Unevaluated diagnostic plus the visible Parsing--Unconsumed residue is the correct fail-soft (P2 acceptance doctrine); the frame is not partially applied.

Must run after SiemensCycle800TiltSyntax (this syntax owns the once-per-block TiltTransform modal carry: it carries only when no earlier syntax authored the section on this block) and before G53p1RotaryPositionSyntax / the coordinate-offset syntaxes, so the frame entry lands ahead of CoordinateOffset in the chain (McXyz = ProgramXyz · M_frame · M_offset · … — the programmable frame applies to program coordinates first, then the settable G54 frame, matching the Sinumerik frame chain).

SiemensStopreSyntax

Consumes the Siemens STOPRE flag (stop preprocessing — the control's look-ahead buffer sync) from Flags and records a non-modal block-root Stopre section. STOPRE has no effect in offline simulation (there is no preprocessing buffer to flush), so an Stopre–NoOp Unsupported Message is emitted: recognized, intentionally not simulated, safe offline.

Capture side: STOPRE is a bare word collected by the Siemens preset's FlagSyntax word list.

SiemensToolOffsetSyntax

Siemens cutting-edge tool offset activation: consumes a standalone D word (D1 activates edge 1 of the active tool, D0 cancels compensation), resolves the effective length via GetToolHeightOffset_mm(int, int) ($TC_DP3, geometry − wear) for the (active tool, D) pair, and writes the same downstream state as the ISO sibling ToolHeightOffsetSyntax: the IToolHeightCompensationDef section (with Term = “D”) plus the ToolHeightCompensation entry in the ProgramToMcTransform chain — sharing the transform Source keeps the two brands' compensation mutually exclusive via AddOrReplaceTransform's in-place replacement.

The active tool number comes from the block's (or previous block's) ToolChange section; a string tool name resolves through FindToolNumberByName(string). Modal ownership follows the same yield protocol as the ISO sibling: blocks without a D word re-resolve only when the previous section's Term is ours ("D"); an ISO term (G43/G44/G49) leaves the section to ToolHeightOffsetSyntax — real Siemens files mix both dialects (G43H1 headers next to D1 blocks). Must therefore be placed after ToolHeightOffsetSyntax (and after ToolChangeSyntax) in the Logic bundle, and before the brand pivot gate (SiemensPivotTransformationSyntax in the Siemens list) so the pivot entry stays at the chain tail.

Consuming Parsing.D here (Logic) intentionally precedes RadiusCompensationSyntax (PostLogic): on Siemens, D selects the cutting edge — it is not the Fanuc G41 D5 radius argument, and radius state derives from the same (T, D) edge ($TC_DP6; wiring the radius value is a follow-up).

SiemensTraoriSyntax

Siemens TRAORI/TRAFOOF (orientation transformation = RTCP): the Siemens sibling of G43p4RtcpSyntax. While TRAORI is active, the IToolHeightCompensationDef section carries Term = “TRAORI” and the ToolHeightCompensation chain entry becomes a tool-normal · offset translation at the block endpoint ABC (MakeToolHeightMat(IMachineKinematics, Vec3d, double)), tagged KindDynamic when the rotary state changes across the block — the single signal that routes the block to MotionForm.ClLinear per-step IK.

Tool length ownership stays with the (T,D) machinery: on real Sinumerik, TRAORI uses the active D edge's length. Activation adopts the compensation the D edge (or a mixed-dialect ISO G43) has already resolved — SiemensToolOffsetSyntax runs earlier in the bundle, so an explicit D1 on any TRAORI-modal block first resolves Term = "D" and this syntax re-takes the section with the fresh Offset_mm. The adopted owner is recorded in PriorTermKey; TRAFOOF hands the section back to it (default "D"), because plain length compensation survives TRAORI deactivation on the control — TRAFOOF only ends the orientation-following. A TRAFOOF with no active TRAORI (the corpus' ubiquitous defensive preamble) is consumed silently.

Must run after ToolHeightOffsetSyntax / SiemensToolOffsetSyntax / the coordinate-offset syntaxes (mirroring G43p4RtcpSyntax's Fanuc slot) and before SiemensPivotTransformationSyntax, whose gate recognizes the TRAORI term and folds the kinematic pivot. Silently degrades to a plain UnitZ · offset translation when IMachineKinematics is absent.