# px4-configuration

Repository that collects scripts to configure and modify PX4 from a companion Linux computer. All tooling is built on top of [MAVSDK-Python](https://github.com/mavlink/MAVSDK-Python).

## Installation

### Development Installation

```bash
# Optional: create a virtual environment
python3 -m venv .venv
source .venv/bin/activate

# Install the package (installs all required dependencies)
pip install -e .
```

### Building a Wheel Package

To build a distributable wheel (`.whl`) file:

```bash
# Install build tools (if not already installed)
pip install build

# Build the wheel package
python -m build --wheel

# The wheel file will be created in the dist/ directory
# Example: dist/px4_configuration-0.1.0-py3-none-any.whl
```

To build both wheel and source distribution:

```bash
python -m build
```

**Installing from a built wheel:**

```bash
# Install from the wheel file
pip install dist/px4_configuration-0.1.0-py3-none-any.whl
```

## Requirements

- Python 3.8+
- PX4 flight controller connected over serial (e.g. `/dev/pixhawk`)
- User added to the `dialout` group for serial access (`sudo usermod -aG dialout $USER`)

## Scripts

_All scripts use a serial connection to talk to PX4._

- `scripts/calibrate.py` – run gyro, accel, mag, level and (future) ESC calibration
- `scripts/set-params.py` – bulk upload parameters from `.params` files in `configs/`
- `scripts/upload-sdcard-config.py` – upload files (e.g. `extras.txt`) to the PX4 SD card via MAVLink FTP
- `scripts/shell.py` – open an interactive PX4 NSH shell session over MAVLink
- `scripts/px_uploader.py` – PX4 firmware uploader (original PX4 script, unverified here)

## REST API (FastAPI)

The companion computer can expose the same functionality through a REST API located in `px4_configuration/api/`.

### Run the API server

```bash
# Using the packaged console script
px4-config-api --host 0.0.0.0 --port 8000

# Or via the helper module
python run_api.py

# Or directly with uvicorn
uvicorn px4_configuration.api.main:app --host 0.0.0.0 --port 8000
```

### Endpoints

- `GET /api/health` – health check
- `POST /api/calibration/start` – start selected calibrations, returns Server-Sent Events (SSE) with progress
- `POST /api/params/upload` – upload a `.params` file (multipart form), SSE progress stream
- `POST /api/sdcard/upload` – upload a file (e.g. `extras.txt`) to the SD card, SSE progress stream
- `WS /api/shell/connect` – interactive PX4 shell over WebSocket

All endpoints accept optional `port` and `baudrate` (defaults `/dev/pixhawk`, `2000000`). SSE responses emit JSON payloads with keys such as `type`, `message`, `progress`, etc.

### Calibration Message Structure

The `/api/calibration/start` endpoint returns structured JSON messages via Server-Sent Events (SSE). Each calibration type has a specific message format:

#### Accelerometer Calibration

```json
{
  "type": "accelerometer_progress",
  "progress": 0.17,
  "status_text": "down side result: [0.020 0.819 -9.750]",
  "pending_orientations": ["back", "front", "left", "right", "up"],
  "current_orientation": "down",
  "current_message": "measuring",
  "result": [0.020, 0.819, -9.750],
  "is_complete": false
}
```

**Fields:**
- `pending_orientations`: List of remaining orientations to measure (e.g., `["back", "front", "left", "right", "up"]`)
- `current_orientation`: Currently detected orientation being measured (e.g., `"down"`, `"left"`)
- `current_message`: Instruction type - `"hold_still"`, `"rest_detected"`, `"measuring"`, `"rotate"`, `"orientation_detected"`, `"already_completed"`, `"complete"`
- `progress`: Progress value (0.0 to 1.0)
- `result`: Measurement result array `[x, y, z]` when available
- `is_complete`: Boolean indicating completion

**Completion message:**
```json
{
  "type": "accelerometer_complete",
  "message": "Accelerometer calibration finished",
  "is_complete": true
}
```

#### Magnetometer Calibration

```json
{
  "type": "magnetometer_progress",
  "progress": 0.33,
  "status_text": "right orientation detected",
  "pending_orientations": ["back", "front", "left", "up"],
  "current_orientation": "right",
  "current_message": "orientation_detected",
  "is_complete": false
}
```

**Fields:**
- `pending_orientations`: List of remaining orientations to measure
- `current_orientation`: Currently detected orientation
- `current_message`: Instruction type - `"rotate"`, `"hold_still"`, `"rest_detected"`, `"motion_detected"`, `"orientation_detected"`, `"already_completed"`, `"complete"`
- `progress`: Progress value (0.0 to 1.0) that increments during rotation
- `is_complete`: Boolean indicating completion (true when progress >= 1.0)

**Completion message:**
```json
{
  "type": "magnetometer_complete",
  "message": "Magnetometer calibration finished",
  "is_complete": true
}
```

#### Gyroscope Calibration

```json
{
  "type": "gyroscope_progress",
  "progress": 0.5,
  "status_text": null,
  "current_message": "calibrating",
  "is_complete": false
}
```

**Fields:**
- `progress`: Progress value (0.0 to 1.0)
- `current_message`: `"calibrating"` during progress, `"complete"` when done
- `is_complete`: Boolean indicating completion (true when progress >= 1.0)

**Completion message:**
```json
{
  "type": "gyroscope_complete",
  "message": "Gyroscope calibration finished",
  "is_complete": true
}
```

#### Level Horizon Calibration

```json
{
  "type": "horizon_progress",
  "progress": 0.4,
  "status_text": null,
  "current_message": "calibrating",
  "is_complete": false
}
```

**Fields:**
- `progress`: Progress value (0.0 to 1.0)
- `current_message`: `"calibrating"` during progress, `"complete"` when done
- `is_complete`: Boolean indicating completion (true when progress >= 1.0)

**Completion message:**
```json
{
  "type": "horizon_complete",
  "message": "Level horizon calibration finished",
  "is_complete": true
}
```

#### Status Messages

General status messages are also emitted:
```json
{
  "type": "status",
  "message": "Starting accelerometer calibration..."
}
```

```json
{
  "type": "error",
  "message": "Calibration failed: <error details>"
}
```

```json
{
  "type": "success",
  "message": "All calibrations completed"
}
```

## Notes

- Ensure the vehicle is disarmed and stationary before running calibration or parameter uploads.
- The API and scripts require serial access; add your user to the `dialout` group if needed.
- Example parameter files and `extras.txt` live under the `configs/` directory.


