13.1.3. 보정 데이터 프로토콜: RTCM 3.x 메시지 인코딩/디코딩 소스코드 레벨 분석

13.1.3. 보정 데이터 프로토콜: RTCM 3.x 메시지 인코딩/디코딩 소스코드 레벨 분석

정밀 동적 측위(Real-Time Kinematic, RTK)를 실현하기 위해서는 기준국(Base Station)에서 획득한 오차 보정 데이터를 이동국(Rover)으로 실시간 전송해야 한다. 현재 PX4-Autopilot 생태계 및 대부분의 상용 GNSS(Global Navigation Satellite System) 시스템은 국제 해양 무선 기술 위원회(Radio Technical Commission for Maritime Services)가 제정한 RTCM v3 (RTCM 10403.3) 규격을 표준 보정 데이터 프로토콜로 채택하고 있다.

본 절에서는 상용 PX4-Autopilot(펌웨어 버전 v1.14 기준) 및 QGroundControl(v4.3 기준) 아키텍처 상에서 RTCM 3.x 데이터가 어떻게 패키징되고, MAVLink 프로토콜을 통하여 기체로 전달되며, 종국적으로 온보드(Onboard) GPS 드라이버에서 어떻게 디코딩되는지 소스코드 레벨에서 상세히 분석한다.

1. RTCM 3.x 데이터 전송 아키텍처 개요

지상 관제 시스템(Ground Control Station, GCS)인 QGroundControl은 베이스 스테이션 모듈과 연결되어 RTCM 스트림을 수신한다. 이 데이터 스트림은 일반적으로 UART/USB 직렬 포트나 NTRIP(Networked Transport of RTCM via Internet Protocol) 클라이언트를 통해 유입된다. 수신된 바이너리 데이터는 그대로 전송될 경우 통신 대역폭과 신뢰성에 악영향을 미칠 수 있으므로, QGroundControl은 데이터를 MAVLink 메시지 중 하나인 GPS_RTCM_DATA (메시지 ID 233) 패킷으로 분할 및 캡슐화(Encapsulation)하여 기체의 조종 컴퓨터(Flight Controller)로 전송한다.

sequenceDiagram
    participant Base as Base Station (GNSS)
    participant QGC as QGroundControl (v4.3)
    participant Mav Router as MAVLink Stream
    participant PX4 as PX4-Autopilot (v1.14)
    participant Rover as Rover GNSS (u-blox)

    Base->>QGC: RTCM 3.x Binary Stream (NTRIP/Serial)
    QGC->>QGC: Chunking (Max 180 bytes per MAVLink packet)
    QGC->>PX4: MAVLink (GPS_RTCM_DATA) 전송
    PX4->>PX4: gps_inject_data uORB 토픽 발행
    PX4->>PX4: gps 드라이버 내 uORB 구독
    PX4->>Rover: 파싱된 원시 RTCM 바이트 배열 전송 (UART/I2C)
    Rover-->>PX4: RTK Fix (Carrier phase solution) 전환

이 다이어그램에서 볼 수 있듯, GCS는 단순히 데이터를 분할 캡슐화할 뿐 프로토콜 내부를 디코딩하지는 않는다. 반면 PX4-Autopilot 내부의 GPS 드라이버(예: src/drivers/gps 디렉터리 하단의 u-blox 호환 드라이버)는 수신한 uORB 토픽을 풀어서 시리얼 포트를 통해 물리적인 Rover 모듈로 그대로 바이너리 패스스루(Pass-through)를 수행하기도 하나, 데이터 무결성 검증, 로컬 저장 및 통계 수집 등을 목적으로 일부 디코딩 연산을 함께 수반한다.

2. RTCM 3.x 프레임 구조 (Frame Structure)

