PX4 MAVSDK – C++ Programming 제 [1편] 라이브러리 개요 및 아키텍처
안녕하세요! 마케팅팀 에이든(Aiden)입니다.
오늘은 전 세계적으로 가장 널리 사용되는 오픈 소스 비행 제어 스택인 PX4 Autopilot과, 이를 외부 컴퓨터(Companion Computer)에서 제어하기 위한 핵심 도구인 MAVSDK C++ 라이브러리에 대해 다뤄보려 합니다.
첫 번째 시간인 오늘은 코드를 본격적으로 작성하기 전에 반드시 알아야 할 MAVSDK의 탄생 배경, 통신 프로토콜, 그리고 전반적인 시스템 아키텍처를 설명해 드리겠습니다.

MAVSDK의 탄생 배경과 MAVLink 프로토콜
과거의 드론은 조종사가 조종기를 들고 수동으로 조작하는 방식이 주를 이루었습니다. 하지만 오늘날의 드론은 단순한 비행체를 넘어, 카메라와 라이다(LiDAR) 등 다양한 센서를 탑재하고 인공지능(AI)을 통해 스스로 경로를 계획하고 장애물을 회피하는 ‘자율 비행 로봇(Autonomous Flying Robot)’으로 진화했습니다.
이러한 고도의 자율성을 구현하려면 드론 내부의 비행 제어기(FCU, Flight Control Unit)와 고성능 연산을 담당하는 외부 컴퓨팅 자원(Companion Computer) 간의 원활한 소통이 필수적입니다. 이 둘을 연결해 주는 다리 역할을 하는 것이 바로 MAVSDK(MAVLink SDK)입니다. 과거 ‘Dronecode SDK’로 불렸던 이 프로젝트는 드론 표준 통신 프로토콜인 MAVLink를 현대적인 C++ 객체 지향 언어로 추상화하여, 연구자들이 복잡한 통신 규격에 얽매이지 않고 자율 비행 알고리즘 자체에 집중할 수 있도록 돕습니다.

💡 MAVLink 프로토콜이란?
MAVSDK의 뼈대가 되는 MAVLink(Micro Air Vehicle Link)는 자원이 매우 제한된 마이크로 컨트롤러와 상위 컴퓨터 간의 통신을 위해 설계된 초경량 바이너리 직렬화 프로토콜입니다.
- 데이터 직렬화 메커니즘: MAVLink는 XML 기반의 메시지 정의 파일로부터 소스 코드를 자동 생성합니다. 텍스트 기반인 JSON이나 XML보다 대역폭 소모가 훨씬 적고 CPU 연산 부하를 최소화하면서도 높은 전송 속도를 유지합니다.
- MAVLink v2.0의 진화: 현재 MAVSDK가 지원하는 MAVLink v2.0은 최대 24비트의 확장된 메시지 ID 체계를 지원하여 수천 개의 메시지 유형을 정의할 수 있습니다. 또한 메시지 서명(Signing)을 통한 보안 기능이 추가되어 데이터 스푸핑 공격을 방지합니다.
2. PX4 Autopilot 내부 구조와 uORB 미들웨어
MAVSDK C++ 코드를 잘 작성하려면, 우리가 명령을 내릴 대상인 PX4 오토파일럿이 내부적으로 어떻게 움직이는지 이해해야 합니다. PX4는 크게 비행 스택(Flight Stack)과 미들웨어(Middleware)로 나뉩니다.
미들웨어 계층의 핵심은 uORB(Micro Object Request Broker)라는 비동기 메시지 버스입니다. uORB는 게시-구독(Publish-Subscribe) 모델을 기반으로 동작합니다.

