Files
appRobotDriver/doc/ToDo_3_Config.md
2026-06-11 22:05:45 +02:00

8.4 KiB

ToDo 3 — Konfiguration

Ausgangslage

Konfiguration ist aktuell über drei Orte verstreut:

Ort Beispiele
Hardcodiert im Code Controller-Ports (2300, 5000), Passphrase 'abcd'
Env-Variablen GRBL_BASE_IP, ROBOT_DEFAULT_FEEDRATE, PORT, …
robot.json Geometrie, Rendering-Parameter, Pose-Estimation-Optionen

Ergebnis: Wer einen Roboter in einer anderen Umgebung betreibt, muss Code lesen, um zu wissen was anzupassen ist. Und es ist unklar, welches Programm für welchen Abschnitt zuständig ist.


Architektur-Entscheidung

robot.json ist die einzige Wahrheitsquelle für alles, was roboter-spezifisch ist.
Eine robot.json beschreibt einen konkreten Roboter vollständig — sie kann weitergegeben werden, wenn der Roboter in einer anderen Umgebung eingesetzt wird.

Env-Variablen bleiben nur für deployment-spezifische Werte, die nichts mit dem Roboter selbst zu tun haben:

Variable Grund
PORT (2095/2098) Server-Port ändert sich je Deployment, nicht je Roboter
HTTPS_KEY_PATH, HTTPS_CERT_PATH, HTTPS_PASSPHRASE Sicherheits-Infrastruktur
ROBOT_API_KEY Geheimnis, darf nie in einer weitergebbaren Datei stehen

Änderungen an robot.json

1 — Kinematik-Typ (kinematics)

Die Kinematik-Parameter (Armlängen, Achsen, Gelenk-Kette) sind bereits vollständig in links enthalten und werden von robot/RobotConfig.js daraus abgeleitet. Einzig der Name des Solver-Algorithmus fehlt noch:

"kinematics": {
  "_owner": "appRobotDriver",
  "type": "arm3segmentlinearx"
}

Kein Duplizieren von links-Daten. RobotConfig.js liest z.B.:

  • links.Arm1.skeleton.to[1] → l1
  • links.Ellbow.skeleton.to[0] → l3

2 — Feedrate und Controller-Zuordnung in jointToParent

Beide Infos gehören direkt zum Gelenk, weil sie die Hardware-Eigenschaft eines konkreten Joints beschreiben:

"jointToParent": {
  "name": "Slider",
  "type": "linear",
  "axis": [1, 0, 0],
  "origin": [0, 0, 16],
  "variable": "x",
  "feedrate": 2000,
  "controller": "base"
}
  • feedrate — maximale Vorschubgeschwindigkeit dieses Joints in mm/min (linear) oder °/min (revolute). Überschreibt den globalen Default aus motion.defaultFeedrate.
  • controller — Verweis auf den Schlüssel in controllers. Darüber weiss der Driver, welche Variable auf welchem Controller-Kanal liegt. Die heutigen hardcodierten Achszuordnungen ('x','y','z' / 'a',null,null / …) werden damit überflüssig.

3 — Controller-Endpunkte (controllers)

Top-Level-Abschnitt, nur IP und Port. Die Achszuordnung ergibt sich aus den controller-Verweisen in den Joints (kein Duplikat).

"controllers": {
  "_owner": "appRobotDriver",
  "base":  { "ip": "fluidNcBase.local",   "port": 2300, "protocol": "telnet" },
  "elbow": { "ip": "fluidNcEllbow.local", "port": 5000, "protocol": "telnet" },
  "hand":  { "ip": "fluidNcHand.local",   "port": 5000, "protocol": "telnet" }
}

Der Driver liest controllers für IP/Port, scannt dann links nach jointToParent.controller === "base" und bekommt so ["x", "y", "z"] als Achsliste.

4 — Globale Bewegungs-Defaults (motion)

Werte, die für alle Joints gelten, sofern kein feedrate im Joint hinterlegt ist. Ausserdem Software-Flags, die keine natürliche Heimat in einem einzelnen Joint haben:

"motion": {
  "_owner": "appRobotDriver",
  "defaultFeedrate": 2300,
  "speedMode": "legacy",
  "speedModeOptions": ["legacy", "correct"]
}

speedMode und defaultFeedrate lösen die Env-Vars ROBOT_DEFAULT_FEEDRATE und ROBOT_SPEED_MODE ab.


Interne Abhängigkeiten in robot.json

Mit controller-Verweisen in den Joints entstehen interne Cross-References. Die robot.json darf solche haben — das ist bewusste Design-Entscheidung, die Redundanz vermeidet. Ein späterer validator.py muss diese Konsistenz prüfen:

Referenz Regel
jointToParent.controllercontrollers.* Jeder Verweis muss auf einen existierenden Controller-Schlüssel zeigen
Marker-IDs Jede ID darf global nur einmal vergeben sein
parent in links Muss auf einen existierenden Link zeigen, kein Zyklus

