Добавить имитаторы МЛЭ и ГБО с 3D-сценой, съёмкой рельефа и пресетами.

Вкладки позволяют готовить рельеф, двигать АНПА, накапливать поверхность по лучам и сохранять скриншоты окон; ГБО использует бортовые секторы 12–75° и чёрные зоны вне обзора.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-21 15:43:08 +03:00
co-authored by Cursor
parent 8b248e1d54
commit 6cfc16e53c
18 changed files with 5512 additions and 12 deletions
+195 -1
View File
@@ -18,7 +18,15 @@ from pydantic import BaseModel
from builtin_presets import BUILTIN_PRESETS, get_builtin_preset
from demo_generator import DEMO_SURFACE_TYPES, demo_payload
from pipeline_insights import compute_insights
from dataset_generator import iter_generate_dataset, load_object_points_from_obj_text, load_scene_preview
from dataset_generator import (
iter_generate_dataset,
list_dataset_runs,
load_dataset_run,
load_object_points_from_obj_text,
load_scene_preview,
resolve_output_dir,
)
from mle_simulator import load_last_settings, prepare_mle_scene, save_last_settings, save_survey_surface
from scene_generator import (
catalog_payload as generator_catalog_payload,
export_npy_float64,
@@ -123,6 +131,54 @@ class DatasetPreviewBody(BaseModel):
maxPoints: int = 25000
class DatasetLoadBody(BaseModel):
outputDir: str
class MlePrepareBody(BaseModel):
seed: int = 42
sizeX: float = 40.0
sizeY: float = 60.0
resX: int = 80
resY: int = 120
outputDir: str = "mle_runs"
settings: dict[str, Any] | None = None
class MleSaveSurfaceBody(BaseModel):
outputDir: str
vertices: list[list[float]]
faces: list[list[int]]
filename: str = "seafloor.obj"
class MleSettingsBody(BaseModel):
outputDir: str = "mle_runs"
settings: dict[str, Any]
class GboPrepareBody(BaseModel):
seed: int = 42
sizeX: float = 40.0
sizeY: float = 60.0
resX: int = 80
resY: int = 120
outputDir: str = "gbo_runs"
settings: dict[str, Any] | None = None
class GboSaveSurfaceBody(BaseModel):
outputDir: str
vertices: list[list[float]]
faces: list[list[int]]
filename: str = "seafloor.obj"
class GboSettingsBody(BaseModel):
outputDir: str = "gbo_runs"
settings: dict[str, Any]
def preset_to_pipeline_config(preset: dict[str, Any]) -> dict[str, Any]:
if "preprocessPlugins" in preset and "reconstructionPlugin" in preset:
return preset
@@ -481,6 +537,26 @@ def dataset_preview(body: DatasetPreviewBody) -> dict[str, Any]:
raise HTTPException(status_code=500, detail=f"Failed to load scene: {exc}") from exc
@app.get("/api/dataset/runs")
def dataset_runs(outputDir: str = "sonar_dataset") -> dict[str, Any]:
try:
base_path = resolve_output_dir(outputDir or "sonar_dataset")
runs = list_dataset_runs(outputDir or "sonar_dataset")
return {"baseDir": str(base_path), "runs": runs}
except OSError as exc:
raise HTTPException(status_code=500, detail=f"Failed to list dataset runs: {exc}") from exc
@app.post("/api/dataset/load")
def dataset_load(body: DatasetLoadBody) -> dict[str, Any]:
try:
return load_dataset_run(body.outputDir)
except FileNotFoundError as exc:
raise HTTPException(status_code=404, detail=str(exc)) from exc
except OSError as exc:
raise HTTPException(status_code=500, detail=f"Failed to load dataset run: {exc}") from exc
@app.post("/api/generator/export")
def generator_export(body: GeneratorExportBody) -> Response:
from urllib.parse import quote
@@ -718,5 +794,123 @@ def dataset_spa() -> FileResponse:
return index()
@app.get("/mle")
def mle_spa() -> FileResponse:
return index()
@app.post("/api/mle/prepare")
def mle_prepare(body: MlePrepareBody) -> dict[str, Any]:
try:
result = prepare_mle_scene(
seed=body.seed,
size_x=body.sizeX,
size_y=body.sizeY,
res_x=body.resX,
res_y=body.resY,
output_dir=body.outputDir or "mle_runs",
settings=body.settings,
)
if body.settings:
try:
save_last_settings(body.settings, output_dir=body.outputDir or "mle_runs")
except OSError:
pass
return result
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc
except OSError as exc:
raise HTTPException(status_code=500, detail=f"Failed to prepare MLE scene: {exc}") from exc
@app.get("/api/mle/settings")
def mle_get_settings(outputDir: str = "mle_runs") -> dict[str, Any]:
return load_last_settings(output_dir=outputDir or "mle_runs")
@app.put("/api/mle/settings")
def mle_put_settings(body: MleSettingsBody) -> dict[str, Any]:
try:
return save_last_settings(body.settings or {}, output_dir=body.outputDir or "mle_runs")
except OSError as exc:
raise HTTPException(status_code=500, detail=f"Failed to save MLE settings: {exc}") from exc
@app.post("/api/mle/save-surface")
def mle_save_surface(body: MleSaveSurfaceBody) -> dict[str, Any]:
try:
return save_survey_surface(
output_dir=body.outputDir,
vertices=body.vertices,
faces=body.faces,
filename=body.filename or "seafloor.obj",
)
except FileNotFoundError as exc:
raise HTTPException(status_code=404, detail=str(exc)) from exc
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc
except OSError as exc:
raise HTTPException(status_code=500, detail=f"Failed to save survey surface: {exc}") from exc
@app.get("/gbo")
def gbo_spa() -> FileResponse:
return index()
@app.post("/api/gbo/prepare")
def gbo_prepare(body: GboPrepareBody) -> dict[str, Any]:
try:
result = prepare_mle_scene(
seed=body.seed,
size_x=body.sizeX,
size_y=body.sizeY,
res_x=body.resX,
res_y=body.resY,
output_dir=body.outputDir or "gbo_runs",
settings=body.settings,
)
if body.settings:
try:
save_last_settings(body.settings, output_dir=body.outputDir or "gbo_runs")
except OSError:
pass
return result
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc
except OSError as exc:
raise HTTPException(status_code=500, detail=f"Failed to prepare GBO scene: {exc}") from exc
@app.get("/api/gbo/settings")
def gbo_get_settings(outputDir: str = "gbo_runs") -> dict[str, Any]:
return load_last_settings(output_dir=outputDir or "gbo_runs")
@app.put("/api/gbo/settings")
def gbo_put_settings(body: GboSettingsBody) -> dict[str, Any]:
try:
return save_last_settings(body.settings or {}, output_dir=body.outputDir or "gbo_runs")
except OSError as exc:
raise HTTPException(status_code=500, detail=f"Failed to save GBO settings: {exc}") from exc
@app.post("/api/gbo/save-surface")
def gbo_save_surface(body: GboSaveSurfaceBody) -> dict[str, Any]:
try:
return save_survey_surface(
output_dir=body.outputDir,
vertices=body.vertices,
faces=body.faces,
filename=body.filename or "seafloor.obj",
)
except FileNotFoundError as exc:
raise HTTPException(status_code=404, detail=str(exc)) from exc
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc
except OSError as exc:
raise HTTPException(status_code=500, detail=f"Failed to save GBO survey surface: {exc}") from exc
if (WEB_DIST / "assets").is_dir():
app.mount("/assets", StaticFiles(directory=WEB_DIST / "assets"), name="assets")