페트론 2022. 1. 15. 22:25

Goal of Lecture


  • Dockerfile의 이론에 대해 학습한다.
  • 실습을 통해 Dockerfile의 사용법을 숙지한다.
  • 실습을 통해 URSim 구동을 위한 Dockerfile을 작성해본다.

01. What is Dockerfile?

2주차 강의에서 "hello-world" 이미지를 이용하여 컨테이너를 생성.

이러한 도커 이미지를 생성하는 방법에는 크게 2가지가 존재.

  1. 기존 이미지에 대해 컨테이너를 생성한 후, 컨테이너에서 수정을 진행한 후, 해당 컨테이너를 새로운 이미지로 작성.
  2. 기존 이미지 기반의 Dockerfile을 생성하여, 수정할 내용을 입력한 후, Dockerfile 빌드를 통해서 새로운 이미지 생성.

첫 번째 방법의 경우, 따로 문서작성이 필요하지 않기 때문에 작업이 편리하다는 장점이 있지만, 해당 이미지가 어떠한 모듈 혹은 패키지를 기반으로 작성되었는지 명확하게 인지하기 힘들 수 있음.

이를 해결하기 위해서 두 번째 방법을 이용하여 문서화를 통해 도커 이미지를 생성하는 것이 권장됨.

Command

FROM

Base Image를 지정하는 명령어. Ubuntu와 같은 기본 OS가 사용될 수 있고, 이외에 필요한 기능이 설치된 이미지(ROS, Python 등)를 사용할 수 있음.

MAINTAINER

이미지를 생성한 사람의 정보를 설정.

설정하지 않아도 실행에 문제는 없음.

RUN

해당 도커 이미지에 모듈 및 패키지를 설치할 때 사용하는 명령어.

CMD

RUN과 같이 해당 도커 이미지에 모듈 및 패키지를 설치할 때 사용하는 명령어. 다만 CMD 명령어는 해당 도커 이미지로 생성한 컨테이너가 시작될 때 실행됨.

ENTRYPOINT

CMD와 같이 해당 도커 이미지로 생성한 컨테이너가 시작될 때 실행됨. 다만 ENTRYPOINT 명령어는 중복해서 사용하는 것이 불가능함. 따라서 변경사항이 없는 작업에 대해서 ENTRYPOINT 명령어를 사용해야함.

ADD

Host PC의 파일이나 디렉토리를 도커 이미지로 복사할 때 사용.

도커 컨테이너 내부에 디렉토리가 존재하지 않는 경우, 자동으로 생성.

URL을 지정해 파일을 추가하는 것도 가능함.

tar 압축파일인 경우에 압축을 자동으로 풀어줌.

COPY

ADD와 같이 Host PC의 파일이나 디렉토리를 도커 이미지로 복사할 때 사용. 다만 COPY 명령어는 URL 지정이 불가능하며, 압축파일을 자동으로 풀어주지 않음.

VOLUME

Host PC의 폴더를 도커 컨테이너에 연결 시킬 때 사용함. 즉, 도커 내부에서 호스트 컴퓨터에서 지정한 곳의 파일을 읽거나 쓸 수 있음.

WORKDIR

RUN, CMD, ENTRYPOINT와 같은 명령어를 수행할 디렉토리를 나타냄. 터미널창에서 cd 명령어를 입력하는 것과 같음.

EXPOSE

도커 컨테이너를 외부에 노출하고자 할 때, 포트를 지정해줌.

ENV

도커 컨테이너에 대해서 환경변수를 지정할 때 사용함.

02. URSim

URSim은 Universal Robot Simulator의 약자로써, Universal Robot에서 개발한 UR 로봇 Simulator.

실제 로봇을 제어할 때와 같은 시스템 인터페이스를 갖지만, 실제 로봇이 연결된 것은 아니기 때문에 제한되는 기능도 존재함.

  • Emergency stop can not be used
  • Input IO state can not be set
  • Paths are perfect
  • Collisions with self or with surrounding objects do not work
  • Force mode will not work

