MAVSDK-Python 프로그래밍 완벽 가이드 [제6편]: MAVSDK-Python 기본 샘플 프로그램 분석
안녕하세요! 자율비행 로봇과 드론 제어 알고리즘 연구에 매진하고 계신 대학생 및 연구원 여러분. MAVSDK-Python 연재 블로그의 여섯 번째 시간에 오신 것을 환영합니다.
지난 5편에서는 프로그래밍의 가장 큰 허들이었던 파이썬의 비동기 프로그래밍(asyncio) 문법을 드론 제어의 관점에서 완벽하게 이해하는 시간을 가졌습니다. 이제 우리는 드론에게 명령을 내릴 수 있는 어휘(클래스)와, 대화하는 방식(비동기 처리)을 모두 터득했습니다.
새로운 언어를 배울 때 가장 빨리 실력을 키우는 방법은 원어민이 쓴 훌륭한 예문을 분석해 보는 것이겠죠? MAVSDK-Python 프로그래밍 역시 가장 빨리 익히는 방법은 제공되는 공식 샘플 프로그램들을 분석하고 직접 실행해 보는 것입니다.
이번 **[제6편: MAVSDK-Python 기본 샘플 프로그램 분석]**에서는 자율비행 연구의 기초가 되는 핵심 샘플 코드들을 하나씩 뜯어보며, 지금까지 배운 이론이 실제 코드에서 어떻게 구현되는지 자세히 친절하게 설명해 드리겠습니다.
1. 샘플 프로그램 준비 및 실행 방법
코드를 분석하기 전, 먼저 샘플 프로그램들을 여러분의 PC 또는 교육용 VM에 다운로드해야 합니다. 터미널을 열고 아래의 명령어를 입력하여 Github 저장소에서 튜토리얼 코드를 복제(Clone)해 옵니다.
cd ~
git clone https://github.com/maponarooo/mavsdk-python-tutorials
cd mavsdk-python-tutorials
다운로드가 완료되었다면, SITL(가상 시뮬레이터)을 실행해 둔 상태에서 아래와 같이 파이썬 스크립트를 실행하여 기체가 움직이는지 확인해 볼 수 있습니다.
python3 takeoff_and_land.py