소스 코드 단에서 RTCM 데이터를 파싱하기 위해서는 해당 바이너리 포맷 규격을 정확히 이해해야 한다. RTCM 3.x 메시지 프레임은 아래와 같은 전송 레이어 구조를 갖는다.

  • Preamble: 시작 동기 바이트, 0xD3 (8비트)
  • Reserved: 프로토콜 고정 비트, 일반적으로 000000 (6비트)
  • Length: 페이로드 데이터의 바이트 길이 (10비트)
  • Data Message: 실제 메시지 페이로드 (가변 길이, Length에 의존)
  • CRC: 데이터 무결성을 검증하기 위한 Qualcomm 24-bit CRC (24비트)

전체 구조에서 볼 때 페이로드를 제외한 오버헤드는 6바이트로 구성된다. GPS 드라이버 내의 디코더는 직렬 버퍼에서 0xD3 바이트를 색인(Index)하는 것을 시작으로 상태 머신(State Machine)을 구동한다.

2.1 RTCM 3.x 디코더 상태 머신 모델

PX4 내비게이션 소스 코드(src/drivers/gps/rtcm.cpp 등)에서 RTCM 파서는 전형적인 유한 상태 머신(Finite State Machine, FSM)을 따른다.

stateDiagram-v2
    [*] --> WAIT_SYNC : Start
    WAIT_SYNC --> WAIT_LENGTH : Preamble (0xD3) 수신
    WAIT_LENGTH --> READ_PAYLOAD : 16-bit Header 전체 수신 (Length 추출)
    READ_PAYLOAD --> CHECK_CRC : Length 만큼 Data 수신 완료
    
    CHECK_CRC --> WAIT_SYNC : CRC 에러 발생 (버리기)
    CHECK_CRC --> PROCESS_DATA : CRC 검증 성공
    PROCESS_DATA --> WAIT_SYNC : 처리 완료 (다음 패킷 대기)

3. PX4-Autopilot 시스템 내 RTCM 패싱 및 디코딩 구현 분석

PX4-Autopilot v1.14 버전을 기준으로 RTCM 기능은 gps 드라이버 데몬 내에서 주로 처리된다. 메인 루프인 GPS::Run() 메서드 주기에서 uORB 폴링(Polling)을 통해 gps_inject_data_s 구조체의 메시지들이 있는지 점검한다.

3.1 gps_inject_data 구조체 처리

uORB 레벨에서 전송되는 구조체는 MAVLink의 GPS_RTCM_DATA에서 변환된 형태를 띠며 다음과 유사하게 정의된다.

// msg/gps_inject_data.msg (uORB Definition)
uint64 timestamp       // 시간 스탬프 (마이크로초)
uint16 len             // 배열 내의 유효 데이터 바이트 수
uint8 flags            // LSB 비트는 패킷의 단편화(Fragmentation) 식별 등 활용
uint8[182] data        // 바이너리 데이터 블록

수신 버퍼 로직에서는 드물지만 패킷의 유실이나 순서 변경을 고려하여 data 내부에 존재하는 직렬화된 데이터 스트림을 드라이버의 송신 링 버퍼(Ring Buffer)로 안전하게 주입(Injection)한다.

3.2 CRC-24Q 검사 알고리즘 구현부

드라이버 내부 깊숙한 곳에서는 기준국(Base Station)에서 획득한 RTCM 데이터가 UART 채널로 전송되는 도중 손상되지 않았는지를 검증하기 위해 연산을 수행한다. Qualcomm 알고리즘인 CRC-24Q (다항식 P(x) = x^{24} + x^{23} + x^{18} + x^{17} + x^{14} + x^{11} + x^{10} + x^7 + x^6 + x^5 + x^4 + x^3 + x + 1, 식별자 0x1864CFB) 를 사용한다.

소스 코드 관점에서 해당 CRC 계산은 빠른 연산을 위해 미리 계산된 룩업 테이블(Look-up Table)을 이용하는 방식으로 전개된다. 이는 MCU(Micro Controller Unit)의 컴퓨팅 오버헤드를 줄이기 위한 필수적인 공학적 기법이다.

