[Robosynapse] Control Server: Docker 위에 ROS2 올리기

2026-09-19
robosynapseros2

로봇 매니퓰레이션 시스템을 만들 때 가장 먼저 필요한 것은 로봇 팔에 명령을 보내고 상태를 받아오는 Control Server입니다. 이 글은 제가 진행 중인 robosynapse 프로젝트에서 UR7e와 AgileX Piper 두 종류의 로봇 팔을 위한 Control Server를 구축한 과정을 정리한 것입니다. ROS2 환경을 Docker로 올리는 것부터 로봇과의 네트워크 연결, 드라이버와 MoveIt 실행까지 순서대로 다룹니다.

전체 구조는 단순합니다. Control Server는 ROS2 Humble 컨테이너 안에서 로봇 드라이버와 MoveIt을 돌리고, 상위의 Inference Server(VLA 모델이 도는 곳)가 보내는 명령을 로봇에 전달합니다. 두 서버는 한 머신에 있을 수도, 분리되어 있을 수도 있습니다.

0. 왜 Docker 위에 ROS2인가

ROS2는 배포판(Humble, Iron, ...)마다 Ubuntu 버전 의존성이 강하고, 호스트에 직접 설치하면 환경이 쉽게 오염됩니다. osrf/ros:humble-desktop-full 이미지를 쓰면 어떤 호스트에서든 동일한 환경을 재현할 수 있고, 로봇마다 컨테이너를 분리해 ROS_DOMAIN_ID로 격리하는 것도 간단해집니다. 여러 대의 로봇을 한 서버에서 다룰 때 이 구조의 이점이 더 커집니다.

1. UR7e Control Server

1-1. ROS2 Humble 컨테이너 띄우기

RViz 같은 GUI를 컨테이너 안에서 쓰기 위해 X11 소켓을 공유하고, DDS 통신을 위해 --net=host로 띄웁니다.

ROS2 Docker Entryxhost +local:root

docker run -it \
    --name ros2_humble \
    --privileged \
    --net=host \
    --ipc=host \
    --gpus all \
    -e DISPLAY=$DISPLAY \
    -v /tmp/.X11-unix:/tmp/.X11-unix:rw \
    -v ~/ros2_ws:/root/ros2_ws \
    --device /dev/video0:/dev/video0 \
    --device /dev/input:/dev/input \
    osrf/ros:humble-desktop-full

# 이후 재사용
docker start ros2_humble
docker exec -it ros2_humble /ros_entrypoint.sh bash

1-2. UR 드라이버 설치

UR 시리즈는 ROS 공식 배포판(rosdistro)에 릴리즈되어 있어서 apt 바이너리 설치 한 줄이면 끝납니다.

ROS2 UR Package Installsudo apt update
sudo apt install -y ros-humble-ur
sudo apt install -y ros-humble-ros2controlcli   # force control 용

주의할 점: 이 패키지들은 컨테이너 내부 파일시스템(/opt/ros/humble/...)에 설치되므로 컨테이너를 rm하면 사라집니다. 자주 다시 만든다면 Dockerfile에 넣거나 commit해 두는 것이 좋습니다.

1-3. 로봇과의 내부망 설정

Control Server와 로봇은 같은 스위치에 물려 있어야 하고, 로봇 컨트롤박스와 같은 대역의 고정 IP를 서버 쪽 이더넷 인터페이스에 부여합니다.

내부망 설정sudo ip addr add 172.16.0.10/24 dev enp1s0
ip -br addr   # 확인

위 방식은 재부팅하면 사라지므로, netplan으로 고정해 둡니다.

/etc/netplan/01-robot.yamlnetwork:
  version: 2
  ethernets:
    enp1s0:
      addresses: [172.16.0.10/24]
sudo netplan apply

1-4. UR Driver & MoveIt 실행

UR Driver Init & MoveItsource /robo-synapse/config/setup_env.sh

ros2 launch ur_robot_driver ur_control.launch.py \
    ur_type:=ur7e robot_ip:=172.16.0.3 launch_rviz:=false

ros2 launch ur_moveit_config ur_moveit.launch.py \
    ur_type:=ur7e