2. 기초 비행 제어: takeoff_and_land.py & goto.py
가장 기본이 되는 비행 제어 샘플부터 살펴보겠습니다. 이 샘플들은 모두 mavsdk.action.Action 클래스를 사용하여 기체의 움직임을 제어합니다.
① takeoff_and_land.py (이착륙 샘플)
드론 비행의 알파와 오메가인 이착륙을 수행하는 코드입니다. Action 클래스 내의 메서드들을 순차적으로 호출합니다.
- await drone.action.arm(): 드론의 프로펠러를 회전시킵니다 (무장).
- await drone.action.takeoff(): 지정된 고도로 이륙합니다.
- await drone.action.land(): 현재 위치에서 하강하여 착륙합니다.
이때 연구원 여러분이 반드시 명심해야 할 점이 있습니다. arm() 명령 후 너무 오랜 시간(보통 몇 초 이상) takeoff() 명령을 내리지 않으면 드론은 안전을 위해 자동으로 무장을 해제(Disarm)해 버립니다.
또한, GPS 신호가 제대로 잡히지 않은 상태에서 arm()을 시도하면 ActionError: COMMAND_DENIED라는 에러가 발생하며 프로그램이 종료됩니다. 이는 버그가 아니라 비행 제어기(FC)가 위험을 감지하고 명령을 거부한 것이므로, 항상 try... except 구문으로 예외 처리를 해주는 습관을 들여야 합니다.
② goto.py (목표 좌표 이동 샘플)
이륙 후 특정 GPS 좌표로 기체를 곧바로 이동시키고 싶을 때 사용하는 샘플입니다.
- await drone.action.goto_location(latitude_deg, longitude_deg, absolute_altitude_m, yaw_deg)
위도를 나타내는 latitude_deg, 경도 longitude_deg, 그리고 해발 고도 기준인 절대 고도 absolute_altitude_m, 기수의 방향을 결정하는 yaw_deg를 파라미터로 입력하면 기체가 부드럽게 해당 위치로 날아갑니다. 특정 지점으로 긴급 이동해야 하는 연구 시나리오에 유용합니다.
3. 드론 상태 모니터링: telemetry.py
비행 제어만큼이나 중요한 것이 기체의 상태를 실시간으로 모니터링하고 데이터를 수집하는 것입니다. 논문에 들어갈 그래프를 그리기 위해서는 데이터 로깅이 필수적이죠. 이 역할을 담당하는 샘플이 telemetry.py입니다.
이 샘플은 mavsdk.telemetry.Telemetry 클래스를 활용하며, 지난 편에서 배운 **비동기 반복문 async for**를 적극적으로 사용합니다.
import asyncio
from mavsdk import System
async def print_battery(drone):
# 배터리 정보를 무한히 수신하는 비동기 스트림
async for battery in drone.telemetry.battery():
print(f"배터리 전압: {battery.voltage_v}V, 남은 용량: {battery.remaining_percent}%")
async def run():
drone = System()
await drone.connect()
# ... 연결 확인 코드 생략 ...
# 백그라운드 태스크로 배터리 출력 함수 실행
asyncio.ensure_future(print_battery(drone))
# 30초 동안 대기하면서 백그라운드 작업이 돌아가게 함
await asyncio.sleep(30)
이 샘플 코드를 응용하면 battery() 외에도 gps_info()(GPS 위성 수 등), in_air()(공중에 있는지 여부), position()(위도, 경도, 고도) 등의 정보를 한 번에 모니터링할 수 있습니다.
<그림> telemetry.py 실행 시 배터리 전압, GPS 수신 상태, 기체의 현재 고도 및 위치 데이터가 터미널에 실시간으로 끊임없이 스크롤되며 출력되는 화면
4. 웨이포인트 자율비행: mission.py
mission.py 샘플은 드론이 여러 목적지(Waypoint)를 순차적으로 방문하며 복잡한 임무를 수행하도록 만드는 스크립트입니다. 농업용 드론의 방제 경로 설정이나, 3D 매핑을 위한 지그재그 비행 등을 구현할 때 필수적인 mavsdk.mission.Mission 클래스를 사용합니다.
코드의 실행 흐름은 다음과 같습니다.
- 여러 개의
MissionItem(경유지 좌표, 고도, 이동 속도, 카메라 촬영 여부 등)을 생성하여 리스트로 만듭니다. - await drone.mission.upload_mission(mission_plan): 작성된 임무 플랜을 기체로 업로드합니다.
- await drone.mission.start_mission(): 업로드된 임무의 시작을 명령합니다.
- await drone.mission.set_return_to_launch_after_mission(True): 이 옵션을 활성화하면, 마지막 경유지 임무를 마친 후 드론이 이륙했던 원래 위치로 스스로 돌아옵니다 (RTL: Return To Launch).
이 코드를 실행하고 QGroundControl(QGC) 화면을 확인해 보면, 우리가 코드로 작성한 경로가 QGC 화면에 똑같이 시각화되어 드론이 따라가는 것을 볼 수 있습니다.
5. 심화 제어 (미리보기): Offboard 관련 샘플들
학부생 수준을 넘어, 컴퓨터 비전 기반의 객체 추적이나 실시간 장애물 회피 알고리즘을 연구하는 분들이라면, 앞서 살펴본 단순한 GPS 이동(goto)이나 웨이포인트 비행(mission)만으로는 정밀한 제어가 불가능합니다.
초당 수십 번씩 제어 신호를 쏘아주어 기체를 조종하는 Offboard (오프보드) 모드를 사용해야 하며, 이를 위한 샘플 프로그램들도 풍부하게 제공됩니다.
- offboard_position_ned.py: Local NED (North-East-Down) 좌표계를 기준으로 “출발지에서 북쪽으로 5m, 동쪽으로 10m 가라!”고 위치를 명령하는 방식입니다 (
set_position_ned()). - offboard_velocity_body.py: 기체의 현재 방향(Body 프레임)을 기준으로 “앞으로 2m/s, 우측으로 1m/s로 날아라!”고 속도를 명령합니다 (
set_velocity_body()). 카메라가 향하는 방향을 기준으로 움직일 때 매우 직관적입니다. - offboard_velocity_ned.py: 글로벌 방위를 기준(NED)으로 “북쪽 방향으로 2m/s 속도로 이동해라!”고 명령합니다 (
set_velocity_ned()). - Offboard_position_velocity_ned.py: 목표 위치뿐만 아니라 속도 정보(Feed-Forward)까지 동시에 주어(
set_position_velocity_ned()), 위치 제어기(Position Controller)가 목표 지점에 더욱 빠르고 정밀하게 도달할 수 있도록 돕는 고급 제어 방식입니다.
오프보드 제어는 강력하지만, 코드가 조금만 잘못되어도 기체가 추락할 수 있는 위험한 모드이기도 합니다. 따라서 이 모드는 이어지는 연재에서 아주 상세히 독립된 챕터로 다룰 예정입니다.
마치며
이번 제6편에서는 MAVSDK-Python이 제공하는 훌륭한 교보재인 **기본 샘플 프로그램(takeoff_and_land, goto, telemetry, mission 등)**의 구조와 핵심 함수들을 분석해 보았습니다.
코드를 눈으로 읽는 것과 직접 타이핑하여 실행해 보는 것은 천지 차이입니다. 여러분의 개발 환경에서 샘플들을 실행해 보시고, 이동 좌표나 이륙 고도를 입맛에 맞게 수정해 보시기를 강력히 권장합니다.
다음 **[제7편: OFFBOARD 모드 이해하기]**에서는 드론 제어의 꽃이자, 연구원들이 가장 많이 질문하고 부딪히는 오프보드(Offboard) 모드의 개념과 전제 조건들에 대해 깊이 파헤쳐 보겠습니다.
직접 샘플을 실행하시면서 생기는 의문점이나 버그가 있다면 언제든 댓글로 남겨주세요. 여러분의 성공적인 연구와 비행을 진심으로 응원합니다!
YouTube 강좌

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