### 0.0.1 UBX 프레임 헤더(0xB5 0x62), 클래스(Class), ID, 페이로드 길이 및 16비트 Fletcher 체크섬 아키텍처
U-Blox 고유의 UBX 바이너리 프로토콜은 모든 메시지 패킷이 단 한 글자의 예외도 용납하지 않는 엄격하고 통일된 바이트(Byte) 배열 규칙을 따른다. NMEA처럼 쉼표를 찾으러 다닐 필요 없이, 수신된 바이트들을 C/C++ 구조체 메모리에 그대로 밀어 넣어(Type Casting) 직관적으로 디코딩할 수 있는 패러다임을 제공한다.
하나의 완전한 UBX 메시지 프레임(Frame)은 다음과 같은 6개의 계층화된 세그먼트로 구성된다.
- Sync Char 1 (
0xB5,µ) - Sync Char 2 (
0x62,b) - Class (1 Byte)
- ID (1 Byte)
- Payload Length (2 Bytes, Little Endian)
- Payload (가변 길이, Length 바이트만큼)
- Checksum (2 Bytes, CK_A, CK_B)
본 절에서는 이 구조가 왜 실시간 파싱(RTOS) 환경에서 그토록 강력한 성능을 발휘하는지 각 세그먼트의 역할과 아키텍처적 관점에서 조명한다.
0.1 동기화 헤더(Sync Chars)와 매직 넘버(Magic Number)
PX4의 GPS 직렬 파서는 언제 들이닥칠지 모르는 노이즈 속에서 진짜 위성 데이터의 시작점을 극도의 확률적 구별력을 통해 잡아내야 한다.
- UBX의 시작을 알리는 동기화 바이트 2개는 항상 16진수
0xB5와0x62의 조합으로 고정되어 있다. 이를 ASCII 코드 문자로 치환하면 마이크로(Micro)를 뜻하는 특수기호µ와 알파벳 소문자b(µ-blox의 상징)가 된다. - 이 두 바이트의 시퀀스가 임의의 노이즈 데이터 스트림 내부에 우연히 연속으로 발생할 확률은 1/65536 이다. 만약 파싱 중 체크섬 검증에 실패하여 상태 머신이 리셋되더라도, 파서 엔진은 입력 버퍼를 뒤지며 다시 단숨에
0xB5 0x62를 낚아채어 다음 프레임의 추적을 재개(Resync)할 수 있다.
0.2 메시지 분류 체계: Class와 ID의 2차원 매핑
UBX 프로토콜은 자신이 내뿜는 수십 가지 메시지들을 체계적으로 라우팅(Routing)하기 위해, 내용의 성격에 따라 대분류(Class)와 소분류(ID)라는 두 개의 바이트 계층 구조를 둔다.
- Class (대분류): 내비게이션 결과물(
NAV,0x01), 모듈 하드웨어 설정(CFG,0x06), 위성 상태 모니터링(MON,0x0A), 수신기 측위 정보(RXM,0x02) 등으로 크게 묶인다. - ID (소분류): 대분류 내에서 개별 패킷을 특정한다. 예를 들어 Class가
0x01(NAV)일 때, ID0x07은 위치/속도/시간 통합 정보(PVT)를 의미하고, ID0x04는 정밀도 정보(DOP)를 지시한다. - 통역기(Dispatcher)의 이점: PX4 소스코드는 구조체를 열어 이
[Class][ID]조합을switch-case문으로 즉각 판별한다. 만약 EKF2가 요구하지 않는MON계열 메시지(0x0A)가 들어왔다면, 뒤따라오는 수십 바이트의 페이로드를 일일이 분석할 필요 없이 Length만큼 버퍼 포인터를 점프(Skip)시켜 버리면 그만이다.
0.3 리틀 엔디안(Little Endian) 기반 페이로드 길이(Length) 정의
UBX 패킷 헤더의 5번째와 6번째 바이트는 바로 뒤에 따라붙을 실제 데이터(Payload) 덩어리가 몇 바이트인지 알려주는 페이로드 길이(Length) 영역이다.
- 16비트 정수(최대 65535바이트) 공간을 할당받아, 통상 40~100바이트 내외로 끝나는 단기 메시지부터 수천 바이트에 달하는 위성 궤도력(Ephemeris) 덤프까지 유연하게 수용한다.
- 엔디안 특성 일치: 가장 결정적인 효율성은 이 Length 값과 이후 페이로드 내부의 모든 정수/실수형 데이터가 일관되게 리틀 엔디안(Little Endian) 배열 포맷을 채택했다는 점이다. 공교롭게도 PX4를 구동하는 ARM Cortex-M 계열 MCU도 리틀 엔디안 연산 구조를 지닌다. 따라서 도착한 직렬 버퍼 배열의 주소(Address)에 대고 C 언어의 구조체형 체(Sieve) 포인터 단 하나만 캐스팅(Casting)해 씌워주면, 엔디안을 뒤집어 변환하는 빅-리틀 간 함수 호출 비용조차 0(Zero)으로 수렴하게 된다.
0.4 16비트 Fletcher 체크섬 알고리즘 무결성 검증
가변 길이인 페이로드 배열이 모두 전송된 직후, 패킷의 꼬리에는 메시지가 손상되지 않았음을 증명하는 2바이트 크기의 체크섬(CK_A, CK_B)이 자리한다. NMEA가 취약한 단순 XOR 방식을 쓰다 비트 상쇄 결함에 노출된 것과 달리, UBX는 훨씬 더 강력하고 연산량은 해시(Hash)급으로 가벼운 RFC 1145 Fletcher’s Checksum 8비트 듀얼 누산 버전을 채택했다.
- Fletcher 수식 메커니즘:
체크섬 영역 두 변수(CK_A,CK_B)는0으로 초기화된다. 대상 범위는 Sync 문자를 제외한 Class 바이트부터 Payload의 맨 마지막 바이트까지이다. 파서는 이 범위 내의 바이트 데이터(Buffer[i])가 하나씩 도착할 때마다 아래 두 줄의 식을 반복 수행한다.CK_A = CK_A + Buffer[i] CK_B = CK_B + CK_A
이후 도출된 `CK_A`와 `CK_B` 값이 전송된 꼬리의 체크섬 두 바이트와 정확히 일치해야만 메시지를 승인(Ack)한다.
* **오류 검출의 우월성**: 단순 XOR가 놓치고 마는 '연속된 짝수 비트 반전(Bit Flip)'이나 '바이트 순서 뒤바뀜(Transposition)' 에러를, Fletcher 알고리즘은 누산기 `CK_B`가 과거 데이터의 가중치를 누적 기억하고 있기 때문에 거의 100% 잡아낸다. 비행 제어기 입장에서는 CRC-16 급의 에러 검출 성능을 발휘하면서도 나눗셈(Division)이나 비트 시프트(Bit-shift) 같은 무거운 연산 없이 오직 피연산자끼리의 단순 덧셈(Addition)만으로 무결성 장벽을 칠 수 있는 궁극의 타협점인 셈이다.