[build-system] requires = ["setuptools>=68", "wheel"] build-backend = "setuptools.build_meta" [project] name = "gps-denied-onboard" version = "0.1.0" description = "Companion onboard system for GPS-denied UAV navigation" readme = "README.md" requires-python = ">=3.10,<3.12" license = {text = "Proprietary"} authors = [{name = "AZAION onboard team"}] dependencies = [ "numpy>=1.26,<2.0", "scipy>=1.11,<2.0", "pyyaml>=6.0", "pydantic>=2.5,<3.0", # OpenCV pin gate originally enforced >= 4.12.0 (D-CROSS-CVE-1). Held to # 4.11.x while gtsam (4.2 on PyPI) only ships numpy-1.x wheels and # opencv-python>=4.12 mandates numpy>=2. See # _docs/_process_leftovers/_d_cross_cve_1_deferred.md — the gate # will be restored to >=4.12.0 once a numpy-2-compatible gtsam wheel is # available. "opencv-python>=4.11.0.86,<4.12", "psycopg[binary]>=3.1", # AZ-305 / E-C6: `PostgresFilesystemStore` uses ConnectionPool to amortise # pool startup across the read-heavy `read_tile_pixels` path. Pinned to the # 3.x line in lockstep with `psycopg` itself. "psycopg-pool>=3.2,<4.0", "sqlalchemy>=2.0", "alembic>=1.13", "pymavlink>=2.4", # iNav MSP2 wire decoder for C8 inbound (AZ-391). MSPy is request-response # on a serial transport; AP uses pymavlink for the same role. "yamspy>=0.3.3,<0.4", "pyserial>=3.5", "requests>=2.31", "structlog>=24.1", "click>=8.1", # SE(3) math backend for helpers.se3_utils + C1/C2.5/C3/C3.5/C4/C5/C8 consumers (AZ-264 / AZ-277). "gtsam>=4.2,<5.0", # Atomic-rename backend for helpers.sha256_sidecar (D-C10-3, AZ-280). "atomicwrites>=1.4,<2.0", # WGS84 geodesy backend for helpers.wgs_converter (AZ-264 / AZ-279). "pyproj>=3.6,<4.0", # FDR wire format for fdr_client.records (E-CC-FDR-CLIENT / AZ-272). "orjson>=3.9,<4.0", # HTTPS client for C12 FlightsApiClient (AZ-489 / ADR-010). Picked over # `requests` because httpx ships `MockTransport` natively, so the # FlightsApi unit tests need no extra HTTP-mocking dep. "httpx>=0.28,<1.0", # AZ-307 / E-C6: FreshnessGate uses an in-memory R-tree to look up # the sector classification for a (lat, lon) at every write_tile # call. `rtree` is the libspatialindex Python wrapper — small, # stable, sub-microsecond point-in-rect queries at the few-hundred- # sector scale operators ship per flight (NFR p99 ≤ 100 µs). "rtree>=1.0,<2.0", ] [project.optional-dependencies] dev = [ "pytest>=7.4", "pytest-cov>=4.1", "pytest-asyncio>=0.23", "ruff>=0.4", "mypy>=1.8", "types-PyYAML", "types-requests", ] inference = [ "torch>=2.2", "torchvision>=0.17", "onnxruntime>=1.17", # tensorrt is installed out-of-band on Jetson — not a pip dep ] # AZ-302: thermal telemetry backends used by C7's ThermalStatePublisher. # Both are Jetson / NVIDIA-host-only and not import-required for Tier-1; # the publisher selects whichever is importable at start() time and # raises TelemetryUnavailableError if neither is present. telemetry = [ "jetson-stats>=4.2", "pynvml>=11.5", ] indexing = [ "faiss-cpu>=1.7", ] [project.scripts] gps-denied-replay = "gps_denied_onboard.cli.replay:main" [tool.setuptools] package-dir = {"" = "src"} [tool.setuptools.packages.find] where = ["src"] include = ["gps_denied_onboard*"] [tool.pytest.ini_options] minversion = "7.0" testpaths = ["tests"] pythonpath = ["src"] # log_schema.py is the contract-mandated file name (AZ-245 AC-4); kept # in python_files so the contract test is discovered alongside the # standard `test_*.py` pattern. python_files = ["test_*.py", "*_test.py", "log_schema.py"] addopts = [ "--strict-markers", "-ra", ] markers = [ "tier2: tests that require Jetson hardware (auto-skipped on Tier-1)", "gpu: tests that require an NVIDIA GPU", "docker: tests that require Docker compose services", "ardupilot_sitl: tests that require ArduPilot SITL container", "slow: tests slower than ~5s", "contract: contract-suite test (frozen public surfaces)", ] [tool.coverage.run] source = ["src/gps_denied_onboard"] branch = true [tool.coverage.report] show_missing = true skip_covered = false [tool.ruff] line-length = 100 target-version = "py310" src = ["src", "tests"] [tool.ruff.lint] select = ["E", "F", "W", "I", "B", "UP", "RUF"] ignore = ["E501"] [tool.mypy] python_version = "3.10" strict = true warn_unused_ignores = true warn_return_any = true ignore_missing_imports = true mypy_path = "src" packages = ["gps_denied_onboard"]