mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-04-22 11:36:37 +00:00
initial structure implemented
docs -> _docs
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
from .core import *
|
||||
from .flight import *
|
||||
from .processing import *
|
||||
from .chunks import *
|
||||
from .satellite import *
|
||||
from .recovery import *
|
||||
from .results import *
|
||||
from .images import *
|
||||
from .config import *
|
||||
from .api import *
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
from .flight_requests import FlightCreateRequest
|
||||
from .flight_responses import (
|
||||
FlightResponse,
|
||||
FlightDetailResponse,
|
||||
FlightStatusResponse,
|
||||
DeleteResponse,
|
||||
UpdateResponse,
|
||||
BatchUpdateResponse,
|
||||
)
|
||||
from .batch_requests import BatchMetadata, BatchResponse
|
||||
from .user_fix_requests import UserFixRequest, UserFixResponse, ObjectGPSResponse
|
||||
|
||||
__all__ = [
|
||||
"FlightCreateRequest",
|
||||
"FlightResponse",
|
||||
"FlightDetailResponse",
|
||||
"FlightStatusResponse",
|
||||
"DeleteResponse",
|
||||
"UpdateResponse",
|
||||
"BatchUpdateResponse",
|
||||
"BatchMetadata",
|
||||
"BatchResponse",
|
||||
"UserFixRequest",
|
||||
"UserFixResponse",
|
||||
"ObjectGPSResponse",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class BatchMetadata(BaseModel):
|
||||
start_sequence: int
|
||||
end_sequence: int
|
||||
batch_number: int
|
||||
|
||||
|
||||
class BatchResponse(BaseModel):
|
||||
accepted: bool
|
||||
sequences: list[int]
|
||||
next_expected: int
|
||||
message: Optional[str] = None
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
from pydantic import BaseModel
|
||||
from ..core.gps_point import GPSPoint
|
||||
from ..core.camera_parameters import CameraParameters
|
||||
from ..flight.geofences import Geofences
|
||||
|
||||
|
||||
class FlightCreateRequest(BaseModel):
|
||||
name: str
|
||||
description: str
|
||||
start_gps: GPSPoint
|
||||
rough_waypoints: list[GPSPoint]
|
||||
geofences: Geofences
|
||||
camera_params: CameraParameters
|
||||
altitude: float
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
from ..core.gps_point import GPSPoint
|
||||
from ..core.camera_parameters import CameraParameters
|
||||
from ..flight.waypoint import Waypoint
|
||||
from ..flight.geofences import Geofences
|
||||
|
||||
|
||||
class FlightResponse(BaseModel):
|
||||
flight_id: str
|
||||
status: str
|
||||
message: Optional[str] = None
|
||||
created_at: datetime
|
||||
|
||||
|
||||
class FlightDetailResponse(BaseModel):
|
||||
flight_id: str
|
||||
name: str
|
||||
description: str
|
||||
start_gps: GPSPoint
|
||||
waypoints: list[Waypoint]
|
||||
geofences: Geofences
|
||||
camera_params: CameraParameters
|
||||
altitude: float
|
||||
status: str
|
||||
frames_processed: int
|
||||
frames_total: int
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
class FlightStatusResponse(BaseModel):
|
||||
status: str
|
||||
frames_processed: int
|
||||
frames_total: int
|
||||
current_frame: Optional[int] = None
|
||||
current_heading: Optional[float] = None
|
||||
blocked: bool = False
|
||||
search_grid_size: Optional[int] = None
|
||||
message: Optional[str] = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
class DeleteResponse(BaseModel):
|
||||
deleted: bool
|
||||
flight_id: str
|
||||
|
||||
|
||||
class UpdateResponse(BaseModel):
|
||||
updated: bool
|
||||
waypoint_id: str
|
||||
|
||||
|
||||
class BatchUpdateResponse(BaseModel):
|
||||
success: bool
|
||||
updated_count: int
|
||||
failed_ids: list[str] = []
|
||||
errors: Optional[dict[str, str]] = None
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
from ..core.gps_point import GPSPoint
|
||||
|
||||
|
||||
class UserFixRequest(BaseModel):
|
||||
frame_id: int
|
||||
uav_pixel: tuple[float, float]
|
||||
satellite_gps: GPSPoint
|
||||
|
||||
|
||||
class UserFixResponse(BaseModel):
|
||||
accepted: bool
|
||||
processing_resumed: bool
|
||||
message: Optional[str] = None
|
||||
|
||||
|
||||
class ObjectGPSResponse(BaseModel):
|
||||
gps: GPSPoint
|
||||
accuracy_meters: float
|
||||
frame_id: int
|
||||
pixel: tuple[float, float]
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
from .sim3_transform import Sim3Transform
|
||||
from .chunk_handle import ChunkHandle
|
||||
from .chunk_bounds import ChunkBounds
|
||||
|
||||
__all__ = [
|
||||
"Sim3Transform",
|
||||
"ChunkHandle",
|
||||
"ChunkBounds",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
from pydantic import BaseModel
|
||||
from ..core.gps_point import GPSPoint
|
||||
|
||||
|
||||
class ChunkBounds(BaseModel):
|
||||
estimated_center: GPSPoint
|
||||
estimated_radius: float
|
||||
confidence: float
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
from ..core.gps_point import GPSPoint
|
||||
|
||||
|
||||
class ChunkHandle(BaseModel):
|
||||
chunk_id: str
|
||||
flight_id: str
|
||||
start_frame_id: int
|
||||
end_frame_id: Optional[int] = None
|
||||
frames: list[int] = []
|
||||
is_active: bool = True
|
||||
has_anchor: bool = False
|
||||
anchor_frame_id: Optional[int] = None
|
||||
anchor_gps: Optional[GPSPoint] = None
|
||||
matching_status: str = "unanchored"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import numpy as np
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
class Sim3Transform(BaseModel):
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
|
||||
translation: np.ndarray
|
||||
rotation: np.ndarray
|
||||
scale: float
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
from .system_config import SystemConfig
|
||||
from .flight_config import FlightConfig
|
||||
from .database_config import DatabaseConfig
|
||||
from .model_config import ModelConfig
|
||||
from .rotation_config import RotationConfig
|
||||
from .recovery_config import RecoveryConfig
|
||||
|
||||
__all__ = [
|
||||
"SystemConfig",
|
||||
"FlightConfig",
|
||||
"DatabaseConfig",
|
||||
"ModelConfig",
|
||||
"RotationConfig",
|
||||
"RecoveryConfig",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class DatabaseConfig(BaseModel):
|
||||
host: str = "localhost"
|
||||
port: int = 5432
|
||||
database: str = "gps_denied"
|
||||
username: str = "postgres"
|
||||
password: str = ""
|
||||
pool_size: int = 50
|
||||
max_overflow: int = 50
|
||||
pool_timeout: int = 30
|
||||
pool_recycle: int = 3600
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
from ..core.camera_parameters import CameraParameters
|
||||
from ..core.gps_point import GPSPoint
|
||||
|
||||
|
||||
class OperationalArea(BaseModel):
|
||||
name: str = "Eastern Ukraine"
|
||||
min_lat: float = 45.0
|
||||
max_lat: float = 52.0
|
||||
min_lon: float = 22.0
|
||||
max_lon: float = 40.0
|
||||
|
||||
|
||||
class FlightConfig(BaseModel):
|
||||
camera_params: CameraParameters
|
||||
altitude: float
|
||||
operational_area: OperationalArea = OperationalArea()
|
||||
frame_spacing: float = 100.0
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ModelConfig(BaseModel):
|
||||
model_name: str
|
||||
model_path: str
|
||||
format: str = "tensorrt"
|
||||
precision: str = "fp16"
|
||||
warmup_iterations: int = 3
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class RecoveryConfig(BaseModel):
|
||||
search_grid_sizes: list[int] = [1, 4, 9, 16, 25]
|
||||
min_chunk_frames_for_matching: int = 5
|
||||
max_chunk_frames_for_matching: int = 20
|
||||
user_input_threshold_tiles: int = 25
|
||||
chunk_matching_interval_seconds: float = 5.0
|
||||
confidence_threshold_good: float = 0.7
|
||||
confidence_threshold_degraded: float = 0.5
|
||||
min_inlier_count_good: int = 50
|
||||
min_inlier_count_tracking: int = 20
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class RotationConfig(BaseModel):
|
||||
step_angle: float = 30.0
|
||||
sharp_turn_threshold: float = 45.0
|
||||
confidence_threshold: float = 0.7
|
||||
history_size: int = 10
|
||||
|
||||
@property
|
||||
def rotation_iterations(self) -> int:
|
||||
return int(360 / self.step_angle)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
from pydantic import BaseModel
|
||||
from ..core.camera_parameters import CameraParameters
|
||||
from .database_config import DatabaseConfig
|
||||
from .flight_config import OperationalArea
|
||||
|
||||
|
||||
class ModelPaths(BaseModel):
|
||||
superpoint: str = "models/superpoint.engine"
|
||||
lightglue: str = "models/lightglue.engine"
|
||||
dinov2: str = "models/dinov2.engine"
|
||||
litesam: str = "models/litesam.engine"
|
||||
|
||||
|
||||
class APIConfig(BaseModel):
|
||||
host: str = "0.0.0.0"
|
||||
port: int = 8000
|
||||
debug: bool = False
|
||||
|
||||
|
||||
class SystemConfig(BaseModel):
|
||||
camera: CameraParameters
|
||||
operational_area: OperationalArea = OperationalArea()
|
||||
models: ModelPaths = ModelPaths()
|
||||
database: DatabaseConfig = DatabaseConfig()
|
||||
api: APIConfig = APIConfig()
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
from .gps_point import GPSPoint
|
||||
from .camera_parameters import CameraParameters
|
||||
from .pose import Pose
|
||||
from .polygon import Polygon
|
||||
from .validation_result import ValidationResult
|
||||
|
||||
__all__ = [
|
||||
"GPSPoint",
|
||||
"CameraParameters",
|
||||
"Pose",
|
||||
"Polygon",
|
||||
"ValidationResult",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class CameraParameters(BaseModel):
|
||||
focal_length: float
|
||||
sensor_width: float
|
||||
sensor_height: float
|
||||
resolution_width: int
|
||||
resolution_height: int
|
||||
principal_point: tuple[float, float] | None = None
|
||||
distortion_coefficients: list[float] | None = None
|
||||
|
||||
def get_principal_point(self) -> tuple[float, float]:
|
||||
if self.principal_point:
|
||||
return self.principal_point
|
||||
return (self.resolution_width / 2.0, self.resolution_height / 2.0)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
from pydantic import BaseModel, field_validator
|
||||
|
||||
|
||||
class GPSPoint(BaseModel):
|
||||
lat: float
|
||||
lon: float
|
||||
|
||||
@field_validator("lat")
|
||||
@classmethod
|
||||
def validate_lat(cls, v: float) -> float:
|
||||
if not -90 <= v <= 90:
|
||||
raise ValueError("Latitude must be between -90 and 90")
|
||||
return v
|
||||
|
||||
@field_validator("lon")
|
||||
@classmethod
|
||||
def validate_lon(cls, v: float) -> float:
|
||||
if not -180 <= v <= 180:
|
||||
raise ValueError("Longitude must be between -180 and 180")
|
||||
return v
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
from pydantic import BaseModel
|
||||
from .gps_point import GPSPoint
|
||||
|
||||
|
||||
class Polygon(BaseModel):
|
||||
north_west: GPSPoint
|
||||
south_east: GPSPoint
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
import numpy as np
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
class Pose(BaseModel):
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
|
||||
frame_id: int
|
||||
position: np.ndarray
|
||||
orientation: np.ndarray
|
||||
timestamp: datetime
|
||||
covariance: Optional[np.ndarray] = None
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ValidationResult(BaseModel):
|
||||
valid: bool
|
||||
errors: list[str] = []
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
from .flight import Flight
|
||||
from .flight_state import FlightState
|
||||
from .waypoint import Waypoint
|
||||
from .geofences import Geofences
|
||||
from .heading_record import HeadingRecord
|
||||
|
||||
__all__ = [
|
||||
"Flight",
|
||||
"FlightState",
|
||||
"Waypoint",
|
||||
"Geofences",
|
||||
"HeadingRecord",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
from datetime import datetime
|
||||
from pydantic import BaseModel
|
||||
from ..core.gps_point import GPSPoint
|
||||
from ..core.camera_parameters import CameraParameters
|
||||
from .waypoint import Waypoint
|
||||
from .geofences import Geofences
|
||||
|
||||
|
||||
class Flight(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
description: str
|
||||
start_gps: GPSPoint
|
||||
waypoints: list[Waypoint]
|
||||
geofences: Geofences
|
||||
camera_params: CameraParameters
|
||||
altitude: float
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class FlightState(BaseModel):
|
||||
flight_id: str
|
||||
status: str
|
||||
frames_processed: int
|
||||
frames_total: int
|
||||
current_frame: Optional[int] = None
|
||||
blocked: bool = False
|
||||
search_grid_size: Optional[int] = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
from pydantic import BaseModel
|
||||
from ..core.polygon import Polygon
|
||||
|
||||
|
||||
class Geofences(BaseModel):
|
||||
polygons: list[Polygon]
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
from datetime import datetime
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class HeadingRecord(BaseModel):
|
||||
frame_id: int
|
||||
heading: float
|
||||
timestamp: datetime
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class Waypoint(BaseModel):
|
||||
id: str
|
||||
lat: float
|
||||
lon: float
|
||||
altitude: Optional[float] = None
|
||||
confidence: float
|
||||
timestamp: datetime
|
||||
refined: bool = False
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
from .image_data import ImageData
|
||||
from .image_metadata import ImageMetadata
|
||||
from .image_batch import ImageBatch
|
||||
from .processing_status import ProcessingStatus
|
||||
|
||||
__all__ = [
|
||||
"ImageData",
|
||||
"ImageMetadata",
|
||||
"ImageBatch",
|
||||
"ProcessingStatus",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ImageBatch(BaseModel):
|
||||
images: list[bytes]
|
||||
filenames: list[str]
|
||||
start_sequence: int
|
||||
end_sequence: int
|
||||
batch_number: int
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import numpy as np
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
from .image_metadata import ImageMetadata
|
||||
|
||||
|
||||
class ImageData(BaseModel):
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
|
||||
flight_id: str
|
||||
sequence: int
|
||||
filename: str
|
||||
image: np.ndarray
|
||||
metadata: ImageMetadata
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ImageMetadata(BaseModel):
|
||||
sequence: int
|
||||
filename: str
|
||||
dimensions: tuple[int, int]
|
||||
file_size: int
|
||||
timestamp: datetime
|
||||
exif_data: Optional[dict] = None
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ProcessingStatus(BaseModel):
|
||||
flight_id: str
|
||||
total_images: int
|
||||
processed_images: int
|
||||
current_sequence: int
|
||||
queued_batches: int
|
||||
processing_rate: float
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
from .relative_pose import RelativePose
|
||||
from .motion import Motion
|
||||
from .matches import Matches
|
||||
from .alignment_result import AlignmentResult, ChunkAlignmentResult
|
||||
from .rotation_result import RotationResult
|
||||
|
||||
__all__ = [
|
||||
"RelativePose",
|
||||
"Motion",
|
||||
"Matches",
|
||||
"AlignmentResult",
|
||||
"ChunkAlignmentResult",
|
||||
"RotationResult",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import numpy as np
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
from ..core.gps_point import GPSPoint
|
||||
from ..chunks.sim3_transform import Sim3Transform
|
||||
|
||||
|
||||
class AlignmentResult(BaseModel):
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
|
||||
matched: bool
|
||||
homography: np.ndarray
|
||||
gps_center: GPSPoint
|
||||
confidence: float
|
||||
inlier_count: int
|
||||
total_correspondences: int
|
||||
reprojection_error: float = 0.0
|
||||
|
||||
|
||||
class ChunkAlignmentResult(BaseModel):
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
|
||||
matched: bool
|
||||
chunk_id: str
|
||||
chunk_center_gps: GPSPoint
|
||||
rotation_angle: float
|
||||
confidence: float
|
||||
inlier_count: int
|
||||
transform: Sim3Transform
|
||||
reprojection_error: float = 0.0
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import numpy as np
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
class Matches(BaseModel):
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
|
||||
matches: np.ndarray
|
||||
scores: np.ndarray
|
||||
keypoints1: np.ndarray
|
||||
keypoints2: np.ndarray
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import numpy as np
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
class Motion(BaseModel):
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
|
||||
translation: np.ndarray
|
||||
rotation: np.ndarray
|
||||
inliers: np.ndarray
|
||||
inlier_count: int
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
from typing import Optional
|
||||
import numpy as np
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
class RelativePose(BaseModel):
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
|
||||
translation: np.ndarray
|
||||
rotation: np.ndarray
|
||||
confidence: float
|
||||
inlier_count: int
|
||||
total_matches: int
|
||||
tracking_good: bool
|
||||
scale_ambiguous: bool = True
|
||||
chunk_id: Optional[str] = None
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import numpy as np
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
class RotationResult(BaseModel):
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
|
||||
matched: bool
|
||||
initial_angle: float
|
||||
precise_angle: float
|
||||
confidence: float
|
||||
homography: np.ndarray
|
||||
inlier_count: int = 0
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
from .search_session import SearchSession
|
||||
from .confidence_assessment import ConfidenceAssessment
|
||||
from .user_anchor import UserAnchor
|
||||
from .user_input_request import UserInputRequest
|
||||
|
||||
__all__ = [
|
||||
"SearchSession",
|
||||
"ConfidenceAssessment",
|
||||
"UserAnchor",
|
||||
"UserInputRequest",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ConfidenceAssessment(BaseModel):
|
||||
overall_confidence: float
|
||||
vo_confidence: float
|
||||
litesam_confidence: float
|
||||
inlier_count: int
|
||||
tracking_status: str
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
from pydantic import BaseModel
|
||||
from ..core.gps_point import GPSPoint
|
||||
|
||||
|
||||
class SearchSession(BaseModel):
|
||||
session_id: str
|
||||
flight_id: str
|
||||
frame_id: int
|
||||
center_gps: GPSPoint
|
||||
current_grid_size: int = 1
|
||||
max_grid_size: int = 25
|
||||
found: bool = False
|
||||
exhausted: bool = False
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
from pydantic import BaseModel
|
||||
from ..core.gps_point import GPSPoint
|
||||
|
||||
|
||||
class UserAnchor(BaseModel):
|
||||
uav_pixel: tuple[float, float]
|
||||
satellite_gps: GPSPoint
|
||||
confidence: float = 1.0
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
from datetime import datetime
|
||||
import numpy as np
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
from ..satellite.tile_candidate import TileCandidate
|
||||
|
||||
|
||||
class UserInputRequest(BaseModel):
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
|
||||
request_id: str
|
||||
flight_id: str
|
||||
frame_id: int
|
||||
uav_image: np.ndarray
|
||||
candidate_tiles: list[TileCandidate]
|
||||
message: str
|
||||
created_at: datetime
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
from .frame_result import FrameResult, ObjectLocation
|
||||
from .flight_results import FlightResults, FlightStatistics
|
||||
from .refined_frame_result import RefinedFrameResult
|
||||
from .optimization_result import OptimizationResult
|
||||
|
||||
__all__ = [
|
||||
"FrameResult",
|
||||
"ObjectLocation",
|
||||
"FlightResults",
|
||||
"FlightStatistics",
|
||||
"RefinedFrameResult",
|
||||
"OptimizationResult",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
from pydantic import BaseModel
|
||||
from .frame_result import FrameResult
|
||||
|
||||
|
||||
class FlightStatistics(BaseModel):
|
||||
total_frames: int
|
||||
processed_frames: int
|
||||
refined_frames: int
|
||||
mean_confidence: float
|
||||
processing_time: float
|
||||
|
||||
|
||||
class FlightResults(BaseModel):
|
||||
flight_id: str
|
||||
frames: list[FrameResult]
|
||||
statistics: FlightStatistics
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
from datetime import datetime
|
||||
from pydantic import BaseModel
|
||||
from ..core.gps_point import GPSPoint
|
||||
|
||||
|
||||
class ObjectLocation(BaseModel):
|
||||
object_id: str
|
||||
pixel: tuple[float, float]
|
||||
gps: GPSPoint
|
||||
class_name: str
|
||||
confidence: float
|
||||
|
||||
|
||||
class FrameResult(BaseModel):
|
||||
frame_id: int
|
||||
gps_center: GPSPoint
|
||||
altitude: float
|
||||
heading: float
|
||||
confidence: float
|
||||
timestamp: datetime
|
||||
refined: bool = False
|
||||
objects: list[ObjectLocation] = []
|
||||
updated_at: datetime
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class OptimizationResult(BaseModel):
|
||||
converged: bool
|
||||
final_error: float
|
||||
iterations_used: int
|
||||
optimized_frames: list[int]
|
||||
mean_reprojection_error: float = 0.0
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
from ..core.gps_point import GPSPoint
|
||||
|
||||
|
||||
class RefinedFrameResult(BaseModel):
|
||||
frame_id: int
|
||||
gps_center: GPSPoint
|
||||
confidence: float
|
||||
heading: Optional[float] = None
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
from .tile_coords import TileCoords
|
||||
from .tile_bounds import TileBounds
|
||||
from .tile_candidate import TileCandidate
|
||||
|
||||
__all__ = [
|
||||
"TileCoords",
|
||||
"TileBounds",
|
||||
"TileCandidate",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
from pydantic import BaseModel
|
||||
from ..core.gps_point import GPSPoint
|
||||
|
||||
|
||||
class TileBounds(BaseModel):
|
||||
nw: GPSPoint
|
||||
ne: GPSPoint
|
||||
sw: GPSPoint
|
||||
se: GPSPoint
|
||||
center: GPSPoint
|
||||
gsd: float
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
from ..core.gps_point import GPSPoint
|
||||
from .tile_bounds import TileBounds
|
||||
|
||||
|
||||
class TileCandidate(BaseModel):
|
||||
tile_id: str
|
||||
gps_center: GPSPoint
|
||||
bounds: TileBounds
|
||||
similarity_score: float
|
||||
rank: int
|
||||
spatial_score: Optional[float] = None
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class TileCoords(BaseModel):
|
||||
x: int
|
||||
y: int
|
||||
zoom: int
|
||||
|
||||
Reference in New Issue
Block a user