Neues Kinematics
This commit is contained in:
@@ -55,11 +55,11 @@ Quellen: [Serial Protocol](http://wiki.fluidnc.com/en/support/serial_protocol),
|
||||
|
||||
## Designentscheidungen (festgeschrieben)
|
||||
|
||||
**B3 — Umkehr-Kinematik ist disambiguierbar.** Global nicht eindeutig, aber im Arbeitsraum
|
||||
dieses Roboters per **dokumentierter physikalischer Zusatzbedingung** auflösbar
|
||||
(z. B. „Ellbogen höher als Hand" bzw. „Ellbogen hinter der x-Achse"). `motorStateFromPorts()`
|
||||
bekommt eine feste Zweig-Wahl-Regel; die exakte Vorzeichen-Konvention wird beim Herleiten
|
||||
der Umkehrung gepinnt.
|
||||
**B3 — Umkehr-Kinematik.** *Aktualisiert nach der Analyse (ToDo_9a):* Die **Port→Motor**-Rückrechnung,
|
||||
die der Sync braucht, ist linear und **eindeutig** — keine Zweig-Wahl nötig. Die Ellbogen-oben/unten-
|
||||
Mehrdeutigkeit betrifft nur die **kartesische** Inverskinematik `calculateAngles3D()` (Pose →
|
||||
Gelenkwinkel), die der Sync nicht verwendet. Falls dort je eine Disambiguierung gebraucht wird,
|
||||
gilt die physikalische Zusatzbedingung („Ellbogen höher als Hand" bzw. „hinter der x-Achse").
|
||||
|
||||
**B5 — Lockstep als abschaltbare Absicherung.** Durch die koordinierte Feedrate (ToDo_6a
|
||||
`correct`) treffen ohnehin alle Achsen *gleichzeitig* am nächsten Ziel ein — Lockstep ist
|
||||
@@ -125,26 +125,42 @@ erstmals einen Promise zurückgeben/awaiten können.
|
||||
|
||||
---
|
||||
|
||||
## Baustein für Paket 4 + 5: Rückabbildung Port → Motorwerte
|
||||
## Baustein für Paket 4 + 5: Rückabbildung Port → Motorwerte — ✅ DURCHGERECHNET
|
||||
|
||||
> **Erledigt als Analyse.** Vollständige Herleitung: **`doc/ToDo_9a_PortRueckrechnung.md`**.
|
||||
> Verifikation: **`test/Robot.PortInverse.test.js`** (15 Tests grün).
|
||||
|
||||
Beide folgenden Pakete brauchen denselben Baustein: aus den von GRBL gemeldeten
|
||||
`MPos`-Werten der drei Controller die **sieben Motorwerte des Roboters** rekonstruieren
|
||||
(`xMotor, alpha, beta, a, b, c, eMotor`).
|
||||
|
||||
Das ist die **Umkehrung von `portValue()`** (`robot/TelnetSenderGRBL.js`). `portValue()`
|
||||
bildet *eine Roboter-Achse → einen GRBL-Port-Wert* ab, dabei koppeln einige Ports mehrere
|
||||
Achsen (z. B. der z-Port der Hand mischt `c, b, z, y`). Die Rückrichtung muss diese
|
||||
Kopplung **explizit auflösen** — sie ergibt sich nicht automatisch.
|
||||
**Ergebnis:** Für die produktive Verkabelung (`startRobot.js`) ist die Abbildung
|
||||
Motorwerte → gesendete GRBL-Achswerte **linear und eindeutig umkehrbar** — auf Port-Ebene
|
||||
gibt es **keine** Mehrdeutigkeit. `factorTurnLift`/`handOpenInMM` kommen in der produktiven
|
||||
Verkabelung gar nicht vor (nur in nicht-genutzten `portValue`-Zweigen).
|
||||
|
||||
- [ ] `motorStateFromPorts(portReadings)` definieren — algebraische Umkehrung von `portValue()`
|
||||
- Eingang: pro Sender die gelesenen Port-Werte (`{x, y, z}` Base, `{a}` Elbow, `{c, e, b}` Hand)
|
||||
- Ausgang: `{xMotor, alpha, beta, a, b, c, eMotor}`
|
||||
- Grad→Rad zurückrechnen, `factorTurnLift`/`handOpenInMM` herausrechnen, gekoppelte Ports auflösen
|
||||
- **Zweig-Wahl (B3):** wo die Lösung mehrdeutig ist, die dokumentierte physikalische
|
||||
Zusatzbedingung anwenden (z. B. „Ellbogen höher als Hand"). Konvention im Code festhalten.
|
||||
- [ ] **Round-Trip-Invariante** als Test: `portValue(motorStateFromPorts(p)) ≈ p`
|
||||
- dasselbe Muster wie `test/Robot.Kinematics.RoundTrip.test.js`
|
||||
- schützt die Umkehrfunktion gegen Drift gegenüber `portValue()`
|
||||
```js
|
||||
// D = 180/π ; r = { base:{x,y,z}, elbow:{x}, hand:{x,y,z} }
|
||||
xMotor = r.base.x
|
||||
alpha = r.base.y / D
|
||||
beta = (r.base.z + r.base.y) / D
|
||||
a = r.elbow.x / D
|
||||
b = r.hand.z / D
|
||||
c = (r.hand.x + r.hand.z) / D
|
||||
eMotor = r.hand.y / D
|
||||
```
|
||||
|
||||
> **B3 ist hier kein Thema.** Die Ellbogen-oben/unten-Mehrdeutigkeit steckt allein in der
|
||||
> kartesischen Inverskinematik `calculateAngles3D()` (Pose → Gelenkwinkel). Der Sync nutzt
|
||||
> diese Richtung nicht — er geht `MPos → Motorwerte → Vorwärtskinematik → Pose`, beide
|
||||
> Schritte eindeutig. Der gesamte Sync-Pfad ist damit eindeutig.
|
||||
|
||||
Offen für die spätere **Umsetzung** (Paket 4, nicht mehr Analyse):
|
||||
|
||||
- [ ] `motorStateFromPorts()` aus der Analyse in den Produktiv-Code heben (Ort: Sender oder
|
||||
Kinematik-Helfer) und im Sync verdrahten
|
||||
- [ ] **Round-Trip-Invariante** als Dauer-Test mitführen: `portValue(motorStateFromPorts(p)) ≈ p`
|
||||
— schützt gegen Drift, falls sich die Verkabelung in `startRobot.js` ändert
|
||||
|
||||
> Hinweis: Gelesen wird auf dem **aktiven** Sender `TelnetSenderGRBL` (im `data`-Handler,
|
||||
> siehe Paket 1) — nicht auf `FluidNCClient.js`.
|
||||
@@ -167,7 +183,7 @@ sonst nicht, wo der Roboter physisch wirklich steht.
|
||||
im bisher synchronen Dispatch-Pfad.
|
||||
- [ ] Ablauf des Sync:
|
||||
1. an alle drei Sender einmalig `?` senden, je `MPos` aus der Antwort parsen (Paket 3)
|
||||
2. `motorStateFromPorts(...)` → sieben Motorwerte rekonstruieren (Baustein oben, inkl. B3-Zweigwahl)
|
||||
2. `motorStateFromPorts(...)` → sieben Motorwerte rekonstruieren (Baustein oben — linear/eindeutig, ToDo_9a)
|
||||
3. diese auf den Roboter schreiben: `robot.xMotor/alpha/beta/a/b/c/eMotor = …`
|
||||
4. **Vorwärtskinematik** anstoßen: `robot.calculatePositionFromMotorAngles()`
|
||||
→ füllt `robot.x/y/z` und `phi/theta/psi` aus den Hardwarewerten
|
||||
|
||||
Reference in New Issue
Block a user