MAVLink Protocol Library for Python
pymavlink is the official Python MAVLink (Micro Air Vehicle Link) protocol implementation. It provides tools for parsing, generating, and communicating MAVLink messages, enabling Python applications to interact with drones, autopilots, and ground control stations. The library is actively maintained by the ArduPilot community and is currently at version 2.4.49, with frequent updates to add features and fix bugs.
Warnings
- breaking MAVLink protocol version 1 (MAVLink1) and version 2 (MAVLink2) are incompatible. MAVLink2 introduces message signing, longer message names, and expanded component IDs. pymavlink defaults to MAVLink2, but if connecting to an older MAVLink1 device, you must explicitly specify the protocol version.
- gotcha MAVLink message definitions are dialect-specific (e.g., 'ardupilotmega', 'common', 'minimal'). Messages or fields available in one dialect might not exist or have different structures in another. Using the wrong dialect can lead to `AttributeError` when accessing fields or `KeyError` if messages are missing.
- deprecated Python 2 support has been officially dropped. While older pymavlink versions might still have some Python 2 compatibility, active development, new features, and bug fixes are exclusively for Python 3. Attempting to use recent versions with Python 2 may result in unexpected errors or missing functionality.
- gotcha Using `master.recv_match(blocking=True)` can halt your application indefinitely if no message matches the criteria, especially in single-threaded contexts. This can lead to unresponsive interfaces or deadlocks.
Install
-
pip install pymavlink
Imports
- mavutil
from pymavlink import mavutil
- mavlink
from pymavlink import mavlink
- dialects
from pymavlink.dialects import ardupilotmega as m
Quickstart
import os
import time
from pymavlink import mavutil
# Define the connection string for your MAVLink device
# Examples: 'udp:127.0.0.1:14550' (for SITL), 'serial:/dev/ttyACM0:115200' (for a USB serial device)
# You can set the MAVLINK_CONNECTION_STRING environment variable or change this directly.
connection_string = os.environ.get('MAVLINK_CONNECTION_STRING', 'udp:127.0.0.1:14550')
print(f"Attempting to connect to MAVLink device via: {connection_string}...")
try:
# Establish a MAVLink connection. wait_ready=True blocks until the first HEARTBEAT is received.
master = mavutil.mavlink_connection(connection_string, baud=115200, wait_ready=True)
print(f"Connection established! System ID: {master.target_system}, Component ID: {master.target_component}")
# Request an ATTITUDE data stream at 1Hz
# MAV_DATA_STREAM_ALL for all streams, or specific ones like MAV_DATA_STREAM_EXTRA1 for ATTITUDE
# The last '1' is the rate in Hz, '0' would stop the stream.
master.mav.request_data_stream_send(
master.target_system, master.target_component,
mavutil.mavlink.MAV_DATA_STREAM_ALL, 1, 1
)
print("Requested data stream for all messages at 1Hz.")
print("Listening for HEARTBEAT and ATTITUDE messages for 10 seconds...")
start_time = time.time()
while (time.time() - start_time) < 10: # Listen for 10 seconds
# Non-blocking receive for specific message types
msg = master.recv_match(type=['HEARTBEAT', 'ATTITUDE'], blocking=False, timeout=0.1)
if msg:
print(f"Received {msg.get_type()} - {msg}")
if msg.get_type() == 'ATTITUDE':
print(f" Roll: {msg.roll:.2f} deg, Pitch: {msg.pitch:.2f} deg, Yaw: {msg.yaw:.2f} deg")
time.sleep(0.01) # Small delay to prevent busy-waiting
print("Finished listening for messages.")
except Exception as e:
print(f"Error during MAVLink communication: {e}")