Dokumentation Referenz

Dateiformate

_Entwurf (Runde 14): Der Text wird noch geschrieben; die Abschnitte können noch wachsen._

Programme

Ein Programm ist eine G-Code-Textdatei im Dialekt von Grbl 1.1, den Twinwrights eigener Kernel spricht. Studio liest jede solche Datei. Die Programme, die das CAM von Studio schreibt, sehen so aus:

(Sensor bracket)
(tool T1 flat 6 n3 L20, 6061-T6: S13263, F836, plunge F279, depth of cut 1.20 mm, stepover 2.40 mm)
(program zero: on the blank's top; the machine's top first; T1 is the length reference)
G21 G90 G17 G94 G54
G53 G0 Z0
T1 M6
G53 G0 Z0
M3 S13263
G4 P3 (up to speed)
(face X-2..62 Y-2..42, 0.3 mm deep: 1 layer of 12 passes)
...
M5
M9
G53 G0 Z0
M30
TeilWas es ist
ProgrammkopfKommentare: der Titel des Auftrags; das erste Werkzeug, das Material und die wichtigsten Schnittdaten; wo der Nullpunkt des Programms liegt
ModiG21 G90 G17 G94 G54: Millimeter, absolut, die XY-Ebene, Vorschub pro Minute, Nullpunktverschiebung G54
G53 G0 Z…Eine Fahrt an das obere Ende von Z, in Maschinenkoordinaten: am Anfang, bei jedem Werkzeugwechsel und am Ende. Das ist die Höhe, auf der die Referenzfahrt Z zurücklässt.
T… M6Ein Werkzeugwechsel. Die Steuerung misst das neue Werkzeug am Werkzeuglängensensor.
M3 S…, G4 P…Die Spindel ein, dann eine Verweilzeit, während sie auf Drehzahl kommt. Die Pumpe einer wassergekühlten Spindel (M8) kommt zuerst.
Formelement-KommentareJedes Formelement beginnt mit einem Kommentar, der sagt, was es bearbeitet
BewegungenG0, G1 und Kreisbögen G2/G3 mit I und J. Gebohrt wird mit G81 oder mit G83 und Entspanen; die R-Ebene liegt 1 mm über der Oberseite.
EndeM5, M9, die Fahrt nach oben, M30

Kommentare stehen in Klammern. Die Sätze haben keine Nummern.

Studio bewahrt jede Version eines Programms im Programmordner (Dokumente/Twinwright Studio/programs) auf, in einem Ordner mit dem Namen des Programms:

DateiWas sie enthält
v0001.ncDer Text des Programms, wie er gespeichert wurde
v0001.jsonSeine Version, die Zeit (UTC), wer es erstellt hat, warum, die Version, aus der es entstand, sein Hash und seine Sätze
v0001.ops.jsonWas aus jedem Formelement wurde (Bearbeitung, Strategie, Werkzeug, Sätze, Drehzahl, Vorschub): Das Einrichteblatt liest sie

Aufträge und Aufspannungen

Ein Auftrag ist die Beschreibung eines Teils, aus der das CAM Programme erstellt. Er ist ein JSON-Objekt:

SchlüsselBedeutung
nameDer Name des Programms, zum Beispiel bracket.nc
title, descriptionTexte für den Programmkopf und das Einrichteblatt
materialDas Material, zum Beispiel 6061-T6; Bezeichnungen aus anderen Normen werden erkannt
toolDas Werkzeug in der Spindel, als Spezifikation (flat 6 n3 L20)
toolsDie Werkzeugtabelle: {"1": "flat 6 n3 L20", "2": "drill 3.4 118 L20"}. Fehlt sie, gilt die der Maschine.
cuttingWerte, die die gewählten überschreiben: rpm, feed, ap, ae, finish_ap; corner_steps (true oder false: die Innenecken einer Wand zuerst in Stufen schneiden)
safe_zDie Höhe, auf der die Fahrten über das Teil verlaufen, in Millimetern über dem Werkstücknullpunkt
zeroWo der Werkstücknullpunkt liegt: front-left-top (der Standardwert) oder center-top
featuresDie Formelemente, in der Reihenfolge, in der sie gefräst werden. Siehe Programme erstellen.
setupsStatt features: ein Objekt für jede Aufspannung
nestStatt features: auf einer Platte verschachtelte Teile