예를 들어볼까요?
- 센서 드라이버가 가속도 데이터를 측정해 uORB 토픽(Topic)으로 발행(Publish)합니다.
- 위치 추정기(Estimator) 모듈은 이 데이터를 구독(Subscribe)하여 드론의 현재 위치와 속도를 계산합니다.
- PX4의 MAVLink 모듈 역시 이 내부 uORB 토픽을 구독하여 외부의 MAVSDK로 전송할 패킷을 만들고, 반대로 MAVSDK에서 명령이 들어오면 이를 uORB 토픽으로 발행하여 기체를 제어합니다.
즉, MAVSDK에서 takeoff()(이륙) 명령을 내리면, 이는 MAVLink 메시지로 변환되어 드론으로 전송되고, PX4 내부에서는 uORB를 거쳐 최종적으로 모터 제어기까지 도달하게 되는 유기적인 흐름을 가집니다.
3. MAVSDK C++ 아키텍처: 코어(Core)와 플러그인(Plugins)
연구 목적으로 사용되는 컴패니언 컴퓨터나 임베디드 보드(예: Raspberry Pi, NVIDIA Jetson)는 컴퓨팅 자원이 제한적일 때가 많습니다. MAVSDK C++ 라이브러리는 코어(Core)와 독립적인 플러그인(Plugins)으로 분리된 모듈형 아키텍처를 채택하여 성능과 확장성을 동시에 잡았습니다.
1) 코어(Core) 계층
코어는 드론과의 밑바닥 통신을 전담합니다. UDP, TCP, 시리얼 포트 등을 통해 드론이 주기적으로 보내는 하트비트(Heartbeat) 메시지를 분석하여 기체를 ‘발견(Discovery)’합니다. 발견된 드론은 System이라는 C++ 객체로 메모리에 생성됩니다.
2) 플러그인(Plugins) 기반의 기능 분리
드론을 제어하기 위한 각각의 기능들은 완전히 독립된 플러그인으로 제공됩니다. 특정 플러그인을 수정해도 다른 플러그인에는 영향을 주지 않으므로 매우 안전합니다.
- Action: 이륙, 착륙, 시동(Arm) 등 기본적인 비행 동작을 제어합니다.
- Telemetry: GPS 위치, 배터리 상태, 현재 비행 모드 등 센서 데이터를 실시간으로 구독합니다.
- Offboard: 속도, 자세, 위치 설정값(Setpoint)을 통해 컴퓨터 비전이나 AI 알고리즘 결과를 드론에 직접 반영하는 정밀 제어 모드입니다.
- Mission: 웨이포인트(경유지)를 설정하여 복잡한 자율 비행 경로를 업로드하고 실행합니다
4. 객체 지향 프로그래밍(OOP) 및 리소스 관리
MAVSDK C++은 현대적인 C++17 표준을 바탕으로 작성되었습니다. 객체 지향의 특징을 잘 살려 코드가 매우 직관적입니다.

