171 lines
3.0 KiB
Markdown
171 lines
3.0 KiB
Markdown
# appRobotBodyTrack
|
|
|
|
3D-Body-Tracking für Roboter aus Mehrkamera-ArUco-Bildern.
|
|
|
|
**Input**
|
|
- Bilder: `render_*.png`
|
|
- Intrinsics: `render_*.npz`
|
|
- Konfiguration: `robot.json`
|
|
|
|
**Output**
|
|
- Gelenke **R⁷** → `{x, y, z, a, b, c, e}` (mm / Grad)
|
|
|
|
---
|
|
|
|
## Interfaces
|
|
|
|
Eine Logik, drei Zugänge:
|
|
|
|
- **Python**
|
|
- **CLI**
|
|
- **REST (FastAPI)**
|
|
|
|
---
|
|
|
|
## Quickstart
|
|
|
|
### Python
|
|
|
|
```python
|
|
from scripts import estimate_from_dir
|
|
|
|
result = estimate_from_dir("data/Scene8", robot_json="robot.json")
|
|
|
|
print(result.joints)
|
|
print(result.confidence)
|
|
```
|
|
|
|
---
|
|
|
|
### CLI
|
|
|
|
```bash
|
|
pip install -e .
|
|
|
|
python -m scripts data/Scene8 --robot robot.json
|
|
python -m scripts data/Scene8 --robot robot.json --cameras a,b,d
|
|
```
|
|
|
|
---
|
|
|
|
### REST API
|
|
|
|
```bash
|
|
docker compose up
|
|
```
|
|
|
|
**Request:**
|
|
|
|
```python
|
|
import requests
|
|
|
|
resp = requests.post(
|
|
"http://localhost:8446/v1/estimate",
|
|
files=[
|
|
("images", ("render_a.png", open("render_a.png", "rb"))),
|
|
("intrinsics", ("render_a.npz", open("render_a.npz", "rb"))),
|
|
],
|
|
)
|
|
|
|
print(resp.json()["joints"])
|
|
```
|
|
|
|
---
|
|
|
|
## API
|
|
|
|
| Endpoint | Methode | Zweck |
|
|
|----------|--------|------|
|
|
| `/v1/estimate` | POST | Bilder → Gelenke |
|
|
| `/v1/health` | GET | Status |
|
|
| `/v1/config` | GET | aktive Konfiguration |
|
|
|
|
**Maschinenlesbares Schema / interaktive Doku** (automatisch von FastAPI):
|
|
|
|
| URL | Zweck |
|
|
|-----|-------|
|
|
| `/openapi.json` | OpenAPI-Spezifikation (für Client-Generatoren) |
|
|
| `/docs` | Swagger-UI (interaktiv ausprobieren) |
|
|
| `/redoc` | ReDoc-Ansicht |
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"joints": {"x": 50.2, "y": -2.1, "z": 94.8, "a": 20.1},
|
|
"confidence": {"x": "high", "b": "low"},
|
|
"residual_rms": 1.45,
|
|
"n_markers": 56,
|
|
"processing_ms": 1240
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Struktur
|
|
|
|
```
|
|
.
|
|
├── scripts/
|
|
├── config/robot.json
|
|
├── tests/
|
|
└── docker-compose.yaml
|
|
```
|
|
|
|
---
|
|
|
|
## Deployment (Docker / Portainer)
|
|
|
|
> **Pflichtschritt zuerst:** `config/robot.json` muss als **Datei** existieren, bevor
|
|
> der Container startet. Vorlage kopieren und mit der echten Konfiguration füllen:
|
|
>
|
|
> ```bash
|
|
> cp config/robot.json.example config/robot.json
|
|
> ```
|
|
>
|
|
> ⚠️ Fehlt die Datei, legt Docker am Mount-Pfad ein **leeres Verzeichnis** an.
|
|
> Der Server startet dann zwar, aber jeder `/v1/estimate` liefert **500**
|
|
> (`IsADirectoryError`) und `/v1/config` ebenfalls 500. Genau dann diesen
|
|
> Pflichtschritt nachholen und den Container neu starten.
|
|
|
|
**Volume** (Pfad muss zur tatsächlichen Datei zeigen, vgl. `docker-compose.yaml`):
|
|
```yaml
|
|
- ./config/robot.json:/config/robot.json:ro
|
|
```
|
|
|
|
**Start & Healthcheck:**
|
|
```bash
|
|
docker compose up -d
|
|
curl http://<host>:8446/v1/health # {"status":"ok","version":"1.0.0"}
|
|
```
|
|
|
|
---
|
|
|
|
## Konfiguration
|
|
|
|
Zentrale Datei: **`robot.json`**
|
|
|
|
Verwendete Bereiche:
|
|
- `links`
|
|
- `pose_estimation`
|
|
- `vision_config`
|
|
- `movements`
|
|
- `units`
|
|
|
|
---
|
|
|
|
## Stack (minimal)
|
|
|
|
- numpy
|
|
- scipy
|
|
- opencv (aruco)
|
|
- fastapi + uvicorn
|
|
|
|
---
|
|
|
|
## Naming
|
|
|
|
- **BodyTrack** → Tracking (dynamisch) ✅
|
|
- **BodyMap** → Modell / Repräsentation
|
|
- **BodySense** → Wahrnehmung (low-level)
|