Eine Aufspannung hat eigene features und gibt an, wie das Teil aus der vorhergehenden Aufspannung zu ihr gelangt:

SchlüsselBedeutung
turnu: um X gewendet (vorn und hinten tauschen die Plätze); v: um Y (links und rechts)
fixtureAb dieser Aufspannung anders gehalten (vise, clamps, tape …)
zeroDer erneut gefundene Werkstücknullpunkt: front-left-top oder center-top. Fehlt er, gilt nach einem Wenden oder einem neuen Spannmittel front-left-top, sonst der Nullpunkt der vorherigen Aufspannung.
name, tool, tools, cutting, safe_zDie der Aufspannung selbst; sie gehen denen des Auftrags vor
{"name": "bracket.nc", "title": "Sensor bracket", "material": "6061-T6",
 "tools": {"1": "flat 6 n3 L20", "2": "drill 3.4 118 n2 L20"},
 "features": [
  {"op": "face", "x0": -2, "y0": -2, "x1": 62, "y1": 42, "depth": 0.3, "tool": 1},
  {"op": "pocket", "shape": "rect", "x0": 6, "y0": 6, "x1": 28, "y1": 34, "r": 3, "depth": 4, "tool": 1},
  {"op": "pocket", "shape": "circle", "cx": 44, "cy": 20, "d": "Ø12 H7", "depth": 6, "tool": 1},
  {"op": "drill", "points": [[44, 6], [44, 34]], "depth": 8, "tool": 2}]}

Jede Version eines Auftrags wird neben dem Programm aufbewahrt, das sie erzeugt hat, als job-v0001.json: mit ihrer Version, der Zeit (UTC), wer sie erstellt hat (operator oder ai:<client>), einer Notiz, der Programmversion, die sie erzeugt hat, und dem Auftrag selbst. Ein Auftrag in Aufspannungen führt außerdem für jede Aufspannung das Programm, die erzeugte Version und deren Hash auf.

Aufzeichnungen (MCAP)

--mcap FILE zeichnet einen Lauf in eine MCAP-Datei auf (mcap.dev, Formatversion 0): ein Kanal für jede Art von Daten, JSON-Nachrichten, jeder Kanal mit seinem JSON-Schema, nicht in Chunks aufgeteilt und nicht komprimiert, und am Ende eine Zusammenfassung mit den Statistiken und einer CRC. Die Tests von Studio lesen die Dateien wieder ein und prüfen sie gegen die MCAP-Spezifikation; Anwendungen, die MCAP lesen, wie PlotJuggler und Foxglove, sollen sie öffnen können, aber das wurde noch nicht ausprobiert.

  • --rec-period MS legt fest, wie oft die abgetasteten Kanäle geschrieben werden (1 ms, wenn nichts angegeben ist).
  • Eine Aufzeichnung ändert nichts am Lauf: Ein aufgezeichneter Lauf und derselbe Lauf ohne Aufzeichnung sind Bit für Bit gleich.
  • --play FILE.mcap spielt eine Aufzeichnung in Studio ab, mit einer Zeitleiste: Abspielen, Pausieren, Springen, 0,25- bis 10-fache Geschwindigkeit. Während des Abspielens wird nichts simuliert.

Zeit

Die Log-Zeit jeder Nachricht ist die virtuelle Zeit des Zwillings, in Nanosekunden ab dem Einschalten. Die meisten Kanäle tragen außerdem t, dieselbe Zeit in Sekunden. Ein abgetasteter Kanal schreibt nur dann eine Nachricht, wenn sich etwas darin geändert hat.

Der Dateikopf

Ein Metadatensatz mit dem Namen mc1sim sagt, was der Lauf war:

SchlüsselBedeutung
machineDer Name der Maschine
drive_modelDas Antriebsmodell des Laufs: L0, L1, L2, L2/3 (drei Massen) oder L3
f_cpuDer Takt der Steuerung, Hz
nvsEin Hash der gespeicherten Einstellungen der Steuerung zu Beginn des Laufs, 16 Hexadezimalziffern
sample_period_msDie Abtastperiode
timevirtual, ns from power-on

Kanäle

KanalGeschriebenFeldTypEinheitBedeutung
/machineabgetastetposnumber[3]mmWo jede Achse steht: die Mechanik, nicht die Vorstellung der Steuerung davon
mposnumber[3] oder nullmmDie Maschinenposition der Steuerung (MPos); null, solange die Steuerung aus ist
lostnumber[3]Die Schritte, die jede Achse verloren hat
feednumbermm/minDer aktuelle Vorschub der Steuerung
tipnumber[3]mmDie Werkzeugspitze gegenüber dem Werkstück: bei eingeschaltetem Fehlermodell des Zwillings um dessen Fehler verschoben, bei ausgeschaltetem dasselbe wie pos
/drivesabgetastet, mit einem Antriebsmodell ab L1ferr_umnumber[3]µmDer Schleppfehler jedes Antriebs
statestring[3]Der Zustand jedes Antriebs
km1booleanDas Schütz KM1 ist geschlossen
bus48booleanDie 48-V-Versorgung der Antriebe ist eingeschaltet
/spindleabgetastet, mit einem Spindelantriebf_outnumberHzDie Ausgangsfrequenz des Antriebs
rpmnumbermin⁻¹Die Drehzahl der Spindel
ampsnumberADer Ausgangsstrom des Antriebs
load_pctnumber%Die Last, wie der Antrieb sie meldet
torque_nmnumberN·mDas Drehmoment des Motors
bus_vnumberVDie Zwischenkreisspannung des Antriebs
cmd_rpmnumbermin⁻¹Die Drehzahl, die die Steuerung vorgibt
run, pumpbooleanDer Antrieb läuft; die Pumpe ist an
powerstringDie eigene Versorgung des Antriebs: ready, boot oder off
faultstringDer Fehler des Antriebs, wie ihn dessen Anzeige zeigt
/controllerbei ÄnderungstatestringDer Zustand der Steuerung (Off, solange sie aus ist)
alarmintegerDer Alarm, in dem sie sich befindet (0: keiner)
homedintegerDie referenzierten Achsen, je ein Bit: X 1, Y 2, Z 4
limitsintegerDie aktiven Endschaltereingänge, je ein Bit
probe, estop, motor_fault, doorbooleanDie Eingänge für Messtaster, Not-Halt, Motorfehler und Tür (die MC-1 hat keine Tür)
onbooleanDie Steuerung ist eingeschaltet
/powerbei Änderungmains, v24, mcu, km1, bus48booleanNetz; die 24-V-Versorgung; die laufende Steuerung; KM1; die 48-V-Versorgung
vfd_mains, vfd, pumpboolean, string, booleanDas Netz des Spindelantriebs; sein Zustand (none, ready, boot, off); die Pumpe
/serial/insobald es eintriffttextstringDie Bytes, die die Steuerung empfangen hat; Steuerzeichen als \u-Escapes
/serial/outsobald es eintrifftlinestringJede Zeile, die die Steuerung geschrieben hat
/eventssobald sie auftretentextstringJeder Eintrag des Ereignisprotokolls: Marken, die Versorgung, die Antriebe, der Spindelantrieb, Kollisionen, Kabelbrüche
/cutabgetastet, mit einem RohteilcuttingbooleanEs wird Material abgetragen; solange nicht, sind die folgenden Werte 0, außer rpm und removed_mm3
mrr_mm3_snumbermm³/sDie Materialabtragsrate
ap_mm, ae_mmnumbermmDie axiale Schnitttiefe und die radiale Schnittbreite
fz_mmnumbermmDer Vorschub pro Zahn
rpmnumbermin⁻¹Die Drehzahl der Spindel
fx_n, fy_n, fz_nnumberNDie Schnittkraft entlang der Maschinenachsen
torque_nm, power_wnumberN·m, WDas Schnittmoment und die Schnittleistung
kc_j_mm3numberJ/mm³Die spezifische Schnittenergie
removed_mm3numbermm³Das bisher abgetragene Material
/inputsobald es eintrifftlinestringDie Eingaben der Sitzung, Zeile für Zeile, wie --record sie schreibt (siehe Sitzungsprotokolle)
/shadowsobald es eintrifft, im Schattenmodushost_snumbersDie Zeit des Computers
dirstringt zur realen Maschine, r von ihr
datastringDie Bytes, jedes als ein Zeichen U+0000–U+00FF, bis zu 1 KB pro Nachricht
/ui/state, /soundfür den PlayerDer Zustands-Frame der Ansichten (30 pro Sekunde, solange er sich ändert) und der Frame des Klangs (alle 10 ms virtueller Zeit, wenn er sich ändert). Eigene Kanäle von Studio: Ihre Felder können sich von Version zu Version ändern.

