Skip to content

Latest commit

 

History

History
345 lines (251 loc) · 9.03 KB

File metadata and controls

345 lines (251 loc) · 9.03 KB

Contributing to SADE Software Pilots

Welcome! This guide explains how to fork, customize, and submit your custom software pilot.

Quick Start

# 1. Fork the repo on GitHub

# Using the GitHub CLI:
gh repo fork --default-branch-only DroneResponse/sade-software-pilot --clone=true

# OR:
# 1. Navigate to https://github.com/DroneResponse/sade-software-pilot and click "Fork"
# 2. Clone your fork
#     git clone https://github.com/YOUR_USERNAME/sade-software-pilot.git
#     cd sade-software-pilot

# 3. Setup development environment
# just dev-setup

# 4. Customize your mission
# edit the source files under src/software_pilot/

# 5. Test locally
just hooks
just security
just test

# 6. Push and open a PR
git push origin feature/my-mission
# Then open a PR at: https://github.com/DroneResponse/sade-software-pilot

Customizing Your Mission

Edit src/software_pilot/mission.py to implement your mission logic:

async def run_example_mission(config: PilotConfig, drone: ResilientDrone) -> None:
    """Your custom mission implementation."""
    # Fetch drone position
    lat, lon, alt = await drone.fetch_drone_position()
    home = Lla(lat=lat, lon=lon, altitude=alt)

    # Create mission waypoints
    mission = [
        MissionStep(
            short_name="takeoff",
            description="Take off",
            ned=NED(north=0, east=0, down=-50),  # 50m altitude
            home_alt=home.altitude,
            speed=20.0,  # m/s
            home=home,
        ),
        # Add more waypoints...
    ]

    # Execute mission
    await drone.execute_mission(mission)

    # Request SADE zone access if needed
    lease = request_sade_zone_entry(drone, emulate_wait=False)
    if lease:
        print(f"Zone access granted until {lease.expiration_time}")

    # Land
    await drone.action_land()

Writing Tests

Add tests for your mission in tests/:

import pytest
from software_pilot.mission import create_example_mission
from droneresponse_mathtools import Lla

@pytest.mark.asyncio
async def test_mission_creation():
    home = Lla(lat=41.6, lon=-86.3, altitude=229)
    mission = await create_example_mission(home)
    assert len(mission) > 0
    assert mission[0].short_name == "takeoff"

Run tests:

just test

# you can also pass any pytest arguments:
just test -v --capture=no -k test_zone
just test --cov=src --cov-fail-under=70
just test --help

# Run security checks
just security

7. Quality checks

These checks will standardize code style, and catch common bugs and potential problems before running a simulation.

This saves everyone's time in the review process, saves your time when running simulations, and prevents security issues.

# Run linter, formatter, type checking, etc on all files
just hooks
# or pass options
just hooks -d src/software_pilot
just hooks --last-commit --show-diff-on-failure
# useful, as sometimes these will catch bugs before running the code

# Note sometimes hooks will re-format files and apply automated fixes. You just need to
# stage the modified files (git add ...) and try committing them again (git commit -m ...)
# If you really need to skip a check, you can pass `--no-verify` to git commit, but the
# issue will arise again when the PR is open, so we recommend fixing it when you have
# the chance. Alternatively, you can add in-line ignores depending on what kind of
# problem it is.

# Run security checks
just security

8. Commit and Push

git add src/ tests/
# example with commit message
git commit -m "Add search-pattern mission for autonomous grid search"
git push origin feature/your-mission-name

9. Open a Pull Request

On GitHub:

  1. Navigate to your fork
  2. Click Pull RequestsNew Pull Request
  3. Select:
    • Base: main (SADE original repository)
    • Compare: feature/your-mission-name (your fork)
  4. Fill out the PR template.

10. Review Process

A SADE team member will:

  • Request an automated review from an AI agent, highlight points that need fixing
  • Review code quality and security manually
  • Request changes, ask questions, or suggest improvements (marked with [nit])
  • Approve once everything looks good
  • Merge to a custom branch: contrib/{username}/{mission-name}

