LiDAR + 오도메트리 융합
오도메트리로 즉시 시작하고 LiDAR로 보정하는 하이브리드 위치 측정으로 지연 없는 응답성 확보
ros
배경
Wally (벽면 리프트)는 가이드 레일 추적을 위해 RPLidar C1을 사용합니다.
제약:
- LiDAR를 계속 돌리면 모터 소음이 들립니다 (가전제품으로서 납득하기 어려울 정도).
- 연속 작동은 LiDAR 모터 수명도 단축시킵니다.
- LiDAR 시작에 ~3초가 걸립니다 (초기화 + 안정화).
목표: LiDAR의 정밀도는 유지하면서 움직임 시작은 즉각 반응하게 만들기.
핵심 문제
움직이기 전에 LiDAR가 준비될 때까지 기다리면 3초 지연이 생깁니다. UX가 좋지 않습니다.
두 가지 이슈가 있습니다:
- 시작 지연: LiDAR 스핀업, 안정화, 디바운스 체크에 시간이 필요합니다.
- 신뢰성 문제: LiDAR만 쓰면 가려지거나 일시적으로 데이터가 없을 때 위치를 잃습니다.
핵심 아이디어
오도메트리는 즉시 위치를 알려주지만 시간이 지나면 오차가 누적됩니다. LiDAR는 절대 위치를 주지만 시작 시간이 필요합니다.
해결책: 오도메트리로 바로 시작하고, LiDAR가 준비되면 누적된 오차를 보정합니다.
접근 방식
1) 오도메트리 우선 시작 + 백그라운드 LiDAR 초기화
이동 명령이 들어오면:
| 조건 | 동작 |
|---|---|
| Y/각도가 이미 보정됨 | 오도메트리로 바로 시작 |
| 첫 이동 (보정 전) | 최초 보정을 위해 LiDAR 대기 |
한번 보정되면 이후 모든 이동은 오도메트리로 바로 시작합니다. LiDAR를 기다릴 필요가 없습니다.
2) 끊김 없는 소스 전환
입력 소스는 guide_valid 플래그에 따라 바뀝니다:
| LiDAR 상태 | 위치 소스 | 각도 소스 |
|---|---|---|
| 데이터 있음 | LiDAR 직접 | LiDAR 직접 |
| 데이터 없음 | 오도메트리 + 저장된 보정값 | 오도메트리 + 저장된 보정값 |
보정값 저장: LiDAR 데이터가 들어올 때 map_to_odom 오프셋(x, y, yaw)을 업데이트합니다. 데이터가 끊기면 저장된 보정값을 오도메트리에 적용합니다.
3) LiDAR 라이프사이클 관리 (LidarFsm)
RPLidar 공식 노드는 라이프사이클 제어를 지원하지 않아서 직접 상태 머신을 구현했습니다:
WaitDevice → Init → Running ⇄ Idle
- Idle 상태: 안 쓸 때 모터를 정지시켜 소음을 제거합니다.
- 디바운스: 첫 감지 시 카운트 2배, 이후 1배로 처리합니다.
- LiDAR 독립 설계: 핸들러 콜백으로 다른 LiDAR로 쉽게 교체할 수 있습니다.
트레이드오프
- 초기 이동 시 정확도: LiDAR 보정이 오기 전까지(~3초)는 정확도가 낮습니다.
- 보정값 drift: LiDAR 데이터가 오래 끊기면 저장된 보정값이 실제와 어긋납니다.
검증
Wally v2 프로토타입에서 테스트했습니다:
- 오도메트리 우선 시작이 전원을 껐다 켜도 안정적으로 동작
- 소스 전환해도 위치가 튀지 않음
- Idle 상태로 모터 소음 제거
결과
| 지표 | 이전 | 이후 |
|---|---|---|
| 이동 시작 지연 | ~3초 (LiDAR 대기) | 0초 (오도메트리 우선) |
| LiDAR 보정 도착 | - | ~3초 평균 |
| 대기 시 모터 소음 | 계속 울림 | 무음 |
- 끊김 없는 전환: 오도메트리 ↔ LiDAR 전환 시 위치 점프 없음
- LiDAR 수명 연장: Idle 상태 관리로 모터 마모 감소
핵심 교훈
오도메트리 우선 + LiDAR 보정으로 즉각 응답과 절대 정확도 둘 다 확보했습니다:
- 오도메트리로 바로 시작하고, LiDAR가 준비되면 보정
- LiDAR 끊김에 대비해 보정값 저장
- LidarFsm으로 라이프사이클 관리 (소음 감소 + 수명 연장)