This comprehensive guide covers the development workflow, coding standards, testing practices, and deployment procedures for the FGCS project.
-
Node.js (version >= 20.10.0)
- Download from nodejs.org
- Verify:
node --version
-
Yarn (package manager)
- Install:
npm install --global yarn - Verify:
yarn --version
- Install:
-
Python 3.11.9
- Download from python.org
- Verify:
python --version
-
Docker (for SITL simulator)
- Download from docker.com
- Verify:
docker --version
-
Clone the repository:
git clone https://github.com/Avis-Drone-Labs/FGCS.git cd FGCS -
Install pre-commit hooks:
pip install pre-commit pre-commit install
-
Set up Python virtual environment:
cd radio python -m venv venv # Windows venv\Scripts\activate # Linux/Mac source venv/bin/activate pip install -r requirements.txt
-
Install Node.js dependencies:
cd ../gcs yarn install -
Configure environment variables:
cp .env_sample .env
-
Add Maptiler API key: Edit the
.envfile to include your Maptiler API key, it can be generated on maptilers website. -
Generate param definitions:
cd data python generate_param_definitions.pyThis now fetches ArduPlane and ArduCopter definitions for all available 4.x versions (from 4.0 up to latest 4.x) and writes versioned files plus a
gen_apm_params_versions.jsonmanifest.
Windows:
# First time setup
./run.bat /path/to/venv update
# Subsequent runs
./run.bat /path/to/venvLinux/Mac:
./run.bashTerminal 1 - Backend:
cd radio
source venv/bin/activate # or venv\Scripts\activate on Windows
python app.pyTerminal 2 - Frontend:
cd gcs
yarn devTerminal 3 - SITL Simulator (Optional):
docker run -it --rm -p 5760:5760 -v fgcs_ardupilot_cache:/ardupilot_cache kushmakkapati/ardupilot_sitl-
Pull the SITL image:
docker pull kushmakkapati/ardupilot_sitl
-
Start basic simulator (ArduCopter):
docker run -it --rm -p 5760:5760 -v fgcs_ardupilot_cache:/ardupilot_cache kushmakkapati/ardupilot_sitl
-
Connect FGCS to simulator:
- Backend connection string:
tcp:127.0.0.1:5760 - This exposes the MAVLink connection on port 5760
- Backend connection string:
# ArduPlane
docker run -it --rm -p 5760:5760 -v fgcs_ardupilot_cache:/ardupilot_cache kushmakkapati/ardupilot_sitl VEHICLE=ArduPlane
# ArduCopter
docker run -it --rm -p 5760:5760 -v fgcs_ardupilot_cache:/ardupilot_cache kushmakkapati/ardupilot_sitl VEHICLE=ArduCopter# Pinned release (recommended format)
docker run -it --rm -p 5760:5760 -v fgcs_ardupilot_cache:/ardupilot_cache kushmakkapati/ardupilot_sitl VEHICLE=ArduCopter FIRMWARE_VERSION=4.6.3
# Plane pinned release
docker run -it --rm -p 5760:5760 -v fgcs_ardupilot_cache:/ardupilot_cache kushmakkapati/ardupilot_sitl VEHICLE=ArduPlane FIRMWARE_VERSION=4.6.3
# Dynamic selectors
docker run -it --rm -p 5760:5760 -v fgcs_ardupilot_cache:/ardupilot_cache kushmakkapati/ardupilot_sitl VEHICLE=ArduCopter FIRMWARE_VERSION=latest
docker run -it --rm -p 5760:5760 -v fgcs_ardupilot_cache:/ardupilot_cache kushmakkapati/ardupilot_sitl VEHICLE=ArduCopter FIRMWARE_VERSION=stable
docker run -it --rm -p 5760:5760 -v fgcs_ardupilot_cache:/ardupilot_cache kushmakkapati/ardupilot_sitl VEHICLE=ArduCopter FIRMWARE_VERSION=betaAccepted firmware selectors:
latest,stable,beta4.x.y(resolved toCopter-4.x.yfor ArduCopter andPlane-4.x.yfor ArduPlane)Copter-4.x.y/Plane-4.x.yArduCopter-stable/ArduCopter-beta/ArduPlane-stable/ArduPlane-beta
Note: pass VEHICLE=... and FIRMWARE_VERSION=... as trailing command arguments (as shown above), not as -e environment variables.
Using -v fgcs_ardupilot_cache:/ardupilot_cache is recommended so pinned versions are reused between runs.
When you use FIRMWARE_VERSION=latest (same idea for stable and beta), the launcher treats it as a dynamic channel and resolves the current upstream ref each run.
Example timeline:
- Day 1: run with
latest. The container checks out the current upstream ref and builds SITL if needed. - Day 2: upstream
latestmoves to a newer commit/tag. - Day 3: run again with
latest. The launcher resolves the new ref, checks it out, detects commit change, and rebuilds so the binary matches the checked-out source.
This prevents stale binaries from being reused after a ref change.
Important cache note:
fgcs_ardupilot_cacheis primarily used for pinned versions (4.x.y) under/ardupilot_cache.- Dynamic channels use the default worktree (
/ardupilot). With--rm, container filesystem state is ephemeral between runs, so dynamic channels may refetch/rebuild more often.
docker run -it --rm -p 5760:5760 kushmakkapati/ardupilot_sitl \
VEHICLE=ArduCopter LAT=-35.363261 LON=149.165230 ALT=584 DIR=353docker run -it --rm -p 5760:5760 -p 5763:5763 kushmakkapati/ardupilot_sitl-
Create files in your working directory:
custom_params.parm- Custom parameter filemission.txt- Mission waypoints file
-
Mount files into container:
docker run -it --rm -p 5760:5760 -p 5763:5763 \ -v .:/sitl_setup/custom kushmakkapati/ardupilot_sitl VEHICLE=ArduPlane
We use Ruff for Python code formatting and linting:
# Format code
ruff format .
# Check for linting issues
ruff check .
# Fix auto-fixable issues
ruff check --fix .We use Prettier and ESLint:
cd gcs
# Format code
yarn format
# Check linting
yarn lint
# Fix auto-fixable issues
yarn lint:fixBackend tests use pytest with MAVLink simulation:
cd radio
# Run all tests
pytest
# Run with verbose output
pytest -v
# Stop on first failure
pytest -x
# Run specific test file
pytest tests/test_params.py
# Run specific test
pytest -k "test_param_set"
# Generate coverage report
pytest --cov=app --cov-report=html tests/Frontend tests use Playwright to test the electron app:
To run the tests locally you can use:
yarn testThis will build the application locally and then run the playwright tests, this is required because the typescript files need to be compiled. Everytime you make any changes to any of the frontend you must rebuild.
If you want to re-run the tests without re-building:
yarn test:nobuildDesktop release artifacts are built automatically when a version tag is pushed.
Push a tag in semver format prefixed with v:
git tag v0.2.8-alpha.1
git push origin v0.2.8-alpha.1The workflow creates or updates a draft GitHub Release and uploads installers.
The workflow enforces two checks before building:
RELEASE_ALLOWED_OWNERmust match the repository owner.RELEASE_ALLOWED_ACTORmust match the GitHub username that pushed the tag.
- Windows x64:
FGCS-Windows-<version>-Setup.exe - macOS x64:
FGCS-Mac-<version>-Installer-x64.dmg - macOS arm64:
FGCS-Mac-<version>-Installer-arm64.dmg
Releases are uploaded as drafts. After validating artifacts, publish the draft release in GitHub.
If a tagged release fails:
- Delete the tag locally and remotely.
- Fix the issue.
- Recreate and push the tag.
git tag -d v0.2.8-alpha.1
git push origin :refs/tags/v0.2.8-alpha.1