URSim은 오프라인 프로그래밍과 로봇 프로그램, 수동 제어 등을 시뮬레이션하기위한 소프트웨어.

실제 로봇의 Teach Pendant와 동일한 UI로 구축함.

03. Network of Docker Container

Bridge Network

도커 컨테이너는 Host PC 내에서 생성되는 가상환경에서 동작함.

따라서 기본적으로 각각의 컨테이너는 서로 통신이 불가능함.

하지만 도커의 네트워크 설정을 통해 각 컨테이너간의 통신이 가능하도록 할 수 있음.

이를 위해서 도커 네트워크에 대해서 이해할 필요가 있음.

도커의 네트워크 타입은 bridge, host, none가 있으며, 도커를 설치하게 되면 bridge 타입의 docker0 가상의 bridge network가 자동으로 생성됨.

이는 다음의 명령어를 통해 확인할 수 있음.

sudo docker network ls
ifconfig

docker network : 도커 네트워크에 대한 작업을 위한 명령어. 다양한 파라미터를 주어서 도커 네트워크에 대한 여러가지 작업을 가능하게 해줌.

Commands:

  • connect Connect a container to a network
  • create Create a network
  • disconnect Disconnect a container from a network
  • inspect Display detailed information on one or more networks
  • ls List networks
  • prune Remove all unused networks
  • rm Remove one or more networks

ifconfig: 네트워크 확인을 위한 명령어. 설치되지 않은 경우, 다음의 명령어를 통해 설치 가능함.

sudo apt install net-tools

도커 컨테이너가 생성되면 두 가지 네트워크가 함께 생성됨.

  • eth0 : 컨테이너의 네트워크
  • veth : virtual ethernet의 약자로, 컨테이너의 네트워크와 Host PC의 가상 네트워크를 연결해주는 가상 네트워크

아래 그림을 보면, veth을 통해 컨테이너의 eth0 네트워크로부터 docker0 virtual bridge network로 연결되는 것을 확인할 수 있음.

일반적으로 이러한 docker0 bridge network를 이용하여 네트워크 인터페이스를 구축하는 것보다는 직접 가상 네트워크를 생성해 네트워크 인터페이스를 구축하는 것이 권장됨.

04. [Practice] Dockerfile for URSim

System Interface of URSim

우리가 구현할 시스템의 네트워크 인터페이스 구조는 위와 같음.

각각에 대한 간단한 소개는 아래와 같음.

  • bridge-network : 각각의 컨테이너들의 네트워크 통신이 가능하도록 하는 역할.
  • ros-master container : roscore를 실행함으로써, ros master 역할을 하는 컨테이너.
  • dockursim container : ursim을 실행하는 컨테이너. ursim 내부 설정을 통해 ros 통신이 가능.
  • ur-ros-driver container : UR 로봇을 ROS를 통해 제어할 수 있도록 하는 Driver가 작동하는 컨테이너

Create Folder for Practice

본격적으로 Dockerfile을 생성하기 전에 Dockerfile을 관리할 폴더를 생성함.

생성될 폴더의 구조는 다음과 같음.

  • home (~)
    • eh_lecture
      • week_03
        • ur-ros-driver

ros-master와 dockursim의 경우, 기존에 존재하는 도커 이미지를 활용하기 때문에 Dockerfile을 새로 만들 필요가 없음.

다음의 명령어를 통해 폴더를 생성.

mkdir -p ~/eh_lecture/week_03/ur-ros-driver

mkdir -p : -p 파라미터와 함께 사용하면, 상위경로를 포함하여 폴더를 생성함.

이 후, 다음의 명령어를 통해 폴더가 제대로 생성되었는지 확인할 수 있음.

cd eh_lecture/week_03/
ls

bridge network

먼저 각 컨테이너의 네트워크 통신을 가능하게 해줄 bridge network를 생성해주어야함.

