NC optimization and writeback
Important
NC optimization is not finished on the 3.2 line. What follows describes the leg as it stands,
and it is published for review, not for production. Work that depends on optimized output should
stay on the 3.1 line, serviced as 3.1.175.<patch>.
- The optimizer runs on the SoftNc pipeline by default. OptimizeToFiles keeps its signature, its script snippet and its HTTP route, but when EnableSoftNcRunner is on and the session holds played SyntaxPieceLayers, it delegates to the new OptimizeNcFiles; otherwise the frozen HardNc path runs unchanged. The new leg classifies the final SyntaxPiece layer, solves the per-step feed adjustments from milling physics, and regenerates text as anchored token edits over the verbatim source block — lines the optimizer does not touch round-trip byte-identically instead of being re-synthesized. Per-file results are retained in NcOptimizations. EnableIndividualStepAdjustmentLog drives both legs.
- Depth splition re-interpolates through a planned fragment path, with separate modal chains for
the pre-build feed and the emission endpoint, per-step machine-to-program-frame inversion, and
per-fragment arc IJK recomputation — including R-to-IJK conversion — wherever the arc block itself
carries the centre. An arc whose centre lives on a preceding modal block is exempt: its fragments
keep the source block's arc words and share that upstream centre line unchanged, so only their
endpoint and
Fwords move. Two cases where the frozen HardNc optimizer is silently wrong are downgraded to a non-split rewrite rather than reproduced, each warned once per run. The first is an incremental block, and it is now taken by both of its spellings:G91modal state, or a block whose modal state is absolute while individual axis words carry a per-word incremental override — SiemensX=IC(10)and the codedCIC(), klartextIX+20andIC+90. The frozen fragment rewrite carries noG90/G91handling at all and always re-emits a coordinate as an absolute program value, so it splits both shapes and is wrong on each in its own way: theG91line comes back stating an absolute number the control still reads as a distance, and the per-word line keeps its incremental source word, so every fragment re-applies the same distance from its own start. Both now stop atNcOpt--SplitionIncrementalUnsupported. The per-word spelling is also the only one that can reach klartext: that dialect has no modalG90/G91word, so a stamped axis word is the only incremental form it produces. The second case is a klartextC … DR±arc whose modalCCchain left one of the two in-plane axes unstated, so the block's own start point supplied that component — since every fragment would re-derive the centre from its own start; that one reportsNcOpt--SplitionStartPointCenterUnsupported. A klartextCblock whose centre lands entirely on its own start point never reaches that guard: its radius is zero, so play degrades it to a chord under a validation warning of its own. Neither the controller brand nor klartext as such refuses a split: a klartextLblock re-interpolates like an ISO one. - The compensation stage is no longer dead on the SoftNc leg. The HardNc baseline wrote the compensation into the step contexts while its output read the piece packs, so it never emitted a compensated coordinate at all. Each fragment endpoint is now offset — XYZ only, rotary words untouched — by the tool-tip deflection rotated into the leaf program frame the endpoint lives in, so a G68.2 tilted setup is compensated in the right direction. It is consumed on re-interpolated splition fragments only, and CompensationMask defaults to 0, so with no mask set the stage is a strict no-op.
- Output follows the source's decimal digits. Both legs used to write coordinates through a fixed
F4and every F word throughF2, so a program stated to three decimals could come back with a fourth — an alarm on controllers strict about their least input increment. Digit counts are now scanned per word family over the played source texts with comment spans masked, floored at 3/3/0 and capped at 9, and threaded through the whole write path. The word-suppression tolerances and the F comparison grid derive from the resolved digits instead of the old fixed literals. - Leading zeros follow the source, and the project can pin the spelling.
OmitLeadingZero is an output style: on, the writer drops a leading
zero before the decimal (
.5rather than0.5); off, it writes the zero. The option is carried on the project so two machines produce the same bytes, and a report names which style the source itself used. - Optimized NC is written back in the source file's encoding. NC play reads and optimized writes go through DetectRoundTripEncoding — BOM, then strict UTF-8, then Latin-1 — so an ANSI-family file (GBK, Big5, Shift-JIS) re-encodes to its original bytes instead of having every undecodable byte replaced. Comments in those encodings survive the round trip.
- A feed change no longer mints a one-step carrier fragment. Under an arc split that fragment is a
degenerate arc whose start and end nearly coincide, which an incremental-IJK reader — or a control
that treats begin == end as a full turn — expands into a full circle. An
Fre-statement is now handed to the feed run's next emitted fragment, the one that actually runs at that feed. - A splition fragment at the head of the stream writes only the axis words the source stated, so it
can no longer invent a
Z0.whose value under the source's silence is just the home-fallback modal. - Unparsable NC lines survive. A line the parser could not read used to be dropped from the runner's
line list, so the optimized file silently lost it.
HardNcRunnernow rebuilds a parse-failed line as an opaque no-op — the empty-text parse inherits modal state like a blank line, and the raw text is restored for writers — and the optimizer mirrors the fallback, soIFblocks,#-variable macros,G68 R#andGOTOcome through verbatim. ABuildNcLines--ParseFaileddiagnostic still reports the line, and the line stays un-simulated. The output writer is also closed in afinally, so an exception can no longer leave a half-written file locked. First delivered on the 3.1.175.x service line. - A Siemens
CYCLE800swivel counts as a macro line in the piece classifier, so it is preserved rather than treated as an optimizable motion block. - The host key
HiNC:OptCoreNumgoverns both legs again. It used to set only the legacyNcOptProc.CoreNum; once the SoftNc optimizer became the default path the key silently stopped governing anything. It now assigns both (0 = derive from the processor count). - NC text writeback regenerates NC from a program that has already been played, in two stages over
the session's finished syntax pieces: a converter turns the source piece stream into a destination
stream plus a bidirectional source↔destination map keyed by sentence index, and a reverse segmenter
serializes that stream back to lines. The data→text seam is a brand-agnostic sentence composer, first
implemented for Fanuc. A patch-mode writer performs positional token edits —
NaNdeletes a word absorbing one separator space, insertion follows conventional order, trailing zeros trim keeping the dot — and refuses to rewrite variable, bracket and keyword values rather than corrupting them, reportingWriteback-Patch--VariableValue,--KeywordValue,--CommentOnlyTextand--EditUnmatched. Five of its choices follow the dialect rather than the convention: the variable prefix it recognizes and refuses (Qon klartext,Ron Siemens,#elsewhere), the keyword feed values it refuses (klartext'sFMAXandFAUTO), the comment spans it protects (klartext's;and//as well as the parenthesized span), and two that show in the written text. On a klartext file an insertedFlands after the rightmost ofDR+/DR-andRL/RR/R0as well as after its conventional predecessor coordinate words, so the patched block keeps the element order a TNC enforces — coordinates, rotation direction, radius compensation,F,M. And a trailing comment is wrapped in the file's own grammar, the Fanuc family's(text)against klartext's;text, so the optimizer's embedded source note leaves a klartext program valid instead of handing a control a parenthesis it would read as code. - A second diagnostic home. NcManipulationDiagnosticProgress
is a sibling of the play-time
NcDiagnosticProgress, dedicated to NC-rework operations — writeback conversion and optimization — so a play reset never discards manipulation results and vice versa.