// src/drivers/gps/rtcm.cpp 내부 CRC-24Q 검증 코드 예시 (축약 및 각색)
uint32_t crc24q(const uint8_t *data, size_t length)
{
    uint32_t crc = 0x000000;
    for (size_t i = 0; i < length; i++) {
        crc = ((crc << 8) & 0xFFFFFF) ^ crc24q_lookup_table[(crc >> 16) ^ data[i]];
    }
    return crc;
}

제어 루프는 수신한 바이트 길이(Length 필드)를 기반으로 페이로드 및 헤더를 합친 모든 배열 구간을 crc24q_lookup_table과 비트 XOR 연산을 수행하여 24비트의 정수값으로 축소시킨 후, 수신된 마지막 3바이트(CRC 필드)의 값과 비교한다. 두 값이 동일하면 오차가 개입하지 않았다고 간주한다.

4. 메시지 인코딩(Encoding) 및 생성 측면의 고찰

반대의 경우, 기체가 스스로 Base Station 역할을 하는 설정(Moving Baseline 또는 고정형 PX4 RTK Base)에서는 기체의 GPS 모듈에서 추출된 위상의 반송파 식별 정보 등을 RTCM 포맷으로 인코딩하여 직렬 포트를 시뮬레이션하거나 직렬 포트를 통해 내보내야 한다.

이 경우 인코딩 서브루틴은 역순으로 수행된다.

  1. GNSS 칩셋(예: u-blox ZED-F9P 등)이 직렬 인터페이스를 통해 자체 포맷(UBX 헤더 등)으로 관측 데이터(Observation Data) 출력.
  2. gps 드라이버 내의 모듈 스레드가 이를 수신하고 위성 신호 대 잡음비(Carrier-to-Noise Ratio), 의사 거리(Pseudorange), 위상 관측치(Phase Observation)를 추출.
  3. 이 데이터들을 RTCM v3 규격에 해당하는 메시지 타입(예: 1005, 1077, 1087 등) 페이로드 비트 필드에 정렬(Bit Packing).
  4. Length 헤더 부착 및 CRC-24Q 계산 후 꼬리에 부착(Append).
  5. 최종 완성 프레임을 gps_inject_data 형태로 재편성 후 지상국이나 추종 기체로 MAVLink 송신.

이러한 바이너리 패킹 기술은 시프트(Shift) 연산자와 비트 마스킹(Bit Masking) 기법을 활용하여 C++ 구조체 안에서 메모리 정렬(Memory Alignment) 및 엔디안(Endianness)을 극복하도록 설계되어 있다. 이처럼 소프트웨어 시스템 내부의 메모리 복사 최소화 기술(Zero-copy)이 동반된 견고한 설계는 지연시간(Latency)을 핵심으로 여기는 RTK 엔진에서 매우 중요하다.

5. 요약 및 디버깅 팁

PX4-Autopilot 내 RTCM 디코딩 로직의 분석은 정밀 유도 무인기가 어떤 공학적 절차로 센서 데이터를 보정받는지 그 저수준 메커니즘을 드러낸다.

연구자 혹은 시스템 통합 엔지니어로서 uLog 데이터를 분석할 때, 드론이 여전히 ‘3D Fix’ 상태에 머물고 ’RTK Fix’로 진입하지 못하는 상황이 발생한다면 반드시 다음과 같은 소스코드 단계를 검증하라.

  • GCS 측 콘솔을 통해 GPS_RTCM_DATA 바이트 배열이 주기적으로 증가하고 있는지 파악하라.
  • PX4 디버그 콘솔(MAVLink Console 등)에서 listener gps_inject_data 명령어를 통하여 uORB를 거치는 트래픽 발생 여부를 조사하라.
  • 시리얼 버퍼 포화 오류(Overrun)나 CRC Check 불일치율이 드라이버 성능 모니터 데이터 지표에 기록되는지 확인하라. 이것은 UART 통신 선로의 물리적 노이즈가 주된 원인이기 때문이다.