bridge network는 다음의 명령어를 통해 설정 가능.

sudo docker network create --gateway 192.168.56.1 --subnet=192.168.56.0/24 bridge-network

docker network create : 도커 네트워크를 생성. --subnet=192.168.56.0/24 : 서브넷 설정 파라미터. 24는 255.255.255.0을 의미함. --gateway=192.168.56.1 : bridge network의 gateway address 설정 파라미터. bridge-network : 해당 네트워크의 이름을 설정하는 파라미터.

이 후, 네트워크가 제대로 생성되었는지 확인하기 위해 다음의 명령어를 입력함.

sudo docker network ls

위와 같이 bridge-network가 생성된 것을 확인할 수 있음.

ros-master

이제 ros-master 역할을 할 ros-master container를 생성.

ros:melodic 이미지를 사용하여 컨테이너를 생성함.

아래 명령어를 이용해서 컨테이너 생성.

# terminal_1
sudo docker run \\
    --network="bridge-network" \\
    --ip="192.168.56.2" \\
    -e "ROS_MASTER_URI=http://192.168.56.2:11311" \\
    -e "ROS_HOSTNAME=192.168.56.2" \\
    --name="ros-master" \\
    -it \\
    ros:melodic

해당 명령어의 파라미터는 다음과 같음.

Parameters

  • —network="bridge-network" : 앞에서 생성했던 가상 네트워크인 bridge-network를 컨테이너의 네트워크로 설정.
  • --ip="192.168.56.2" : 해당 컨테이너의 ip 주소를 설정.
  • -e "ROS_MASTER_URI=http://192.168.56.2:11311" : ROS Master의 환경변수 설정.
  • -e "ROS_HOSTNAME=192.168.56.2" : ROS Host 환경변수 설정.
  • --name="ros-master" : 컨테이너의 이름 설정.
  • -it : local의 키보드 입력을 컨테이너의 tty에 출력.
  • ros:melodic : 컨테이너의 기반이 되는 이미지.

명령어를 입력하면 아래와 같이 컨테이너로 접속되는 것을 확인할 수 있음.

이 후, 아래 명령어를 통해 ROS Master를 구동.

# terminal_1
roscore

아래와 같이 ROS Master가 구동되는 것을 확인할 수 있음.

dockursim

UR Robot의 제어기는 기본적으로 ROS 통신을 지원하지 않음.

따라서 Remote PC의 UR ROS Driver와 통신을 하기 위해서는 UR Robot 제어기에 추가 설정이 필요.

UR Robot 제어기는 urcap 프로그램을 이용하여 여러가지 기능을 추가적으로 구현할 수 있도록 구성됨.

External Control은 UR Robot 제어기에서 ROS 통신이 가능하도록 지원해주는 프로그램이며, urcap을 이용하여 설치를 수행할 수 있음.

이를 위해서는 먼저 다음의 과정을 진행해야함.

Create Folder for external control

먼저 Host PC에서 다음의 명령어를 이용하여 폴더를 생성.

cd ~/eh_lecture/
mkdir -p ursim

[Update] Download Github Repository

다음 명령어를 이용해 Github에서 Repository를 다운로드함.

해당 파일은 다음의 Github에서 얻을 수 있음.

GitHub - suho0515/DockURSim: A URSim (Universal Robots Simulator) Docker Container with a Browser Accessible Interface

다음 명령어를 통해 다운로드를 진행함.

cd ~/eh_lecture
git clone <https://github.com/suho0515/DockURSim.git>

git clone : Github에서 레포지토리를 다운로드하는 명령어. 만약 git 모듈이 설치되지 않은 경우, 다음의 명령어를 통해 설치를 수행함.

sudo apt install git-all

[Update] Build dockursim

새로 받은 DockURSim 폴더에는 Dockerfile이 이미 존재하고 있음.