Verantwortlichkeits-Tabelle

Jeder Abschnitt hat genau einen Eigentümer (das Programm, das diesen Abschnitt schreiben darf). Konsumenten lesen nur.

Abschnitt Eigentümer (_owner) Konsumenten
kinematics appRobotDriver appRobotDriver (via RobotConfig.js)
motion appRobotDriver appRobotDriver
controllers appRobotDriver appRobotDriver
units appRobotDriver alle
links (inkl. jointToParent.feedrate, .controller) appRobotDriver — Homing darf Marker-Positionen/-Normalen aktualisieren (via PUT /api/robot), aber keine Driver-Felder (feedrate, controller) verändern alle
vision_config appRobotHoming
constraint_rules, observation_weighting, multiview_calculation, pose_estimation, state_pose_params appRobotHoming
renderingInfo appRobotRendering
robot_test_poses, test_camera_positions/targets appRobotHoming, appRobotRendering
defaultPosition appRobotDriver, appRobotRendering
coordinateSystem alle

Sektionen ohne _owner sind manuell konfiguriert und werden von keinem Programm automatisch überschrieben. Der Validator prüft, dass Homing in links nur die erlaubten Felder (position, normal, spin, size in Markern) verändert.


Zugriffsmuster

appRobotDriver — neues Modul robot/RobotConfig.js

Der Driver liest robot.json synchron beim Start (direkt vom Disk, vor dem HTTP-Server-Start). RobotConfig.js ist der einzige Ort im Driver-Code, der robot.json kennt:

const cfg = RobotConfig.load(); // synchron, gibt typisierten Record zurück

cfg.kinematics.type          // → 'arm3segmentlinearx'
cfg.kinematics.l1            // → 250   (abgeleitet aus links.Arm1.skeleton)
cfg.motion.defaultFeedrate   // → 2300
cfg.controllers              // → { base: {ip, port}, elbow: {ip, port}, hand: {ip, port} }
cfg.axesByController('base') // → ['x', 'y', 'z']   (abgeleitet aus links)

Alle process.env-Lesungen für roboter-spezifische Werte wandern hierher. Env-Vars bleiben als Override-Ebene (Env hat Vorrang vor robot.json — nützlich für Tests und schnelle Korrekturen ohne Datei-Änderung).

Alle anderen Apps — HTTP GET

const robot = await fetch('https://appRobotDriver:2098/api/robot').then(r => r.json());

Kein eigenes Zugriffs-Modul nötig.


Umsetzungsschritte

Schritt 1 — robot.json erweitern

  • Abschnitte kinematics, motion, controllers eintragen
  • In jedem jointToParent: feedrate und controller ergänzen
  • Hinweis: controllers enthält explizite axes-Reihenfolge (Baum-Traversal liefert für Hand-Controller falsche Reihenfolge)
  • Beide Kopien aktualisiert: appRobotRendering/data/robot/robot.json und appRobotDriver/data/robot/robot.json

Schritt 2 — robot/RobotConfig.js anlegen

  • Liest robot.json synchron
  • Leitet l1/l2/l3 aus links.*.skeleton.to ab (behebt alten Bug: Ellbow.size[0] existierte nicht)
  • Gibt axesByController(key) aus controllers[key].axes zurück
  • Gibt typisierten Record mit Fallbacks zurück
  • Env-Override-Ebene: GRBL_*_IP, ROBOT_DEFAULT_FEEDRATE, ROBOT_SPEED_MODE, ROBOT_USE_SPEED_CALC

Schritt 3 — startRobot.js und RobotBase.js umstellen

  • startRobot.js: readArmLengthsFromConfig entfernt, ersetzt durch RobotConfig.load(); Controller-Setup config-getrieben (keine hardcodierten IPs/Ports/Achsen mehr)
  • RobotBase.js: akzeptiert optionalen config-Parameter im Konstruktor; Env-Vars bleiben als Fallback
  • Arm3SegmentLinearX und Arm3SegmentRotaryBase: reichen config/params an super() durch

Schritt 4 — HTTPS-Passphrase aus Env-Variable

HTTPS_PASSPHRASE lesen statt hardcodiertem 'abcd'. Default bleibt 'abcd' für lokale Entwicklung.

Schritt 5 — logs/-Verzeichnis automatisch anlegen

fsModule.mkdirSync?.('logs', { recursive: true }) in startRobot.js nach erfolgreichem HTTPS-Load. Bestehende ensureLogDir() in InputWS.js bleibt als zweite Absicherung.


Nicht in dieser ToDo

  • JSON-Schema-Validierung (separates Ticket, koordiniert mit dem geplanten validator.py)
  • Laufzeit-Reload von robot.json ohne Neustart
  • speedMode Details → ToDo 6a