28.2.4. Commander 모듈과의 상태 동기화 프로토콜
Flight Mode Manager (이하 FMM) 데몬이 기체의 ’손과 발’이 되어 궤적 방정식이라는 육체노동을 산출하는 엘리트 행동 대장이라면, 그 위에서 군림하며 전체 시스템의 시동(Arming), 킬 스위치(Kill-switch), 배터리 방전 체크를 주관하는 ‘뇌’ 역할을 하는 최고 사령부 데몬이 바로 Commander 모듈이다.
FMM 데몬은 스스로 자신이 지금 ’수동 모드(Manual)’로 날아야 할지 ’자동 미션(Auto Mission)’으로 날아야 할지 스스로 결정할 권한이 없다. 오직 상부 Commander가 MAVLink(지상 관제소) 제어 신호나 조종기 스위치 조작을 취합, 결재한 뒤 uORB 미들웨어 우체통을 통해 하달하는 상태 명령(State Command) 프로토콜을 수동적으로 동기화(Synchronization) 받아야만 아키텍처 다이내믹 팩토리 스위칭이 가능해진다.
1. 커맨더의 결재 서류: vehicle_status 토픽 아키텍처
Commander 데몬이 FMM을 향해 지시를 내리는 가장 강력하고 거대한 결재 서류 통신망은 vehicle_status.msg uORB 토픽이다.
nav_state(Navigation State):
이 변수는 FMM에게 내리는 절대적인 1계층 작전 지시서다.NAVIGATION_STATE_MANUAL(수동),NAVIGATION_STATE_AUTO_MISSION(자동 웨이포인트),NAVIGATION_STATE_AUTO_RTL(비상 복귀) 등 수십 가지의 열거형(Enum) 상수값으로 쪼개져 있다. FMM 본체의Run()함수는 가장 먼저 이nav_state숫자가 과거 루프 대비 변경되었는지를 확인하고, 변경되었다면switchTask()동적 할당 함수를 굉음과 함께 가동하여 과거 액션 객체를 파괴하고 새 모드 객체 폴더를 램에 로드한다.arming_state(시동 상태):
드론이 현재 바닥에 조용히 죽어있는 상태(Disarmed)인지, 아니면 모터가 맹렬히 회전하며 살벌하게 무장된 상태(Armed)인지를 나타낸다. FMM의 자식 수학 객체들(FlightTask)은 이 플래그가Disarmed일 경우, 아무리 조종기 스틱을 끝까지 꺾더라도 수식 결과(trajectory_setpoint)의 목표 가속도 항을 강제로 0으로 마스킹(Masking)하여 날개가 마음대로 도는 참절 에러를 아키텍처적으로 틀어막는다.
2. 양방향 프로토콜 동기화(Handshake)의 부재와 일방주의(Unidirectional) 철학
PX4 아키텍처에서 가장 흥미로우면서도 초보 개발자들을 당황하게 만드는 부분은, Commander와 FMM 사이의 통신이 TCP/IP의 ACK(Acknowledge) 신호처럼 핑퐁을 치는 양방향 통신(Handshaking)이 아니라는 점이다.
- Commander의 무책임한 일방적 하달:
Commander는 QGC(지상 관제소)로부터 “RTL 모드로 바꿔!” 라는 명령을 받으면, 자신이 관할하는 시동 조건이나 배터리 등에 문제가 없다고 판단할 경우 즉시vehicle_status토픽의nav_state값을 RTL로 무책임하게 덮어쓰고(Publish) 콜백 인터럽트만 남긴 채 쌩하니 갈 길을 가버린다. “FMM이 내 명령을 잘 받았을까? 램 부족으로 RTL 객체 생성에 실패하진 않았을까?” 전혀 되묻지 않는다. - FMM의 수동적 동기화와 실패 권한:
FMM은 깨어나자마자nav_state가 RTL로 바뀌어 있음을 깨닫고 팩토리를 구동한다. 하지만 만약 GPS가 끊어져 있어FlightTaskAutoRtl객체 내부의activate()초기화 함수가false를 뿜으며 거부(Reject)하거나 붕괴해 버려도, FMM은Commander멱살을 잡고 “야 이거 실행 안되잖아, 아까 미션 상태로 도로 돌려놔!” 라고 역으로 상태 변경을 요구할 권한(Publish 권한)이 없다.
3. 유효 거부(Activation Rejection) 시의 섀도우 폴백(Shadow Fallback)
FMM 데몬은 상부(Commander)가 까라면 까야 하지만, 현실적으로 까는 것이 물리적으로 불가능할 때(예: GPS가 튀어 RTL이 불가할 때)는 어떻게 대처할까? 여기서 FMM만의 독창적인 ‘그림자 폴백(Shadow Fallback)’ 상태기동이 일어난다.
// FMM 내부 switchTask 루틴 예방 로직 (의사 코드)
FlightTask* new_task = instantiateTask(commander_nav_state);
// 상부 명령대로 새 임무 객체를 만들어 켰는데, GPS 에러 등으로 부팅을 거부한다면?
if (new_task->activate() == false) {
// 1. 새 객체를 즉시 파괴
delete new_task;
// 2. 상부에 보고하지 않고 자체 판단 하에, GPS 없이도 버틸 수 있는 강제 고도 유지 모드로 섀도우 스위칭
_current_task = instantiateTask(TASK_MANUAL_ALTITUDE);
} else {
_current_task = new_task;
}
상부 데몬(Commander)의 장부(vehicle_status)에는 기체가 여전히 위풍당당하게 RTL 모드로 미션을 수행 중이라고 기록되어 있고 지상 관제소 스크린에도 RTL 아이콘이 빛나고 있지만, 정작 밑단 보일러실(FMM)에서는 몰래 GPS 락이 풀렸음을 깨닫고 자체 깡통 모드(수동 고도 유지)로 핫스와핑하여 기체를 임의 연산 조종하고 있는 소름 돋는 아키텍처 해리(Dissociation) 현상이 발생하게 된다.
이것이 Ardupilot의 거대한 전역 변수 모놀리식 아키텍처와 구별되는 PX4 마이크로서비스(Microservices) 철학의 어두운 단면이자, 동시에 특정 모듈(Commander)의 오판이나 센서 패닉이 전체 시스템의 치명적 Segfault 추락으로 번지는 것을 차단하는 절단 방어막(Decoupled Sandbox) 설계의 탁월한 위엄이다.