# 1. `Navigator` 베이스 클래스의 유한 상태 머신(Finite State Machine) 계층도 및 다형성(Polymorphism) 구현

# 1. Navigator 베이스 클래스의 유한 상태 머신(Finite State Machine) 계층도 및 다형성(Polymorphism) 구현

지상 관제 시스템(GCS) 또는 내부 자율 제어 알고리즘 판단에 의해 자동 비행 모드가 변경되었을 때, 이를 관리하고 실제 하드웨어의 위상 반응으로 체계적으로 전환하는 소프트웨어 운영 기반은 유한 상태 머신(State Machine) 논리를 근간으로 삼는다. PX4-Autopilot의 핵심인 navigator 모듈은 이 상태 머신을 객체 지향 프로그래밍(OOP)의 구조적 핵심 원리인 다형성(Polymorphism)과 상속(Inheritance) 계층도를 통해 극도로 학술적이고 매끄러운 모던 C++ 형태로 구현하고 있다.

본 절에서는 추상 구조체인 NavigatorMode 베이스 클래스가 정의하는 FSM 생명주기(Lifecycle)와, 이를 토대 삼아 독립적으로 뻗어나간 하위 자율 비행 모드(Mission, RTL, Loiter 등)들의 결합 설계 아키텍처를 심도 있게 분석한다.

1.1 NavigatorMode 베이스 클래스와 다형성(Polymorphism) 추상 설계 패턴

PX4의 navigator C++ 소스 구조 트리에서 모든 독립된 자율 비행 모드는 추상 클래스(Abstract Class)인 NavigatorMode 인터페이스를 직접적으로 상속받은 구체 클래스(Concrete Class) 인스턴스로서 존재한다. 공통 분모인 베이스 클래스 NavigatorMode는 하위 비행 모드들이 메인 OS 시스템 내에서 적법하게 구동되기 위해 반드시 재정의(Override)하여 구현해야 하는 매개 순수 가상 함수(Pure Virtual Function)와 표준 상태 인터페이스 속성들을 선언해 두고 있다.

classDiagram
    class NavigatorMode {
        <<Abstract>>
        +on_inactive() void
        +on_activation() void
        +on_active() void
        +on_inactivation() void
        #_navigator: Navigator* 
    }
    
    class Mission {
        +on_activation() void
        +on_active() void
    }
    
    class Loiter {
        +on_activation() void
        +on_active() void
    }
    
    class RTL {
        +on_activation() void
        +on_active() void
    }

    NavigatorMode <|-- Mission
    NavigatorMode <|-- Loiter
    NavigatorMode <|-- RTL

이러한 다형성(Polymorphism) 기반 상속 설계 모델은, 스레드 메인 인스턴스인 Navigator 마스터 클래스가 오직 하위 객체의 베이스 포인터 래퍼인 NavigatorMode* 타입 하나만을 배열 형태로 가리키며 수십 개의 서로 다른 비행 제어 모드의 라이프사이클을 일괄적이고 동적으로 제어할 수 있게 돕는다.

결과적으로, PX4 플랫폼 상에 특수한 연구 목적의 새로운 사용자 지정(Custom) 자율 비행 모드를 이식하고 싶은 엔지니어는, 커맨더(Commander) 내부 함수 스위칭 포인터 제어문을 절단하거나 헤집어야 하는 Ardupilot의 레거시(Legacy Monolithic Switch-case 방식) 모놀리식 구조와 대척점을 이룬다. 오직 NavigatorMode를 상속받는 단일 C++ 클래스 파일 쌍(*.cpp, *.h)을 배포 작성한 뒤 메인 Navigator 배열 모드 포인터 리스트에 플러그인(Plug-in)하기만 하면 기능 단위가 완성되는, 현대 소프트웨어 공학의 정수 **개방-폐쇄 원칙(OCP, Open-Closed Principle)**을 충실히 경험할 수 있다.

1.2 유한 상태 머신(FSM) 라이프사이클 및 전이(Transition) 구문 과정

