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

249 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AppRobotDriver
Dieses Projekt empfängt G-Code und Robotersteuerbefehle, berechnet Inverse Kinematik für einen mehrgliedrigen Roboterarm und leitet die resultierenden Achsenbefehle an mehrere GRBL/FluidNC-Telnet-Sender weiter.
## Architektur
- `startRobot.js` startet zwei HTTPS-Server:
- Eingabe-Server + WebSocket für G-Code und Steuerbefehle
- Info-Server für Status, Position und einfache Weboberfläche
- `server/InputWS.js` empfängt Nachrichten von WebSocket-Clients, prüft sie auf G-Code oder Datei-Kommandos und gibt Positionsdaten zurück.
- `robot/GCode.js` verarbeitet G-Code, übersetzt ihn in Roboter-Koordinaten und triggert `robot.sendCommand()`.
- `robot/RobotBase.js` ist die abstrakte Basisklasse / der Interface-Vertrag: generische Infrastruktur (Zustand, `sendCommand`, Motor-Geschwindigkeiten) plus die zwei abstrakten Kinematik-Methoden.
- `robot/kinematics/Arm3SegmentLinearX.js` ist die konkrete Kinematik (Inverse + Vorwärts) für den aktuellen Arm. Die Auswahl der Kinematik erfolgt über `robot/KinematicsFactory.js` (Umgebungsvariablen `ROBOT_KINEMATICS` / `ROBOT_KINEMATICS_PARAMS`). Siehe `doc/ToDo_12_InverseKinematikConfig_ROADMAP.md`.
- `robot/RobotConfig.js` liest `data/robot/robot.json` beim Start synchron und gibt einen typisierten Konfigurations-Record zurück (Kinematik-Parameter, Bewegungs-Defaults, Controller-Endpunkte). Env-Variablen überschreiben die JSON-Werte.
- `server/RobotConfigService.js` stellt `GET/PUT /api/robot` und `GET /api/robot/history` über den InfoServer bereit (Single Source of Truth für alle Apps). Schreibzugriffe erfordern `Authorization: Bearer <ROBOT_API_KEY>`.
- `robot/TelnetSenderGRBL.js` formatiert die Motor-Positionen in GRBL-kompatible Befehle und sendet sie per Telnet an einen Zielcontroller.
## Eingaben
Die Eingaben kommen per WebSocket an den HTTPS-Server und werden in `server/InputWS.js` verarbeitet.
### Unterstützte Nachrichten
- `Ping`
- Antwort: Wird zurück an alle verbundenen Clients gesendet.
- `M114`
- Antwort: Positionsdaten des Roboters im JSON-Format.
- G-Code-Befehle:
- `G90`, `G91`, `G1`, `G28`
- `G92` (wird intern als `M92` verarbeitet — setzt Motorposition ohne Bewegung)
- Messungen in `X`, `Y`, `Z`, `A`, `B`, `C`, `E`, `F`
- `M1` für direkte Motor-Koordinaten
- Datei-Kommandos:
- `FPoint`, `FPlus`, `FMinus`, `FShow`, `FList`, `FLoad <file>`, `FSave <file>`, `FClear`
- `FFirst`, `FLast` — erkannt, aber noch nicht implementiert
- `M20`, `M23`, `M28`, `M29`
### G-Code-Verarbeitung
- `GCode.receiveGCode(robot, message)`
- Gruppiert Zeilen, unterstützt Inline-Jogging (`$J=`)
- Schaltet zwischen absoluter und relativer Koordinatenverarbeitung
- Aktualisiert Position und Winkel im `robot`-Objekt
- Führt inverse Kinematik aus mit `robot.calculateAngles3D()`
- Sendet das Ergebnis an `robot.sendCommand()`
## Ausgaben
- WebSocket-Broadcasts an alle verbundenen Clients
- Nachdem ein G-Code-Befehl verarbeitet wurde, sendet das System `GCode.getM114(robot)` zurück.
- Für Datei-Kommandos gibt `GCode.receiveFC()` ebenfalls die aktuelle Position zurück.
- Telnet-Ausgabe an GRBL/FluidNC-Geräte
- `TelnetSenderGRBL.execCommand()` erzeugt `G1`/`G90`-Befehle mit Achsenzuordnung und Feedrate.
- Info-Server API
- `/api/status` — zeigt Client-Status, Sender-Status und letzte Befehle/Pings an
- `/api/position` — gibt die aktuelle Roboterposition und Motorwinkel als JSON zurück
## Konfiguration
### Starten
- `npm start`
- Alternativ: `node startRobot.js`
### Umgebungsvariablen
- `PORT`
- Standard: `2095`
- Port für den WebSocket/HTTPS-Eingabeserver
- `GRBL_BASE_IP`
- Standard: `fluidNcBase.local`
- Zielhost für den ersten Telnet-Sender
- `GRBL_ELLBOW_IP`
- Standard: `fluidNcEllbow.local`
- Zielhost für den Ellbogen-Sender
- `GRBL_HAND_IP`
- Standard: `fluidNcHand.local`
- Zielhost für den Hand-Sender
- `ROBOT_DEFAULT_FEEDRATE`
- Standard: `1000` (mm/min)
- Default-Feedrate für `G1`-Befehle, wenn keine `F`-Angabe vorhanden ist
- `ROBOT_SPEED_MODE`
- Werte: `legacy` (Standard) oder `correct`
- `legacy`: alte Speed-Regelung — jeder Sender erhält die kartesische Feedrate `F`
unverändert (Verhalten exakt wie bisher).
- `correct`: koordinierte Feedrate pro Sender, sodass alle Controller den Bewegungs­schritt
gleichzeitig beenden. Aktiviert automatisch `calculateSpeeds()`.
- Details: `doc/ToDo_6a_Speed.md`
- `ROBOT_USE_SPEED_CALC`
- Werte: `true`, `1` oder sonst leer
- Interner Schalter, ob `robot.calculateSpeeds()` rechnet. Ändert allein **nicht** die
Sender-Ausgabe — dafür ist `ROBOT_SPEED_MODE=correct` nötig. Vom Korrekt-Modus
automatisch aktiviert.
- `ROBOT_KINEMATICS`
- Standard: `arm3segmentlinearx`
- Bezeichner der Kinematik-Klasse (case-insensitive). Bekannte Werte: `arm3segmentlinearx`,
`grabit` / `robot02` (Joy-IT Grab-It). Unbekannter Bezeichner → Fehler beim Start.
- `ROBOT_KINEMATICS_PARAMS`
- JSON-Objekt mit Konstruktor-Parametern, z. B. `{"l1":250,"l2":264,"l3":100}`.
Überschreibt die Werte aus `robot.json`. Wird von der Factory als viertes Argument
an den Konstruktor weitergereicht (erlaubt kinematik-spezifische Parameter wie `baseHeight`).
- `ROBOT_API_KEY`
- Statischer Bearer-Token für `PUT /api/robot`. Fehlt die Variable, generiert
`RobotConfigService` beim ersten Start einen zufälligen Key und speichert ihn in
`data/robot/.apikey` (nicht im Repo). Der Key wird beim Start einmalig geloggt.
### HTTPS-Konfiguration
- `https/localhost.key`
- `https/localhost.pem`
- Passphrase: Env-Variable `HTTPS_PASSPHRASE`, Default `abcd`
### robot.json
`data/robot/robot.json` ist die zentrale Konfigurationsdatei für einen konkreten Roboter.
Sie wird von `robot/RobotConfig.js` beim Start synchron gelesen. Fehlt die Datei, startet
der Driver mit Fallback-Defaults und loggt eine Warnung.
Relevante Abschnitte für den Driver:
```json
{
"kinematics": { "type": "arm3segmentlinearx" },
"motion": { "defaultFeedrate": 1000, "speedMode": "legacy" },
"controllers": {
"base": { "ip": "fluidNcBase.local", "port": 2300, "protocol": "telnet", "axes": ["x","y","z"] },
"elbow": { "ip": "fluidNcEllbow.local", "port": 5000, "protocol": "telnet", "axes": ["a",null,null] },
"hand": { "ip": "fluidNcHand.local", "port": 5000, "protocol": "telnet", "axes": ["c","e","b"] }
}
}
```
Armlängen werden aus dem `links`-Abschnitt abgeleitet (`Arm1.skeleton.to[1]` → l1 usw.).
Env-Variablen haben Vorrang vor robot.json (nützlich für Tests und schnelle Korrekturen).
Snapshots werden automatisch vor jedem PUT angelegt (`data/robot/robot_YYYYMMDD_HHmmss.json`).
Snapshots sind nicht im Repo (`.gitignore`), `robot.json` selbst schon.
### Telnet-Sender-Konfiguration
`startRobot.js` erzeugt die `TelnetSenderGRBL`-Instanzen dynamisch aus `cfg.controllers`
(geladen von `robot/RobotConfig.js`). Die Defaults entsprechen drei Controllern:
| Key | Default-IP | Port | Achsen |
|-----|-----------|------|--------|
| `base` | `fluidNcBase.local` | 2300 | `x, y, z` |
| `elbow` | `fluidNcEllbow.local` | 5000 | `a` |
| `hand` | `fluidNcHand.local` | 5000 | `c, e, b` |
IPs können per Env-Variable überschrieben werden (`GRBL_BASE_IP`, `GRBL_ELLBOW_IP`,
`GRBL_HAND_IP`). Alles andere (Port, Achsen, Controller-Anzahl) wird in `robot.json`
konfiguriert.
## Serverschnittstellen
### WebSocket Input Server
- Läuft auf `https://localhost:<PORT>`
- Erwartet WebSocket-Verbindungen und verarbeitet Nachrichten als G-Code oder Steuerbefehle
### Info Server
- Läuft auf `https://localhost:2098`
- Statische Dateien:
- `/`
- `/app.js`
- `/style.css`
- `/allApps.css`
- API-Endpunkte:
- `/api/status`
- `/api/position`
- `/api/robot``GET`: aktuelle `robot.json`; `PUT`: überschreibt sie (Auth erforderlich)
- `/api/robot/history` — Liste aller Snapshots
- `/api/robot/history/:ts` — einen bestimmten Snapshot abrufen
## Wichtige Dateien
- `startRobot.js`
- `server/InputWS.js`
- `server/InfoServer.js`
- `robot/RobotBase.js` — abstrakte Basisklasse / Interface-Vertrag (generische Infrastruktur)
- `robot/kinematics/Arm3SegmentLinearX.js` — konkrete Kinematik (Modell + Inverse/Vorwärts), Default-Arm
- `robot/kinematics/Arm3SegmentRotaryBase.js` — Kinematik für den Joy-IT „Grab-It" (Robot02), 5 Achsen + Greifer mit Drehbasis (`ROBOT_KINEMATICS=grabit`)
- `robot/KinematicsFactory.js` — wählt die Kinematik per Umgebungsvariable
- `robot/RobotConfig.js` — liest `data/robot/robot.json`, gibt typisierten Konfigurations-Record zurück
- `server/RobotConfigService.js` — REST-Endpunkte `/api/robot*` (lesen/schreiben, Snapshots, Auth)
- `data/robot/robot.json` — zentrale Roboter-Konfiguration (Single Source of Truth)
- `robot/GCodeParser.js` — wandelt rohe Nachrichten in strukturierte Befehlsobjekte
- `robot/RobotController.js` — wendet geparste Befehle auf das Modell an (Steuerlogik)
- `robot/GCode.js` — Fassade + Datei-Befehle
- `robot/TelnetSenderGRBL.js`
- `robot/fluidnc/FluidNCClient.js` — alternative WebSocket-basierte FluidNC-Anbindung mit Reconnect-Logik (noch nicht integriert)
- `GCodeFiles/` — enthalten Beispiel- und Log-G-Code-Dateien
## Laufzeitvoraussetzungen
- HTTPS-Zertifikate: `https/localhost.key` und `https/localhost.pem` (Passphrase via `HTTPS_PASSPHRASE`, Default `abcd`).
- `data/robot/robot.json` — wird beim Start eingelesen; fehlt die Datei, startet der Driver mit Defaults + Warnung.
- `logs/` wird beim Start automatisch angelegt (`fs.mkdirSync('logs', { recursive: true })` in `startRobot.js`).
- Telnet-Sender werden sofort beim Start als `cmdReceivers` registriert; interne Reconnect-Logik überbrückt verzögerte Controller-Verbindungen automatisch.
## ToDo / Open Tasks
Architektur- und Refactoring-Aufgaben sind in `doc/ToDo_*.md` dokumentiert:
| Datei | Thema | Status |
|---|---|---|
| `doc/ToDo_1_Parsing.md` | G-Code-Parser-Schicht einführen | ✅ erledigt |
| `doc/ToDo_2_Anbindung.md` | Sender-Interface und Orchestrierung | ✅ erledigt |
| `doc/ToDo_3_Config.md` | Zentralisierte Konfiguration | offen |
| `doc/ToDo_4_GCode.md` | G-Code- und Datei-Handling trennen | offen |
| `doc/ToDo_5_API.md` | WebSocket-Antwortlogik strukturieren | ✅ erledigt |
| `doc/ToDo_6_RobotController.md` | RobotController-Klasse einführen | ✅ erledigt |
| `doc/ToDo_6a_Speed.md` | Speed-Steuerung: Schalter, `calculateSpeeds()`-Fix, koordinierte Feedrate | ✅ erledigt (WS-Sender offen) |
| `doc/ToDo_6b_FileHandling.md` | File-Handling: fehlende Befehle, Cursor im Speicher, Fehler-Feedback | offen |
| `doc/ToDo_7_Tests.md` | Testabdeckung und Stabilität | teilweise |
| `doc/ToDo_8_Bugs.md` | Bekannte konkrete Bugs | teilweise |
| `doc/ToDo_9_HardwareFeedback.md` | Hardware-Feedback-Loop (GRBL-Antworten, Command-Queue, Positionsabgleich) | teilweise (Baustein Port→Motor ✅, Pakete 16 offen) |
| `doc/ToDo_10_VerbindungsVerlust.md` | Verbindungsverlust erkennen, Watchdog, UI-Statusanzeige | offen |
| `doc/ToDo_12_InverseKinematikConfig_ROADMAP.md` | Austauschbare Kinematik: RobotBase, KinematicsFactory, Grab-It | ✅ erledigt |
| `doc/ToDo_14_robot_json_service.md` | robot.json als REST-Service, RobotConfigService, RobotConfig | teilweise (Schritte 14 in appRobotDriver ✅, Schritte 57 offen) |
| `doc/ToDo_49_Cleanup.md` | Pre-Release-Cleanup: tote Code, Zertifikate, ToDos, README | offen |
### Empfohlene Bearbeitungsreihenfolge
```
ToDo_8 Bugs beheben — kurz, blockiert nichts anderes
ToDo_3 Config — Fundament für alles Weitere
ToDo_1 Parser ┐
ToDo_6 RobotController ┘ zusammen, da eng verzahnt
ToDo_4 Datei-Handling — danach, klar abgrenzbar
ToDo_6a Speed-Steuerung — calculateSpeeds bugfix, dann Sender-Integration
ToDo_6b File-Handling Detail — fehlende F-Befehle, Cursor im Speicher
ToDo_2 Sender-Interface — mit Entscheidung: Telnet vs. FluidNC-WebSocket
ToDo_9 Hardware-Feedback — baut auf ToDo_2 auf
ToDo_10 Verbindungsverlust — baut auf ToDo_2 auf, parallel zu ToDo_9 möglich
ToDo_5 API — parallel zu ToDo_2/4 möglich
ToDo_7 Tests — begleitend zu allen obigen
```
Kurzübersicht weiterer offener Punkte:
- [ ] Dokumentation der vollständigen G-Code-Syntax erweitern
- [ ] `FFirst`/`FLast`-Befehle in `GCode.receiveFC()` implementieren
- [ ] `ROBOT_USE_SPEED_CALC` und `motorSpeeds` im echten Betrieb prüfen
- [ ] `FluidNCClient.js` evaluieren: als Ersatz oder Ergänzung zu `TelnetSenderGRBL`?
- [x] HTTPS-Passphrase aus Env-Variable (`HTTPS_PASSPHRASE`) — erledigt
- [x] `logs/`-Verzeichnis beim Start automatisch anlegen — erledigt (`startRobot.js`)