The Ultimate Guide to MAVSDK-Python Programming [Part 2]: Setting up the MAVSDK-Python Development Environment
Hello again, university students and researchers dedicating your time to autonomous flight research and drone application development! In Part 1, we briefly explored the concepts of MAVSDK and the basic prerequisites for programming.
Last time, we installed the package with a simple pip3 install mavsdk command and made a virtual drone take off. However, in a real-world research environment, you will often face much more complex situations. For instance, you might need to set up the environment on an ARM-based embedded board like a Raspberry Pi or Jetson Nano, or you may want to execute your code on a Windows laptop to remotely control a simulator running on a powerful Linux server (Remote Control).
Therefore, in this [Part 2: Setting up the MAVSDK-Python Development Environment], we will go far beyond a simple package installation. We will guide you through the professional process of cloning and building the source code yourself, and configuring the ‘MAVSDK Server’, which is the core component for remote communication.
Let’s dive in and build a robust research environment!
1. Building a Source-Code-Based Development Environment for MAVSDK-Python
If you are a researcher who needs to analyze the internal code or add custom features rather than just using the pre-compiled library, we highly recommend downloading the source code directly from the GitHub repository and building it.
Open your terminal and follow these step-by-step commands carefully.
① Clone the Git Repository and Install Required Packages
First, download the MAVSDK-Python code and install the dependency packages. We will also set up the Protocol Buffers (protobuf) plugin required for gRPC communication.
# Clone the MAVSDK-Python Git repository (including submodules)
cd ~
git clone https://github.com/mavlink/MAVSDK-Python --recursive
cd MAVSDK-Python
# Install protocol buffer plugin prerequisites
cd proto/pb_plugins
pip3 install -r requirements.txt
cd ../..
# Install Python packages required for development and execution
pip3 install -r requirements.txt -r requirements-dev.txt
② Generate gRPC Code and Configure Architecture
MAVSDK internally uses gRPC communication. To enable this, you need to generate Python code from the .proto files.
# Run the code generation script
./other/tools/run_protoc.sh
💡 Tip for Researchers (Embedded Board Users): If you are setting up your environment on an ARM embedded computer like a Jetson Nano or Raspberry Pi, you must explicitly declare the environment variable. Standard PC (x86_64) users can skip this step.
# For 64-bit ARM OS (e.g., Ubuntu 20.04 64bit)
export MAVSDK_SERVER_ARCH=aarch64
# For a 32-bit ARM OS, use 'armv7l' instead.
③ Build the Library and Verify Installation
Finally, build the Python library and install it on your system. Using the -e (editable mode) flag during installation is highly advantageous for R&D, as any modifications you make to the source code will be reflected immediately.
python3 setup.py build
pip3 install -e .
# Verify the version and information to ensure successful installation
pip3 show mavsdk
2. Understanding the Communication Core: ‘mavsdk_server’
Now that the environment is set up, you need to understand the ‘inner workings’ of how your code communicates with the drone.
MAVSDK-Python is not structured in a way where your Python script directly communicates with the drone (PX4) via UDP. Instead, there is always a C++-based backend program called mavsdk_server sitting in the middle.
- Your Python script communicates internally with the
mavsdk_serverusing gRPC (Default Port: 50051). - The mavsdk_server receives these commands, translates them into MAVLink messages, and communicates with the drone (PX4 simulator or real vehicle) using UDP (Default Port: 14540).

