8.8 KiB
RTK(UM982) ROS 2 녹화 명세서
대상: UM982(WTRTK-982) RTK 수신 데이터를 ROS 2 로 발행·녹화하기 위한 이관/구성 명세. 구현체:
um982_driver(C++ ROS 2 노드). 근거 문서:rtk/UM982-명령어검토-및-바이너리포팅.md. 검증: 국가 통합기준점 U0373/U0374 대비 수평 1.4~2.6cm (rtk/Log.md).
1. 개요 & 데이터 흐름
NTRIP(VRS,KGD2002) ──RTCM3──▶ UM982 ──BESTNAV(binary)+GGA(ascii)──▶ um982_driver
▲ │
└──────────────── GGA(VRS 유지, 10s) ◀───────────────────────────┘
│ GnssPVTSolnMsg (10Hz)
▼
/ublox_driver/receiver_pvt
│
ros2 bag record ──▶ .db3/.mcap
- 시리얼 포트는 한 프로세스만 점유 → RTCM 주입과 BESTNAV 파싱이 한 노드(
um982_driver)에 통합. - 녹화는 이 노드가 발행하는 토픽을
ros2 bag record로 담는다.
2. 이관 대상 & 워크스페이스 구성 (무엇을 어떻게 옮기나)
옮길 패키지 2개 (그 외 의존 없음 — 시리얼=termios, NTRIP=POSIX 소켓):
| 패키지 | 역할 | 위치(원본) |
|---|---|---|
gnss_comm |
GnssPVTSolnMsg/GnssTimeMsg 메시지 정의 |
FAST-LIVO2-RTK-ROS2/thirdparty/gnss_comm |
um982_driver |
드라이버 노드(파싱+NTRIP+발행) | FAST-LIVO2-RTK-ROS2/src/um982_driver |
녹화 전용 최소 워크스페이스 (전체 FAST-LIVO2 빌드 불필요):
fhd_rtk_ws/
└── src/
├── gnss_comm/ ← thirdparty/gnss_comm 복사
└── um982_driver/ ← src/um982_driver 복사
cd fhd_rtk_ws
colcon build --packages-select gnss_comm um982_driver
source install/setup.bash
ROS 2 Humble, C++17.
um982_driver는rclcpp,gnss_comm만 의존.
3. 사전 조건 — 수신기 설정 (필수)
드라이버 실행 전 UM982 가 아래를 저장(SAVECONFIG) 하고 있어야 한다. 리포 rtk/config_all.py 한 번 실행:
| 항목 | 값 | 이유 |
|---|---|---|
BESTNAVB COM3 0.1 |
10Hz 바이너리 | 파싱 소스 |
GPGGA COM3 1 |
1Hz | NTRIP VRS 업링크 |
| COM3 baud | 460800 |
RTCM+로그 대역 |
MODE ROVER |
— | 로버 측위 |
CONFIG RTK RELIABILITY 3 1 |
기본 | 오확정 방지 |
⚠️
FRESET시 baud 가 115200 으로 초기화됨 →rtk/set_baud.py재실행 필요.
4. 토픽 & 메시지 명세
4.1 토픽
| 항목 | 값 |
|---|---|
| 토픽명 | /ublox_driver/receiver_pvt (파라미터 gps_topic) |
| 타입 | gnss_comm/msg/GnssPVTSolnMsg |
| 발행 주기 | BESTNAV 주기 = 10 Hz (0.1s) |
| QoS | KeepLast(2000), 기본 신뢰성(reliable) |
| 프레임/스탬프 | 메시지에 std_msgs/Header 없음. 시간은 메시지 내부 time.week/tow |
4.2 GnssPVTSolnMsg 필드 (드라이버가 채우는 값)
| 필드 | 타입/단위 | 채움 | BESTNAV 소스 |
|---|---|---|---|
time.week |
uint32 (GPS week) | ✅ | 헤더 Wn |
time.tow |
float64 (초) | ✅ | 헤더 Ms÷1000 |
latitude |
float64 (deg) | ✅ | lat |
longitude |
float64 (deg) | ✅ | lon |
altitude |
float64 (m, 타원체고) | ✅ | hgt(MSL)+undulation |
height_msl |
float64 (m) | ✅ | hgt |
h_acc |
float64 (m) | ✅ | √(latσ²+lonσ²) |
v_acc |
float64 (m) | ✅ | hgtσ |
vel_n/vel_e/vel_d |
float64 (m/s, NED) | ✅ | hor·cos(trk)/hor·sin(trk)/−vert |
vel_acc |
float64 (m/s) | ✅ | Horspd std |
num_sv |
uint8 | ✅ | #solnSVs |
fix_type |
uint8 (0=no,3=3D) | ✅ | pos_type |
valid_fix |
bool | ✅ | pos_type≠NONE |
diff_soln |
bool | ✅ | pos_type∉{NONE,SINGLE} |
carr_soln |
uint8 (0/1/2) | ✅ | 48/49/50→2, 32/33/34→1, else 0 |
p_dop |
float64 | ➖ 0 | BESTNAV 미제공(필요시 PVTSLN) |
carr_soln: 2=RTK Fixed(NARROW_INT 등), 1=RTK Float, 0=단독/DGPS.
5. 드라이버 파라미터 명세 (config/um982.yaml)
| 파라미터 | 기본값 | 설명 |
|---|---|---|
serial_port |
/dev/ttyUSB0 |
UM982 COM3(USB). 리눅스 /dev/ttyUSB* |
serial_baud |
460800 |
수신기 저장값과 일치 |
gps_topic |
/ublox_driver/receiver_pvt |
발행 토픽(백엔드 gps.gps_topic 와 일치) |
use_ntrip |
true |
false 면 RTCM 주입 안 함(외부 보정 시) |
ntrip_host/port/mountpoint |
RTS1.ngii.go.kr / 2101 / VRS-RTCM34 |
NTRIP 접속 |
ntrip_user/pass |
"" |
⚠️ 리포 평문 커밋 지양 — yaml/CLI/환경변수로 주입 |
gga_send_period |
10.0 |
VRS 유지용 GGA 재전송 주기(s) |
publish_fixed_only |
false |
true=RTK Fixed 해만 발행 |
inflate_cov_when_not_fixed |
true |
fix 아님/코스팅 시 h_acc·v_acc 부풀림 |
max_corr_age |
30.0 |
diff_age 초과 시 코스팅 간주(공분산↑). 0=비활성 |
NTRIP 끊겨도 UM982 는
RTK TIMEOUT(기본 600s) 동안 Fixed 를 코스팅 유지 →max_corr_age로 신뢰 낮춤.
6. 시간 의미 (중요)
- 메시지에 Header/stamp 가 없다. 시간은
time.week(GPS week) +time.tow(주 내 초). - UNIX 복원:
unix = week·604800 + tow + 315964800 − 18(leap)(백엔드optimization.cpp::gpsHandler와 동일). - 유효 조건: 헤더 TimeStatus=
FINE& week>1 (fix 전에는 week=1/UNKNOWN). ros2 bag은 수신 시각(bag timestamp) 을 별도로 기록하지만, 권위 시각은 메시지 내부 week/tow. 센서와의 시각 동기는 이 값 기준.
7. 녹화 절차
7.1 실행
source install/setup.bash
ros2 launch um982_driver um982_driver.launch.py # 또는 아래 run
# 자격증명을 CLI 로 주입:
ros2 run um982_driver um982_driver_node --ros-args \
--params-file src/um982_driver/config/um982.yaml \
-p ntrip_user:=<id> -p ntrip_pass:=<pw>
콘솔에 RTK FIXED 전환 로그가 뜨고, ros2 topic hz /ublox_driver/receiver_pvt ≈ 10Hz 확인.
7.2 GNSS 단독 녹화
ros2 bag record -o rtk_$(date +%F_%H%M) /ublox_driver/receiver_pvt
7.3 센서 + GNSS 동시 녹화 (FAST-LIVO2 후처리용)
ros2 bag record -o run_$(date +%F_%H%M) \
/livox/lidar /livox/imu /left_camera/image \
/ublox_driver/receiver_pvt \
--storage mcap # 없으면 sqlite3(기본)
초기 수십 초 RTK Fixed + 충분한 이동 후 녹화(백엔드 SVD 정합 전제).
rtk/UM982-녹화-및-연동-구현.md§7 참조.
7.4 (권장) 원시 BESTNAV 동시 녹화 — 재처리 대비
현재 드라이버는 파싱 결과만 발행한다. 파싱 로직을 나중에 고쳐 재생성하려면 원시 바이트도 함께 남기는 것을 권장(별도 옵션 필요 — §10).
8. 녹화 데이터 포맷 & 재생
- 저장: ROS 2 bag (
sqlite3.db3기본, 또는mcap.mcap). - 확인:
ros2 bag info run_YYYY-MM-DD_HHMM→ 토픽/메시지 수/기간. - 재생:
ros2 bag play run_YYYY-MM-DD_HHMM→/ublox_driver/receiver_pvt재발행. - FAST-LIVO2 백엔드는 이 토픽을 구독해 첫 fix 를 ENU 원점으로 잡고 GTSAM 융합(
gps.gps_topic일치 필요).
9. 품질/필터 (녹화되는 데이터의 신뢰)
- 백엔드에 fix 품질 필터가 없으므로 드라이버 단에서 처리:
publish_fixed_only=true→ RTK Fixed 해만 녹화(가장 보수적).inflate_cov_when_not_fixed=true+max_corr_age→ fix 아님/코스팅 시h_acc/v_acc를 키워 후처리 가중 약화.
- CRC(Unicore Appendix 1) 통과 프레임만 발행 → 손상 프레임 녹화 안 됨.
10. 확장(옵션) — 원시 스트림 동시 녹화
재처리·디버깅을 위해 원시 BESTNAV/GGA 바이트를 별도 토픽으로 녹화하려면 드라이버에
std_msgs/msg/ByteMultiArray(또는 String) 발행부를 추가하면 된다(예: /um982/raw).
필요 시 요청 → 드라이버에 publish_raw 파라미터로 추가.
11. 검증 체크리스트
rtk/config_all.py로 수신기 설정 저장(BESTNAVB/GPGGA, 460800, MODE ROVER)colcon build --packages-select gnss_comm um982_driver성공serial_port/ NTRIP 자격증명(config or CLI) 확인ros2 topic hz /ublox_driver/receiver_pvt≈ 10Hz, 콘솔RTK FIXEDros2 topic echo로 lat/lon/altitude, time.week(>1)/tow, carr_soln=2 확인ros2 bag record→ros2 bag info로 토픽·기간 확인- (동시녹화) 센서 4종 + GNSS 토픽 모두 bag 에 존재