Files
appRobotRender/benchmark/camera_count/README.md

185 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
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.
# Kamera-Anzahl-Studie
Untersucht, wie sich die Pose-Schätzgenauigkeit verändert, wenn weniger Kameras
verwendet werden. Hauptergebnis ist eine Kurve **k Kameras → Positionsfehler in mm**
an zwei Punkten des Roboters (Handgelenk und Finger).
Hintergrundfrage und Entscheidungslogik: [`doc/camera_number_roadmap.md`](../../doc/camera_number_roadmap.md)
---
## Voraussetzungen
Pro Szene müssen vorhanden sein:
| Datei | Woher |
|---|---|
| `data/simulation/SceneX/render_*.png` | Blender-Renderer |
| `data/simulation/SceneX/render_*.npz` | Kamera-Intrinsik |
| `data/simulation/SceneX/pose.json` | Ground-Truth-Pose |
| `data/robot/robot.json` | Robotermodell |
Neue Szenen werden **automatisch erkannt** — kein Skript anpassen nötig.
Für die Plots zusätzlich `matplotlib` (`pip install matplotlib`); ohne läuft
alles, nur das PNG entfällt.
---
## Metriken
Pro Kamera-Subset werden zwei Positionsfehler per Vorwärtskinematik berechnet —
der euklidische Abstand zwischen geschätzter und wahrer Position eines Punktes:
| Metrik | Punkt | Hängt ab von | Bedeutung |
|---|---|---|---|
| `wrist_error_mm` | Hand-Ursprung | Armgelenke `x,y,z,a` | Wie genau ist der Arm bis zum Handgelenk? |
| `finger_error_mm` | FingerA-Spitze | volle Kette `x..e` | Wie genau ist die ganze Pose inkl. Hand/Finger? |
**Unbeobachtbare Gelenke → leerer Wert (n/a).** Sieht ein Subset z. B. die Hand
nicht, ist `b/c/e` unbeobachtbar — dann ist die *wahre* Fingerposition schlicht
unbekannt und `finger_error_mm` bleibt **leer** (statt mit einer falschen 0
gefüllt zu werden). Das Handgelenk hängt nur von den Armgelenken ab und ist
deshalb meist auch mit wenigen Kameras bestimmbar.
Welche Gelenke einen Punkt bewegen, wird **numerisch** ermittelt (kleine
Auslenkung je Gelenk) — funktioniert daher auch, wenn sich das Robotermodell ändert.
Zusätzliche Spalten:
- `n_unobservable` — Anzahl der 7 Gelenke, die in diesem Subset unbeobachtbar waren.
- `mean_abs_deg` / `max_abs_deg` — Gelenkwinkelfehler (nur **beobachtbare** Gelenke).
- `mean_abs_mm` / `max_abs_mm` — Lineargelenkfehler (`x`, `e`).
> Hinweis: Winkelfehler zählen unbeobachtbare Gelenke **nicht** mit, die
> mm-Positionsfehler lassen sie als n/a aus. Beide blenden also dieselben Fälle
> aus — die `n/a`-Spalte zeigt, wie oft das passiert.
---
## Schritt 1 — Studie laufen lassen
```bat
run\run_camera_study.bat
```
Das wertet alle verfügbaren Szenen aus, k = 3 bis (alle verfügbaren Kameras),
10 zufällige Subsets pro k.
**Optionen:**
```bat
REM Nur bestimmte Szenen
run\run_camera_study.bat --scenes Scene7 Scene9
REM Kamerabereich einschränken
run\run_camera_study.bat --k-min 3 --k-max 5
REM Weniger Samples — schneller, weniger repräsentativ
run\run_camera_study.bat --samples 3
REM Pipeline für vorhandene Subsets erneut laufen lassen
run\run_camera_study.bat --force
REM VOLLSTÄNDIGER Neustart: alles löschen und neu rechnen
run\run_camera_study.bat --clean
REM Nur eine re-gerenderte Szene komplett neu rechnen (Rest bleibt erhalten)
run\run_camera_study.bat --clean --scenes Scene10
```
Oder direkt über Python (z. B. in einer Linux-Umgebung / Docker):
```bash
python benchmark/camera_count/run_camera_study.py --samples 10
```
**Laufzeit & Wiederholläufe:** Pro Kamera-Subset läuft die volle Pipeline
(Schritt 14). Bereits gerechnete Subsets werden **übersprungen** (kein `--force`
nötig für Fortsetzung) — die mm-Auswertung wird dabei trotzdem frisch berechnet,
ein erneuter Lauf ohne `--force` ist also schnell.
**Drei Stufen der Wiederholung:**
| Flag | Wirkung |
|---|---|
| *(kein Flag)* | Vorhandene `robot_state.json` werden wiederverwendet, nur die Auswertung neu gerechnet. Schnell. |
| `--force` | Pipeline läuft erneut, überschreibt `robot_state.json`. Für geänderte Pipeline-Logik. |
| `--clean` | Löscht Zwischenergebnisse vorher komplett. **Nötig nach Re-Rendering.** Ohne `--scenes` wird alles inkl. Ergebnisdateien zurückgesetzt; mit `--scenes` nur die genannten Szenen. |
**Merge:** Ein Lauf über einzelne Szenen (`--scenes`) aktualisiert nur deren
Zeilen in `camera_study.json/.csv` — die übrigen Szenen bleiben erhalten. Du
kannst also eine re-gerenderte Szene neu rechnen, ohne die Gesamtauswertung zu verlieren.
---
## Schritt 2 — Auswertung
```bash
python benchmark/camera_count/analyze.py # finger_error_mm (Standard)
python benchmark/camera_count/analyze.py --metric wrist_error_mm
python benchmark/camera_count/analyze.py --metric mean_abs_deg
```
Beispielausgabe (nur Scene10):
```
Kamera-Anzahl vs. finger_error_mm
k | n | n/a | Mittel | Median | Std | Min | Max
--------------------------------------------------------------------------
3 | 4 | 6 | 1.775 | 1.583 | 0.986 | 0.710 | 3.225
4 | 10 | 0 | 1.955 | 2.034 | 0.696 | 0.503 | 3.317
5 | 10 | 0 | 1.391 | 1.322 | 0.646 | 0.614 | 2.468
6 | 7 | 0 | 1.306 | 1.288 | 0.389 | 0.697 | 1.992
7 | 1 | 0 | 1.251 | 1.251 | 0.000 | 1.251 | 1.251
n/a = Subsets, bei denen dieser Punkt unbeobachtbar war (nicht eingerechnet).
Beste / schlechteste Subsets je k (finger_error_mm):
k=3: best [Scene10] bcd (0.710) worst [Scene10] acf (3.225)
...
```
Hier sieht man sofort: bei **k=3 konnten 6 von 10 Subsets den Finger gar nicht
sehen** (n/a=6). Das ist die eigentliche Aussage — nicht „der Fehler ist klein",
sondern „die meisten 3-Kamera-Anordnungen verlieren die Hand komplett".
Verfügbare Metriken: `finger_error_mm` (Standard), `wrist_error_mm`,
`mean_abs_deg`, `max_abs_deg`, `mean_abs_mm`, `max_abs_mm`.
---
## Ausgabedateien
| Pfad | Inhalt |
|---|---|
| `benchmark/camera_count/results/camera_study.json` | Alle Einzelergebnisse |
| `benchmark/camera_count/results/camera_study.csv` | Dasselbe als CSV (Spalten inkl. `wrist_error_mm`, `finger_error_mm`, `n_unobservable`) |
| `benchmark/camera_count/results/camera_count_<metric>.png` | Boxplot je Metrik |
| `data/camera_study/SceneX/k3_abc/` | Pipeline-Zwischenergebnisse pro Subset |
Die Zwischenergebnisse in `data/camera_study/` sind groß — nicht committen.
---
## Ergebnis interpretieren
Die Studie beantwortet vier Fragen:
1. **Wird die Hand überhaupt gesehen?**
`n/a`-Spalte bei `finger_error_mm`. Viele n/a bei k=3 heißt: zu wenige
Kameras verlieren die Hand systematisch.
2. **Ab welchem k wird der Fehler stabil?**
→ Knick in der Kurve zeigt den Sättigungspunkt.
3. **Welche Kamera-Kombination ist bei kleinem k am besten?**
`analyze.py` gibt beste und schlechteste Subsets aus.
4. **Arm vs. Hand getrennt:** Das Handgelenk (`wrist_error_mm`) ist meist schon
mit 3 Kameras gut bestimmt — der kritische Teil ist die Hand/Finger-Orientierung.
Eine praktische Entscheidungsregel: 3 Kameras gelten als ausreichend, wenn
(a) der Finger in fast allen Subsets beobachtbar ist (wenig n/a) **und**
(b) `finger_error_mm` bei k=3 nicht wesentlich schlechter ist als beim Maximum.
(Schwellwert je nach Anwendung anpassen.)