같은 날 로봇암을 RViz에 연동하는 쪽에서도 문제가 셋 났어요. 이번엔 코드가 아니라 운영이 문제였어요. 빌드 경로, 가상화, 그리고 네트워크 디스커버리요.
패키지는 찾는데 실행 파일만 못 찾을 때
ros2 run이 “No executable found”를 냈어요. 패키지는 인식하는데 실행 파일만 없다는 메시지예요.
WSL2에서 USB 시리얼을 쓰는 두 가지 길
WSL2는 경량 가상 머신이라 윈도우의 USB 장치가 자동으로 안 보여요. 로봇암은 윈도우의 COM 포트에 물려 있는데 ROS 2 노드는 WSL 안에서 돌아야 하니, 둘을 이어줄 다리가 필요해요.
| 방식 | 원리 | 장점 | 대가 |
|---|---|---|---|
| usbipd-win | USB 장치 자체를 WSL에 넘김 | 진짜 시리얼 포트처럼 보임 | 관리자 권한 · 다시 꽂을 때마다 attach |
| TCP 릴레이 | 윈도우에 COM↔TCP 스크립트를 두고 pyserial이 소켓 URL을 포트처럼 엶 | 관리자 권한 없이 바로 됨 | 왕복 지연 100 ms 수준 |
이번엔 아래쪽을 썼어요. 브리지 노드는 소켓으로 받은 시리얼 응답을 ROS 토픽으로, 토픽으로 들어온 명령을 시리얼 문자열로 옮겨주는 번역자 역할이에요. 15 Hz 각도 스트리밍에는 100 ms면 충분하고, 더 촘촘한 제어 주기가 필요해지면 그때 usbipd로 넘어가면 돼요. 릴레이는 스크립트 한 파일이라 걷어내기도 쉬워서, 요구 수준에 맞는 가장 싼 다리를 먼저 놓는 선택이었어요.
통신이 너무 잘 돼서 난 문제
가장 재밌는 문제는 RViz였어요. 로봇 모델이 안 뜨고 관절 슬라이더도 엉뚱하게 움직였어요. 원인은 통신이 아니라 통신이 너무 잘 된 것이었어요.
ROS 2는 미들웨어인 DDS의 자동 디스커버리로 노드들을 이어줘요. 노드가 켜지면 같은 호스트, 같은 ROS_DOMAIN_ID(기본 0)에 있는 노드들이 서로를 자동으로 찾아 연결돼요. 중앙 서버 없이도 토픽이 이어지는 편리한 구조인데, 이날은 그 자동이 문제가 됐어요.
“토픽은 많은데 내 노드가 이상하다” 싶으면 ros2 topic list로 남의 스택이 섞여 있는지 먼저 보는 습관이 생겼어요.
배선이 아니라 운영이었어요
| 함정 | 어긋난 두 층 |
|---|---|
| 설치 경로 | 빌드 도구가 놓는 위치 ↔ 실행 도구가 찾는 위치 |
| WSL2 USB | 가상 머신 ↔ 호스트의 USB 장치 경계 |
| DDS 도메인 | 디스커버리가 이어주는 범위 ↔ 내가 의도한 범위 |
세 문제 다 코드 로직은 멀쩡했어요. 로봇 소프트웨어를 돌린다는 건 노드를 짜는 일 못지않게 이 층들을 다루는 일이라는 걸, 같은 패턴을 두 번째 조립하면서 배웠어요.
실물과 RViz를 한 명령으로 모는 디지털 트윈과 간이 라이다 실측에서 만든 브리지 노드와 RViz 구성 패턴을 로봇암에 그대로 재사용했는데, 패턴이 같아도 운영 환경이 달라지니 새 함정이 나왔어요. 같은 날의 다른 축은 부분 수신과 개루프 서보 부팅 점프 — 시리얼 텔레옵의 함정과 joint_states와 robot_description, 그리고 서보 두 점 캘리브레이션에 있어요.