Claude: über nacht arbeiten. Pipeline verbessern

This commit is contained in:
chk
2026-06-02 06:04:41 +02:00
parent e5b41e9110
commit 30e97eb4bd
252 changed files with 125356 additions and 52694 deletions

112
POSE_PIPELINE.md Normal file
View File

@@ -0,0 +1,112 @@
# Pose-Erkennungs-Pipeline
Aus Mehrkamera-Fotos eines Roboters werden die Gelenkwinkel (`x,y,z,a,b,c,e`)
geschätzt. Kern: Jeder ArUco-Marker wird über seine **4 triangulierten Ecken**
als volle 6-DOF-Pose (Position **+ gemessene Normale**) rekonstruiert; daraus
werden die Gelenkwinkel über die Kinematik (`robot_fk.py`) bestimmt.
## Ergebnis (Stand: Nacht-Build)
Benchmark über 10 valide Sim-Posen (Scene49b, 11, 12; Scene10 war fehlerhaft
gerendert und ausgeschlossen), Methode **hybrid**:
| Metrik | Wert |
|---|---|
| Winkelfehler mittel | **0,25°** |
| Winkelfehler std (Stabilität) | 0,13° |
| Winkelfehler schlechtester | 1,57° |
| Positionsfehler mittel | 0,10 mm |
Zwei Vorbedingungen waren entscheidend und sind erledigt:
1. **npz-fy-Bug** in `render_robot.py` gefixt (war ~15 % Brennweitenfehler bei 16:9).
2. **Eck- statt Center-Triangulation** — liefert pro Marker eine Normale (~1,2° genau, validiert in `benchmark/stage0_corner_normals.py`).
## Pipeline (run/run_pipeline.bat)
```
1_detect_aruco_observations Fotos -> *_aruco_detection.json (inkl. 4 Ecken)
2_estimate_camera_from_observations -> *_camera_pose.json
3_multiview_bundle_adjustment_v4 -> aruco_positions_initial.json (Center; für Viewer/Vergleich)
3b_corner_marker_poses -> aruco_marker_poses.json (Eck-Pose + Normale)
pose_estimation -> robot_state.json (Gelenkwinkel + Konfidenz)
```
Aufruf: `.\run_pipeline.bat ..\data\simulation\Scene8`
## Pose-Estimation (pipeline/pose_estimation.py)
Parametrisiert über **Gelenk-Variablen** (nicht Links), damit Sonderfälle dieses
Roboters generisch funktionieren:
- Glieder ohne eigene Marker (Base/`x`, Hand/`b`, Palm/`c`) — über Kind-Marker bestimmt.
- Geteilte Variable (`e` für FingerA+FingerB) — eine Unbekannte.
- Verdeckte Mittelglieder — durch globales BA überbrückt.
### Vier Methoden (robot.json → `pose_estimation.method`)
| Methode | Idee | Benchmark (mean / worst) |
|---|---|---|
| `sequential_vector` | analytisch aus Marker-Paar-Vektoren | 0,32° / 1,72° |
| `sequential_fk` | blockweise 1D/Block-LS entlang der Kette | 0,43° / 1,84° |
| `global_ba` | alle Winkel gemeinsam, robuste Loss | 0,25° / 1,57° |
| **`hybrid`** (Default) | sequenzieller Init → globales BA | **0,25° / 1,57°** |
### robot.json-Konfiguration
```json
"pose_estimation": {
"method": "hybrid",
"marker_observation": "corner_pose", // oder "center_point"
"use_normals": true,
"normal_weight": 100.0, // höher = stabiler bei wenigen Markern
"robust_loss": "huber",
"huber_delta_mm": 8.0,
"max_iterations": 200,
"min_cameras_per_marker": 2,
"per_link_method": {} // optional: Methode pro Glied
}
```
`normal_weight=100` wurde empirisch gewählt: stabilisiert sicht-arme Posen
deutlich (Worst-Case-Winkel halbiert), kostet bei gut sichtbaren Posen nur ~0,2°.
### Konfidenz pro Gelenk
`robot_state.json → movements[v].confidence`: `high` (≥2 Marker/Variable im
Block), `medium` (≥1), `low` (unterbestimmt — misstrauen!), `none` (0 Marker).
Für die Kollisionssicherheit: Gelenke mit `low`/`none` nicht ungeprüft anfahren;
ggf. Homing/`a`-Drehung für mehr Sichtbarkeit (Multi-Pose).
## Benchmark- & Eval-Werkzeuge (benchmark/)
| Tool | Zweck |
|---|---|
| `stage0_corner_normals.py` | Eck-Normalen-Genauigkeit gegen GT (Go/No-Go) |
| `eval_pose.py` | geschätzte Gelenkwinkel vs. `pose.json` |
| `run_benchmark.py` | Scenes × Methoden → Matrix + Aggregat (CSV/JSON) |
| `pipeline/9_evaluateMarker.py` | Marker Position + Normale pro Glied vs. `render_*.json` |
Beispiele:
```
python benchmark/run_benchmark.py # alle bereiten Scenes, alle Methoden
python benchmark/run_benchmark.py --scenes 5 8 --methods hybrid
python benchmark/stage0_corner_normals.py --evalDir data/evaluations/Scene5 --gt data/simulation/Scene5/render_a.json
python benchmark/eval_pose.py data/evaluations/Scene5/robot_state.json data/simulation/Scene5/pose.json
```
## Viewer (run/robot_viewer.html)
Lade `aruco_marker_poses.json` als „aruco" → der **Observed-normals**-Pfeil zeigt
jetzt die **gemessene** Normale, eingefärbt nach Winkelabweichung zur Modell-
Normale (grün <2° / gelb 25° / rot >5°). Statistik-Panel zeigt Normal mean/max.
## Offene Punkte / Ideen
- **Adaptive `normal_weight`**: pro Marker nach Sicht-Qualität gewichten →
best-case und worst-case gleichzeitig optimal (statt fester Kompromiss 100).
- **Multi-Pose-Fusion**: mehrere Aufnahmen bei verschiedenen `a`-Winkeln in
*eine* globale BA werfen — für Posen, in denen die Hand sonst verdeckt ist.
- **Reale Kameras**: Schritt 1 nutzt aktuell für alle Bilder `render_a.npz`
(Sim: alle Kameras gleich). Real bräuchte jede Kamera ihre eigene Intrinsik-npz.
- **`center_point`-Vergleich** im Benchmark (`--observation center_point`) braucht
`aruco_positions_initial.json` pro Scene (Schritt 3).
```