What we look for:

  • ✅ No security issues: safe file I/O, no shell invocation, no obfuscated code, limited remote calls, etc.
  • ✅ Comprehensive tests: this will shorten the feedback loop for you, as it is faster to run tests than to submit a simulation.

11. Use Your Custom Pilot

Once approved and merged, the simulation config will look like this:

Payload subject to change.

{
    "pilot": {
        "repo_url": "https://github.com/YOUR_USERNAME/sade-software-pilot",
        "repo_branch": "contrib/YOUR_USERNAME/mission-name",
        "custom_settings": {
            "grid_size_m": 100,
            "search_altitude_m": 150
        }
    },
    "drones": [ ... ],
    "environment": [ ... ]
}

API Reference

Core Classes

ResilientDrone

Main interface to drone operations.

Methods:

Method Description
await drone.connect() Connects to autopilot
await drone.fetch_drone_position() Gets lat/lon/alt
await drone.execute_mission(mission_steps) Uploads and executes waypoints
await drone.action_arm() Arms the drone
await drone.action_takeoff() Takes off
await drone.action_land() Lands
await drone.telemetry_position() Streams live position
await drone.telemetry_health() Streams health status

MissionStep

Represents a single waypoint in a mission.

Constructor:

MissionStep(
    short_name="waypoint_1",          # brief identifier
    description="fly north 100m",     # human-readable description
    ned=NED(north=100, east=0, down=-50),  # coordinates relative to home
    home_alt=229.0,                   # sea-level altitude of home
    speed=20.0,                       # m/s
    home=home_lla,                    # Lla object for home position
)

NED

North-East-Down coordinate system (relative to home position).

NED(
    north=100,   # meters north of home
    east=50,     # meters east of home
    down=-100,   # meters below home (negative = up)
)

SADE Zone Access

request_sade_zone_entry(drone, emulate_wait=False)

Request airspace access for a specific zone.

Returns: SadeZoneLease if approved, None if denied

Example:

lease = request_sade_zone_entry(drone, emulate_wait=False)
if lease:
    print(f"Access granted until {lease.expiration_time}")
    # Now it's safe to enter the zone
else:
    print("Access denied, returning home")
    await drone.action_land()

Configuration

PilotConfig

Configuration passed to your pilot at startup.

Attributes:

  • drone_id: int - Unique drone identifier
  • mavsdk_port: int - gRPC autopilot port
  • mavlink_port: int - MAVLink UDP port
  • mqtt_broker_address: str - MQTT broker for telemetry
  • sade_zone_config_path: Path | None - Zone configuration file
  • custom_settings: dict[str, Any] - User-provided settings

Example:

async def run_mission(config: PilotConfig):
    print(f"Flying drone {config.drone_id}")
    print(f"Custom settings: {config.custom_settings}")
    speed = config.custom_settings.get("speed_mps", 15.0)

Troubleshooting

Dependency Conflicts

Problem: uv sync fails with dependency resolution error

Solution:

  • Check that dependencies don't conflict with SADE core
  • See pyproject.toml for current versions
  • Propose version updates in your PR

Import Errors

Problem: ImportError: cannot import name 'ResilientDrone'

Solution:

# Ensure package is installed in editable mode
uv sync

# Then run with uv
uv run python src/software_pilot/mission.py

Autopilot Connection Fails

Problem: ConnectionError: Could not connect to drone

Solution:

  • Verify MAVSDK port matches simulator configuration
  • Check Firmware is running and listening
  • Monitor logs: docker compose logs sade-sim

Tests Don't Run

Problem: ModuleNotFoundError during pytest

Solution:

# Ensure tests can import your package
cd sade-software-pilot
uv run pytest tests/ -v

Getting Help

Code of Conduct

Be respectful, inclusive, and professional. We appreciate all contributions!


Happy flying! 🚁