해당 Dockerfile에서는 Local의 "~/eh_lecture/DockURSim/ursim" 폴더와 바인딩하는 명령어가 추가되어 있기 때문에, ursim 폴더 내부에 존재하는 'run' 파일과 'programs/externalcontrol-1.0.5.urcap' 파일이 컨테이너에 생성됨.

run : 컨테이너 내부에서 웹 포팅을 수행하는 스크립트. 해당 스크립트가 컨테이너 내부에 존재하지 않으면 웹 포팅이 불가능.

cd ~/eh_lecture/DockURSim/

sudo docker build -t dockursim:latest .

Run dockursim Container

dockursim은 ursim을 구동하여 포트 포워딩을 통해 웹에서 확인이 가능하도록 만들어진 이미지로써, dockhub에서 확인할 수 있음.

Docker Hub

먼저 로봇의 설정파일을 local에 저장하기 위해 가상 드라이브 생성.

sudo docker volume create dockursim

이 후, 다음의 명령어를 통해 드라이브가 생성되었는지 확인할 수 있음.

sudo docker volume ls

이 후, 다음의 명령어를 통해 dockursim을 구동할 수 있음.

sudo docker run \\
    --network="bridge-network" \\
    --ip="192.168.56.3" \\
    --name="dockursim" \\
    -e ROBOT_MODEL=UR10 \\
    -p 8080:8080 \\
    -p 29999:29999 \\
    -p 30001-30004:30001-30004 \\
    -v ~/eh_lecture/DockURSim/ursim/programs:/ursim/programs \\
    -v dockursim:/ursim \\
    --privileged \\
    --cpus=1 \\
    dockursim:latest

해당 명령어의 파라미터는 다음과 같음.

Parameters

  • -d : Background Mode
  • —network="bridge-network" : 앞에서 생성했던 가상 네트워크인 bridge-network를 컨테이너의 네트워크로 설정.
  • --ip="192.168.56.3" : 해당 컨테이너의 ip 주소를 설정.
  • --name="dockursim" : 컨테이너의 이름 설정.
  • -e ROBOT_MODEL=UR10 : 로봇 모델 환경변수에 대해 UR10으로 설정.
  • -p 8080:8080 : Port Forwarding, 로봇 인터페이스에 대한 HTTP Port.
  • -p 29999:29999 : Port Forwarding, Universal Robots Dashboard Server Interface Port.
  • -p 30001-30004:30001-30004 : Port Forwarding, Universal Robots의 다양한 인터페이스 Port.
  • -v ~/eh_lecture/DockURSim/ursim/programs:/ursim/programs : Local PC의 폴더와 컨테이너의 폴더를 바인딩. 웹 포팅에 사용되는 run 파일과 ROS 통신에 사용되는 external control urcap 파일을 컨테이너에 생성함.
  • -v dockursim:/ursim : Local PC의 폴더와 컨테이너의 폴더를 바인딩.
  • --privileged : 관리자 권한으로 컨테이너를 다룸.
  • --cpus=1 : 시뮬레이터에 대해 급증할 수 있는 연산량을 cpu 1개로 제한.
  • dockursim:latest : 컨테이너의 기반이 되는 이미지.

Setting ursim

dockursim은 HTTP 포트 포워딩을 통해 컨테이너 내부에서 작동하는 ursim을 확인할 수 있도록 구성되어있음.

ursim을 확인하기 위해서는 웹페이지를 오픈하여 아래의 주소를 입력.

<http://localhost:8080>

아래와 같이 ursim이 켜지는 것을 확인할 수 있음.

이 후, Confirm Safety Configuration 버튼을 눌러 창을 닫아줌.

오른쪽 상단의 메뉴버튼을 클릭.

메뉴에서 Settings 클릭.

왼쪽 메뉴에서 [System] → [URCaps] 선택, 하단의 '+' 버튼 클릭.

externalcontrol-1.0.5.urcap 선택 후, 하단의 'Open' 버튼 클릭.

