28.2.3.1. uORB 토픽 폴링(Polling) 및 동기화 메커니즘

28.2.3.1. uORB 토픽 폴링(Polling) 및 동기화 메커니즘

수많은 비동기 센서 프로세스들이 얽혀 돌아가는 리얼타임 비행 제어 시스템에서, Flight Mode Manager (이하 FMM)는 각기 다른 주파수로 쏟아져 들어오는 파편화된 외부 우체통(uORB 토픽) 데이터 조각들을 어떻게 단일하고 모순 없는 하나의 ’시간 동기화된 현실(Synchronized Reality)’로 꿰매어 자식 수학 객체들(FlightTask)에게 주입하는가? 그 처절한 동기화(Synchronization)와 폴링(Polling) 아키텍처 기술을 살펴본다.

1. uORB C++ API의 비동기적 본질과 updated() 폴링의 미학

uORB(Micro Object Request Broker) 미들웨어는 PX4 OS 커널 안에서 철저히 비동기(Asynchronous) 메시지 파이프라인으로 동작한다. GPS 센서 모듈이 위성 픽스 신호를 잡아 sensor_gps 토픽을 발행(Publish)하는 그 순간에, 멀리 떨어져 있는 위치 제어 쪽 수신 모듈이 그 메모리를 직접 폴링(Polling)하여 읽어갈지 말지는 발행자 쪽에서는 전혀 신경 쓰지 않는 철저한 디커플링(Decoupling) 방식을 고수한다.

따라서 구독자(Subscriber) 역할인 FMM 입장에서는 언제 새로운 편지가 자기 앞 우체통에 도착했는지 아키텍처적으로 매우 우아하고 값싼 비용으로 스캐닝(Scanning)할 수단이 필요하며, 여기서 핵심은 updated() API 함수다.

  • bool uORB::Subscription::updated():
    이 C++ 래퍼 함수는 자신이 구독하는 커널 버퍼에 예전에 읽어갔던 것 이후로 “단 한 바이트라도 진짜로 갱신된(새로 도착한) 신상 데이터가 존재하는가?“를 단순히 1비트 논리값(True/False)으로 빠르게 찍어보는 컴파일러 수준의 가벼운 검문소 역할을 한다.
    이 가벼운 함수 호출 덕분에 FMM 데몬은 매 2.5ms 주기마다 무겁게 모든 메시지의 전체 바이트 덩어리를 CPU 캐시로 무지성 덤프(복사)하여 과거 값과 일일이 C++ Memcmp(비교) 연산을 수행하는 끔찍한 오버헤드를 원천적으로 회피할 수 있다. 오직 updated()true를 반환하는 그 토픽 우체통만 골라서 타겟팅 핀포인트로 메모리 복사 작업(copy())을 수행한다.

2. 블로킹(Blocking) 없는 전역 뷰(Global View)의 순간적 스냅샷 결합

FMM의 Run() 함수는 CPU 마이크를 잡고 있는 지극히 짧은 약 1ms 이하의 찰나 동안, 무려 수십 개의 다양한 외부 uORB 토픽들을 순회하며 최신 값을 업데이트하여 흡수한다.
이 싹쓸이 폴링 파이프라인(ex: _update_topics() 내부 함수) 로직의 핵심 철학은 타스크 **‘블로킹 방지(Non-blocking)’**와 **‘스냅샷 동기화(Snapshot Sync)’**다.

  • Non-blocking 폴링:
    FMM은 “아직 vehicle_status 편지가 안 왔네, 여기서 while 돌면서 조금만 더 올 때까지 기다려볼까?” 같은 블로킹 대기 구문을 절대, 네버 허용하지 않는다. updated()false라면 미련 없이 버리고(과거의 낡은 메모리 캐시 값을 그대로 재사용), 즉각적으로 다음 줄의 센서 토픽 우체통으로 쿨하게 넘어가 버린다. 이 절차적 무정함 덕분에 FMM 데몬은 절대 커널 스레드 위에서 지연(Delay Lock)되지 않고 항시 보장된 초고강도 리얼타임 루프 주파수(400Hz)를 방어해 낸다.
  • 스냅샷 동기화(Snapshot Sync):
    파편화된 시간축으로 발행된 조종기 입력(manual_control_setpoint: 보통 50Hz), 배터리 전압(battery_status: 보통 10Hz), 3D 위치(vehicle_local_position: 보통 100~400Hz) 데이터들을 FMM은 Run() 진입 순간의 단일 틱(Tick) 동안 하나의 거대한 내부 C++ 포인터 메모리 구조체 묶음(State Variables)으로 강제 통합 캡쳐(Capture)해 버린다.
    비록 각 센서의 실제 측정 시간(Timestamp)은 미묘하게 마이크로초 단위로 어긋나 있을망정, 자식 클래스인 FlightTask의 수학 함수(update 로직) 입장에서는 마치 “세상 모든 정보가 자신이 함수를 돌리는 이 순간에 한꺼번에 동기화되어 찍힌 완벽한 단일 평면 프레임 사진(Snapshot)” 인 것처럼 환상을 제공받고, 타임 매칭에 대한 어떠한 고민 없이 순수 행렬 수학 곱셈 계산에만 집중할 수 있게 된다. 이것이 FMM 브로커가 제공하는 가장 위대한 데이터 가공 서비스다.

3. 이종 주파수 병합에 따른 에일리어싱(Aliasing) 및 타임아웃 방어막

고속의 EKF 위치 추정 데이터(400Hz)와 저속의 조종관 물리 스틱 패킷(50Hz)이 한 솥 안에서 끓여지게(동기화) 되면 필연적으로 시간 주파수 이질성 문제가 발생한다.

  • 디스크리트 필터링(Discrete Filtering):
    FMM은 manual_control_setpoint 스틱 아날로그 값 같이 듬성듬성 느리게 들어오는 저주파 신호를, 자신의 400Hz 초고속 루프 안건 메인 재료로 쓸 때 계단 현상(Step Jump)이 일어나 기체 모터에 팍팍 튀는 명령이 들어가는 것을 막기 위해, 자신의 Run() 틱(Tick) 내부에서 일차 지연 필터(Low-pass Filter)나 스무딩 가감속(Slew Rate) 로직을 이격 동기화 간극을 메워주는 접착제로 발라준다.
  • Timestamp 기반 데이터 타임아웃 센싱:
    FMM은 단지 새로운 데이터가 updated() 되었는지 확인하는 것에서 끝나는 것이 아니라, 흡수한 uORB 구조체 내부의 타임스탬프(timestamp 멤버 프로퍼티) 헤더를 자신의 현재 CPU 마이크로타임(hrt_absolute_time())과 냉정하게 빼기 연산을 진행해 검열한다.
    만약 특정 중요 센서 토픽 메시지의 도달 지연 시간(Delta Time)이 0.5초(500,000us) 이상 벌어졌다면, uORB 파이프 통신선 어딘가가 무너졌거나 상단 모듈이 크래시(Crash)났음을 의미하는 ‘Stale Data(썩은 유통기한 초과 데이터)’ 현상으로 간주하고, 이를 무시하거나 FMM 관할의 비상 페일세이프(Failsafe Task) 로직으로 강제 라우팅해 버리는 무시무시한 통신 동기화 검증 톨게이트 역할을 함께 수행해 낸다.