ROS 도커에서 사용해보기 - 튜토리얼 1

By qsp , Created on 1st Sep 2021

정말 오랜만에 블로그 포스팅을 하는데..
docker를 이용해서 ROS를 실행하는 것을 튜토리얼 식으로 정리했다~
미루고 미루다가 이제야 올리게 됨

그 동안은 직업학교도 수료하고 그 동안 포트폴리오 했던 것들을 정리했고
취업하기위해 여기저기 회사도 알아보는 중인데, 입사지원도 했는데 별 소식이 없다 으엉 ㅠ

에라이~ 그냥 놀자~ 이러면서 있는데, 딱히 뭐한것도 없는데 시간은 정말 잘 간다.

현재 막연하고 불안하지만 그럼에도 불구하고 공부도 하고 포스팅도 해야할 것 같다

왜 docker 로 ROS를 사용?

ros melodic을 도커로 사용하게 된 것은 아무래도 현재 쓰고 있는 리눅스가 ubuntu가 아니여서 그렇다
그래서 docker를 사용해서 최대한 같은 환경에서 할 수 있었기 때문이다.

현재는 CentOS 8 사용 중인데, 아직까지는 CentOS가 좋기 때문에 우분투로 구지 옮겨야 할지 모르겠다
물론 LTS 지원이 갑자기 끝나버려서, 아마도 올해 내로 리눅스를 바꿔야할 시점이 올 듯 하다

또는 ubuntu을 사용하고 있지만 다른 ROS2를 설치해본다던가 등으로 사용할 수도 있을 듯 하다


먼저 Dockerfile 만들기

원하는 곳에 디렉토리를 만들어 주고 그 안에 Dockerfile 과 docker-compose.yml을 만들어줘야하는데

먼저 docker-ros 라는 이름으로 디렉토리를 만들어 봄

mkdir docker-ros
cd docker-ros

그리고 docker-ros로 이동해서 원하는 에디터를 열어서 작업을 해준다
먼저 Dockerfile 이라는 이름으로 파일을 만든다

FROM ros:melodic-ros-core-bionic

RUN apt-get update && apt-get install -y \
    ros-melodic-desktop-full