두 launch를 모두 띄운 뒤, 마지막으로 티치 펜던트에서 실행 버튼을 눌러야 외부 제어(External Control)가 시작됩니다. 이걸 잊으면 드라이버는 떠 있는데 로봇이 움직이지 않는 상태가 됩니다. robosynapse에서는 Control/Inference Server가 분리된 환경과 아닌 환경을 자동으로 감지하는 스크립트(run_ur_driver.sh, run_ur_moveit.sh)로 이 과정을 감싸 두었습니다.

2. Piper Control Server

AgileX Piper는 UR과 결이 다릅니다. 가장 큰 차이 두 가지:

2-1. 컨테이너 띄우기

UR과 동일한 ros:humble 이미지에서 시작하되, CAN 장치 접근을 위해 /dev와 udev를 통째로 마운트합니다.

Piper Docker Entrydocker run -it \
  --name ros2_humble \
  --privileged \
  --net=host \
  --ipc=host \
  -e DISPLAY=:0 \
  -v /tmp/.X11-unix:/tmp/.X11-unix:rw \
  -v /dev:/dev \
  -v /run/udev:/run/udev:ro \
  -v $HOME/workspace:/root/workspace \
  osrf/ros:humble-desktop-full

# robosynapse에서는 스크립트 한 줄로:
bin/control_server/create_docker.sh piper   # 컨테이너 ros2_humble_piper, domain=42

2-2. piper_ros 빌드

ROS2 Piper Package Install# 1. Piper ROS 패키지 clone
sudo chown -R $USER:$USER ~/workspace
git clone -b humble https://github.com/agilexrobotics/piper_ros.git ~/workspace/piper_ros
ls ~/workspace/piper_ros   # src/ can_activate.sh find_all_can_port.sh 보이면 OK

# 2. 의존 패키지 설치
apt update && apt install -y python3-pip can-utils ethtool \
  ros-humble-ros2-control ros-humble-ros2-controllers ros-humble-controller-manager
pip3 install python-can scipy piper_sdk

# 3. colcon build
cd /root/workspace/piper_ros
source /opt/ros/humble/setup.bash
colcon build
source install/setup.bash

ros2 pkg list | grep piper   # 확인

2-3. CAN 통신 활성화

Piper가 제공하는 스크립트로 CAN 포트를 찾아 1Mbps로 올립니다. 인터페이스 이름은 can_piper0을 기본으로 씁니다.

CAN communicationcd /root/workspace/piper_ros
apt install -y iproute2
bash find_all_can_port.sh
bash can_activate.sh can_piper0 1000000   # 인터페이스 이름 + bitrate

ip -br link show can_piper0   # UP 확인
candump can_piper0            # 팔이 프레임을 쏘는지 확인 (Ctrl+C)

컨테이너 안에서 뭔가 이상하면 호스트에서도 검증해 볼 수 있습니다:

lsusb | grep -i can
ip -d link show can_piper0 | grep bitrate   # bitrate 1000000
candump can_piper0

2-4. Piper Driver & MoveIt 실행

Piper Driver Init & MoveIt# 1. piper driver
cd /root/workspace/piper_ros
source install/setup.bash
source /root/workspace/robo-synapse/config/setup_env_container.sh
ros2 launch piper start_single_piper.launch.py \
    can_port:=can_piper0 auto_enable:=true

# 상태 확인
ros2 topic list
ros2 topic echo /joint_states_feedback

# 2. moveit
apt update && apt install -y ros-humble-moveit
ros2 launch piper_with_gripper_moveit demo.launch.py

auto_enable:=true가 중요합니다. false로 두면 드라이버는 뜨지만 모터가 enable되지 않아 execute가 동작하지 않습니다.

3. Bimanual Piper: 컨테이너로 팔 분리하기

Piper 두 대를 양팔로 쓰는 bimanual 구성은 현재 개발 중입니다. 정리가 끝나는 대로 이 섹션에 추가할 예정입니다.

정리

다음 글에서는 이 Control Server 위에 올라가는 Inference Server(VLA) 세팅을 다룰 예정입니다.

← Back to Blog