Think back to the sample code from Part 1: await drone.connect(system_address="udp://:14540"). When you instantiate the System() class in your Python code without passing any parameters, the Python library automatically runs mavsdk_server -p 50051 in the background for you. Thanks to this automated process, we were able to program comfortably without worrying about spinning up the server manually.
3. Building the MAVSDK Server Directly for Remote Communication
However, during research, the computer running the Python script and the computer running the simulator (SITL) are often different. For instance, you might want to run a heavy 3D simulator like ROS/Gazebo on a high-performance Linux desktop, while executing your autonomous flight control algorithms from your Windows laptop.
In such cases, you cannot rely on Python to automatically spin up the server on the remote machine. You must build and run an independent MAVSDK Server directly on your Linux environment. The process is a bit lengthy, but once established, it offers immense freedom for remote control research.
① Install Required Dependencies
Since the server is written in C++, various compilers and libraries are required.
sudo apt update && sudo apt upgrade -y
sudo apt install -y cmake ninja-build g++ git \
protobuf-compiler libprotobuf-dev \
libgrpc++-dev libgrpc-dev \
libssl-dev curl unzip
② Download MAVSDK C++ Source Code and Configure CMake
Here, we are downloading the core MAVSDK C++ repository, not the Python wrapper. By default, the server building feature is disabled, so you must add the -DBUILD_MAVSDK_SERVER=ON option during CMake configuration.
git clone https://github.com/mavlink/MAVSDK.git --recursive
cd MAVSDK
# Configure CMake (Enable mavsdk_server build)
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DBUILD_MAVSDK_SERVER=ON -Bbuild/default -S.
③ Parallel Build and Moving the Executable
To shorten the compilation time, we will use multiple CPU cores (-j8). Once the build is complete, we will copy the executable file to /usr/local/bin so it can be run from anywhere in the terminal.
# Build in parallel using 8 CPU cores
cmake --build build/default -j8
# Copy to the system directory
sudo cp ~/MAVSDK/build/default/src/mavsdk_server/src/mavsdk_server /usr/local/bin/
Now, if you type mavsdk_server -p 50051 in the terminal, you will see the server running standalone!.
4. Auto-starting MAVSDK Server for Convenience (systemd Configuration)
Manually opening a terminal to turn on the server every time you test your drone is tedious. By utilizing Linux’s systemd service, you can configure it to run automatically in the background every time the computer boots. This step is optional but highly recommended for a seamless research environment.
In your terminal, type sudo nano /etc/systemd/system/mavsdk_server.service to open a new file, and paste the content below. (You can change User=$USER to your current Linux account username).
[Unit]
Description=MAVSDK Server
After=network.target
[Service]
ExecStart=/usr/local/bin/mavsdk_server -p 50051
Restart=always
User=$USER
[Install]
WantedBy=multi-user.target
After saving (Ctrl+O, Enter) and exiting the editor (Ctrl+X), register and start the service with the following commands:
sudo systemctl daemon-reload
sudo systemctl enable mavsdk_server
sudo systemctl start mavsdk_server
Now, your Linux machine is ready to accept external Python code 24/7!.
5. Testing the Python Connection from a Remote Environment
Now that the server is successfully built, let’s write some Python code on your remote computer (e.g., your laptop) to control the drone on the Linux PC.
The most critical difference when writing this code is how you initialize the System() class. Instead of letting Python start a local server, you must explicitly specify the IP address of the Linux server we just built so that it connects remotely.
import asyncio
from mavsdk import System
async def run():
# 💡 Key Point: Specify the IP and gRPC port of the remote MAVSDK Server.
# Replace the example IP "172.21.77.220" with your actual Linux PC's IP.
drone = System(mavsdk_server_address="172.21.77.220", port=50051)
# Attempt to connect to the server. (It skips auto-starting the embedded server)
await drone.connect()
print("Connecting to the drone via remote MAVSDK Server...")
# Check the drone's communication state
async for state in drone.core.connection_state():
if state.is_connected:
print("-- Successfully connected to the remote drone!")
break
# Since this is a simple connection test, we exit here
print("-- Ending the test.")
if __name__ == "__main__":
asyncio.run(run())
If you run the script and see the “– Successfully connected to the remote drone!” message, you have successfully completed a perfect architecture that allows you to freely control the drone across Windows/Mac/Linux systems without geographical constraints!.
Wrapping Up
In Part 2, we covered fairly deep topics essential for professional R&D, ranging from building the MAVSDK-Python environment from the source code to understanding the underlying mechanics of mavsdk_server and configuring remote communication.
Although this environment setup process might seem lengthy and you might have encountered a few errors, it is incredibly valuable time spent. You now have a solid understanding of the autonomous drone’s communication architecture (gRPC and UDP) and the ability to handle networks proficiently.
Now that the perfect stage (development environment) is set, it is time for the real performance. In our next post, [Part 3: Complete Understanding of Python ‘asyncio’ and Exploring Core Classes], we will break down ‘asyncio’, the core syntax of MAVSDK programming, and explore various control libraries (like Telemetry and Action) in an easy-to-understand manner.
If you have any questions or ran into any errors, please feel free to leave a comment. See you in the next part. Thank you!

Author: maponarooo, CEO of QUAD Drone Lab
Date: March 3, 2026