Pin-Verläufe (VCD)

--vcd FILE schreibt die Pins der Steuerung als VCD-Datei (IEEE 1364), die GTKWave und PulseView lesen: Der Scope mcu enthält die Pins der Steuerung, jede Änderung zu dem Taktschritt, in dem sie geschieht (die Schritt-Pins als Impulse von $0 Mikrosekunden); der Scope machine enthält die Leitungen außerhalb der Steuerung: die Versorgungen, KM1, den Spindelantrieb, die Pumpe, den Not-Halt-Taster, den Werkzeuglängensensor, die fünf Schalter. Die Zeitskala beträgt 1 ns.

Sitzungsprotokolle

--record FILE schreibt die Eingaben einer Sitzung, jede mit ihrer virtuellen Zeit: was die Sender-Programme gesendet haben, die Echtzeitbefehle, die Befehle der Ansichten. --replay FILE führt die Sitzung Bit für Bit noch einmal aus, mit derselben Version von Studio und denselben Maschinendateien. --replay FILE --branch S spielt sie bis S Sekunden ab und läuft von dort live weiter; mit --record hat der Zweig ein eigenes Protokoll, das vom übergeordneten Protokoll ausgeht (# branch <parent> <ticks>). Ein Protokoll ist Text; seine Zeilen sind Studios eigenes Format und können sich von Version zu Version ändern.

Das Weltarchiv

Was der Zwilling zwischen den Sitzungen behält, so wie es eine reale Maschine tut, wenn sie aus- und wieder eingeschaltet wird: wo die Achsen stehen, das Rohteil mit seinen Schnitten, das Werkzeug in der Spindel, der Speicher der Steuerung und die Uhr der Platine sowie die Wärme, die abkühlt, während die Maschine aus ist. Die Steuerung startet kalt: Die Maschine wird erneut referenziert.

Das Fenster bewahrt die Welt jeder Maschine im Zustandsordner auf (unter Windows %LOCALAPPDATA%\Twinwright\Studio): die der ersten Maschine in world, die der anderen in machines\<id>\world. --world DIR verwendet einen anderen Ordner; --world-reset beginnt mit dem Werkszustand. Stapelläufe, Tests, Wiederholungen, abgespielte Aufzeichnungen und die Hintergrundmaschinen der KI behalten keine Welt, es sei denn, --world ist angegeben. Eine Instanz zur Zeit öffnet eine Welt; eine zweite beginnt mit dem Werkszustand und speichert nichts.

DateiWas sie enthält
world.jsonDer Stand am Ende der Sitzung (siehe unten), zuerst nach world.json.tmp geschrieben, dann umbenannt
stock.snapDie Zellen des Rohteils, geschnitten oder nicht (binär, TWSTOCK1)
eeprom.binDer nichtflüchtige Speicher der Steuerung: ihre Einstellungen, Nullpunktverschiebungen und Werkzeugdaten, bei jeder Änderung sofort durchgeschrieben

world.json:

SchlüsselBedeutung
worldDie Version des Formats: 1
saved_at, saved_epochWann es gespeichert wurde: UTC und Sekunden seit 1970
versionDie Version von Studio, die es gespeichert hat
posWo die Achsen standen, mm (X, Y, Z)
toolDas Werkzeug in der Spindel, als Spezifikation (flat 6 n3 L20)
tool_tableDie Werkzeugtabelle des Auftrags: {"1": "flat 6 n3 L20", ...}
tool_autoDer Zwilling spielt bei einem Werkzeugwechsel den Bediener: Er setzt das Werkzeug aus der Tabelle ein und drückt Zyklusstart
setupDie Werkstückspannung und das Rohteil, wie sie „Aufspannung speichern“ im Fenster schreibt (null: keine)
cellsstock.snap enthält die Zellen des Rohteils
thermalDie Wärme: screws (jede Gewindespindel über dem Rahmen), frame (über 20 °C), ambient (der Raum über 20 °C), part_heat und part_offset (das Werkstück über dem Rahmen: was die Schnitte einbringen, und ein vorgegebener Versatz), alle in K; spindle_um, die Längung der Spindel in µm
rtcDer Stand der Uhr der Platine, s
probe_calDer Messtaster, wie er zuletzt kalibriert wurde: der Durchmesser der Kugel, ihr wirksamer Radius, das Lobing und seine Phase, der Durchmesser der Ringlehre, die größte Abweichung, wann und von wem (erst nach einer Kalibrierung)
odometertravel_mm und reversals jeder Achse, spindle_h (die Stunden der Spindel) und on_h (die Stunden der Anwendung), über die Sitzungen aufsummiert

Beim nächsten Start stehen die Achsen dort, wo sie standen; dasselbe Rohteil kommt mit seinen Zellen zurück, ebenso das Werkzeug und die Tabelle; die Wärme hat sich so lange abgekühlt, wie die Maschine aus war, jedes Teil mit seiner eigenen Zeitkonstante seinem Ruhewert entgegen; die Uhr der Platine ist weitergelaufen. --world-off S gibt an, wie lange die Maschine aus war (für Tests; sonst die Zeit seit dem Speichern). Beim Start angegebene --pos, --tool, --stock, --setup und --part haben Vorrang vor dem Archiv.

Lizenzdateien

Eine Lizenzdatei (.twlic) ist ein JSON-Objekt in UTF-8, signiert mit Ed25519. Studio prüft sie auf dem Computer, ohne Netzwerk. Wo die Dateien liegen und wie sie verwendet werden: Lizenzen, Arbeitsplätze und Aktivierung.

Dieses Beispiel stammt aus den gemeinsamen Testvektoren. Es ist mit dem Testschlüssel signiert (kid test), den Release-Builds nicht akzeptieren:

{"v": 1, "kid": "test", "id": "TWL-TEST000001", "edition": "pro", "kind": "subscription", "seats": 1,
 "holder": "Weber Lab, TU Example", "issued": "2026-11-02T10:00:00Z", "valid_until": "2027-11-02T10:00:00Z",
 "renew_after": "2027-10-28T10:00:00Z", "updates_until": null, "fp": ["0123456789abcdef0123456789abcdef"],
 "mc1_serial": null,
 "sig": "h3FTqZnDYtq8Q7_0ZuELLeDrTfyZnkTPgvDWSywTyl7BCJJxGIyhrBQUjYHJiE1_WOWaFarqbveFiMLrEfUyCA"}

Felder

FeldTypBedeutung
vintegerDie Version des Formats: 1. Studio behandelt eine Datei einer anderen Version als ungültig.
kidstringWelcher der Schlüssel von Twinwright die Datei signiert hat
idstringDie Nummer der Lizenz: TWL- und 10 Buchstaben und Ziffern. Die Verlängerung sendet sie.
editionstringmaker oder pro
kindstringsubscription, perpetual (Kauflizenz) oder owner (MC-1-Besitzer)
seatsintegerDie Anzahl der Arbeitsplätze
holderstringFür wen die Lizenz gilt: eine Person oder eine Organisation. Nie eine E-Mail-Adresse.
issuedDatum und UhrzeitWann die Datei signiert wurde, UTC, YYYY-MM-DDTHH:MM:SSZ
valid_untilDatum und Uhrzeit oder nullAbonnement: das Ende des bezahlten Zeitraums. Kauflizenz: das Ende des Erstattungszeitraums in der ersten Datei, null in der dauerhaften.
renew_afterDatum und Uhrzeit oder nullAb wann Studio versucht, die Datei zu verlängern
updates_untilDatum oder nullKauflizenz, MC-1-Besitzer: Die bis zu diesem Tag veröffentlichten Versionen haben die kostenpflichtigen Funktionen
fpArray von ZeichenkettenDie Computer, an die die Lizenz gebunden ist: die Hashes ihrer Fingerabdrücke, bis zu drei je Arbeitsplatz
mc1_serialstring oder nullMC-1-Besitzer: die Seriennummer der Maschine. Studio prüft die Maschine beim Betrieb nicht.
sigstringDie Ed25519-Signatur der anderen Felder, base64url ohne Padding

Ein Feld, das Studio nicht kennt, ist Teil der signierten Bytes, und Studio ignoriert seine Bedeutung.

Die signierten Bytes

Die Signatur deckt die Datei ohne sig ab, geschrieben in einer kanonischen Form:

  • Schlüssel in der Reihenfolge der Unicode-Codepoints;
  • kein Leerraum;
  • Zeichenketten mit den kürzesten Escape-Folgen von JSON;
  • Ganzzahlen ohne Dezimalpunkt; keine anderen Zahlen, und kein Schlüssel doppelt.

Studio schreibt die Datei in dieser Form, bevor es die Signatur prüft. Leerzeichen, Zeilenumbrüche und die Reihenfolge der Schlüssel in der Datei spielen deshalb keine Rolle. Ein geänderter Wert lässt die Prüfung fehlschlagen.

Der Hash des Fingerabdrucks

Der Hash besteht aus den ersten 32 Hexadezimalziffern von SHA-256 über die Bytes twinwright-fp-v1, ein Nullbyte und die ID des Computers:

SystemDie ID des Computers
WindowsDer Wert MachineGuid unter HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography
Linux/etc/machine-id

Ohne beides erzeugt Studio eine zufällige ID und legt sie im Lizenzordner ab (machine.id); sie zu löschen macht den Computer zu einem anderen. Die ID selbst verlässt den Computer nie.

Zum Beispiel ergibt die ID 8b1c3a0e-5f2d-4c7a-9e61-2d0f4b7a1c55 den Hash 0a2d31bb82176516415efa7b3a340562.

Der Anforderungscode

Der Anforderungscode für die Offline-Aktivierung ist das kanonische UTF-8-JSON {"fp": <the hash>, "version": <Studio's version>} in base64url ohne =-Padding. Zum Beispiel ergeben der Hash 0123456789abcdef0123456789abcdef und die Version 1.0.0:

eyJmcCI6IjAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmIiwidmVyc2lvbiI6IjEuMC4wIn0

TwinwrightStudio.exe --licence-request gibt den Anforderungscode dieses Computers aus.

Testdateien

Eine Testphase ist eine Lizenzdatei wie die anderen, vom Lizenzserver von Twinwright signiert: "kind": "trial", der Hash dieses Computers in fp und valid_until 30 Tage nach Beginn der Testphase. Sie wird nie verlängert. Eine von Hand geänderte Testdatei gilt nicht mehr.

Das Maschinenarchiv

Jeder Schlüssel des Archivs einer Maschine, mit den Werten der MC-1: Schema des Maschinenprofils.