30.3.6. 동시성(Concurrency) 제어를 통한 페이로드(카메라, 짐벌) 트리거 uORB 메시지 발행 및 제어기 동기화

30.3.6. 동시성(Concurrency) 제어를 통한 페이로드(카메라, 짐벌) 트리거 uORB 메시지 발행 및 제어기 동기화

상업용 무인항공기(UAV)의 매핑(Mapping), 정사영상(Orthophoto) 촬영, 감시 정찰(ISR) 임무에 있어서 기체의 위치 제어만큼이나 중요한 것이 페이로드(카메라, 짐벌 등)의 정밀한 동기화 제어이다. Mission 모드는 단순히 항공기를 공간 상으로 옮기는 것뿐만 아니라, MAV_CMD_DO_MOUNT_CONTROL, MAV_CMD_IMAGE_START_CAPTURE, MAV_CMD_DO_SET_CAM_TRIGG_DIST 등 MAVLink의 수많은 페이로드 제어 명령(Do-command)들을 처리한다.
이 장에서는 이러한 명령들이 기체의 물리적 이동(Navigation)을 지연시키지 않으면서 어떻게 동시성(Concurrency)을 가지고 uORB 메시지로 파생되는지, 그리고 navigator 모듈이 독립된 camera_triggervmount 데몬과 상호작용하는 아키텍처를 분석한다.

1. 항법 명령(Nav)과 실행 명령(Do)의 비동기적(Asynchronous) 분리

임무 항목(Mission Item)은 크게 기체의 위치를 바꾸는 항법 명령(예: MAV_CMD_NAV_WAYPOINT)과 위치에 구애받지 않고 즉시 또는 병렬로 실행되는 실행 명령(예: MAV_CMD_DO_MOUNT_CONTROL)으로 나뉜다.

만일 기체가 1번 웨이포인트에서 2번 웨이포인트로 날아가면서 지속적으로 사진을 촬영해야 한다면, 내비게이터(Navigator)는 사진 촬영 명령(DO) 완료를 기다리느라 이동 명령(NAV) 수행을 멈춰서는 안 된다. 즉, 시스템 설계 상 스레드 블로킹(Thread Blocking) 없는 동시성(Concurrency) 구조가 필수적이다.

PX4의 mission.cpp 로직은 다음 임무 항목을 평가할 때, 해당 항목이 DO 계열의 비차단(Non-blocking) 명령이면 즉각적으로 vehicle_command uORB 토픽을 시스템에 흩뿌리고(Broadcast) 단 1회의 루프(약 20ms 이내)에 항목을 완수(Acceptance) 처리한 뒤, 쉴 틈 없이 바로 다음 NAV 명령을 읽어 들여와 비행을 지속한다.

2. 짐벌 제어 (vmount) 및 카메라 트리거 (camera_trigger) 동기화

navigator가 던진 페이로드 명령은 별도의 백그라운드 프로세스(Daemon)들에 의해 소모된다.

2.1 ) 카메라 트리거 시스템 (camera_trigger_s)

측량용 사진 촬영 비행 시, 거리 기반 트리거(MAV_CMD_DO_SET_CAM_TRIGG_DIST)가 하달되면 navigator 모듈이 직접 거리를 계산하며 셔터를 누르지 않는다.
대신 navigator는 “트리거 간격: X 미터“라는 상태 파라미터만을 포함한 제어 토픽을 열어두고, 독립적으로 실행 중인 camera_trigger 모듈이 EKF2의 vehicle_local_position 주행 거리계(Odometry)를 구독하여 스스로 유클리드 거리를 적분(Integration)하다가 지정된 간격마다 하드웨어 PWM(또는 MAVLink Camera Protocol) 파장을 쏜다.
이는 관심사의 분리(Separation of Concerns)를 통해 navigator의 연산 부하를 획기적으로 낮추는 결과를 낳는다.

2.2 ) 짐벌 및 마운트 제어 (vmount)

마찬가지로 MAV_CMD_DO_MOUNT_CONTROL 명령이 수신되면, 롤/피치/요 타겟 각도는 vehicle_command를 통해 vmount (Vehicle Mount) 데몬으로 이첩된다. vmount 데몬은 카메라 짐벌의 역기구학(Inverse Kinematics)이나 MAVLink v2 Gimbal Protocol로 이를 변조하여 최종 액추에이터(Actuator)나 페이로드 컨트롤러로 전달한다.

3. 페이로드 동시성 제어 아키텍처 (Mermaid Diagram)

다음은 navigator의 메인 루프를 방해하지 않고 카메라와 짐벌이 각각의 스레드에서 MAVLink 명령을 소화하는 병렬 처리 아키텍처 모식도이다.

graph TD
    A[mission.cpp: Read Next Item] --> B{Command Type?}
    
    B -- "Nav (Blocking)" --> C[FlightTaskAuto: Position Control]
    C -->|Wait for Acceptance| C
    
    B -- "Do (Non-blocking)" --> D[Broadcast 'vehicle_command' via uORB]
    D -->|Instant Acceptance| A
    
    D -.-> E[camera_trigger Daemon]
    D -.-> F[vmount Daemon]
    
    E -->|Continuous Integral| G{Distance > Threshold?}
    G -- Yes --> H[Hardware PWM / MAVLink Shutter]
    G -- No --> E
    
    F --> I[Gimbal Attitude Setpoint Output]

4. 동기화 관점에서의 타임스탬프(Timestamp) 무결성

지형 정사영상(Orthomosaic Mapping) 생성 시 사진의 정확한 GPS 메타데이터(Exif) 타깅은 생명과 같다. PX4는 트리거 명령을 보낸 직후 카메라 핫슈(Hot-shoe) 커넥터나 피드백 라인을 통해 셔터가 물리적으로 동작한 정확한 하드웨어 인터럽트 시간(camera_capture_s)을 시스템 클럭 기반 절대 시간(hrt_absolute_time())으로 역기록(Log)한다.

이는 단순히 “명령을 보냈다“는 소프트웨어적 시점이 아니라 “센서가 실제로 활성화되었다“는 하드웨어적 시점과 정확히 해당 순간의 EKF2 추정 위치(Position)를 매칭시키기 위함으로, 이 동시성(Concurrency)과 타임스탬프 동기화 기능이야말로 상업용 조사 프레임워크에서 PX4-Autopilot이 널리 채택되는 결정적 이유 중 하나이다.

5. Ardupilot 대비 아키텍처적 우수성

Ardupilot은 전통적으로 카메라 및 마운트 제어 코드가 비행 모드(mode_auto.cpp) 안이나 AP_Mount, AP_Camera 라이브러리로 메인 스레드 구조에 다루기 힘들게 얽혀 있는 경우가 많았다(최근에는 개선되고 있으나 역사적 설계가 그러하다).
반면 PX4는 RTOS(NuttX) 환경의 다중 스레딩을 극한으로 응용하여, camera_triggervmount를 완전히 **독립된 독립체(Entity)**로 운용한다.
개발자가 기체 특수 목적(예: 소화기 투하, 로봇 팔 제어, 다중 라이다 동기화 등)에 맞는 새로운 페이로드를 장착할 경우, 기존의 비행 제어 및 navigator 소스 코드를 단 한 줄도 수정할 필요 없이, 오직 새로운 uORB 백그라운드 데몬만 추가로 띄우면(Spawning) 된다는 점에서 객체 지향적이고 모듈화된 아키텍처의 백미라 칭할 수 있다.