여기서 보이는 창은 컨테이너의 /ursim/programs 폴더의 화면이며, 기존에 로컬의 ~/eh_lecture/ursim/programs 에 있는 externalcontrol-1.0.5.urcap 파일이 동기화되어 보이게 됨.

하단의 Restart 버튼 클릭.

ursim이 재시작된 후, 기존의 화면으로 들어가면, ExternalControl URCap이 활성화되어 있는 것을 확인할 수 있음.

ExternalControl 이 제대로 설치된 것.

[Update] URSim에서는 Remote Control 부분을 Local로 설정. (실제 로봇에서는 Remote Control로 진행해야함.)

이 후, 왼쪽의 [System] → [Remote Control] 메뉴로 들어가 'Enable' 버튼 클릭.

Remote Control : UR Robot을 원격제어하기 위해서 활성화시켜야함.

실제 로봇에서는 [System]의 [Network]도 수정해주어야 하지만, ursim에서는 설정하지 않아도 문제없음.

이 후, 'Exit' 버튼을 클릭하여 Setting 창을 닫은 뒤, 좌측의 [Systems] → [External Control] 메뉴를 선택하고,

Host IP와 Host Name을 192.168.56.4로 바꾸어줌.

192.168.56.4 : ur-ros-driver container의 ip address.

이 후, 좌상단의 'Program' 을 클릭하고,

좌측의 [URCaps] → [External Control] 을 클릭하면,

중앙의 Robot Program에 External Control 프로그램이 추가되는 것을 확인할 수 있음.

이 후, 상단의 [Save] → [Save All] 선택하여,

Filename : ros

입력 후, 저장.

이 후, 우 상단의 'Local' 버튼을 클릭하여 'Remote Control' 모드로 선택.

이제 URSim의 UR 로봇은 구동할 준비가 된 상태.

ur-ros-driver

이제 External Control 과의 통신을 통해 URSim의 UR Robot을 구동할 수 있도록 하는 ur-ros-driver에 대한 Dockerfile을 작성하고 컨테이너를 실행.

먼저 다음의 명령어를 통해 Dockerfile 생성.

cd ~/eh_lecture/week_03/ur-ros-driver/
gedit Dockerfile

해당 도커파일에 다음의 내용을 입력.

이 후, ctrl + s 를 눌러 저장.

# syntax=docker/dockerfile:1
FROM osrf/ros:melodic-desktop-full

RUN /bin/bash -c "apt-get update &&\\
    sudo apt install ros-melodic-rqt-joint-trajectory-controller &&\\
    source /opt/ros/melodic/setup.bash &&\\
    mkdir -p ~/catkin_ws/src && cd ~/catkin_ws &&\\
    git clone <https://github.com/UniversalRobots/Universal_Robots_ROS_Driver.git> src/Universal_Robots_ROS_Driver &&\\
    git clone -b calibration_devel <https://github.com/fmauch/universal_robot.git> src/fmauch_universal_robot &&\\
    sudo apt update -qq &&\\
    rosdep update &&\\
    rosdep install --from-paths src --ignore-src -y &&\\
    cd ~/catkin_ws &&\\
    catkin_make &&\\
    source devel/setup.bash"

해당 Dockerfile은 ros:melodic 이미지를 기반으로 하며,

RUN 명령어를 이용하여 UR Robot Driver와 RQT를 통해 UR Robot을 제어할 수 있도록 rqt-joint-trajectory-controller 패키지를 설치.

Ref.

GitHub - UniversalRobots/Universal_Robots_ROS_Driver: Universal Robots ROS driver supporting CB3 and e-Series

Wiki

이 후, 다음의 명령어를 이용해 Dockerfile을 빌드하고 이미지를 생성.

cd ~/eh_lecture/week_03/ur-ros-driver/
sudo docker build -t ur-ros-driver:latest .

