13.3.2.2. VRS(Virtual Reference Station) 망 연동: QGC 백엔드에서 NMEA GGA 메시지 자동 생성 및 캐스터(Caster) 역전송 주기(1Hz) 로직
네트워크 RTK (NTRIP) 시스템이 단순히 정적(Static) 베이스 스테이션의 데이터를 일방적으로 전달받기만 하는 과거의 브로드캐스팅(Broadcasting) 방식을 넘어서기 시작한 것은 가상 기준점(VRS, Virtual Reference Station) 개념의 도입 덕분이다. VRS 시스템에서 드론은 자신을 중심으로 한 반경 수 센티미터 이내의 맞춤형 전리층 보정 데이터를 캐스터(Caster) 서버로부터 발급받기 위해, 자신의 현재 위치를 끊임없이 서버로 역업로드(Reverse-upload)해야 한다.
본 절에서는 QGroundControl(QGC)이 어떻게 인터넷 망을 타고 캐스터와 대화하는지 분석하며, QGC 백엔드 C++ 코드가 에 의존하여 NMEA $GPGGA 문장을 조립하고 이를 캐스터로 1\text{Hz} 주기로 전송하는 소프트웨어 메커니즘을 심층 해부한다.
1. VRS 아키텍처와 양방향 통신의 필연성
과거 단방향 NTRIP 마운트포인트에 접속하면, 사용자는 단순히 가장 가까운 물리적 관측소 한 곳의 데이터를 받았다. 기체가 기준국에서 멀어질수록(Baseline Extention) 대기권 굴절 오차가 다르게 작용하여 센티미터급 정밀도를 잃게 된다.
그러나 최신 VRS 마운트포인트(예: VRS-RTCM31)를 호출하면 중앙 서버는 클라이언트(드론)의 3D 좌표를 요구한다.
- 좌표 수신: 서버가 드론의 현재 위치 정보를 받아들인다.
- 보간 매트릭스 도출: 드론 주변에 위치한 실제 CORS 관측소 3~4곳의 데이터를 취합하여, 드론의 정확한 위치 상공에 가상의 베이스 스테이션이 존재하는 것처럼 이온층/대류권 오차를 수학적으로 보간(Interpolate)해낸다.
- 개인화된 RTCM 전송: 오직 이 특정 드론 하나만을 위해 최적화된 RTCM3 패킷을 캐스터를 통해 내려보낸다.
이 프로세스를 유지하기 위해서는, 비행 중인 기체의 위치가 이동할 때마다 QGC가 최신 NMEA 파라미터를 캐스터에게 지속적으로 쏘아주어야 하는 ’양방향 통신 루프’가 필수적이다.
2. QGC 통신망 구조와 MAVLink 브릿징 Механизм
QGC 클라이언트는 기체의 상태를 보고하는 MAVLink 메시지를 텍스트 기반의 국제 표준 해양 통신 규격인 NMEA(National Marine Electronics Association) 0183 문장으로 번역해야 한다. 이 연산은 GPSManager 와 연동된 NTRIP C++ 계층에서 백그라운드 스레드로 처리된다.
2.1 MAVLink 위치 메시지 수집 (Data Fetching)
드론 내부의 PX4-Autopilot은 현재 내부 GPS 칩셋이 산출해 낸(자체 오차가 포함된 Float 형태의) 원시 3D 좌표를 $1\text{Hz} \sim 5\text{Hz}$ 주기로 MAVLink GLOBAL_POSITION_INT(ID: 33) 혹은GPS_RAW_INT` (ID: 24) 패킷에 담아 지상으로 내보낸다.
QGC의 텔레메트리 매니저 클래스는 이 패킷을 낚아채어 위도(Latitude), 경도(Longitude), 그리고 해수면 고도(AMSL, Altitude) 멤버 변수를 추출한다.
2.2 NMEA $GPGGA 파싱(Parsing) 및 스트링 조합 로직
추출된 부동 소수점 각도 좌표계는 NMEA 0183 통신 포맷인 $GPGGA 의 복잡한 아스키(ASCII) 문자열 구조로 재조립(String concatenation)되어야 한다. C++ 계층에서는 sprintf나 QString::asprintf 함수를 사용하여 다음과 같은 버퍼(Buffer) 양식을 채워 넣는다.
$GPGGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh
hhmmss.ss: QGC가 현재 인식한 UTC 시간(Timestamp).llll.ll,a: 위도 정보(a는 N 또는 S). DDMM.MMMMM 형태로 변환 연산(도, 분)이 수행된다.yyyyy.yy,a: 경도 정보(a는 E 또는 W).x: GPS Quality Indicator (보통 단독 측위 상태를 의미하는1로 세팅하여 보냄).x.x,M: MAVLink에서 넘겨받은 해수면 고도(Meters).*hh: 앞에 쓰인 모든 문자의 XOR 연산을 통해 도출한 8비트 체크섬(Checksum, Hex).
이 NMEA 문장의 끝에는 반드시 통신 종단 바이트인 \r\n (CRLF)를 부착해야만 캐스터 서버가 한 줄의 끝(End-of-line)을 인식한다.
3. 캐스터(Caster) 역전송 주기 제어와 소켓 핸들링
NMEA 문자열 조립이 끝났다고 끝이 아니다. 이를 어느 주기로 캐스터 소켓 파이프라인(TCP)에 꽂아 넣을 것인지 타이밍 제어(Throttling)를 수행해야 한다.
3.1 1\text{Hz} 타이머 스레드 운용
QGC의 C++ NTRIP 클라이언트 객체 내에는 전용 QTimer 가 1000\text{ ms} (1\text{Hz}) 주기로 회전하고 있다.
만약 MAVLink GPS_RAW_INT 메시지가 5\text{Hz} 의 광속으로 쏟아진다 해도, QGC는 이 NMEA 변환을 매번 수행하여 인터넷 소켓을 향해 무차별 폭격을 가하지 않는다. 왜냐하면 캐스터 서버 입장에서 단일 클라이언트로부터 초당 5\text{회}의 $GPGGA 텍스트가 날아오면 이를 디도스(DDoS)성 트래픽 요건으로 간주하여 해당 클라이언트의 IP를 강제 블록(Ban)시켜 버릴 수 있기 때문이다.
따라서 QTimer는 정확히 1\text{초} 에 한 번씩만 최신 MAVLink 객체 캐시 포인터에 접근하여 NMEA 구조체를 생성하고 QTcpSocket::write() 함수를 통해 캐스터 스트림 버퍼로 밀어 올린다.
3.2 상태 비동기(Asynchronous) 소켓 에러 처리
인터넷 연결이 약해져서 1\text{Hz} 주기로 밀어 넣은 NMEA 텍스트의 TCP \text{ACK} 피드백이 오지 않거나, 서버 측 파이프가 혼잡해져 소켓이 블로킹(Blocking) 될 위기에 처하면, QGC의 시그널-슬롯 로직은 이 I/O 에러를 감지한다. 이 순간 QGC는 로컬 텔레메트리로 전송되던 MAVLINK_MSG_ID_GPS_RTCM_DATA 스레드를 즉각 일시 통제하고, 사용자 UI 화면 최상단에 “NTRIP Network Connection Reconnecting…” 이라는 경고 알럿(Alert)을 띄우게 된다.
결과적으로, PX4 기체가 하늘에서 한 뼘을 이동할 때, 그 변경된 좌표는 텔레메트리 보드를 통해 400미터를 내려와 노트북의 C++ 코어를 거치고, NMEA 형태의 텍스트로 치환되어 또다시 수백 킬로미터 밖의 캐스터 서버 소켓 망을 타고 들어간다. 서버는 즉각 이에 맞춰진 진리(RTCM) 데이터를 되돌려준다. 이 무한한 1Hz 단위의 양방향 루프 연산이야말로, 단순 GPS 수신기를 밀리미터 단위의 고해상도 측량기로 승격시키는 현대 항공 IT 기술의 거대한 혈관 시스템이다.