docker probleme
This commit is contained in:
97
build/lib/scripts/api/server.py
Normal file
97
build/lib/scripts/api/server.py
Normal file
@@ -0,0 +1,97 @@
|
||||
"""FastAPI REST-API für appRobotBodyTrack."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
|
||||
from fastapi import FastAPI, File, HTTPException, UploadFile
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from scripts import __version__, estimate_from_dir
|
||||
|
||||
_robot_json: Optional[Path] = None
|
||||
|
||||
|
||||
def create_app(robot_json: str | Path | None = None) -> FastAPI:
|
||||
"""App-Fabrik — setzt optionale Server-weite robot.json-Konfig."""
|
||||
global _robot_json
|
||||
if robot_json:
|
||||
_robot_json = Path(robot_json).resolve()
|
||||
# Frühe, klare Warnung statt kryptischem 500 zur Laufzeit.
|
||||
# Häufige Falle: Docker legt für einen fehlenden Bind-Mount-Pfad
|
||||
# ein leeres VERZEICHNIS an — dann ist _robot_json zwar vorhanden,
|
||||
# aber keine Datei.
|
||||
if not _robot_json.is_file():
|
||||
import warnings
|
||||
grund = "ist ein Verzeichnis" if _robot_json.is_dir() else "existiert nicht"
|
||||
warnings.warn(
|
||||
f"robot.json {grund}: {_robot_json}. "
|
||||
f"/v1/config liefert 404, /v1/estimate verlangt einen robot_json-Upload. "
|
||||
f"Bei Docker: liegt die Datei wirklich am gemounteten Host-Pfad?",
|
||||
RuntimeWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return _app
|
||||
|
||||
|
||||
_app = FastAPI(title="approbot-pipeline", version=__version__)
|
||||
|
||||
|
||||
@_app.get("/v1/health")
|
||||
def health():
|
||||
return {"status": "ok", "version": __version__}
|
||||
|
||||
|
||||
@_app.get("/v1/config")
|
||||
def config():
|
||||
if _robot_json is None or not _robot_json.is_file():
|
||||
raise HTTPException(404, "Keine robot.json konfiguriert (Datei fehlt oder ist ein Verzeichnis)")
|
||||
data = json.loads(_robot_json.read_text(encoding="utf-8"))
|
||||
return data.get("pose_estimation", {})
|
||||
|
||||
|
||||
@_app.post("/v1/estimate")
|
||||
async def estimate(
|
||||
images: List[UploadFile] = File(..., description="Kamerabilder (render_<id>.png)"),
|
||||
intrinsics: List[UploadFile] = File(..., description="Kamera-Intrinsiken (render_<id>.npz)"),
|
||||
robot_json: Optional[UploadFile] = File(default=None, description="robot.json (überschreibt Server-Konfig)"),
|
||||
):
|
||||
"""Pose-Schätzung aus Kamerabildern.
|
||||
|
||||
Multipart-Upload:
|
||||
images[] — render_a.png, render_b.png, ...
|
||||
intrinsics[] — render_a.npz, render_b.npz, ... (gleiche Reihenfolge)
|
||||
robot_json — optional, überschreibt die Server-Konfiguration
|
||||
"""
|
||||
with tempfile.TemporaryDirectory(prefix="approbot_req_") as tmp:
|
||||
tmp_path = Path(tmp)
|
||||
|
||||
if robot_json is not None:
|
||||
rj_path = tmp_path / "robot.json"
|
||||
rj_path.write_bytes(await robot_json.read())
|
||||
elif _robot_json and _robot_json.is_file():
|
||||
rj_path = _robot_json
|
||||
else:
|
||||
raise HTTPException(400, "Keine robot.json angegeben (weder Upload noch gültige Server-Konfig)")
|
||||
|
||||
for img in images:
|
||||
(tmp_path / img.filename).write_bytes(await img.read())
|
||||
for npz in intrinsics:
|
||||
(tmp_path / npz.filename).write_bytes(await npz.read())
|
||||
|
||||
try:
|
||||
result = estimate_from_dir(tmp_path, robot_json=rj_path, eval_dir=tmp_path)
|
||||
except FileNotFoundError as exc:
|
||||
raise HTTPException(400, str(exc))
|
||||
except Exception as exc:
|
||||
raise HTTPException(500, str(exc))
|
||||
|
||||
return JSONResponse({
|
||||
"joints": result.joints,
|
||||
"confidence": result.confidence,
|
||||
"residual_rms": result.residual_rms,
|
||||
"n_markers": result.n_markers,
|
||||
"processing_ms": result.processing_ms,
|
||||
})
|
||||
Reference in New Issue
Block a user