docker build : Dockerfile을 이용하여 빌드를 수행하여 이미지를 생성함. -t ur-ros-driver:latest : 빌드될 이미지의 이름을 지정함. 이 때, latest는 [tag] 정보가 됨. 이는 1.0, 2.0 등의 값이 될 수 있음. . : 해당 경로에 존재하는 Dockerfile을 이용한다는 의미.

이 후, 다음의 명령어를 통해 생성된 이미지를 확인할 수 있음.

sudo docker images

이 후, 다음의 명령어를 통해 ur-ros-driver 컨테이너를 생성함.

sudo docker run \\
    --network="bridge-network" \\
    --ip="192.168.56.4" \\
    --name="ur-ros-driver" \\
    -e "ROS_MASTER_URI=http://192.168.56.2:11311" \\
    -e "ROS_HOSTNAME=192.168.56.4" \\
    -e DISPLAY=unix$DISPLAY \\
    -v /tmp/.X11-unix:/tmp/.X11-unix:rw \\
    --privileged \\
    --cpus=1 \\
    -it \\
    ur-ros-driver:latest

이 후, 컨테이너의 bash에 다음의 명령어를 입력하여 드라이버 노드 구동.

source ~/catkin_ws/devel/setup.bash

roslaunch ur_robot_driver ur10_bringup.launch robot_ip:=192.168.56.3

roslaunch : 해당 패키지에 관련된 ROS 노드들의 집합을 동시에 실행시키는 명령어. ur_robot_driver : 패키지 명. ur10_bringup.launch : UR10 로봇에 대한 launch 파일 실행. robot_ip:=192.168.56.3 : 로봇의 ip address를 파라미터로 알려줌. 이 때, 로봇의 ip address는 dockursim container의 ip address가 됨. (192.168.56.3)

rqt-joint-trajectory-controller

이제 ROS를 이용하여 UR Robot을 구동할 준비가 완료되었음.

이제 rqt-joint-trajectory-controller를 이용하여 URSim의 UR Robot을 구동.

이를 위해서 먼저 xhost를 실행하여 도커의 x host 접속을 허용함.

# terminal_4
xhost +local:docker

이 후, 다음의 명령어를 통해 ur-ros-driver container에 접속.

# terminal_4
sudo docker exec -it ur-ros-driver bash

이 후, 컨테이너의 bash에 다음의 명령어를 입력하여 RQT를 실행.

# terminal_4
source ~/catkin_ws/devel/setup.bash
rqt

UR Robot을 가시화하기 위하여 URSim에서 좌하단의 Paused 버튼 클릭.

이 후, RQT에서 [Plugins] → [Service Caller] 실행.

이 후, Service 스크롤 메뉴에서 각각 다음의 순서로 Call 수행.

  1. /ur_hardware_interface/dashboard/power_on : UR Robot의 전원을 ON.

/ur_hardware_interface/dashboard/brake_release : UR Robot의 Break를 풀어줌. (토크 발생)

/ur_hardware_interface/dashboard/play : 설정된 프로그램 실행. (External Control 실행.)

! Reponse는 모두 True 값으로 반환되어야 함.

[Update] 만약 컨트롤러가 작동하지 않는 경우, dockursim과 ur-ros-driver 컨테이너를 재시작.

이 후, 아래의 Sevice를 Call 하여 Response 확인.

/controller_manager/list_controllers

이 때, 'scaled_pos_joint_traj_controller'의 상태가 running 인 것을 확인.

scaled_pos_joint_traj_controller : 우리가 rqt-joint-trajectory-controller 에서 사용해야할 컨트롤러.

이 후, [Plugins] → [Robot Tools] → [joint trajectory controller] 를 선택하여, 스크롤 메뉴에서 [/controller_manager], [/scaled_pos_joint_trajectory_controller] 선택.

이 후, 전원버튼을 누르고 각 조인트 값을 변경하면 URSim의 로봇이 제어되는 것을 확인할 수 있음.

해당 부분에서 오류 발생시 시스템 리부팅 후, 재수행

반응형