本文是 AI 神經網路自走車 第五篇。官方文件提供的安裝法為直接裝入系統之中。為了統一環境和隔離應用,引入 docker container 是一個不錯的選擇,這邊分享如何自行 build ROS2 的 docker image,以及如何使用 container 化的 ROS2。
目錄
準備 ROS2 Docker file
我們參考 ros2_trt_post repository 為 nvidia jetson 系列平台寫的 docker file,改成一般通用型的 docker file 來實作。
簡單解釋一下裏面在做的事情:
- image base 原本是使用 nvcr.io/nvidia/l4t-base:r32.4.3 這個 nvidia jetson 平台專用的 image,我們改成 ubuntu:18.04 ,這樣其他平台如 raspberry pi 也能使用(之後文章我們會使用 nvidia jetson nano,如果你也用一樣的平台的話,請修改回 nvcr.io/nvidia/l4t-base:r32.4.3)
- 安裝的 ROS 版本為 eloquent,並裝在 /opt/ros/eloquent 下
- 設定 locale 和 lang 為 en_US.UTF-8
- 裝入一些基本套件如 git 、cmake、build-essential 等等
- 將 ROS deb repo 加入 apt 來源,並且開始安裝相關套件
- 設定 entrypoint,把已經寫好的 ros_entrypoint.sh 複製到 image 裏面
ARG BASE_IMAGE=ubuntu:18.04
FROM ${BASE_IMAGE}
ARG ROS_PKG=ros_base
ENV ROS_DISTRO=eloquent
ENV ROS_ROOT=/opt/ros/${ROS_DISTRO}
ENV DEBIAN_FRONTEND=noninteractive
WORKDIR /workspace
# change the locale from POSIX to UTF-8
RUN locale-gen en_US en_US.UTF-8 && update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
ENV LANG=en_US.UTF-8
# add the ROS deb repo to the apt sources list
RUN apt-get update && \
apt-get install -y --no-install-recommends \
git \
cmake \
build-essential \
curl \
wget \
gnupg2 \
lsb-release \
&& rm -rf /var/lib/apt/lists/*
RUN wget --no-check-certificate https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc && apt-key add ros.asc
RUN sh -c 'echo "deb [arch=$(dpkg --print-architecture)] http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" > /etc/apt/sources.list.d/ros2-latest.list'
# install ROS packages
RUN apt-get update && \
apt-get install -y --no-install-recommends \
ros-eloquent-ros-base \
ros-eloquent-launch-xml \
ros-eloquent-launch-yaml \
ros-eloquent-vision-msgs \
ros-eloquent-image-tools \
libpython3-dev \
python3-colcon-common-extensions \
python3-rosdep \
&& rm -rf /var/lib/apt/lists/*
# init/update rosdep
RUN apt-get update && \
cd ${ROS_ROOT} && \
rosdep init && \
rosdep update && \
rm -rf /var/lib/apt/lists/*
# compile yaml-cpp-0.6, which some ROS packages may use (but is not in the 18.04 apt repo)
RUN git clone --branch yaml-cpp-0.6.0 https://github.com/jbeder/yaml-cpp yaml-cpp-0.6 && \
cd yaml-cpp-0.6 && \
mkdir build && \
cd build && \
cmake -DBUILD_SHARED_LIBS=ON .. && \
make -j$(nproc) && \
cp libyaml-cpp.so.0.6.0 /usr/lib/aarch64-linux-gnu/ && \
ln -s /usr/lib/aarch64-linux-gnu/libyaml-cpp.so.0.6.0 /usr/lib/aarch64-linux-gnu/libyaml-cpp.so.0.6
# setup entrypoint
COPY ./ros_entrypoint.sh /ros_entrypoint.sh
RUN echo 'source ${ROS_ROOT}/setup.bash' >> /root/.bashrc
RUN chmod +x /ros_entrypoint.sh
ENTRYPOINT ["/ros_entrypoint.sh"]
CMD ["bash"]
WORKDIR /
可以發現最後一步設定 entrypoint 的時候需要 ros_entrypoint.sh 這個檔案,接下來我們開始準備
準備 ros_entrypoint.sh
這份檔案很簡單,讓 container 剛建立完成時,就去 source ROS2 的 setup.bash,初始化 ROS2 的環境變數。如果沒有這一行,建立起來的 container 是無法使用 ROS2 的。此步驟很重要,之後建立自己的 ROS package 時也需要做一樣的初始化,ROS2 才能正確地找到 package,這部分會在文章後半提及。
我們將這份檔案存為 ros_entrypoint.sh,與 Dockerfile 放在同一個目錄底下,準備開始 build ROS2 docker image。
#!/bin/bash
set -e
# setup ros2 environment
source "/opt/ros/\$ROS_DISTRO/setup.bash"
exec "\$@"
Build RO2 Docker image
在 Dockerfile 同樣的目錄中使用以下指令開始 build ROS2 docker image
docker build -f Dockerfile -t ros2:latest .
依照每個平台的效能不同,可能需要一段不算短的時間,可以先喝杯咖啡休息一下。
進入 ROS2 docker container
build 完畢,我們使用以下指令建立一個一次性的 ROS2 container,並直接進入他的 shell
docker run -it --rm ros2:latest bash
進入 container 後,我們可以試著印出目前已有的 topic
root@e50b6063314a:/src$ ros2 topic list
如果有正確印出,表示 ROS2 有正確安裝到 docker image 裡,且 entrypoint 也有設定正確,container 裡面有正確的環境變數給 ROS 使用。
在 ROS2 container 裡 build package
假定你已經寫了幾個 package,我們可以在 container 裡面 build code 看看。尚未了解 ROS 專案結構的朋友們可以先到 如何開發第一個 ROS2 應用一文閱讀。
舉例來說,你在自己的家目錄下建立的 src 資料夾,裡面放入了兩個 package
.
└── src
├── a_package
│ ├── setup.py
│ ├── setup.cfg
│ ├── package.xml
│ └── a_package
│ ├── xxxx.py
│ └── yyyy.py
└── b_package
├── CMakeLists.txt
├── package.xml
└── b_package
├── file1.cpp
└── file2.cpp
我們可以先在 src 同級目錄下建立一個 build.sh,方便以後 build code。
這邊 colcon build 後面帶 –symlink-install 的原因是讓 python code 的 package 只安裝 symlink 到 ROS2 裡面,如此開發中修改 python source code 後,都不需要再跑一次 build,重新 ros run 即可生效,大大減少時間浪費!
#!/bin/bash
rosdep install -i --from-path . -y # 安裝 package 依賴的套件
colcon build --symlink-install # build package
建立完畢後記得
chmod +x build.sh
以後執行只需要在 container 裡面輸入以下指令即可
root@e50b6063314a:/src$ ./build.sh
當然,在啟動 container 的時候記得要把自己的 source code mount 進去 container 哦
docker run -it --rm -v $HOME/src:/src ros2:latest bash
在 ROS2 container 裡 run package
還記得前面 build image 的時候引入的 ros_entrypoint.sh 的目的嗎?讓 ROS 相關的環境變數可以正確設置。同理如果今天要使用自己開發的 package,也需要做類似的事情。
一樣,記得啟動 container 的時候要 mount source code
docker run -it --rm -v $HOME/src:/src ros2:latest bash
回顧前面的 src 資料夾樹狀圖,當 build 完後會發現 package 下多一個資料夾為 install,裡面有很多 setup.*sh 的檔案
.
└── src
├── a_package
│ ├── setup.py
│ ├── setup.cfg
│ ├── package.xml
│ ├── a_package
│ │ ├── xxxx.py
│ │ └── yyyy.py
│ └── install
│ ├── setup.sh
│ ├── setup.bash
│ ├── setup.zsh
在 container 裡,我們用 setup.bash 設置環境變數
root@e50b6063314a:/src$ source a_package/install/setup.bash
之後就可以執行自己 package 的指令了
root@e50b6063314a:/src$ ros2 run a_package some_cmd
對於 ROS 初學者最後兩節不清楚沒關係,趕快閱讀 如何開發第一個 ROS2 應用 快速了解吧!如果覺得我文章內容對你有幫助的話,請在文章後面幫我按 5 個讚!讓我知道大家都喜歡什麼內容哦!
AI 神經網路自走車
上一篇:十分鐘快速認識 ROS (Robot Operating System)
下一篇:如何開發第一個 ROS2 應用