# 1. 스레드 안전성(Thread-safety) 및 이벤트 구동(Event-driven) 폴링 메커니즘 설계 (`navigator_main.cpp`)

# 1. 스레드 안전성(Thread-safety) 및 이벤트 구동(Event-driven) 폴링 메커니즘 설계 (navigator_main.cpp)

PX4-Autopilot의 코어 자율 비행 로직을 실행하는 navigator 모듈은 내부적으로 NuttX RTOS 환경 기반의 단일 스레드(Single-thread) 애플리케이션으로 동작한다. 본 절에서는 src/modules/navigator/navigator_main.cpp 파일의 소스 코드 구조를 중심으로, navigator 데몬(Daemon) 상에서 어떻게 완벽한 스레드 안전성(Thread-safety)을 확보하며, 비동기 이벤트 구동(Event-driven) 방식의 폴링(Polling) 메커니즘을 적용하여 CPU 점유율을 최적화하는지를 심층적으로 분석한다.

1.1 프로세스 진입점(Entry point) 및 스레드 우선순위 초기화

navigator가 활성화될 때 시스템 파이프라인 상에서 가장 먼저 호출되는 진입점(Entry Point) 모듈은 navigator_main() 메인 함수이다. 이 함수는 NuttX 환경에서 백그라운드 태스크를 생성(Spawn)하며 시스템 힙 영역에 Navigator 싱글톤(Singleton) 인스턴스를 무기한 유지시킨다.

초기화 단계에서 가장 돋보이는 펌웨어 아키텍처 설계는 task_spawn() API를 직접 호출하여 메인 스레드에 보수적인 우선순위(Priority)와 정해진 스택(Stack) 사이즈를 할당하는 정책이다. navigator는 모터의 델타 출력을 관장하는 mc_pos_control(다중 로터 위치 제어)이나 mc_att_control(다중 로터 자세 제어) 대비 상대적으로 낮은 백그라운드 우선순위(Default Priority)를 부여받는다. 이는 하드 리얼타임(Hard Real-time) 제어기의 진동 제어 타이밍 마진을 탈취하지 않기 위한 선점형 스케줄링(Preemptive Scheduling) 환경 설계의 철칙 중 하나이다.

1.2 이벤트 구동형 폴링(Event-driven Polling)의 동작 구문 체계

모듈 성능 최적화의 핵심은 navigator_main.cpp 내부의 while(!_task_should_exit) 무한 루프 블록 내 구현된 px4_poll() 시스템 콜 기반 대기 구문이다. navigator는 특정 시간이 경과할 때마다 스스로 연산을 강행하는 타이머(Timer) 콜백 방식이 아닌, 특정 ’사건(Event)’이 충족되었을 때만 반응하는 수동적인 데이터 파이프라인 구조를 구축하였다.

sequenceDiagram
    participant EKF2 as EKF2 / Estimator
    participant uORB as uORB Messaging Bus
    participant Navigator as navigator_main.cpp
    participant Controller as Position Controller
    
    Navigator->>uORB: px4_poll() 폴링 감시 대기 (Blocking)
    Note over Navigator, uORB: CPU 자원 컨텍스트 슬립(Sleep)
    
    EKF2->>uORB: vehicle_local_position 발행 (통상 50Hz)
    uORB-->>Navigator: 데이터 수신 인터럽트 트리거(Wake-up)
    
    activate Navigator
    Navigator->>Navigator: MAVLink 명령 및 전역 파라미터 Fetch
    Navigator->>Navigator: NavigatorMode::on_active() 다형성 산술 호출
    Navigator->>uORB: position_setpoint_triplet_s 설정점 발행
    deactivate Navigator
    
    uORB->>Controller: 위치 제어 타겟 갱신 유도
    Navigator->>uORB: 리소스 반납 후 다시 px4_poll() 대기 진입

관찰을 기다리는 핵심 파일 디스크립터(File Descriptor)는 확장 칼만 필터(EKF2, Estimator) 노드가 지속 퍼블리시하는 vehicle_local_position uORB 토픽이다.

  1. navigatorpx4_poll()을 블로킹 함수로 호출하여 vehicle_local_position 메시지 타임스탬프가 갱신될 때까지 스스로 스케줄러 레디 큐(Ready Queue)에서 내려와 수면(Sleep) 상태를 지속한다.
  2. EKF2 추정기가 WGS84 좌표를 국소 투영한 최근접 기체의 GPS 위치와 3차원 속도 벡터 및 공분산(Covariance)을 새롭게 발행(Publish)하면 px4_poll()의 블로킹이 즉각 해제된다.
  3. 활성화된 스레드 뎁스에서 navigator는 MAVLink 기반의 vehicle_command 구조체 데이터, 상태 토픽, 통신 링크 인디케이터를 일괄 Fetch(수집)한 뒤 논리적 경로 계획 로직을 완수한다.

