G28 Singularität und Planungen
This commit is contained in:
@@ -122,34 +122,95 @@ Umgesetzt:
|
||||
- **Spiegelung an der x-z-Ebene** in `Arm3SegmentLinearX` (`_mirrorWorkspaceY`): die
|
||||
interne Mathematik (`_ikPlusY`/`_fkPlusY`) rechnet weiter in +y, die öffentlichen
|
||||
Methoden spiegeln die Workspace-Pose (y, pY, φ, ψ; θ bleibt) → α=0 zeigt nach −y.
|
||||
- **G28** (Home) auf −y umgestellt: `y = -(l1+l2+l3)`, `phi = +π/2`.
|
||||
- **G28** (Home) auf −y umgestellt **und Singularität behandelt**: die voll ausgestreckte
|
||||
Stellung (`|y| = l1+l2+l3`) ist eine Handgelenk-Singularität, in der die IK `a`/`c` nicht
|
||||
bestimmen kann (Müll wie `a=135°, c=45°` → Finger schräg). G28 setzt dort die Motorwerte
|
||||
**direkt** (`alpha=beta=a=c=0`, `b=π` = gerade Hand) und füllt die Pose per FK.
|
||||
- **Tests:** `test/Robot.Kinematics.NegativeY.test.js` (Grundstellung −590, Homing-Pose
|
||||
in −y, Round-Trip in −y, a=0 → Knick-Achse ∥ x).
|
||||
- **Migration:** `Robot.02_UpperArm` und der G28-Test auf −y umgestellt.
|
||||
- **Doku:** `doc/Info_G92.md` Y/Z (und C/A nach der Spiegelung) aktualisiert.
|
||||
|
||||
### Phase 2 — Handgelenk-/Finger-Nullstellung (B, C) — OFFEN
|
||||
### Phase 2 — Handgelenk-/Finger-Nullstellung (B, C, Greifer) — OFFEN
|
||||
|
||||
> **Voraussetzung (User):** Erst Visualisierung/Überprüfung der Finger, dort werden noch
|
||||
> Fehler vermutet. **a-Achse ist bereits korrekt** (a=0 → Knick-Achse ∥ x) — Phase 2
|
||||
> betrifft nur **B (Knick)**, **C (Roll)** und die **Greifer-Kopplung**.
|
||||
> **Voraussetzung (User):** Erst die Finger visualisieren/prüfen — dort werden noch Fehler
|
||||
> vermutet. **a-Achse ist bereits korrekt** (a=0 → Knick-Achse ∥ x). Phase 2 betrifft
|
||||
> **B (Knick)**, **C (Roll)** und die **Greifer-Kopplung**.
|
||||
|
||||
1. **Finger/Hand visualisieren** und gegen die echte Mechanik prüfen (User).
|
||||
2. **B-Konvention:** gerade Hand soll **0°** sein (derzeit 180°; physischer Knick = 180° − B).
|
||||
Mapping festlegen (z.B. `b → 180° − b` an der Schnittstelle) und FK/IK anpassen.
|
||||
3. **C-Nullpunkt:** neutral soll **0°** sein (derzeit `ψ = 90° − C`).
|
||||
⚠️ Der C↔ψ-Bezug ist **posenabhängig** (`acos(cos β · sin a)`); ein global sauberes
|
||||
`c=0 = neutral` braucht ggf. eine tiefere Umparametrierung — **vor** der Umsetzung bewerten.
|
||||
4. **Greifer-Kopplung** `eMotor = e − b − c` prüfen: mischt mm (e) mit Radiant (b, c)
|
||||
— gegen die echte Sehnen-Mechanik validieren.
|
||||
5. Tests + `Info_G92.md` nachziehen.
|
||||
**Ziel-Konvention:** gerade Hand → **B = 0°** (statt 180°); neutraler Roll → **C = 0°**;
|
||||
Greifer-Kopplung konsistent und gegen die echte Mechanik kalibriert.
|
||||
|
||||
#### Vorab-Erkenntnis aus dem Code (wichtig!)
|
||||
|
||||
Die b/c/e-Konvention ist an **mehreren** Stellen kodiert, die **gemeinsam** geändert werden
|
||||
müssen. **Invariante:** solange die Hardware-Nullpunkte nicht neu kalibriert werden, müssen
|
||||
die an FluidNC gesendeten Port-Werte **gleich bleiben** — eine reine Modell-Umbenennung darf
|
||||
die Hardware-Bewegung nicht verändern.
|
||||
|
||||
Fundstellen:
|
||||
|
||||
| Datei / Stelle | aktuelle Kodierung |
|
||||
|----------------|--------------------|
|
||||
| `Arm3SegmentLinearX._fkPlusY` | `vHand = rotate(vecUnterarm, n, b)`; `psi = c − acos(−n.z)` → **b=π = gerade** |
|
||||
| `Arm3SegmentLinearX._ikPlusY` | `b = acos(cosB)` (∈[0,π]); `c = acos(cosC) + psi` → **c hat posenabh. Offset** |
|
||||
| `Arm3SegmentLinearX.gripperMotorFromOpening` | `eMotor = e − b − c` (b,c in **rad**) — **Greifer-Kopplung #1** |
|
||||
| `RobotController` G92/M92 | `b = B/D`, `c = C/D`, `eMotor = gripperMotorFromOpening(e)` |
|
||||
| `RobotController` M1 | `b += B`, `c += C` (relativer Motor-Jog) |
|
||||
| `RobotController` G28 | `b = π`, `c = 0` (Phase 1) → nach B-Umstellung auf `b = 0` ändern |
|
||||
| `portInverse.js` | `b = hand.z/D`, `c = hand.x/D + b` (Port→Motor, Hardware-Sync) |
|
||||
| `TelnetSenderGRBL.execCommand` / `portValue` | Hand-Ports: `z = b·D`, `x = (c−b)·D`; **e-Port mit `factorTurnLift=1.2`** — **Greifer-Kopplung #2** |
|
||||
|
||||
#### Aufgaben
|
||||
|
||||
1. **Finger visualisieren** (User) → Soll-Bild, gegen das kalibriert wird.
|
||||
|
||||
2. **Greifer-Kopplung vereinheitlichen.** Es existieren **zwei widersprüchliche** Kopplungen:
|
||||
- Kinematik: `eMotor = e − b − c` (b,c in rad)
|
||||
- Sender: `e-Port = e + 1.2·b·D − c·D` (b,c in Grad, Faktor **1.2** nur auf b)
|
||||
|
||||
Eine Quelle der Wahrheit festlegen und gegen die echte Sehnenmechanik messen.
|
||||
(`factorOpenTurn = 1.92` im Sender ist deklariert, aber **ungenutzt** → klären/entfernen.)
|
||||
|
||||
3. **B-Konvention (gerade = 0°).** Durchgängig:
|
||||
- FK/IK in `Arm3SegmentLinearX` (b-Definition / acos-Zweig),
|
||||
- `gripperMotorFromOpening` nachziehen,
|
||||
- G92-Eingabe (`b = B/D`) + M1 + G28,
|
||||
- `portInverse.js` (Umkehrung),
|
||||
- **Sender-Formeln so kompensieren, dass die FluidNC-Ports unverändert bleiben** —
|
||||
ODER bewusst die Hardware-Nullpunkte neu kalibrieren (Entscheidung dokumentieren).
|
||||
|
||||
4. **C-Nullpunkt (neutral = 0°).** Der `c↔ψ`-Bezug ist **posenabhängig**
|
||||
(`ψ = acos(cos β · sin a) − c`). Ein konstantes `c=0=neutral` ist **nicht global** möglich,
|
||||
ohne die Hand-Parametrierung zu ändern. Bewerten: c als reinen Gelenkwinkel führen
|
||||
(Offset herausrechnen) oder die ψ-Definition anpassen.
|
||||
|
||||
5. **l3-Ableitung korrigieren** (`RobotConfig.js`): `l3` kommt aus
|
||||
`Ellbow.skeleton.to[0] = 90` (Ellbogen-Versatz), **nicht** aus der echten Hand-/Finger-
|
||||
Länge — das erklärt die beobachteten −550 statt −590. Aus der echten Finger-Geometrie ableiten.
|
||||
|
||||
6. **Tests + Doku** nachziehen: Round-Trip mit neuer Konvention, Greifer-Kopplung,
|
||||
G92-Referenztabellen in `Info_G92.md`, sowie diese Datei.
|
||||
|
||||
#### Ansatz-Entscheidung (vor Umsetzung)
|
||||
|
||||
- **Klein/lokal:** nur die **G92-Eingabe** umrechnen (appRobotHoming sendet B=0/C=0 für
|
||||
gerade/neutral, Driver mappt intern auf die alte Konvention). Wenig Risiko, aber das
|
||||
interne Modell bleibt „unsauber".
|
||||
- **Groß/sauber:** interne Konvention durchgängig umstellen (alle Fundstellen oben) mit
|
||||
Hardware-Port-Invariante. Sauberes All-Zero-Home, aber koordinierter Eingriff.
|
||||
|
||||
#### Verifikation
|
||||
|
||||
Jede B/C/Greifer-Änderung gegen **Visualisierung UND einen Hardware-Test** (eine Achse
|
||||
isoliert) prüfen — das Modell allein genügt hier nicht, weil es um die Hardware-Abbildung geht.
|
||||
|
||||
### Verifikation (Definition of Done)
|
||||
|
||||
- **Phase 1 (erfüllt):** G92 der Grundstellung → Driver `y ≈ −590, z ≈ 0`; appRobotHoming
|
||||
sendet die gemessenen α/β/a **direkt** (ohne Spiegelung); volle Suite grün.
|
||||
- **Phase 2 (Ziel):** Grundstellung mit **allen** Gelenkwinkeln 0 (inkl. B=C=0); Finger
|
||||
visuell korrekt.
|
||||
sendet die gemessenen α/β/a **direkt** (ohne Spiegelung); **G28 fährt sauber gestreckt
|
||||
nach −y** (a=0, kein Singularitäts-Müll); volle Suite grün.
|
||||
- **Phase 2 (Ziel):** Grundstellung mit **allen** Gelenkwinkeln 0 (inkl. B=C=0); Greifer-
|
||||
Kopplung vereinheitlicht; Finger visuell korrekt.
|
||||
|
||||
---
|
||||
|
||||
@@ -157,6 +218,8 @@ Umgesetzt:
|
||||
|
||||
- **y-Flip (Phase 1):** Spiegelung in `Arm3SegmentLinearX` (`_mirrorWorkspaceY`, genutzt von
|
||||
`calculateAngles3D` und `calculatePositionFromMotorAngles`). Am Roboter bestätigt.
|
||||
- **G28-Singularität (Phase 1):** voll ausgestreckt setzt `RobotController` die Motorwerte
|
||||
direkt (statt der singulären IK) → Finger sauber entlang −y.
|
||||
- **atan2-Fix** in der IK (`gamma = Math.atan2(pZ, pY)`): macht die interne IK für −y
|
||||
mathematisch korrekt — Voraussetzung des y-Flips.
|
||||
- **Winkel-Konventionen** (Y/Z/A/B/C/E) sind in [doc/Info_G92.md](Info_G92.md) dokumentiert
|
||||
|
||||
Reference in New Issue
Block a user