Your first Python script that talks to a simulated drone

8 min read
Laptop with abstract code lines sending a dashed arrow to a generic quadcopter lifting off on a blue grid

In this post

Here’s a surprising fact: the autopilot software inside many real drones can run on your laptop, with no drone attached at all. So if you know a little Python and have always wondered how code makes a drone lift off, you can try it today. Nothing can crash into a wall, because the wall isn’t real. New to Python for drones? Here’s why Python is a good first language. This post shows how to write a first script that connects to a simulated drone, reads its altitude and takes off.

Key takeaways

  • You don’t need a drone to start: ArduPilot’s SITL runs a real autopilot on your laptop.
  • Your Python script talks to the autopilot by sending MAVLink messages, and pymavlink gives you direct access to them.
  • A first script takes six steps: connect, wait for a heartbeat, read altitude, switch to GUIDED, arm and take off.

How does Python code actually talk to a drone?

Think of a restaurant. You (the script) don’t cook. You hand a written order to the kitchen (the autopilot), and the kitchen does the hard work of keeping the drone level and steady. The order slips are written in a shared format called MAVLink. Your script writes the slips, and the autopilot reads them and acts. It also sends slips back, such as “I’m alive” and “I’m 3 metres up”.

Laptop and quadcopter exchanging message envelopes along two arrows, commands going out and telemetry coming back
Your script sends commands as messages, and the autopilot replies with messages about its own state.

MAVLink, pymavlink and SITL in one line each

MAVLink: a small messaging protocol that drones, ground stations and scripts use to talk to each other.

pymavlink: a Python library from the ArduPilot project for sending and receiving MAVLink messages.

SITL (software in the loop): the real ArduPilot flight software running on your computer, with the drone and its sensors simulated.

Before you code: what should the drone do?

It helps to see “arm and take off” before you write it. You can fly a takeoff and hover by keyboard in the free Aasma browser simulator at sim.aasmaaerospace.in, with no install needed. Once you’ve felt the climb and the hover, the script’s steps make more sense. One thing to be clear on: that browser simulator is separate from SITL. Your Python script won’t connect to it. It’s just a quick way to build a picture in your head.

How do you set up a simulated drone in SITL?

SITL gives you the same ArduPilot code that flies real copters, fed by a simulated world. Install steps change over time, so follow the SITL setup guide in the official ArduPilot docs, written and maintained by the ArduPilot community. Once it’s set up, you start a simulated copter with a command like sim_vehicle.py -v ArduCopter. This also starts MAVProxy, a small ground station that forwards MAVLink to a network address. In a typical setup the script can listen on UDP port 14550 (a numbered network channel) on your own machine. Check the docs for the address your setup uses.

Optional: watch it on a map

QGroundControl or, on Windows, Mission Planner can connect to the same simulation. Then you see the drone climb on a map while your script runs. If the ground station and your script both want port 14550, give your script its own output port (the SITL docs show how).

Hand-drawn laptop showing three side-by-side windows: a console, a code editor and a map with a small drone icon
One laptop can run the simulator, your script and a ground station map at the same time.

Your first pymavlink script, step by step

Install the library with pip install pymavlink, start SITL, then save this as first_flight.py:

from pymavlink import mavutil

# Steps 1 and 2: connect and wait for a heartbeat
master = mavutil.mavlink_connection('udpin:127.0.0.1:14550')
master.wait_heartbeat()
print("Connected to system", master.target_system)

# Step 3: read altitude (relative_alt is in millimetres)
msg = master.recv_match(type='GLOBAL_POSITION_INT', blocking=True)
print("Altitude:", msg.relative_alt / 1000, "m")

# Step 4: switch to GUIDED mode
guided = master.mode_mapping()['GUIDED']
master.mav.set_mode_send(master.target_system, mavutil.mavlink.MAV_MODE_FLAG_CUSTOM_MODE_ENABLED, guided)

# Step 5: arm the motors
master.mav.command_long_send(master.target_system, master.target_component, mavutil.mavlink.MAV_CMD_COMPONENT_ARM_DISARM, 0, 1, 0, 0, 0, 0, 0, 0)
master.motors_armed_wait()
print("Armed")

# Step 6: take off to 5 metres
master.mav.command_long_send(master.target_system, master.target_component, mavutil.mavlink.MAV_CMD_NAV_TAKEOFF, 0, 0, 0, 0, 0, 0, 0, 5)

