feat(simulation): add Gaussian UGV runtime pipeline

This commit is contained in:
DCCONSTRUCTIONS
2026-08-28 11:50:47 +03:00
parent c4c2392c79
commit 722e60e5ef
21 changed files with 4685 additions and 628 deletions
+50 -19
View File
@@ -4,7 +4,7 @@ from __future__ import annotations
from typing import Any, Literal
from fastapi import APIRouter, BackgroundTasks, Header, HTTPException, Request, Response
from fastapi import APIRouter, Header, HTTPException, Request, Response
from fastapi.responses import FileResponse
from pydantic import BaseModel, ConfigDict, Field
@@ -46,11 +46,18 @@ class SimulationProjectUpdate(BaseModel):
scene_type: Literal["interior", "outdoor", "object"]
class SimulationEulerRotation(BaseModel):
model_config = ConfigDict(extra="forbid", frozen=True)
x: float = Field(ge=-360, le=360)
y: float = Field(ge=-360, le=360)
z: float = Field(ge=-360, le=360)
class SimulationLayerViewerSettings(BaseModel):
model_config = ConfigDict(extra="forbid", frozen=True)
inverted: bool
axis: Literal["x", "y", "z"]
rotation_degrees: SimulationEulerRotation
class SimulationCameraViewerSettings(BaseModel):
@@ -60,14 +67,35 @@ class SimulationCameraViewerSettings(BaseModel):
invert_vertical: bool
class SimulationUgvDimensions(BaseModel):
model_config = ConfigDict(extra="forbid", frozen=True)
length: float = Field(ge=0.01, le=1_000_000_000)
width: float = Field(ge=0.01, le=1_000_000_000)
height: float = Field(ge=0.07, le=1_000_000_000)
ground_clearance: float = Field(ge=0.01, le=1_000_000_000)
class SimulationUgvViewerSettings(BaseModel):
model_config = ConfigDict(extra="forbid", frozen=True)
preset_name: str = Field(min_length=1, max_length=80)
mass_kg: float = Field(ge=0.01, le=1_000_000_000)
dimensions_m: SimulationUgvDimensions
max_speed_mps: float = Field(ge=0, le=1_000_000_000)
max_turn_rate_degrees: float = Field(ge=0, le=1_000_000_000)
invert_steering: bool
class SimulationViewerSettings(BaseModel):
model_config = ConfigDict(extra="forbid", frozen=True)
schema_version: Literal["missioncore.simulation-viewer-settings/v1"] = VIEWER_SETTINGS_SCHEMA
schema_version: Literal["missioncore.simulation-viewer-settings/v3"] = VIEWER_SETTINGS_SCHEMA
quality: Literal["low", "medium", "high", "ultra", "maximum"]
visual: SimulationLayerViewerSettings
collision: SimulationLayerViewerSettings
camera: SimulationCameraViewerSettings
ugv: SimulationUgvViewerSettings
class SimulationProjectDocument(BaseModel):
@@ -162,11 +190,14 @@ def build_simulation_projects_router(
def source_upload_state(project_id: str, file_id: str) -> Response:
try:
offset, byte_length = store.upload_state(project_id, file_id)
return Response(status_code=204, headers={
"Upload-Offset": str(offset),
"Upload-Length": str(byte_length),
"Cache-Control": "no-store",
})
return Response(
status_code=204,
headers={
"Upload-Offset": str(offset),
"Upload-Length": str(byte_length),
"Cache-Control": "no-store",
},
)
except SimulationProjectNotFoundError as exc:
raise HTTPException(status_code=404, detail="Исходный файл не найден.") from exc
@@ -199,11 +230,14 @@ def build_simulation_projects_router(
source_file = next(
item for item in project["source"]["files"] if item["file_id"] == file_id
)
return Response(status_code=204, headers={
"Upload-Offset": str(source_file["uploaded_bytes"]),
"Upload-Length": str(source_file["byte_length"]),
"Cache-Control": "no-store",
})
return Response(
status_code=204,
headers={
"Upload-Offset": str(source_file["uploaded_bytes"]),
"Upload-Length": str(source_file["byte_length"]),
"Cache-Control": "no-store",
},
)
except SimulationProjectNotFoundError as exc:
raise HTTPException(status_code=404, detail="Исходный файл не найден.") from exc
except SimulationProjectConflictError as exc:
@@ -212,13 +246,10 @@ def build_simulation_projects_router(
raise HTTPException(status_code=400, detail=str(exc)) from exc
@router.post("/projects/{project_id}/build", response_model=SimulationProjectDocument)
def build_project(
project_id: str,
background_tasks: BackgroundTasks,
) -> dict[str, Any]:
def build_project(project_id: str) -> dict[str, Any]:
try:
project = service.begin_build(project_id)
background_tasks.add_task(service.process, project_id)
service.enqueue(project_id)
return project
except SimulationProjectNotFoundError as exc:
raise HTTPException(status_code=404, detail="Проект симуляции не найден.") from exc