# ROS2 PC 이관 체크리스트 이 대시보드는 **Mac에서 만들고, 가짜(mock) rosbridge 서버로 검증**했습니다. FAST-LIVO2가 실제로 도는 ROS 2 Humble PC로 옮겨서 마무리해야 할 것들을 정리합니다. 사용법 자체는 `PCD_Viewer_가이드.md`에 있습니다. 이 문서는 **이관과 남은 작업**만 다룹니다. --- ## 0. 지금 어디까지 확실한가 정직하게 갈라두면 실기에서 삽질이 줄어듭니다. | 항목 | 상태 | |---|---| | UI·측정(거리/포지션)·파일 로드 | ✅ 실제 PCD로 확인 | | rosbridge 프로토콜, 토픽 자동 바인딩, 누적, 카메라, 텔레메트리 | ⚠️ **목 서버로만 확인** — 실기 미검증 | | 라이브 맵 위 측정 | ⚠️ 목 서버 데이터로 확인 | | 복셀 다운샘플 누적 + 재색인 | ⚠️ 목 서버로 확인 (25초 세션에서 유지율 41%→20%로 수렴) | | 오프라인(CDN 차단) 구동 | ✅ unpkg 차단 상태로 확인 (3절) | | 실제 FAST-LIVO2 토픽 이름·타입·필드 | ❌ **미확인 — 4절에서 기록할 것** | | 실제 환경에서의 복셀 유지율·적정 크기 | ❌ 미확인 — 실기에서 6절 보고 조정 | --- ## 1. 옮길 파일 ``` pcd_viewer.html ← 대시보드 본체 (이거 하나면 동작) PCD_Viewer_가이드.md ← 사용법 ROS2_이관_체크리스트.md ← 이 문서 tools/mock-rosbridge.mjs ← 로봇 없이 테스트용 (선택, Node 필요) ``` `.pcd`는 옮길 필요 없습니다(용량만 큼). 실시간으로 볼 거고, 파일이 필요하면 그 PC에서 생성됩니다. ```bash scp -r ~/Documents/"pcd viwer" user@ros2-pc:~/pcd_dashboard ``` --- ## 2. 호스트 세팅 ### 2-1. rosbridge ```bash sudo apt install ros-humble-rosbridge-suite ros2 launch rosbridge_server rosbridge_websocket_launch.xml # :9090 ``` - `rosapi` 노드가 함께 떠야 합니다(위 launch에 포함). 토픽 목록을 읽는 데 씁니다. - 확인: `ros2 node list | grep -E "rosbridge|rosapi"` ### 2-2. 뷰어 서빙 ```bash cd ~/pcd_dashboard python3 -m http.server 8000 # 0.0.0.0 바인딩(기본) → 다른 PC에서도 접속 가능 ``` ### 2-3. 다른 PC에서 볼 때 - 브라우저: `http://<호스트IP>:8000/pcd_viewer.html` - LIVE 주소: `ws://<호스트IP>:9090` ← **localhost 아님** - 방화벽: 8000, 9090 열기 ```bash sudo ufw allow 8000/tcp && sudo ufw allow 9090/tcp ``` > **보안**: rosbridge는 인증이 없습니다. 붙는 사람이 토픽을 발행할 수도 있습니다. > 신뢰된 LAN 안에서만 쓰고, 공인 IP로 열지 마세요. --- ## 3. 로봇 PC가 오프라인이면 (Three.js 로컬화) 기본값은 CDN(unpkg)에서 Three.js를 받습니다. 인터넷이 없으면 뷰어가 아예 안 뜹니다. **아래 절차는 unpkg를 차단한 상태에서 실제로 검증했습니다.** 인터넷 되는 PC에서 받아서 같이 옮기면 됩니다: ```bash cd ~/pcd_dashboard mkdir -p vendor/three/controls vendor/three/loaders curl -L -o vendor/three/three.module.js https://unpkg.com/three@0.160.0/build/three.module.js curl -L -o vendor/three/controls/OrbitControls.js https://unpkg.com/three@0.160.0/examples/jsm/controls/OrbitControls.js curl -L -o vendor/three/loaders/PCDLoader.js https://unpkg.com/three@0.160.0/examples/jsm/loaders/PCDLoader.js ``` `pcd_viewer.html`의 importmap을 이렇게 고칩니다 (디렉터리 구조를 지켜야 addon들이 `three`를 찾습니다): ```html ``` --- ## 4. 첫 연결 — 순서와 기록할 것 ### 4-1. 먼저 ROS 쪽에서 확인 ```bash ros2 topic list -t # 이름과 타입을 함께 ros2 topic hz /cloud_registered # 발행 주파수 ros2 topic echo /cloud_registered --field fields --once # x/y/z/rgb/intensity 구성 ros2 topic echo /cloud_registered --field width --once # 스캔당 점 개수 ``` ### 4-2. 여기에 실제 값을 적어두세요 (지금은 추정) | 슬롯 | 뷰어가 기대하는 타입 | 실제 토픽 이름 | 실제 타입 | 비고 | |---|---|---|---|---| | CLOUD | `sensor_msgs/msg/PointCloud2` | (기록) | | 점/스캔: ___ , Hz: ___ | | ODOM | `nav_msgs/msg/Odometry` | (기록) | | | | PATH | `nav_msgs/msg/Path` | (기록) | | 없을 수도 있음 | | IMAGE | `sensor_msgs/msg/CompressedImage` | (기록) | | raw `Image`면 5-1 | > 뷰어는 **이름이 아니라 타입으로** 토픽을 찾습니다. 이름이 달라도 타입만 맞으면 드롭다운에 뜹니다. > 자동 선택이 틀리면 드롭다운에서 바꾸면 됩니다. ### 4-3. 대시보드 연결 1. 브라우저 → LIVE 칸에 `ws://localhost:9090` → `연결` 2. **토픽 4칸이 채워지는지** 확인 3. **TELEMETRY의 Hz가 뜨는지** 확인 (`—`면 그 토픽은 조용하다는 뜻) 4. 맵이 자라는지, `F`로 뷰가 맞는지 5. 거리 모드로 라이브 맵 위 두 점 측정 --- ## 5. 실기에서 걸릴 만한 것들 ### 5-1. 카메라가 안 뜬다 — 가능성 높음 지금은 `CompressedImage`만 받습니다. FAST-LIVO2는 `/origin_img`를 **raw `sensor_msgs/msg/Image`**로 낼 수 있고, 그러면 IMAGE 드롭다운이 비어 있습니다. 우회(권장 — 대역폭도 훨씬 유리): ```bash ros2 run image_transport republish raw in:=/origin_img compressed out:=/origin_img/compressed ``` 근본 해결: 뷰어에 raw Image 디코딩 추가 (7절). ### 5-2. 클라우드에 rgb가 없다 `rgb`가 없으면 `intensity`를 회색 계조로 씁니다. 둘 다 없으면 균일 회색입니다. FAST-LIVO2는 컬러 맵을 내므로 보통 `rgb`가 있지만, 설정에 따라 다릅니다. ### 5-3. 대역폭 전송은 JSON + base64라 바이너리의 약 1.33배입니다. 점당 16바이트면 **점당 약 21바이트**. ``` 대역폭 ≈ 점/스캔 × Hz × 21 B/점 예) 10,000 × 10 Hz × 21 B ≈ 2.1 MB/s ≈ 17 Mbps 30,000 × 10 Hz × 21 B ≈ 6.4 MB/s ≈ 51 Mbps ``` 같은 PC(localhost)나 유선 LAN이면 괜찮고, **Wi-Fi로 원격에서 보면 빠듯**합니다. ### 5-4. `rosapi 응답이 없습니다` rosbridge는 떴는데 rosapi가 없는 경우입니다. launch 파일을 확인하거나 `ros2 run rosapi rosapi_node`를 따로 띄우세요. --- ## 6. 누적 버퍼와 복셀 크기 정하기 `/cloud_registered`는 **매 스캔을 통째로** 내보내고 스캔끼리 공간이 크게 겹칩니다. 그대로 쌓으면 6M 버퍼가 **1분 남짓**에 찹니다(1만 점 × 10Hz 기준). 그래서 **복셀 누적이 기본으로 켜져 있습니다**(5cm). 이미 점이 있는 복셀의 점은 버리므로, 누적량이 **돌린 시간이 아니라 본 공간 크기**에 비례합니다. 원리는 가이드 6-3절. ### 6-1. 실기에서 할 일: 유지율 보고 크기 정하기 TELEMETRY의 **복셀** 행에 `5cm · 유지 18.0%`처럼 나옵니다. | 유지율이 | 뜻 | 조치 | |---|---|---| | 계속 50~100% | 복셀이 너무 작아 사실상 원본을 쌓는 중 | 크기를 키우세요 | | 시간이 갈수록 하강·수렴 | 정상. 새로 보는 공간만 늘고 있음 | 그대로 | | 5% 이하인데 맵이 성김 | 복셀이 너무 큼 | 줄이세요 | 크기를 바꾸면 **이미 쌓인 점도 즉시 재색인**됩니다(키우면 그 자리에서 솎임). 목 서버 기준 20cm → 50cm 재색인에서 108,690점 → 7,799점(7.2%)으로 줄었습니다. ### 6-2. 그래도 부족하면 ``` 버퍼가 차는 시간 ≈ LIVE_CAP / (점/스캔 × Hz × 유지율) ``` - **LIVE_CAP 상향**: `pcd_viewer.html`의 `const LIVE_CAP = 6_000_000;` → 예: `40_000_000`. 메모리는 **점당 약 15바이트**(40M ≈ 600MB). 좋은 PC면 감당됩니다. - **누적 맵 토픽 구독**: FAST-LIVO2가 누적 맵 토픽(`/cloud_map` 등)을 낸다면, 그걸 물리고 **매번 통째로 교체**하는 방식이 더 쌀 수 있습니다. → 4-2에서 실제 토픽 확인. > 복셀을 **끄면** 원본을 그대로 쌓습니다. 짧고 고밀도인 계측용입니다. 버퍼는 빨리 찹니다. > 가득 차면 조용히 버리지 않고 **"가득 참"이라고 말하고 멈춥니다.** --- ## 7. 남은 개발 항목 (우선순위 순) > **완료**: 복셀 다운샘플 누적(크기 슬라이더 + 재색인 포함). 6절 참고. > 다만 복셀 인덱스는 `Set`이라 점 하나당 수십 바이트를 씁니다. 유지 점수가 수백만을 > 넘어가면 타입드 배열 해시로 바꾸는 게 다음 최적화입니다(지금은 필요 없을 가능성이 큼). ### 7-1. raw `sensor_msgs/msg/Image` 지원 - `CompressedImage`가 없는 환경 대비(5-1). rgb8/bgr8/mono8 → canvas ImageData. - 대역폭이 크므로 throttle 필수. ### 7-2. CBOR 전송 - `subscribe`에 `compression: 'cbor'` + CBOR 디코더. base64 오버헤드(1.33배)를 없앱니다. - 원격에서 볼 때만 의미 있음. localhost면 후순위. ### 7-3. 라이브 맵 저장 - 지금은 누적본을 **내보낼 수 없습니다**. FAST-LIVO2가 자체 저장하므로 필수는 아니지만, "지금 화면의 이 맵"을 `.pcd`로 떨구는 버튼이 있으면 계측 워크플로에 유용합니다. ### 7-4. GPS 지오레퍼런싱 (위경도 표시) - 가이드 8절 참고. 실시간이 붙었으므로 `sensor_msgs/msg/NavSatFix` 슬롯을 하나 더 두면 세션 중에 궤적↔GPS 정합을 계산할 수 있습니다. ### 7-5. 기타 후보 - 화면 하단 미니맵(위에서 본 궤적), 뷰 프리셋(Top/Front/Side) - 여러 세션 비교(파일 + 라이브 동시 표시) — 지금은 활성 클라우드가 하나뿐입니다 --- ## 8. 로봇 없이 테스트하기 (mock) FAST-LIVO2를 안 켜고 대시보드만 확인할 때 씁니다. **Node 18+ 필요**(의존성 없음). ```bash node tools/mock-rosbridge.mjs # ws://localhost:9090 ``` 가짜로 내보내는 것: `/cloud_registered`(10Hz, 컬러 PointCloud2), `/aft_mapped_to_init`(20Hz), `/path`(5Hz), `/origin_img`(5Hz, PNG). 뷰어에서 `ws://localhost:9090`으로 연결하면 실제와 같은 경로로 동작합니다. > 이 목 서버는 **개발용**입니다. 실기 검증을 대신하지 못합니다 — 실제 토픽 이름·필드·주파수는 > 4절에서 반드시 확인하세요. --- ## 9. 이관 순서 요약 1. 파일 복사 (1절) 2. 오프라인이면 Three.js 로컬화 (3절) 3. rosbridge + http.server 실행 (2절) 4. `ros2 topic list -t`로 **실제 토픽 기록** (4-2) 5. 대시보드 연결 → 4칸·Hz·맵 성장 확인 (4-3) 6. 카메라 안 뜨면 republish (5-1) 7. **복셀 유지율 확인** → 크기 조정. 그래도 모자라면 LIVE_CAP 상향 (6절)