# Watch the altitude rise
while True:
    msg = master.recv_match(type='GLOBAL_POSITION_INT', blocking=True)
    alt = msg.relative_alt / 1000
    print("Altitude:", round(alt, 1), "m")
    if alt >= 4.7:
        break

# Then land
land = master.mode_mapping()['LAND']
master.mav.set_mode_send(master.target_system, mavutil.mavlink.MAV_MODE_FLAG_CUSTOM_MODE_ENABLED, land)
print("Landing")

Steps 1 and 2: connect and wait for a heartbeat

The first line opens a link to the address SITL is sending to. A heartbeat is a short message the autopilot sends about once a second to say “I’m here”. wait_heartbeat() pauses until one arrives, which also tells pymavlink which system to talk to.

Step 3: read altitude

The autopilot keeps sending telemetry, which is live data about itself. The GLOBAL_POSITION_INT message includes relative_alt, the height above the take-off point in millimetres, so the script divides by 1,000. On the ground it should print roughly zero.

Steps 4 and 5: switch to GUIDED and arm

GUIDED is the ArduPilot Copter flight mode that accepts commands from outside, like your script. In other modes, the takeoff command is ignored. The Copter docs explain each mode. Arming switches the motors on. Before it agrees, ArduPilot runs pre-arm checks, such as “do I have a position fix?” If a check fails, it refuses: that’s a safety feature, not a bug.

Step 6: take off, then land

MAV_CMD_NAV_TAKEOFF carries the target height in its last parameter, here 5 metres. The loop prints the altitude as it climbs. Once the drone is near 5 metres, the script switches to LAND mode and the drone comes down on its own.

If it doesn’t work: common first-run problems

Stuck at “waiting for heartbeat”?

Check that SITL is still running and that the address and port in your script match where SITL sends data. A ground station holding the same port is another common cause.

Arming refused?

The simulated drone may still be getting its GPS fix after start-up. Give it a minute, and read the console messages: they say which pre-arm check failed.

Takeoff ignored?

The drone is either not in GUIDED mode or not armed. Also, ArduPilot disarms on its own if you arm and then wait too long, so send the takeoff right after arming. Moving to a real drone later? That brings its own setup steps, so read about first drone setup mistakes before you start.

Using PX4 instead? Try MAVSDK-Python

If your drone or simulator runs PX4 rather than ArduPilot, look at MAVSDK-Python. It’s a higher-level Python API for PX4, so you call functions rather than build messages by hand. A follow-up post in this series will walk through a first MAVSDK script. You’ll also see DroneKit-Python in many tutorials. It’s an older API, so treat it as background reading rather than your starting point.

What to try next

Small changes teach a lot. Try these:

  • Change the takeoff height to 10 metres.
  • Print battery data as well as altitude.
  • Make the drone hover for ten seconds before it lands.

For a bigger picture, follow the free drone programming learning path. If you’d like to code a small board directly, see programming an ESP32 drone.

FAQ

Can I program a drone with Python without buying one?

Yes. ArduPilot SITL runs the autopilot on your computer, so you can write, break and fix scripts with nothing at risk. The same pymavlink approach can later talk to a real autopilot.

Which Python library should I use to program a drone?

pymavlink is a good fit if you want to learn MAVLink directly with ArduPilot. MAVSDK-Python is a higher-level API aimed at PX4. DroneKit-Python is older and still turns up in many tutorials.

Is there a free course for drone programming with Python?

Start with Aasma’s free drone programming learning path. Pair it with the official ArduPilot Copter docs and the pymavlink repository, which are the real references behind this script.

Fly it before you code it

Want to feel what your script will do before you run it? Fly a takeoff and hover in the free Aasma browser simulator at sim.aasmaaerospace.in, with no install needed. When you’re ready for real hardware, have a look at Aasma’s drone learning kits. Build it. Fly it. Code it. Your script just received a heartbeat and sent a takeoff command. But what’s actually inside those messages, and which others could you send?

Try it in the simulator

Free, in your browser. Nothing to install.

Share with a friend who builds drones

Fly a drone in your browser

Free, six missions, nothing to install.

Teaching drones at your college?

We run hands-on workshops in your lab, with our drones and this simulator.

Keep reading

Scroll to Top