이러한 설계 기법은 고정 루프 방식을 맹신했던 이전 아키텍처나 단일 메인 루프를 기반으로 모드 스위칭을 단행하는 전통적 모놀리식(Monolithic) Ardupilot 스케줄러 아키텍처와 비교하였을 때, 불필요 루프 주기 보상 연산의 CPU 낭비를 원천 차단하고 저주파수 태스크 관리가 극히 효율적이라는 확고한 장점을 지닌다.

1.3 스레드 안전성(Thread-safety) 무결성과 Lock-free 데이터 복사 철학

자율 비행 분산 시스템 구축 사례에서 코드 생명력을 위협하는 가장 치명적인 결함 요소는 데이터 경합 수정을 위해 뮤텍스(Mutex), 크리티컬 섹션(Critical Section), 세마포어(Semaphore) 등을 남용하다 발생하는 교착 상태(Deadlock)나 스케줄러 우선순위 역전(Priority Inversion) 현상이다.

navigator_main.cpp가 주창하는 설계 철학은 공유 메모리 객체에 의도적 락(Lock)을 걸지 않는다는 이념이다. navigator는 앞서 설명한 단일 스레드 기반 인스턴스 환경을 구비하고 있으므로, 외부 객체 루틴이 navigator 내부의 프로퍼티에 명시적인 직접 메모리 포인터 접근을 감행할 수 없도록 강하게 은닉(Encapsulation)되어 있다.
지상 관제 시스템의 MAVLink 수신 처리기 단위나 커맨더(Commander) 데몬이 navigator 로직에 간접 지시를 내리고자 할 경우 오직 시스템 광대역 망인 uORB 메시징 버스를 경유해서만 struct 형태의 데이터를 비동기 발송할 수 있다.

이와 같이 발송된 페이로드 데이터는 락 루틴이 병행 배제된 환경하에서, navigator가 이벤트 트리거 스레드로 깨어난 직후 순차적으로 orb_copy() 함수 버퍼 처리를 통해 자가 로컬 지역 변수로 완전히 스태틱하게 복사(Clone)된 뒤 비로소 산술 연산에 동원된다.
결론적으로 시스템 레벨의 동시 메모리 읽기/쓰기 경합(Race Condition) 시나리오가 데이터 수동성 모델을 매개로 수학적으로 근절되며, 후가공 분석 시 정적 분석(Static Analysis) 린터링(Linting) 도구가 모듈의 스레드 안전성을 극히 수월하게 검증해 낼 수 있는 기반이 마련된다.

1.4 로컬 변수 캐싱(Caching)을 통한 레이턴시 돌파 및 구조적 예외 제어

메인 사이클 구문 내에서의 변수 제어 및 파라미터(Parameter) 관리는 잦은 하드웨어 플래시 메모리 입출력 딜레이를 회피하기 위하여 소프트웨어 레이어 레벨 로컬 캐싱 기법으로 대체된다. navigator는 범용 parameter_update 토픽 계층이 수신된 직후의 시점에 한하여 C++ 클래스의 소속 파라미터 계수를 SRAM 프레임 상에서 리딩 재평가한다. QGroundControl(QGC)과 같은 GCS 모듈에서 비행 개입 시 NAV_ACC_RAD와 같은 항법 관여 파라미터를 동적으로 변경하더라도, 백그라운드에서 트리거 되는 updateParams() 과정 중 스레드 메모장에 안전하게 섀도잉(Shadowing)되어 궤적 산출에 이중 지연 간섭 없이 동기화된다.

궁극적으로 철학적인 이벤트 폴링 주기 최적화, 락-프리(Lock-free) 기반의 데이터 구독 파이프라인 도면, 객체 지향 캡슐화적 파라미터 캐시 관리가 절묘하게 응집된 navigator_main.cpp는, 수십 종류에 달하는 다중 센서 복합 명령 데이터를 무결하게 단일화하고 타임 바운드(Time-bound) 내에 비동기적 궤적을 신뢰도 있게 분출해 내는 POSIX 표준 무인항법 소프트웨어 공학의 집결체라 규정지을 수 있다.