### 0.0.1 GPS 통신 파싱(Parsing) 엔진 및 최적화 기법
이전 절에서 다룬 전기전자적 하드웨어 설계가 완벽히 구축되어 깨끗한 위성 신호가 수신되더라도, 기체가 자율 비행을 수행하기 위해서는 이 아날로그 전파 데이터를 비행 제어기(FC)가 이해할 수 있는 디지털 변수(위도, 경도, 고도, 속도 등)로 변환하는 소프트웨어적 ‘해석’ 과정이 필수적이다.
GPS 모듈은 끊임없이 문자열이나 이진(Binary) 데이터 스트림을 직렬 포트(UART)나 CAN 버스로 쏟아낸다. PX4-Autopilot 내부에 위치한 **GPS 드라이버(Driver) 및 파싱 엔진(Parsing Engine)**은 이 쉴 새 없이 쏟아지는 데이터의 홍수 속에서 의미 있는 패킷을 추출하고, 오류를 검증하며, 최종적으로 uORB 메시지로 발행(Publish)하는 극한의 실시간(Real-time) 데이터 처리 공장 역할을 수행한다.
0.1 직렬 스트림(Serial Stream) 처리를 위한 상태 머신(State Machine) 아키텍처
GPS 모듈에서 전송되는 데이터는 파일(File)처럼 한 번에 다운로드되는 것이 아니라, 1바이트씩 꼬리를 물고 연속적으로 흘러들어오는 비동기 스트림(Stream)이다. 언제 패킷이 시작되고 어디서 끝나는지 메인 쓰레드는 미리 알 방법이 없다.
따라서 PX4의 GPS 파서(Parser) 구현체들은 전통적이고 견고한 유한 상태 머신(Finite State Machine, FSM) 아키텍처를 기반으로 설계되어 있다.
- 예를 들어 NMEA
$기호나 UBX의0xB5 0x62동기화 바이트(Sync Byte)를 기다리는 상태(STATE_WAIT_SYNC)에서 출발하여, 바이트가 들어올 때마다 상태를 전이(Transition)시키며 페이로드(Payload)를 조립(STATE_GOT_PAYLOAD)하고, 마지막 체크섬(Checksum)을 검증하는 상태(STATE_CHECKSUM)에 도달한다. - 이러한 바이트 단위(Byte-by-Byte) 콜백(Callback) 처리는 메인 루프를 블로킹(Blocking)하지 않으며, 중간에 노이즈 바이트가 섞여 들어와도 즉시 상태를 초기화(Reset)하여 다음 패킷의 시작을 민첩하게 포착할 수 있는 탁월한 회복 탄력성(Resilience)을 제공한다.
0.2 프로토콜 다형성(Polymorphism)과 자동 감지(Baudrate & Protocol Auto-detection)
Pixhawk 등에 사용자가 GPS를 꽂았을 때, PX4 제어기는 해당 모듈의 통신 속도(Baudrate)나 전송 프로토콜(NMEA, UBX, RTCM 등)을 미리 알지 못한다. 그럼에도 꽂고 나면 몇 초 안에 인식되는 것은 GPS 드라이버의 백그라운드 자동 감지(Auto-detection) 스케줄러 덕분이다.
- PX4 소스코드의
src/drivers/gps디렉토리 하위에는GPSDriverUBX,GPSDriverNMEA,GPSDriverRTCM등 벤더별 프로토콜 파서 클래스들이 존재한다. - 디바이스 드라이버가 구동되면 9600, 38400, 115200 등 흔히 쓰이는 보드레이트를 순차적으로 스니핑(Sniffing)하며 버퍼를 읽어 들인다. 만약 버퍼 안에서
0xB5 0x62패턴이 연속으로 발견되면 내부 포인터를 다형성(Polymorphism)에 의해GPSDriverUBX인스턴스로 바인딩(Binding)시키고, 이후부터는 수신 체계를 단일 프로토콜 파싱으로 완전히 고정시킨다.
0.3 멀티 쓰레드 제약과 파싱 최적화(Optimization)의 당위성
멀티로터의 자세 제어(Attitude Control) 루프가 초당 400번~800번(400Hz~800Hz) 이상 회전해야 하는 극한의 NuttX RTOS 환경에서, 직렬 포트를 통해 초당 10번(10Hz)씩 쏟아지는 수백 바이트의 GPS 버퍼를 처리하는 일은 심각한 CPU 오버헤드(Overhead)를 유발할 수 있다.
- 제로 카피(Zero-Copy) 및 인-플레이스(In-place) 처리: 버퍼 복사(memcpy)로 인한 메모리 사이클 낭비를 막기 위해, 수신된 DMA(Direct Memory Access) 버퍼 포인터 위치에서 직접 형변환(Type Casting)을 수행하여 데이터를 추출한다.
- 부동 소수점(Floating Point) 연산 억제: GPS 좌표(예:
37.1234567)는 정밀도가 극도로 높다. 이를 파싱하는 과정에서 값비싼 실수형double연산을 반복하는 대신, 소수점을 의도적으로 제거하고 정수 단위(1e7을 곱한int32_t형태)로 밀어붙이는 고정 소수점(Fixed-point) 꼼수로 연산 주기를 단축한다.
본 장의 이어지는 하위 절들에서는 NMEA ASCII 프로토콜과 u-blox UBX Binary 프로토콜의 파싱 엔진 코드가 실제로 어떻게 구현되어 있으며, 연산 병목을 어떻게 최적화하고 있는지 심층적으로 분석한다.