Dokumentieren

This commit is contained in:
chk
2026-06-16 15:31:25 +02:00
parent 578b955508
commit f929c19f4b
3 changed files with 42 additions and 35 deletions

View File

@@ -154,7 +154,7 @@ die aktuelle Konfiguration.
## Offene Punkte ## Offene Punkte
- [~] **Arm-Marker eintragen** (Nutzer): `links.Arm1/Ellbow/Arm2/Hand.markers` in `robot.json` — Arm1 + Ellbow eingetragen, Arm2/Hand offen - [~] **Arm-Marker eintragen** (Nutzer): `links.Arm1/Ellbow/Arm2/Hand.markers` in `robot.json` — Arm1 + Ellbow eingetragen, Arm2/Hand offen
- [~] **Erstmals testen**: Homing-Run mit echtem Roboter — Arm1 erkannt (x, y); Ellbow scheitert noch an fehlenden Markern - [~] **Erstmals testen**: Homing-Run mit echtem Roboter — Arm1 (x, y) und Ellbow (z) laufen durch; Arm2/Hand noch zu prüfen. Ellbow brach zunächst ab (4b: nur 2 Marker sichtbar, deren Verbindungsvektor parallel zur Gelenkachse liegt → keine Baseline), seit 2026-06-16 über Fallback-1/-2 in `4b_revolute_angle.py` gelöst — Details: [`Homing_1_StepByStep.md`](Homing_1_StepByStep.md)
- [x] **X-Schätzung verfeinern** (2026-06-14): `estimateXFromMarkers()` rechnet den kinematischen Gelenk-Offset heraus statt rohem Mittelwert — behebt den ~110 mm Versatz der Modell-Marker - [x] **X-Schätzung verfeinern** (2026-06-14): `estimateXFromMarkers()` rechnet den kinematischen Gelenk-Offset heraus statt rohem Mittelwert — behebt den ~110 mm Versatz der Modell-Marker
- [x] **Unit-Test für X-Schätzung** (2026-06-14): reine Geometrie nach `server/homingXEstimate.cjs` ausgelöst, `test/homingXEstimate.test.js` (9 Tests, inkl. Regression gegen den Offset-Bug) - [x] **Unit-Test für X-Schätzung** (2026-06-14): reine Geometrie nach `server/homingXEstimate.cjs` ausgelöst, `test/homingXEstimate.test.js` (9 Tests, inkl. Regression gegen den Offset-Bug)
- [ ] **y-Restfehler** (~2°): erkannt 30° → ausgegeben 28°; vermutlich X-Rest-Rauschen + 4b-Fit-Residuum, noch zu untersuchen - [ ] **y-Restfehler** (~2°): erkannt 30° → ausgegeben 28°; vermutlich X-Rest-Rauschen + 4b-Fit-Residuum, noch zu untersuchen

View File

