# appRobotHoming

Browserbasierte Bedienoberfläche für das kameragestützte **Homing** und die
**Kalibrierung** eines Roboterarms. Das Frontend kommuniziert mit einem Node.js-Backend
(BFF-Proxy), das Kamera-Bilder, ArUco-Erkennung und Gelenk-Winkel-Schätzung
über Python-Skripte orchestriert.

## Architektur

```
Browser ──HTTPS──▶ Reverse-Proxy ──HTTPS──▶ appRobotHoming-Backend (Port 2093)
                                                   │  server/server.js
                                    intern (HTTP): │
                                                   ├──▶ WebCam-Service   (Bilder, NPZ)
                                                   └──▶ Robot-Driver     (POST /api/state)
```

**Frontend (`public/`):** statische Seiten — Homing, Kalibrierung, Board-Viewer,
Scene-Viewer. Kein direkter Zugriff auf interne Services.

**Backend (`server/server.js`):** HTTPS-BFF auf Port 2093. Liefert Frontend aus,
orchestriert Python-Skripte (SSE-Stream) und liest/schreibt `robot.json`.

## Funktionen

| Seite | Pfad | Beschreibung |
|-------|------|--------------|
| Homing | `/` (`index.html`) | Homing-Run starten, Status, GCode-Ausgabe |
| Kalibrierung | `/calibration.html` | Tabs: Camera NPZ · Board · X-Achse · Arm1-Y · **Marker** |
| Board-Viewer | `/boardViewer.html` | 3D-Viewer: Board-Marker, Skeleton FK, Arm-Marker mit Spin |
| Scene-Viewer | `/sceneViewer.html` | Standalone-Viewer (Datei-Upload, keine Server-Abhängigkeit) |
| Homing-Detail | `/homing.html` | Detail-Ansicht eines Homing-Laufs |

## Homing-Ablauf

```
Foto alle Kameras
  → 1_detect_aruco_observations.py   (ArUco-Erkennung, pro Kamera)
  → 2_estimate_camera_from_observations.py   (Kamera-Pose)
  → 3b_corner_marker_poses.py   (Marker-Triangulierung)
  → X-Position schätzen (JS: server/homingXEstimate.cjs)
  → 4b_revolute_angle.py  Arm1 / Ellbow / Arm2 / Hand   (Gelenk-Winkel)
  → POST ROBOT_URL/api/state
```

SSE-Events (`log` / `step` / `analysis` / `done`) streamen den Fortschritt live
ins Frontend. Der Board-Viewer zeigt das Skeleton progressiv nach jedem erkannten Gelenk.

Details: [`doc/Homing_ROADMAP.md`](doc/Homing_ROADMAP.md)

## Kalibrierung

Einmaliger Vorgang nach mechanischen Änderungen:

| Schritt | Tab | Ergebnis |
|---------|-----|---------|
| 1 Camera NPZ | Camera NPZ | Kamera-Intrinsics als `.npz` |
| 2 Board | Board | `links.Board.markers` in `robot.json` |
| 3 X-Achse | Robot X Axis | alle Marker-Positionen rotiert |
| 4 Arm1-Y | Arm1 – Y | `links.Arm1.jointToParent.origin[1,2]` |
| 5 Arm-Marker | Marker | Spin-Korrektur, Orientierungs-Verifikation |

Details: [`doc/Kalibrierung.md`](doc/Kalibrierung.md) ·
[`doc/Kalibrierung_Marker.md`](doc/Kalibrierung_Marker.md) ·
[`doc/accessRobotAPI.md`](doc/accessRobotAPI.md) (robot.json via Driver)

## robot.json

Zentrale Konfiguration aller Gelenke, Marker und Kinematik-Parameter.

```
ROBOT_JSON = process.env.ROBOT_JSON || 'scripts/robot_1781069752019.json'
```

Enthält: `links.{Link}.markers[].{id, position, normal, size, spin}`,
`links.{Link}.jointToParent`, `defaultPosition`, `robot_test_poses`.

## API-Übersicht

| Endpoint | Methode | Zweck |
|----------|---------|-------|
| `/api/robot` | GET | robot.json lesen |
| `/api/robot/set-arm-marker-spin` | POST | Spin eines Arm-Markers setzen |
| `/api/robot/set-joint-origin` | POST | Joint-Origin Y/Z setzen |
| `/api/robot/assign-by-z` | POST | Marker nach Z-Bereich zuordnen |
| `/api/robot/adopt-x-axis` | POST | X-Achse übernehmen |
| `/api/board/run` | POST | Board-Pipeline starten (SSE) |
| `/api/board/latest` | GET | Letzter Board-Run (Marker + Robot) |
| `/api/homing/run` | POST | Homing-Lauf starten (SSE) |
| `/api/homing/send-state` | POST | State an Robot-Driver senden |
| `/api/homing/run-data` | GET | Debug-Daten eines Runs |
| `/api/calibration/*` | POST/GET | Kalibrierungs-Session verwalten |

## Konfiguration

| Variable | Bedeutung |
|----------|-----------|
| `HTTPS_PORT` | Port (Default `2093`) |
| `WEBCAM_URL` | Interner WebCam-Service |
| `ROBOT_URL` | Interner Robot-Driver |
| `ROBOT_JSON` | Pfad zu robot.json (Default `scripts/robot_1781069752019.json`) |
| `HTTPS_KEY_PATH` / `HTTPS_CERT_PATH` / `HTTPS_PASSPHRASE` | self-signed Cert |

## Dateien & Struktur

```
public/          Frontend (HTML, JS, CSS)
  boardViewer.html   3D-Viewer mit Three.js FK, Arm-Markern, Spin-Rendering
  sceneViewer.html   Standalone-Viewer (nur Datei-Upload)
  calibration*.html  Kalibrierungs-Tabs (lazy-geladen)
  client.js          Homing-Frontend-Logik
  calibration.js     Kalibrierungs-Frontend-Logik

server/
  server.js          Express-Backend, alle API-Routes
  editRobot.js       robot.json lesen/schreiben
  homingOrchestrator.js  Homing-Ablauf (SSE-Stream)
  homingXEstimate.cjs    X-Schätzung (reine Geometrie, unit-getestet)
  spinNormalize.cjs      Spin-Normalisierung [0,360) (unit-getestet)

scripts/
  robot_1781069752019.json   Haupt-Konfiguration (robot.json)
  1_detect_aruco_observations.py
  2_estimate_camera_from_observations.py
  3b_corner_marker_poses.py
  4b_revolute_angle.py

test/
  homingXEstimate.test.js    X-Schätzungs-Geometrie (9 Tests, inkl. Regression)
  spinNormalize.test.js      Spin-Normalisierung (5 Tests)
  yAxisComputeJs.test.js     Y-Achsen-Berechnung
  yAxisRotation.test.js      Rotations-Mathe

doc/
  Homing_ROADMAP.md       Homing-Ablauf und Implementierungs-Status
  Kalibrierung.md         Kalibrierungs-Schritte 1–4
  Kalibrierung_Marker.md  Arm-Marker: Datenmodell, Spin-Verifikation, Roadmap P1–P5
  ToDo.md                 Offene Punkte
```

## Nutzung

```bash
npm install
npm test        # Jest-Tests (14+ Tests)
npm start       # HTTPS-Backend auf Port 2093
```

Danach: `https://<host>:2093/`

> self-signed Zertifikat → einmalige Browser-Warnung bestätigen.
> Frontend benötigt laufendes Backend (API-Calls beim Laden).
