
앞선 글에서 컨테이너 환경을 만들었으니, 이제 그 안에서 UR 로봇의 ROS2 패키지를 빌드하고 공식 시뮬레이터가 실제로 실행되는지 확인한다.
이전에 복제해 둔 저장소는 UR 로봇(ur_driver, ur_description, ur_simulation_gz 등), 모션 플래닝(moveit2 등), 제어(ros2_control 등) 세 영역이 있다. 바이너리 대신 소스로 받는 이유는 업스트림 코드를 직접 읽으며 배우는 게 목적이고, 이 저장소에서 ur_description의 형상 매크로 등을 include해서 재사용하기 때문이다.
주의 — 이미지를 빌드할 때 ur-description, ur-moveit-config, ur-msgs, ur-robot-driver를 apt 바이너리로 같이 설치하면 안 된다. 소스와 바이너리가 겹치면 시뮬레이션 실행 시 충돌한다.
컨테이너를 띄운 뒤, 언더레이부터 빌드한다. 오버레이가 언더레이를 소싱해서 쓰는 구조라 순서가 중요하다.
먼저 내가 올려둔 개발 환경을 복제한 위치로 이동한 후 컨테이너를 실행한다.
environment/jazzy.sh
컨테이너 쉘이 나타나면 아래와 같이 ur_ws로 이동한 후 빌드한다.
cd ~/ur_ws
colcon build
source install/setup.bash
최초 빌드 때에는 패키지가 많아서 시간이 꽤 걸린다.
언더레이가 제대로 빌드됐는지부터 UR 공식 예제로 확인했다.
vglrun ros2 launch ur_simulation_gz ur_sim_moveit.launch.py ur_type:=ur5e
이 런치를 실행하면 Gazebo와 Rviz 둘 다 실행된다. ros2 실행 명령 앞에 vglrun을 넣은 이유는 3D 가속을 컨테이너 환경에서 사용하기 위해서이다. vglrun을 넣을 때와 뺄 때에 대해서 CPU 리소스 사용량을 확인해 보면 된다.

앞의 스크린샷과 같이 RViz와 Gazebo 둘 다 정상적으로 실행 되었다. 그런데 RViz에서 Plan → Execute를 하면 RViz 속 팔만 움직이고 Gazebo 속 팔은 그대로였다.
원인은 컨트롤러 이름 불일치였다. ur_moveit_config는 원래 실물 로봇용 패키지라, 실물 드라이버가 쓰는 scaled_joint_trajectory_controller를 기본적으로 사용하도록 설정되어 있다. 반면 ur_simulation_gz에는 그 컨트롤러가 아예 정의돼 있지 않고 joint_trajectory_controller를 사용하도록 되어 있다. 즉, MoveIt이 존재하지 않는 컨트롤러에게 명령을 보내고 있었던 것.
ros2 control list_controllers로 실제 떠 있는 컨트롤러 이름을 확인하고, MoveIt을 멈추게 한뒤 joint controller(JTC)에 직접 궤적을 던져서 그 아래 구간(JTC → gz_ros2_control → Gazebo)은 이상이 없다는 것을 확인.
그러고 나서 ur_ws/src/ur_driver/ur_moveit_config/config/moveit_controllers.yaml
파일에서 'scaled_joint_trajectory_controller:' 항목을 찾아 'default:'를 false로 바꾸고 'joint_trajectory_controller:' 항목의 'default:'를 true로 변경하여 다시 런치를 실행하였다.
(--symlink-install로 빌드해 둔 덕분에 yaml만 고치면 리빌드 없이 런치 재실행만으로 바로 반영됐다.)
진단 과정과 원인 분석은 저장소 docs에 더 자세히 정리해 뒀다.
아래는 RViz와 Gazebo 연동 화면

정리