@@ -19,38 +19,44 @@ nächste Stufe ist ein **reiner Fallback** — sie greift nur, wenn die vorherig
**keine einzige** brauchbare Baseline liefert (z. B. Marker nicht sichtbar, oder **keine einzige** brauchbare Baseline liefert (z. B. Marker nicht sichtbar, oder
Marker-Paar zufällig parallel zur Drehachse): Marker-Paar zufällig parallel zur Drehachse):
1. **Primär** — zwei Marker auf dem Ziel-Link selbst. `v_model`/`v_obs`-Differenzvektor, 1. **Primär** (`TIER_PRIMARY`) — zwei Marker auf dem Ziel-Link selbst.
⟂ zur Gelenkachse projiziert, Winkel zwischen beiden gemessen. Braucht nur die `v_model`/`v_obs`-Differenzvektor, ⟂ zur Gelenkachse projiziert, Winkel zwischen
Achs*richtung* (aus FK der schon gelösten Vorgänger), nicht die Pivot-*Position*. beiden gemessen. Braucht nur die Achs*richtung* (aus FK der schon gelösten
2. **Fallback-1** *(Konzept 2026-06-16, noch nicht implementiert)* — zwei Marker auf Vorgänger), nicht die Pivot-*Position*.
2. **Fallback-1** (`TIER_FALLBACK_1`, implementiert 2026-06-16) — zwei Marker auf
dem **direkten Kind-Link**, deren Verbindungsvektor (im Kind-Lokalframe) parallel dem **direkten Kind-Link**, deren Verbindungsvektor (im Kind-Lokalframe) parallel
zur **eigenen** Achse des Kind-Links liegt → invariant gegen dessen noch zur **eigenen** Achse des Kind-Links liegt (Toleranz `--child-axis-tol`, default
unbekannten Winkel, daher als Stellvertreter für „zwei Marker am Ziel-Link" nutzbar. 1mm) → invariant gegen dessen noch unbekannten Winkel, daher als Stellvertreter
Beispiel: Ellbow (Achse X) ← Arm2-Marker 144↔148 bzw. 143↔146 (Arm2-Achse Y, ⟂ zu X, für „zwei Marker am Ziel-Link" nutzbar. Beispiel: Ellbow (Achse X) ← Arm2-Marker
beide Paare exakt achsparallel in Arm2s Lokalframe). Wie Primär unabhängig von der 144↔148 bzw. 143↔146 (Arm2-Achse Y, ⟂ zu X, beide Paare exakt achsparallel in
Pivot-Position — eine separate „ist die nächste Achse senkrecht"-Prüfung ist nicht Arm2s Lokalframe). Wie Primär unabhängig von der Pivot-Position — eine separate
nötig, das ergibt sich automatisch aus der bestehenden Mindest-Baseline-Prüfung nach „ist die nächste Achse senkrecht"-Prüfung war nicht nötig, das ergibt sich
der Projektion. automatisch aus der bestehenden Mindest-Baseline-Prüfung nach der Projektion.
3. **Fallback-2** *(implementiert)* — ein einzelner Marker auf dem Ziel-Link gegen den 3. **Fallback-2** (`TIER_FALLBACK_2`, implementiert) — ein einzelner Marker auf dem
Gelenk-**Pivot** selbst (Pivot + Achse aus FK der Vorgänger). Einzige Stufe, die mit Ziel-Link gegen den Gelenk-**Pivot** selbst (Pivot + Achse aus FK der Vorgänger).
nur 1 sichtbaren Marker funktioniert — aber zusätzlich abhängig von der Pivot- Einzige Stufe, die mit nur 1 sichtbaren Marker funktioniert — aber zusätzlich
*Position* (also den geschätzten Vorgänger-*Werten*, nicht nur deren Achsrichtung). abhängig von der Pivot-*Position* (also den geschätzten Vorgänger-*Werten*, nicht
nur deren Achsrichtung). Letzter Rückfall, nur falls Fallback-1 auch nichts findet
(kein Kind-Link, oder dessen Marker nicht sichtbar/nicht achsparallel).
→ Code: `scripts/4b_revolute_angle.py` (`estimate_revolute_angle()`), Konstante → Code: `scripts/4b_revolute_angle.py` (`estimate_revolute_angle()`); Konstanten
`PIVOT_FALLBACK_ID`, Feld `"method"` im Ergebnis-JSON. `TIER_PRIMARY`/`TIER_FALLBACK_1`/`TIER_FALLBACK_2`/`PIVOT_FALLBACK_ID`; Felder
`"method"` (top-level) und `"tier"`/`"link"` (je `per_pair`-Eintrag) im Ergebnis-JSON.
### Befund 2026-06-16 (wichtig für Priorisierung) ### Befund 2026-06-16 (Anlass für Fallback-1)
Im Testlauf `test/homing/20260616_120456` waren am Ellbow nur Marker 129/132 sichtbar, Im Testlauf `test/homing/20260616_120456` waren am Ellbow nur Marker 129/132 sichtbar,
deren Verbindungsvektor exakt parallel zur Ellbow-Achse liegt → Primär-Methode liefert deren Verbindungsvektor exakt parallel zur Ellbow-Achse liegt → Primär-Methode liefert
nichts, Fallback-2 (Pivot) springt ein und meldet `z ≈ -4.33°` (intern konsistent, nichts. **Vor** Fallback-1 sprang Fallback-2 (Pivot) ein und meldete `z ≈ -4.33°`
Exit 0). Eine unabhängige Gegenrechnung (Least-Squares über alle Ellbow- *und* (intern konsistent, Exit 0) — eine unabhängige Gegenrechnung (Least-Squares über alle
Arm2-Marker, `z`+`a` frei) zeigt aber ein Minimum bei `z ≈ -38°` — die Fallback-2-Schätzung Ellbow- *und* Arm2-Marker, `z`+`a` frei) zeigte aber ihr Minimum bei `z ≈ -38°`, also
liegt hier ca. 3540° daneben. Die (noch nicht implementierte) Fallback-1-Rechnung mit ca. 3540° daneben. **Mit** Fallback-1 (Arm2-Marker 144↔148/143↔146) liefert derselbe
Arm2-Marker 144↔148/143↔146 hätte `z ≈ -44°` ergeben, sehr nah am Least-Squares-Minimum, Lauf jetzt `z ≈ -44.15°` (circular_σ 0.80°) — deutlich näher am Least-Squares-Minimum.
weil sie (wie Primär) nicht von der Pivot-Position abhängt. → Fallback-1 ist nicht nur Bestätigt auch downstream: die anschließende Arm2-Schätzung (Primär, eigene Marker)
„nice to have", sondern in diesem Fall klar genauer als Fallback-2. hatte mit der alten Fallback-2-Kette einen Ausreißer und `circular_σ 45.8°`; mit der
Detaillierte Aufarbeitung/Entscheidung: siehe `Homing_2_improvement.md` (geplant). Fallback-1-Kette sind alle vier Arm2-Paare konsistent, `circular_σ 5.1°`.
→ Fallback-1 war hier kein „nice to have", sondern ca. 35° Genauigkeitsgewinn.
Weitere/künftige Befunde: siehe `Homing_2_improvement.md` (geplant).
## robot.json-Struktur (Kurzreferenz) ## robot.json-Struktur (Kurzreferenz)
@@ -64,10 +70,10 @@ Detaillierte Aufarbeitung/Entscheidung: siehe `Homing_2_improvement.md` (geplant
## Offene Punkte / noch zu dokumentieren ## Offene Punkte / noch zu dokumentieren
- [ ] State-JSON-Schema im Detail (`accumulated_state`, `per_pair`, `method`, `circular_std_deg`) - [ ] State-JSON-Schema im Detail (`accumulated_state`, `per_pair`, `method`, `circular_std_deg`)
- [ ] `--min-baseline` Tuning / Auswirkung - [ ] `--min-baseline` / `--child-axis-tol` Tuning / Auswirkung
- [ ] Fallback-1 Implementierung (Aufwandsschätzung: klein-mittel, ~2-3h — Kern-Mathematik - [x] Fallback-1 Implementierung (2026-06-16, `scripts/4b_revolute_angle.py`)
`_model_spoke_world()`/`_pair_estimate()` bereits vorhanden und wiederverwendbar; - [ ] Mehrstufige Rekursion (Enkel-Links) für Fallback-1 — aktuell bewusst nur
neu: Kind-Link-Suche, Achsparallelitäts-Filter, 3-stufige Tier-Logik) + Tests direkter Kind-Link, siehe Code-Kommentar bei `_child_links()`
- [ ] y-Restfehler (~2°) aus `Homing.md` → Offene Punkte - [ ] y-Restfehler (~2°) aus `Homing.md` → Offene Punkte
## Verweise ## Verweise

View File

@@ -238,9 +238,10 @@ und der dafür nötige Code-Hook: Abschnitt „Integrationsschritte").
- **Die `pose_estimation.method`-Option erlaubt gezieltes A/B-Testen** ohne - **Die `pose_estimation.method`-Option erlaubt gezieltes A/B-Testen** ohne
Codeänderung: `--method sequential_vector|sequential_fk|global_ba|hybrid` per Codeänderung: `--method sequential_vector|sequential_fk|global_ba|hybrid` per
CLI-Override, oder dauerhaft über `robot_1781069752019.json` CLI-Override, oder dauerhaft über `robot_1781069752019.json`
`pose_estimation.method`. Nützlich, um z. B. `hybrid` parallel zur bestehenden `pose_estimation.method`. Nützlich, um den Effekt des Startwerts zu isolieren:
4b-Kette laufen zu lassen und beide Ergebnisse zu vergleichen, bevor irgendetwas einmal kalt (zeigt das Problem aus „Wichtige Einschränkung"), einmal mit
ersetzt wird. 4b-Startwert (sobald der Code-Hook existiert) — als Regressionstest für genau
diese Einschränkung.
- **`finger_block_joints`/`per_link_method`** stehen schon (leer) in der - **`finger_block_joints`/`per_link_method`** stehen schon (leer) in der
robot.json — vorbereitete, aber im Skript bisher ungenutzte Erweiterungspunkte robot.json — vorbereitete, aber im Skript bisher ungenutzte Erweiterungspunkte
aus appRobotRendering. aus appRobotRendering.
@@ -300,7 +301,7 @@ python scripts/5_pose_estimation.py data/homing/<run>/aruco_marker_poses.json \
- Allgemeiner Ablauf: [`Homing.md`](Homing.md) - Allgemeiner Ablauf: [`Homing.md`](Homing.md)
- Vorheriger Schritt (Kamera/Triangulation, liefert den gemeinsamen Input): - Vorheriger Schritt (Kamera/Triangulation, liefert den gemeinsamen Input):
[`Homing_0_Camera.md`](Homing_0_Camera.md) [`Homing_0_Camera.md`](Homing_0_Camera.md)
- Alternative/Ist-Zustand (4b-Kette, dieselbe Aufgabe anders gelöst): - Vorstufe (4b-Kette, liefert den hier benötigten Startwert):
[`Homing_1_StepByStep.md`](Homing_1_StepByStep.md) [`Homing_1_StepByStep.md`](Homing_1_StepByStep.md)
- Ursprung & Validierung: Projekt **`appRobotRendering`**, - Ursprung & Validierung: Projekt **`appRobotRendering`**,
`pipeline/pose_estimation.py` + `doc/pipeline.tex` (Abschnitte „Pose-Estimation: `pipeline/pose_estimation.py` + `doc/pipeline.tex` (Abschnitte „Pose-Estimation: