Fly a drone¶
Take off, fly a square, and land with the same code on any supported platform. You pick a backend (a firmware plus a transport), start its driver (or a simulator), set a pose source, and run a mission. Only the factory key and its config change between platforms; the flight calls stay identical.
Pick your backend in the tab below and it stays selected through install, driver, and mission code. New to the workspace? Do the Installation first.
1. Install the backend¶
Install control, then add the driver your vehicle uses:
No extra install: pymavlink ships with the core SDK. make drone-mavros adds the
geoid data used for GPS altitude.
No extra install: pymavlink ships with the core SDK. make drone-mavros adds the
geoid data used for GPS altitude.
2. Set the pose source¶
For ArduPilot and PX4 the environment selects the pose source on the config:
| Environment | Pose source | Config argument |
|---|---|---|
| Outdoor | GPS | pose_source=PoseSource.GPS |
| Indoor (GPS-denied) | Vision (VSLAM) | pose_source=PoseSource.VISION |
Indoor flight
A vision-pose feed into the FCU's EKF is required indoors; see Localization. Bebop and Crazyflie fly indoors without GPS and ignore this setting.
3. Start the driver¶
Start the driver or bridge your mission connects to before running it (examples default
to start_driver=False). Connection overrides go through env vars (FCU_URL, DEV, BAUD,
IP).
Outdoor needs no bridge; the mission opens the link itself. Indoor starts the vision-pose bridge:
Outdoor needs no bridge; the mission opens the link itself. Indoor starts the vision-pose bridge:
No hardware yet? Fly in simulation
make sim-install FIRMWARE=ardupilot # one-time (use FIRMWARE=px4 for PX4)
make sim-start # terminal 1
make sim-bridge # terminal 2
PROTOCOL=mavlink / PROTOCOL=dds on sim-bridge. Full
matrix: Simulation.
4. Write the mission¶
Build the drone with your backend's factory key and config. The flight calls after it are the same for every backend.
Fly a 2 m square, then land:
drone.takeoff(altitude=2.0)
drone.move_to(x=2.0, y=0.0, z=0.0)
drone.move_to(x=2.0, y=2.0, z=0.0)
drone.move_to(x=0.0, y=2.0, z=0.0)
drone.move_to(x=0.0, y=0.0, z=0.0)
drone.land()
nectar.shutdown()
The bundled examples fly the same box on any backend, flown by the PID navigator where the
backend supports it. Each tab is the exact command for that platform (outdoor GPS shown; for
indoor flight swap --mode indoor on navigation.py or --env indoor on basic.py to the
vision pose source):
nectar-activate
python3 nectar/nectar/examples/control/navigation.py \
--drone mavlink --connection tcp:127.0.0.1:5762 \
--mode outdoor --strategy pid \
--test rectangle --altitude 2.0 --distance 2.0 --precision 0.15
On hardware, pass your serial link instead, e.g. --connection /dev/ttyUSB0.
navigation.py does not cover this backend; the position box in basic.py does:
Expected result
The drone arms, climbs to the target altitude, flies a 2 m box (0.6 m for Crazyflie) with 0.15 m arrival precision, then lands and disarms.
Go deeper¶
- Control reference: the factory, the
Droneprotocol, capabilities, and the full backend matrix. - Vehicle core · Transports · PID tuning · Obstacles · Localization.
- Control examples: navigation suite, interactive REPL, servo test.