# 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-Skelettspitze | 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`). --- ## 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 ``` **Drei Stufen der Wiederholung:** | Flag | Wirkung | |---|---| | *(kein Flag)* | Vorhandene `robot_state.json` werden wiederverwendet, nur Auswertung neu. Schnell. | | `--force` | Pipeline läuft erneut. Für geänderte Pipeline-Logik. | | `--clean` | Löscht Zwischenergebnisse vorher. **Nötig nach Re-Rendering.** | **Merge:** Ein Lauf über einzelne Szenen aktualisiert nur deren Zeilen in `camera_study.json/.csv` — die übrigen Szenen bleiben erhalten. --- ## 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: ``` 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 ... 7 | 1 | 0 | 1.251 | 1.251 | 0.000 | 1.251 | 1.251 n/a = Subsets, bei denen dieser Punkt unbeobachtbar war (nicht eingerechnet). ``` Bei k=3: **6 von 10 Subsets sehen den Finger gar nicht** (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 (inkl. `wrist_error_mm`, `finger_error_mm`, `n_unobservable`) | | `benchmark/camera_count/results/camera_count_.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 1. **Wird die Hand überhaupt gesehen?** → `n/a`-Spalte bei `finger_error_mm`. 2. **Ab welchem k wird der Fehler stabil?** → Knick in der Kurve. 3. **Welche Kombination ist bei kleinem k am besten?** → beste/schlechteste Subsets. 4. **Arm vs. Hand getrennt:** `wrist_error_mm` ist meist schon mit 3 Kameras gut; der kritische Teil ist die Hand/Finger-Orientierung.