# 일반적인 melodic 설치위한 과정
RUN apt-get install --no-install-recommends -y \
    build-essential \
    python-rosdep \
    python-rosinstall \
    python-vcstools \
    python-rosinstall-generator \
    python-wstool \
    && rm -rf /var/lib/apt/lists/*

# rsodep 최초실행  init 및 update만 하면 sudo 로 하라는 에러발생
RUN rosdep init \
  && rosdep update \
  && rosdep fix-permissions

RUN apt-get update && \
  apt-get install -y software-properties-common

RUN echo 'source /opt/ros/$ROS_DISTRO/setup.bash' >> /root/.bashrc && \
  echo "source /root/catkin_ws/devel/setup.bash" >> /root/.bashrc

파일을 저장하자

그리고 이번에는 docker-compose.yml 파일을 만들어 줘야한다

version: "3.9"
services: 

  ros:
    container_name: ros
    build: 
      context: .  # 현재 디렉토리
      dockerfile: Dockerfile  

저장을 해주자~ 나름 엄청 심플하다~
의미는 container_name으로 ros로 지정
build 부분에서 . 즉, 현재 디렉토리를 의미하므로 현재디렉토리에서
Dockerfile을 참고해서 build하게 된다

이제 아주 기본적인 준비는 되었으니~ 터미널을 열어서 docker-compose build를 실행해준다

cd docker-ros
docker-compose build

이미지를 다운받고 시간이 조금 걸린다~

Successfully built 20e88a71ac1a
Successfully tagged docker-ros_ros:latest

이렇게 나오면 잘 되고 있는 것이고

Warning: running 'rosdep update' as root is not recommended.
  You should run 'sudo rosdep fix-permissions' and invoke 'rosdep update' again without sudo.

중간에 워닝이 나오지만 무시하자

사실 유저를 만들어서 without sudo로 해야하는데 관리자 권한으로 만들어져서 그렇다
다음번에는 유저를 만들어봐야겠다. 관리자 권한으로 시작하는 것은 비추지만
하다보니 거기까지는 아직 시도를 못해봄 (일단~ 추후 업데이트를 해야겠다)


이제 docker를 실행한다

docker-compose up

이런식으로 나오면서 도커가 종료가 된다.

Recreating ros ... done
Attaching to ros
ros exited with code 0

도커 컨테이너로 진입을 해야하는데 이렇게 해서는 ros를 사용할 수 없다

컨테이너를 확인해볼 차례이다.

docker ps -a

를 해보면

CONTAINER ID   IMAGE                         COMMAND                  CREATED          STATUS                      PORTS                                   NAMES
9cd6465fc3bb   docker-ros_ros                "/ros_entrypoint.sh …"   46 seconds ago   Exited (0) 44 seconds ago                                           ros

사실 길게 나오는데 중요한 것은 IMAGE 만 알면 된다
그러면 직접 입력해서 도커 컨테이너를 실행해보자

docker run -it --rm docker-ros_ros

그러면 컨테이너가 실행이 되면서

root@7c5cefd2a336:/#

이런식으로 프롬포트가 바뀌는 것을 확인할 수가 있다~

하지만

bash: /root/catkin_ws/devel/setup.bash: No such file or directory

이런 에러가 난다~ 이유는 Dockerfile에서 설정해준 .bashrc 파일에서 catkin_ws를 참조해야하는데
디렉토리가 연결이 안되어 있어서 그렇다. 이것은 아래에서 해결하자

이제 진짜 ros가 깔려있는가? 궁금하면

cd /opt/ros/melodic

확실히 ros가 깔려있는게 보인다

하지만 여기에는 몇가지 문제가 있다 catkin_ws도 없고
rosrun으로 turtlesim노드를 실행하려고 해도

qt.qpa.screen: QXcbConnection: Could not connect to display 
Could not connect to any X display.

이런식으로 에러가 나며 실행이 되지 않는다. (이것도 아래에서)

도커 컨테이너를 빠져나오자~

exit


catkin_ws 지정해보자

먼저 소스파일을 빌드할 수 있게 되는 workspace 디렉토리를 만들어줘야하는데
도커 컨테이너 만들어 주는 것이 아니고, 로컬에 (host컴)의 디렉토리를 만들어서
도커 컨테이너에서 사용을 할 수 있게 해주면 된다

먼저 원하는 곳에 catkin_ws를 만들어주는데
이미 만든 docker-ros 디렉토리 안에다가 만들어 catkin_ws 디렉토리를 만들었다
(원래 ros의 컨벤션처럼 /home/[계정]/caktin_ws 에 만들어도 됨)

cd ~/docker-ros
mkdir catkin_ws

docker run을 할 때 옵션을 넣어서 실행을 해준다

docker run --rm -it \
  -v ~/docker-ros/catkin_ws:/root/catkin_ws \
  -v ~/.ssh:/root/.ssh \
  --network host \
  --env ROS_MASTER_URI=http://localhost:11311 \
  --name ros \
  docker-ros_ros

--rm 옵션을 넣은 이유는 현재는 약간 테스트 성격이므로
컨테이너를 빠져나올 때 자동으로 컨테이너를 지울 수 있게 해주는 옵션임
이 옵션을 빼면 컨테이너가 계속 생성이 되어서 따로 지워야 한다


-v 옵션을 넣어서 volume을 지정해 주는 것인데 현재 디렉토리 기준으로
위에서 만든 로컬 호스트 컴의 catkin-ws 를 도커 컨테이너의 /root/catkin_ws로 연결을 해주는 것 (이때는 절대경로로 입력해줘야 한다)

이제 프롬포트 부분이 바뀌면서 도커 컨테이너가 실행된것을 알 수 있다

root@localhost:/# 

컨테이너 안에서 위에서 연결한 catkin_ws를 들어가보자

cd /root/catkin_ws

해당 디렉토리가 연결되어 있는 것을 알 수 있고, 기존 로컬의 호스트에서 catkin_ws에 패키지를 다운받거나
또는 도커 컨테이너 안에서 create_catkin_pkg 를 통해서 패키지를 만들어 줄 수도 있다

catkin_ws 디렉토리를 로컬 호스트쪽에 만들어 놓은 이유는 관리가 좀 더 편하고
컨테이너가 이상해지거나 혹은 지워지거나 해도 로컬의 소스파일들은 남아있을 수 있어서 더 편하고
패키지들을 git으로 사용할 때 도커 컨테이너에서 사용을 안하고 로컬에서 관리하면 됨
(컨테이너 안에서 하려면 git을 설치해야하고)
또 소스파일을 열 에디터도 로컬에서 열 수가 있으므로 생성/수정할 때 사용할 때 편하다

이제 exit로 도커 컨테이너를 빠져나온다


display 연결하기

잠깐! 실행을 하기 전에 디스플레이 서버를 Wayland로 지정을 해줘야한다~
적어도 CentOS에서는 Wayland와 X11 디스플레이 서버를 선택해서 사용할 수가 있는데
Wayland로 로그인을 해야지 도커 컨테이너에서 실행을 했을 때 gui 를 사용할 수가 있다

X11서버로 할 수 있는 방법이 있겠지만 못찾음 ㅠㅠ
X11 디스플레이 서버이면 제대로 GUI 화면을 띄울 수가 없다
로그아웃 후 Wayland로 로그인을 하자
그리고 CentOS 기준이고, 그래픽카드는 AMD ATI 라데온 기준입니다

이제 도커 컨테이너에서 GUI로 실행되는 프로그램을 가동시켜보자
디스플레이도 로컬 호스트 컴퓨터의 (원래 컴퓨터)의 자원을 사용해서 사용할 수 있게
허용을 해주면 도커에서도 사용할 수 있게 된다

먼저 docker그룹이 디스플레이를 사용할 수 있게 해준다

xhost + local:docker

이렇게 하면 docker 가 접근 컨트롤 리스트에 추가되서

non-network local connections being added to access control list

로컬의 디스플레이 자원을 사용할 수 있게 됨

이제 위에서 docker run 커맨드를 사용하는데 몇가지 추가 되었다

docker run --rm -it \
  -v ~/docker-ros/catkin_ws:/root/catkin_ws \
  -v ~/.ssh:/root/.ssh \
  --network host \
  --env ROS_MASTER_URI=http://localhost:11311 \
  -e DISPLAY=$DISPLAY \
  -v /tmp/.X11-unix:/tmp/.X11-unix \
  --env="QT_X11_NO_MITSHM=1" \
  docker-ros_ros \
  bash

추가된 부분은

-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
--env="QT_X11_NO_MITSHM=1" \

디스플레이 관련해서 추가해준 것임

-v 옵션으로 X socket 을 access하게 된다 그리고 AMD 라데온 그래픽 관련해서 사용했던 것이라

nvidia 에서는 --env="QT_X11_NO_MITSHM=1" 없이 사용하면 될 듯하다

-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \

Nvidia 그래픽카드라면 아마도 위의 2줄의 코드만으로 작동할 듯 하다
기본으로 사용하는 것이라서 아마도 될 듯하다 (보통의 다른곳에서도 그렇게 설명하는 듯하다)
하지만 그래픽 카드가 nvidia가 아니어서 정확하지는 않습니다. 해본적이 없음 ㅠ

이제 터틀심을 실행해보자 위의 커맨드가 실행이 된 상태에서 컨테이너가 들어가지면

rosrun turtlesim turtlesim_node 

roscore가 실행이 안되어 있어서 에러가 난다

[ERROR] [1630444179.181622408]: [registerPublisher] Failed to contact master at [localhost:11311].  Retrying...

다른 터미널을 열어서 roscore를 실행해줘야한다 먼저 터미널을 새로 열어준다

docker ps

를 해보면 현재 실행되고 있는 컨테이너를 보여준다

CONTAINER ID   IMAGE            COMMAND                  CREATED          STATUS          PORTS                                   NAMES
10565531b197   docker-ros_ros   "/ros_entrypoint.sh …"   10 minutes ago   Up 10 minutes                                           thirsty_pare

여기에서 CONTAINER ID 또는 NAMES를 이용해서 도커 컨테이너를 실행할 수 있다
이번에는 exec라는 명령어를 사용해서 bash 쉘을 열어보자

docker exec -it 10565531b197 bash

또는 컨테이너 이름으로 실행

docker exec -it thirsty_pare bash

이렇게 명령어를 쳐주면 먼저 열어놓은 컨테이너에 들어갈 수가 있다

roscore  

를 실행해주자~

다시 먼저 열어놓은 터미널로 돌아와서

rosrun turtlesim turtlesim_node 

거북이가 잘 실행된다

이번에는 컨트롤 + c를 눌러서 종료한 뒤에

rviz

역시 잘 실행된다


이제 매번 이렇게 사용하면 귀찮으므로

다음번 포스팅에서 docker-compose를 해서 하는 법을 알아보자~ docker-compose.yml로 쉽게 실행하기


댓글

댓글이 없습니다.