28.2.4.2. 상태 불일치(State Mismatch) 감지 및 비상 복구(Fallback) 통신 루프

28.2.4.2. 상태 불일치(State Mismatch) 감지 및 비상 복구(Fallback) 통신 루프

이전 장들에서 누누이 강조했듯, PX4 비행 스택은 메인 보드인 Commander가 내린 nav_state 명령(예: “RTL 모드로 진입하라”)을 하위 실무자인 Flight Mode Manager (이하 FMM)가 무조건적으로 수행할 수 있으리라 맹신하지 않는다. GPS 안테나가 뽑혀 있거나 나침반 지자기 센서가 캘리브레이션 락(Lock)에 걸려 있다면, FMM의 FlightTaskAutoRtl 객체는 초기화(activate())를 거부하고 자체적으로 깡통 수동 고도 모드(ManualAltitude)로 섀도우(Shadow) 핫스와핑해버리는 이중 인격(Dissociation) 상태, 즉 상태 불일치(State Mismatch) 상황에 처하게 된다.

그렇다면 상부의 뇌(Commander)는 하부의 손발(FMM)이 자신의 명령을 씹어버리고 임의대로 움직이고 있다는 이 치명적인 하극상(Mismatch)을 어떻게 눈치채고 전체 시스템을 비상 복구(Fallback) 궤도에 올려놓는가?

1. Mismatch의 인지: uORB 피드백 파이프라인

디커플링(Decoupling)된 비동기 아키텍처 세계에서 Commander는 FMM의 클래스 내부 프라이빗 포인터 변수(_current_task)를 다이렉트로 열어서 읽어볼 권한이 없다. 따라서 FMM 쪽에서 자신이 현재 ‘실제로’ 돌리고 있는 수학 객체의 정체를 정직하게 위로 보고해 줘야 한다.

  • FMM의 실태 보고서 (commander_state 또는 vehicle_status 응답):
    FMM은 팩토리 패턴을 돌려 실제로 동작에 성공한 자식 태스크 객체(위 예시의 경우 Position/RTL 계산 거절 후 fallback된 ManualAltitude 객체)가 구동 중임을, 역방향 uORB 토픽(피드백 구조체)에 담아 커널 버스로 쏴 올린다. (최신 PX4 버전에서는 FMM이 아예 권한 거부 신호 자체를 uORB로 명시적으로 튕겨내기도 한다)
  • Commander의 교차 검증:
    Commander 데몬은 자신이 0.5초 전에 하달했던 장부 상의 nav_state(예: AUTO_RTL)와, 지금 FMM으로부터 올라온 “나 실은 수동 고도 모드 돌고 있어“라는 피드백 보고서를 교차 대조(Cross-validation)한다. 이 두 값이 명백하게 틀어지는 순간, Commander의 메인 상태 머신 스코프 안랩에는 시뻘건 **Mismatch Alert(불일치 경보)**가 터지게 된다.

2. Commander의 비상 복구(Fallback) 라우팅 프로토콜

Commander는 상태 불일치를 감지했다고 해서 “FMM 모듈 고장!” 하고 전체 커널 시스템을 패닉(Kernel Panic)으로 내던져 버리는 멍청한 짓을 하지 않는다. 대신, 현재 이 드론이 겪고 있는 비참한 하드웨어 센서 환경 위에서 그래도 비행기(드론)가 가장 안전하게 목숨을 부지할 수 있는 최적의 차선책(Fallback State)이 무엇인지 계산하는 두뇌 풀가동 루프에 돌입한다.

  1. 우선순위 강등 검색 (Degrade Priority):
    목표했던 ’자동 복귀(RTL)’를 GPS 에러로 FMM이 거부했음을 확인하면, Commander는 내부의 거대한 상태 결정 폴백 트리(Fallback Tree)를 타고 한 단계 낮은 자율성 단계로 목표를 하향시킨다.
    “GPS를 못 써서 RTL 위치를 모른다면, 차라리 고도만 잡고 그 자리에 무식하게 하늘에 떠있자. nav_state = AUTO_LOITER로 명령을 바꿔서 다시 하달해 볼까?”
  2. 재검증과 2차 강등:
    하지만 GPS가 없으므로 FMM은 이 AUTO_LOITER 제어 명령마저도 false 로 튕겨내 버린다 (Hovering 위치를 잡지 못하므로).
  3. 최후의 기계적 생존 단계 (Descend / Failsafe):
    Commander는 결국 위치 기반의 모든 스마트한 오토/수동 모드들이 모두 막혀있음을 피드백 루프로 인지하고, 최후의 보루인 nav_state = DESCEND (비상 수직 낙하 着陸) 상태로 vehicle_status 토픽을 최종 확정 갱신해 버린다. 이 Descend 모드는 GPS나 비전 센서 따위는 전혀 필요 없고, 오직 기압계(Barometer)와 자이로(Gyroscope)만으로 모터 회전수를 깎아내려 기체를 천천히 자유 낙하시키는 최하위 티어 생존 모드다.

3. GCS(QGroundControl)와의 상태 동기화 및 조종사 알림

내부 임베디드 OS 안에서 FMM과 Commander가 피 터지게 폴백(Fallback) 라우팅을 타는 동안, 땅에서 모니터를 보고 있던 인간 조종사는 어떻게 이 치명적인 Mismatch 상황을 알 수 있을까?

Commander는 MAVLink 데몬을 향해 현재 자신의 상태 머신 루틴 안에서 벌어지는 비상 사태를 실시간 MAVLink 패킷(예: STATUSTEXT, HEARTBEAT)으로 암호화하여 지상 관제소 텔레메트리 안테나로 뿌린다.

조종사의 QGroundControl 화면에는 다음과 같은 순서로 공포스러운 에러 메시지들이 뜨게 된다:

  1. “RTL mode rejected by Flight Mode Manager” (FMM의 명령 거부 보고)
  2. “Failsafe enabled: no local position” (Commander의 원인 분석 및 페일세이프 트리거)
  3. “Landing at current position” 혹은 음성 경고 “Emergency Descent” (Commander의 최후의 폴백 상태 결정을 GCS에 동기화 반영)

이처럼 PX4의 Commander-FMM 폴백 통신 루프는, 센서 부품 하나가 죽었을 뿐인데 드론 전체가 통제 불능으로 날아가버리는(Fly-away) 아마추어스러운 참사를 완벽히 봉쇄하고, 마치 숙련된 인간 기장이 계기판 에러를 맞고서 매뉴얼대로 차단기를 하나하나 내려가며 버틸 수 있는 최후의 모래주머니(Fallback)를 찾아내 착륙해 내는 강건한 아키텍처 생존 철학을 우아한 소프트웨어 C++ 분산 파이프라인으로 구현해 낸 극한의 명작이라고 평가할 수 있다.