가장 먼저 생성해야 하는 것은 프로그램의 라이프사이클을 관리하는 Mavsdk 객체입니다. 이후 연결된 드론을 나타내는 System 객체를 얻어오며, 모든 플러그인(Action, Telemetry 등)은 이 System 객체를 바탕으로 공유 포인터(std::shared_ptr) 형태로 안전하게 생성됩니다. 메인 프로그램이 종료되면 부모 객체가 파괴됨에 따라 관련된 모든 리소스가 메모리 누수 없이 자동으로 정리됩니다.
예제 1)
#include <mavsdk/mavsdk.h>
#include <mavsdk/plugins/action/action.h>
#include <iostream>
using namespace mavsdk;
int main() {
// 1. 코어 엔진 초기화
Mavsdk mavsdk{Mavsdk::Configuration{ComponentType::GroundStation}};
// 2. 시뮬레이터(SITL) UDP 포트로 연결
ConnectionResult connection_result = mavsdk.add_any_connection("udpin://0.0.0.0:14540");
if (connection_result != ConnectionResult::Success) {
std::cerr << "연결 실패: " << connection_result << '\n';
return 1;
}
// 3. 드론 시스템 발견 대기
auto system = mavsdk.first_autopilot(3.0);
if (!system) {
std::cerr << "시간 초과: 드론을 찾을 수 없습니다.\n";
return 1;
}
// 4. Action 플러그인 인스턴스화
auto action = Action{system.value()};
std::cout << "드론 시스템에 성공적으로 연결되었습니다!\n";
return 0;
}🚨 예외(Exception) 처리 대신 결과(Result) 반환
로보틱스나 실시간 임베디드 시스템에서 try-catch 같은 예외 처리는 실행 시간을 예측하기 어렵게 만들 수 있습니다. 따라서 MAVSDK는 예외를 발생시키지 않습니다. 대신 모든 함수 호출은 Action::Result나 Telemetry::Result와 같은 열거형(Enum) 값을 반환합니다. 개발자는 이 반환값을 확인하여 명령이 성공했는지, 현재 드론 상태 때문에 명령이 거부되었는지 명확하게 판단할 수 있습니다.
5. 실시간 제어를 위한 비동기(Asynchronous) 모델
자율 비행 알고리즘을 연구하다 보면, 데이터를 받아오느라 프로그램이 멈춰있는 블로킹(Blocking) 현상이 발생해선 안 됩니다. MAVSDK는 고성능 실시간 처리를 위해 이벤트 기반의 비동기 아키텍처를 제공합니다.
콜백(Callback) 스레드와 주의점
드론으로부터 최신 원격 측정(Telemetry) 데이터가 도착하면, MAVSDK 내부의 백그라운드 스레드가 우리가 등록한 콜백 함수를 즉시 호출해 줍니다.
예제 2)
#include <mavsdk/plugins/telemetry/telemetry.h>
// telemetry 플러그인 객체가 있다고 가정
telemetry.subscribe_position([](Telemetry::Position position) {
std::cout << "현재 고도: " << position.relative_altitude_m << " m\n";
});
⚠️ 연구원들을 위한 실무 팁!
모든 사용자 콜백은 MAVSDK의 전용 콜백 스레드 하나에서 순차적으로 실행됩니다. 따라서 이 콜백 함수 내부에서 컴퓨터 비전 연산(OpenCV), 딥러닝 추론, 파일 시스템 저장 등 시간이 오래 걸리는(무거운) 작업을 수행해서는 절대 안 됩니다.
콜백 스레드가 묶여버리면 후속 센서 데이터 업데이트가 지연되어 전체 시스템의 반응성(Latency)이 나빠지고, 오프보드(Offboard) 제어 시 Failsafe가 발동해 드론이 추락할 위험도 있습니다.
무거운 알고리즘 연산은 std::thread를 활용해 별도의 작업(Worker) 스레드에서 처리하고, 콜백 함수는 최신 데이터를 전역 변수에 가볍게 갱신하는 용도로만 사용하는 것이 좋습니다.
이번 1편에서는 자율 비행 로봇 시스템에서 MAVSDK C++이 왜 필요한지, MAVLink와 PX4는 어떤 구조로 통신하는지, 그리고 코어-플러그인 형태의 객체 지향 및 비동기 설계 철학에 대해 살펴보았습니다.
단순한 코드 작성법을 넘어, “이 라이브러리가 왜 이렇게 설계되었는가”를 이해하는 것은 비행 알고리즘에 있어서 매우 중요한 토대가 됩니다.
다음 2편: MAVSDK 활용을 위한 C++ 핵심 문법에서는 C++에 익숙하지 않은 분들도 쉽게 따라오실 수 있도록, MAVSDK 프로그래밍에 꼭 필요한 STL, 참조(&), 람다 함수 등의 문법을 예제와 함께 자세히 다루도록 하겠습니다.
YouTube 강좌

작성자: 에이든(Aiden), 쿼드(QUAD) 드론연구소 마케팅팀
기고일: 2026.03.09