모든 NavigatorMode 기반 파생 객체는 PX4 스케줄러가 방출하는 타임 틱(Tick) 진행 및 이벤트 인터럽트에 연계하여, 철저하게 분절된 4단계의 유한 상태 머신 이벤트 가상 함수 위상을 거치도록 설계되었다.

  1. on_inactive(): 특정 모드가 시스템에 내장되어 있으나 현재 활성화되지 않은 백그라운드 대기 상태일 때, 메인 루프에 의해 간헐적으로 주기별 호출된다. 범용적으로는 리소스를 축내지 않고 아무 연산을 수행하지 않지만, 일부 모드(예: RTL)는 비활성 상태의 이면에서도 홈 타겟의 위치 갱신이나 경로 상의 이착륙 안전 고도 델타 변화를 미리 캐싱(Caching)해 두는 식의 백그라운드 대비 업무를 수행할 수 있다.
  2. on_activation(): GCS나 통신 컴퓨터의 MAVLink set_mode 펄스 명령으로 해당 항법 모드가 최초로 진입(Enter)할 때 시스템 루프에서 단 한 번 호출(One-shot)된다. 시스템 상태 플래그 초기화, 임시 로컬 궤적 변수 리셋, 홈 위치 혹은 랑데부(Rendezvous) 좌표 기반 초기 복귀 궤적 계산, 초기 설정점 삼중체(Setpoint Triplet) 메시지 구조체 할당 및 장전(Arming) 등의 극초기 마운트 작업이 이 구역 Scope에서 진행된다.
  3. on_active(): 해당 모드가 자율 비행 제어 권한을 위임받아 현재 활성 상태(Active)를 점유하고 있을 때, 50Hz 등의 빠른 폴링 주기 맥박마다 지속적으로 반복 호출되는 비행 연산의 심장부이다. 갱신된 GPS 로컬 위치 오차를 반영하여 실제 추종 궤적 벡터를 갱신하고, 재계산된 삼중체를 uORB 토픽 베이스 큐를 통해 물리적 하위 제어기(mc_pos_control)로 지속 퍼블리시하여 모터를 구동시킨다.
  4. on_inactivation(): 조종사의 외부 매뉴얼 스틱 강제 개입 물리 신호, 또는 상위 통제 제어망의 또 다른 비행 모드로의 스위칭 명령, 배터리 방전 등 Failsafe 발동의 사유로 해당 모드가 제어권을 조기 반납하고 종료(Exit)될 때 단일 1회 호출된다. 점유하던 궤적 메모리 구조체의 초기화 해제, 잔여 플래그 데이터 방출 작업이 절도 있게 수행된다.

1.3 의존성 주입(Dependency Injection)과 데이터 캡슐화(Encapsulation) 모델

NavigatorMode의 하위 파생 유전자 클래스인 Mission 혹은 Loiter 모듈 내부 코드를 포렌식 관점으로 관찰 시, 이들은 자가 동작을 구현하기 위해 MAVLink 메시지 드라이버단에 직접 수신 커서로 연동하거나 파라미터 계수를 OS 파티션으로부터 직통 연결하여 Fetch하지 않는다는 사실을 발견할 수 있다.

경로 추종과 비행 논리 기능에 절대적으로 필요한 거의 모든 공용 자원(홈 3차원 좌표, 추정된 최신 GPS 삼각 좌표, MAVLink 수신 명령 버퍼 버스, 파라미터 계수 데이터베이스)은 메인 마스터 인스턴스인 Navigator 루트 클래스가 일원화된 체인으로 통합 수집하여 무결하게 관리한다. 그 직후, 자식 객체의 생성 주기에서 베이스 포인터 객체를 보호 변수(protected 포인터 멤버: _navigator) 형태로 주입(Dependency Injection)하여 준다.

이를 통해 C++ Mission 클래스 파생 개발자는 _navigator->get_home_position()과 같은 캡슐화된 직관적이고 일률적인 인터페이스 체계만 호출함으로써 메모리 위험도 없이 시스템 전역 자원에 무결하게 접근하게 된다. 이는 치명적인 크래시 회피가 목숨과 이어진 무인 제어 소프트웨어 아키텍처 설계 시 **높은 응집도(High Cohesion)**와 **낮은 결합도(Low Coupling)**를 유지시키는 PX4 아키텍처의 강력한 백본(Backbone)으로 작용한다.

1.4 상태 머신의 비정상(Abnormal) 논리 전이 방어 로직

navigator 로직이 상위 명령에 의해 모드를 전환(Transition)할 때, 상태 머신 컨트롤러는 맹목적으로 모드 전환 스위칭을 단행하거나 승인하지 않는다. 예컨대 자율 임무를 수행하는 Mission 모드로 진입하기 직전, 내부 can_run() 가상 함수 콜백 시그너처가 인터셉트(Intercept) 과정을 거쳐 사전 호출된다. 이 함수는 다음의 무결성 전제 조건(Preconditions)을 깐깐하게 논리적으로 심사 검증한다.

  • 최하단 EKF2 위치 좌표의 글로벌 혁신율(Global Position Validity) 및 GPS 위성 고착이 HDOP 기준치 이내인가?
  • 유효한 임무 스크립트 아이템(SD 카드 탑재된 Dataman 모듈 연동)이 정상적으로 램(RAM) 이관 업로드 및 락킹(Locking)되어 있는가?
  • 홈 좌표(Home Position) 데이터가 유의미한 수단으로 기하학적으로 무결하게 시스템상에 인가되어 있는가?

만약 can_run() 내부 분기 호출 결과 이 중 단 한 번의 불(Boolean) 타입 검증이라도 false가 연산 반환될 경우, 상태 머신 계층 플로우는 예외 컴파일 에러를 악의적으로 throw 하지는 않되, 조용히 시스템 이벤트를 로깅하고 모드 전환 콜 명령을 무시한다. 나아가 필요 구문 시 더 안전한 보수적 상태(예: 즉각 제동인 Hold 또는 회귀인 RTL)로 폴백(Fallback) 라우팅을 강제 유도함으로써 시스템이 불완전 데이터로 인한 치명적 추락 역기능을 사전 차단하는 학술적 설계 안전 장치 구조를 탑재하고 있다.