# 1. MissionBlock 추상화 계층 및 임무 데이터 파이프라인 (mission_block.cpp)
PX4-Autopilot의 자동 비행 모드 중에서도, 사전에 프로그래밍된 궤적과 이벤트(웨이포인트 비행, 페이로드 투하, 고도 임계치 도달 등)를 순차적으로 통과하는 핵심 컨텍스트는 Mission 모드와 비상 복귀를 수행하는 RTL 모드 등이다. 이러한 궤적 계획 기반의 자동 비행 모드들은 각기 다른 시맨틱(Semantic) 특성을 띠지만, 내부적으로 기하학적 설정점을 생성하고 SD 카드의 데이터를 관리하는 공통의 파이프라인을 공유한다.
이 공통된 수학적, 자료구조적 속성들을 코드 중복 없이 일원화하여 관리하기 위해 탄생한 객체 지향 추상화(Abstraction) 레이어가 바로 MissionBlock 클래스이다. 본 절에서는 MissionBlock이 어떻게 NavigatorMode와 개별 임무 모드 사이에서 데이터 파이프라인(Data Pipeline) 브리지 역할을 하는지, 그리고 내부 캐시(Cache) 메커니즘을 심층 분석한다.
1.1 MissionBlock 모듈의 아키텍처 계층도
PX4 C++ 소스 코드(src/modules/navigator/mission_block.h)에서 클래스 상속 다이어그램을 그려보면, MissionBlock은 가장 추상적인 루트 베이스인 NavigatorMode 클래스를 1차적으로 상속(Inheritance)받아, 약간의 구체화를 더한 2차 중간 베이스 클래스(Intermediate Base Class)로 작용함을 알 수 있다.
classDiagram
class NavigatorMode {
<<Abstract>>
+on_activation()
+on_active()
}
class MissionBlock {
<<Abstract>>
#_mission_item: mission_item_s
+set_loiter_item()
+set_takeoff_item()
+set_land_item()
#mission_item_to_position_setpoint()
}
class Mission {
+on_active()
}
class RTL {
+on_active()
}
class Takeoff {
+on_active()
}
NavigatorMode <|-- MissionBlock
MissionBlock <|-- Mission
MissionBlock <|-- RTL
MissionBlock <|-- Takeoff
- 설계의 목적: 만일
Mission,RTL,Takeoff와 같은 구체적인(Concrete) 비행 모드들이NavigatorMode에서 직계 상속을 받았다면, “위도/경도 좌표를 받아서 고도를 설정하고, 이를 MAVLink 규격과 맞추는” 동일한 중복 코드가 수백 줄씩 각 모드 클래스에 방치되었을 것이다. - 해결책:
MissionBlock이라는 중간 관리자 클래스를 두어, “웨이포인트 아이템(mission_item_s)을 조작하고 이를 하위 제어기가 납득 가능한 위치 설정점(position_setpoint_s)으로 번역하는 핵심 유틸리티 함수(예:mission_item_to_position_setpoint())를 모듈화하여 상속시켜 준다.
1.2 임무 데이터 모델과 mission_item_s 자료 구조체 파이프라인
조종사가 QGroundControl(QGC) 등 지상 관제 시스템에서 마우스 클릭으로 웨이포인트를 생성할 때, 기체 내부까지 데이터가 도달하는 과정은 복잡한 다단 변환(Multi-stage Translation) 파이프라인을 거친다.
- GCS 단 (QGC): 지도 상의 좌표(WGS84 LLA) 및 커맨드 타입(예:
MAV_CMD_NAV_WAYPOINT)이 래핑된MISSION_ITEM_INTMAVLink 패킷으로 인코딩된다. - MAVLink 수신단 (maverick_receiver): 통신 모뎀을 거쳐
mavlink_receiver스레드에 진입하면, 이 패킷들은 보안 및 무결성 검사(CRC 체크, Sequence Number 정합성)를 거친 후 uORB 토픽 구조체로 역직렬화(Deserialization)된다. - Dataman 스토리지 계층: 임무 데이터의 특이점은 개수가 수십에서 수백 개를 호가할 수 있으므로, 램(RAM)의 한계를 고려하여 이를 즉시 배열에 하드코딩하지 않고,
dataman(Data Manager)이라는 데이터베이스 캐시 매니저를 통해 비휘발성 메모리(마이크로 SD 카드) 또는 SRAM의 제한된 캐시 영역에 페이징(Paging) 기록한다. MissionBlockFetching:MissionBlock상속 객체가 현재 수행 중인 웨이포인트(예: 인덱스 3번)를 소화하고 다음 아이템(인덱스 4번)이 필요해질 때,dataman서브시스템을 호출(dm_read())하여 단일mission_item_s구조체 하나만을 시스템 메모리(Heap/Stack)로 인출(Fetch)한다.
이 파이프라인은 과거 Ardupilot(APM) 모델이 수백 개의 웨이포인트 배열을 EEPROM에 동기식으로 일괄 로드하면서 시스템에 I/O 병목(Bottleneck) 현상을 유발했던 한계를 극복하기 위해 설계된 강력한 ‘동적 데이터 스와핑(Dynamic Data Swapping)’ 아키텍처이다.
1.3 WGS84 직교 투영(Orthographic Projection)과 설정점(Setpoint) 매핑 함수
MissionBlock 안에서 가장 학술적으로 중요하게 다루어지는 산술 멤버 함수는 **mission_item_to_position_setpoint()**이다. GCS가 전송한 임무 아이템은 필연적으로 지구 타원체 모델 기반의 범지구적 좌표계(WGS84 LLA: 위도 Latitude, 경도 Longitude, 해발 고도 Altitude)로 적재된다.
그러나 하위 백엔드 역할을 담당하는 멀티로터나 고정익 위치 제어기(mc_pos_control)는 컴퓨터 비전 역학과 행렬 연산의 유연성을 위해 이륙 지점을 원점(0,0,0)으로 하는 3차원 국소 평면 직교 좌표계(NED: North-East-Down 기반 데카르트 좌표) 환경에서 유체역학 PID 피드백 루프를 구동한다.
따라서 MissionBlock은 mission_item_to_position_setpoint() 함수를 통해, LLA 기반의 MAVLink 이정표를 삼각함수와 하버사인(Haversine) 공식을 포괄하는 Glocal-to-Local 직교 투영 알고리즘(Map Projection) 엔진을 통과시켜, 미터(Meter) 단위 체계의 직교 벡터 목표물(position_setpoint_s)로 환산한다.
- 이 과정에서 EKF2가 선언해 둔 로컬 좌표의 (0,0) 원점을 참조점(Reference Point)으로 활용하여 WGS84 구면좌표 오차를 평면 오차로 국소 보정하게 된다.
- 고도(Altitude) 제어 역시 지형 추적(Terrain Following) 유무, 또는 해발고도(AMSL)와 지표고도(AGL) 간의 스태틱 오프셋 보상을 코드 레벨에서 선제적으로 덧칠해 넣어 하위 제어기의 판단력을 가볍게 덜어준다.
1.4 is_mission_item_reached() 도달 판별(Acceptance Radius) 알고리즘
기체가 현재 목표 이정표에 논리적, 물리적으로 “도달(Reached)“했는지 판별하여 다음 배열 스토리지로 트랜지션할 것을 결정하는 권한 역시 MissionBlock의 인터페이스가 소유한다.
단순히 3D 유클리디안 거리가 0에 근접했다고 하여 도달로 판정할 경우, GPS 수신 단말의 고유 오차율반경 1~2m로 인하여 기체가 영원히 타겟을 벗어나지 못하고 나선 구도(Toilet-bowling) 궤적을 그리며 무한 대기하는 참사가 일어날 수 있다.
이러한 특이점(Singularity) 문제를 해결하기 위해, MissionBlock::is_mission_item_reached() 함수는 3중 휴리스틱 필터를 채택한다.
- 평면 반경 교차 검사: 현재 기체의 X-Y 수평 위치가
NAV_ACC_RAD(경로점 수용 한계 반경 파라미터) 이내의 실린더 체적 공간에 진입했는지 일차적으로 검사한다. - 고도 도달 검사: 고도 방향 차분 오차가
NAV_MC_ALT_RAD마진 내에 교합되었는지, 또는 고정익의 넉넉한 글라이딩 로스를 감안하여 슬로프 내에 안착했는지를 별도 분기로 판단한다. - 통과 선회(Transition By-pass) 예측 보상: 만약 현재 웨이포인트가 기체를 멈추지 않고 그대로 통과하는 비행경로의 중간 관문(Fly-through Waypoint)이라면,
navigator는 엄격한 실린더 진입(Acceptance)을 검증하지 않고 삼중체(Triplet) 기반의 사이각 선외삽 반경에 도달한 순간을 선제적으로 “Reached(통과함)“로 논리적 조기 판정 유보시켜, 위치 제어기로 하여금 가속도를 누그러뜨리지 않고 매끄럽게 다음 타겟을 향해 부드러운 호를 그리도록 시그널을 연계시킨다.
종적을 모아보면, 궤적 명령 번역의 핵심 코어 엔진룸인 MissionBlock은 그 우아한 추상성 덕택에, PX4 소스 코드가 수만 줄에 호가하는 비대칭적 if-else 분기 난립 없이도, 오로지 이 클래스 하나의 유지 보수를 통해 ’Return To Launch’와 ‘자율 맵핑 비행’ 양쪽 모두의 코너링 평활화 성능을 동시에 향상할 수 있는 강력한 유지보수 역량을 개발 커뮤니티에 선사하고 있다.