ROS 2 公式文書(英語) 日本語訳シリーズです。
本ブログの日本語翻訳版のトップページは以下のリンクを参照下さい。
※2019/05/11 現在のものです。
概要
Open Robotics はマルチプラットフォーム用にビルド済みの ROS 2 パッケージを提供していますが、それでも以下のようなさまざまな理由で多くの開発者がクロスコンパイルに頼っている状況です。
- 開発マシンがターゲットシステムと一致しない。
- 特定のコアアーキテクチャ向けにビルドを調整する(例:Raspberry Pi 3 用にビルドする場合は
-mcpu = cortex-a53 -mfpu = neon-fp-armv8
と設定)。 - Open Robotics がリリースしたビルド済みイメージでサポートされているもの以外の異なるファイルシステムをターゲットにしている。
このドキュメントでは、ROS 2 ソフトウェアスタックをクロスコンパイルする方法の詳細と、Arm コアベースのシステムへのクロスコンパイルの例を紹介します。
- 注意
- ビルド中に無効にしなければならない(クロスコンパイルが無効な) ROS 2 パッケージがいくつかあります。 4. ビルドの章を参照してください。
どう動くのか?
単純なソフトウェアのクロスコンパイル(外部ライブラリに依存しないなど)は比較的単純で、ネイティブツールチェーンの代わりにクロスコンパイラツールチェーンを使用するだけで済みます。
このプロセスをより複雑にする要因はいくつかあります。
- 構築中のソフトウェアは、ターゲットアーキテクチャをサポートしている必要があります。ターゲットアーキテクチャに応じて、アーキテクチャ固有のコードをビルド中に適切に分離して有効にする必要があります。例としてはアセンブリコードがあります。
- すべての依存関係(ライブラリなど)は、ビルド済みパッケージとして存在するか、またはそれらを使用するターゲットソフトウェアがクロスコンパイルされる前にクロスコンパイルされる必要があります。
- ビルドツール(colcon など)を使用して(スタンドアロンソフトウェアとは対照的に)ソフトウェアスタックをビルドする場合、開発者がスタック内の各ソフトウェアで使用されている基盤ビルドシステムでクロスコンパイルを有効にできる仕組みが必要です。
ROS 2 のクロスコンパイル
ROS 2 は数多くの依存関係を持つ豊富なソフトウェアスタックですが、主に 2 種類のパッケージを使用しています。
- クロスコンパイルを必要としない Python ベースのソフトウェア。
- クロスコンパイルを行うためのメカニズムを提供する CMake ベースのソフトウェア。
さらに、ROS 2 ソフトウェアスタックは、各パッケージ/ライブラリの個々のビルドに使用される CMake インスタンスにパラメータを転送する仕組みをもつ Colcon でビルドされています。
ROS 2 をネイティブでビルドする場合、(ROS 2 ディストリビューションの一部である)パッケージをコンパイルする前にすべての依存関係(例えば Python と他のライブラリ)をダウンロードする必要があります。クロスコンパイルするときも、同様です。最初にターゲットシステムのファイルシステムにすべての依存関係がインストールされている必要があります。
次の章では、ROS 2を クロスコンパイルするための cmake-toolchains と CMAKE_SYSROOT 機能の使用方法について詳しく説明します。
CMake toolchain-file
CMake toolchain-file
は、クロスコンパイル用に CMake を設定するための変数を定義するファイルです。基本的なエントリは以下のとおりです。
CMAKE_SYSTEM_NAME
:ターゲットプラットフォーム。例:linux
CMAKE_SYSTEM_PROCESSOR
:ターゲットアーキテクチャ。例:aarch64
やarm
CMAKE_SYSROOT
:ターゲットファイルシステムへのパスCMAKE_C_COMPILER
:Cクロスコンパイラ。例:aarch64-linux-gnu-gcc
CMAKE_CXX_COMPILER
:C ++クロスコンパイラ。例:aarch64-linux-gnu-g++
CMAKE_FIND_ROOT_PATH
:ファイルシステムを見つけるためにfind_*
コマンドによって使用される代替パス
ROS 2 をクロスコンパイルするときは、次のオプションを設定する必要があります。
CMAKE_FIND_ROOT_PATH
:find_*
コマンドによって使用される代替パス。これを使用して ROS 2/install
フォルダへのパスを指定します。CMAKE_FIND_ROOT_PATH_MODE_*
:プログラム、パッケージ、ライブラリ、およびインクルードの検索方法。通常は、NEVER
(host-fs を検索)、ONLY
(sysroot を検索)、ONLY
(sysroot を検索)、およびONLY
(sysrootを検索)PYTHON_SOABI
:ROS 2 によって生成された Python ライブラリのインデックス名。例:cpython-36m-aarch64-linux-gnu
THREADS_PTHREAD_ARG "0" CACHE STRING "Result from TRY_RUN" FORCE
:バイナリはホストシステムで実行できないため、TRY_RUN
コマンドの結果を矯正的に 0(成功)にします。
toolchain-file は、-DCMAKE_TOOLCHAIN_FILE=path/to/file
パラメータでパスを指定して CMake に提供されます。これにより、ビルド中のソフトウェアのCMAKE_CROSSCOMPILING
変数もtrue
に設定されます。
CMAKE_SYSROOT
は ROS 2 にとって特に重要です。パッケージには多くの依存関係(python、openssl、opencv、poco、eigen3 など)が必要だからです。すべての依存関係がインストールされているターゲットファイルシステムにCMAKE_SYSROOT
を設定すると、CMake はクロスコンパイル中にそれらを見つけることができます。
- 注意
- あなたは CMake のページでより多くの情報を見つけることができます。
ROS 2 ソースコードをダウンロードするとき、一般的な toolchain-file はリポジトリ ros2/cross_compile/cmake-toolchains にあり、別々にダウンロードすることができます。それを使用することに関する更なる例は、Arm のクロスコンパイルの章に記してあります。
対象ファイルシステム
前述のように、ROS2はクロスコンパイルするために提供される必要がある異なるライブラリを必要とします。
ファイルシステムを取得する方法はいくつかあります。
- ビルド済みイメージをダウンロードする。
- ターゲットへの依存関係のインストールとファイルシステムのエクスポート(sshfs などを使用)をする。
- qemu + docker(または chroot)を使ってホストマシン上にファイルシステムを生成する。
- 注意
Docker + qemu
の使い方については、次の Arm のクロスコンパイルの章を参照してください。
ビルドプロセス
ビルドプロセスはネイティブコンパイルと似ています。唯一の違いは、toolchain-file
を指定するための Colcon
への追加の引数です。
colcon build --merge-install \ --cmake-force-configure \ --cmake-args \ -DCMAKE_TOOLCHAIN_FILE="<path_to_toolchain/toolchainfile.cmake>"
toolchain-file
は、クロスコンパイラ
とターゲットファイルシステム
の情報を CMake に提供します。 colcon は ROS 2 のすべてのパッケージで与えられたtoolchain-file
で CMake を呼び出します。
Arm のクロスコンパイルの例
ROS 2 のソースコードをダウンロードした後、git clone https://github.com/ros2/cross_compile.git src/ros2/cross_compile
でクロスコンパイルアセットをワークスペースに追加できます。これらは、Arm コアのクロスコンパイル方法に関する実用的な例です。
以下のターゲットがサポートされています。
- Ubuntu-arm64:ARMv8-A ベースのシステムで使用します。
- Ubuntu-armhf:最新の ARMv7-A ベースのシステムと一緒に使用します。
主な手順は次のとおりです。
- 開発ツールのインストール
- ROS2ソースコードのダウンロード
- ROS2クロスコンパイルアセットのダウンロード
- sysrootを準備する
- ROS2ソフトウェアスタックのクロスコンパイル
次のセクションでは、これらの各ステップについて詳しく説明します。簡易設定もありますので、それについては自動クロスコンパイルを見てください。
- 注意
- これらのステップは Ubuntu 18.04(Bionic)でテストされました。
1. 開発ツールをインストールする
このステップは、ネイティブに構築する場合と似ていますが、違いもあります。ライブラリとツールの一部は、代わりに sysroot に含まれるため、必要とされないライブラリとツールがあります。以下のパッケージが必要です
sudo apt update && sudo apt install -y \ cmake \ git \ wget \ python3-pip \ qemu-user-static \ g++-aarch64-linux-gnu \ g++-arm-linux-gnueabihf \ pkg-config-aarch64-linux-gnu python3 -m pip install -U \ vcstool \ colcon-common-extensions
- 注意
- pip を使って vcstool と colcon-common-extensions をインストールできますので、特別な apt リポジトリを追加する必要はありません。
Docker はターゲット環境を構築するために使用されます。インストールについてはDcoker の公式文書に従ってください。
2. ROS 2 のソースコードをダウンロードする
次にワークスペースを作成して ROS 2 ソースコードをダウンロードします。
mkdir -p ~/cc_ws/ros2_ws/src cd ~/cc_ws/ros2_ws wget https://raw.githubusercontent.com/ros2/ros2/release-latest/ros2.repos vcs-import src < ros2.repos git clone https://github.com/ros2/cross_compile.git src/ros2/cross_compile cd ..
3. sysroot を準備する
Docker と qemu を使ってすべての ROS 2 依存関係について解決済みの arm Ubuntu イメージをビルドします。qemu-static
バイナリをワークスペースにコピーします。これは、dockerを 使用して ros2 依存関係をターゲットファイルシステムにインストールするために使用されます。
mkdir qemu-user-static
cp /usr/bin/qemu-*-static qemu-user-static
ROS 2 の標準セットアッププロセスが、arm docker 内で実行されます。これは、arm マシンをエミュレートするqemu-static
のおかげで可能となっています。使用されているベースイメージは Docker Hub の Ubuntu Bionic です。
docker build -t arm_ros2:latest -f ros2_ws/src/ros2/cross_compile/sysroot/Dockerfile_ubuntu_arm . docker run --name arm_sysroot arm_ros2:latest
結果のコンテナをTAR形式にエクスポートして抽出します。
docker container export -o sysroot_docker.tar arm_sysroot mkdir sysroot_docker tar -C sysroot_docker -xf sysroot_docker.tar lib usr opt etc docker rm arm_sysroot
このコンテナは、作成されたファイルシステムを実行してデモコードを実行するための仮想ターゲットとして、後ほど使用できます。
4. ビルド
汎用toolchain-file
で使用される変数を設定します
export TARGET_ARCH=aarch64 export TARGET_TRIPLE=aarch64-linux-gnu export CC=/usr/bin/$TARGET_TRIPLE-gcc export CXX=/usr/bin/$TARGET_TRIPLE-g++ export CROSS_COMPILE=/usr/bin/$TARGET_TRIPLE- export SYSROOT=~/cc_ws/sysroot_docker export ROS2_INSTALL_PATH=~/cc_ws/ros2_ws/install export PYTHON_SOABI=cpython-36m-$TARGET_TRIPLE
以下のパッケージは、クロスコンパイル中にエラーを引き起こします(調査中)。今のところ無効にする必要があります。
touch \ ros2_ws/src/ros2/rviz/COLCON_IGNORE \ ros2_ws/src/ros-visualization/COLCON_IGNORE
構築済みのPoco
には、SYSROOT ではなくホストシステムでlibz
とlibpcre
を検索するという既知の問題があります。現時点での回避策として、両方のライブラリをホストのファイルシステムにリンクしてください。
mkdir -p /usr/lib/$TARGET_TRIPLE ln -s `pwd`/sysroot_docker/lib/$TARGET_TRIPLE/libz.so.1 /usr/lib/$TARGET_TRIPLE/libz.so ln -s `pwd`/sysroot_docker/lib/$TARGET_TRIPLE/libpcre.so.3 /usr/lib/$TARGET_TRIPLE/libpcre.so
次に、toolconin-file
を指定して colcon でビルドを開始します。
cd ros2_ws colcon build --merge-install \ --cmake-force-configure \ --cmake-args \ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ -DCMAKE_TOOLCHAIN_FILE="$(pwd)/src/ros2/cross_compile/cmake-toolchains/generic_linux.cmake" \ -DSECURITY=ON
完了です!インストールディレクトリとビルドディレクトリには、クロスコンパイルされたファイル(クロスコンパイルアセット)が出力されます。
自動クロスコンパイル
上記のステップはすべて Dockerfile にも含まれており、自動化/CI に使用できます。
まず、dockerfile をダウンロードしてイメージを構築します。
wget https://raw.githubusercontent.com/ros2/cross_compile/master/Dockerfile_cc_for_arm docker build -t ros2-crosscompiler:latest - < Dockerfile_cc_for_arm
それでは、イメージを実行します。(しばらく時間がかかります。。。)
docker run -it --name ros2_cc \ -v /var/run/docker.sock:/var/run/docker.sock \ ros2-crosscompiler:latest
- メモ
- -v /var/run/docker.sockにより、DockerをDocker内で使用することができます。
ビルドの結果はros2_ws
ディレクトリ内になります。このディレクトリは次のコマンドでエクスポートできます。
docker cp ros2_cc:/root/cc_ws/ros2_ws .
ビルド済みの ROS 2 に対するクロスコンパイル
事前に構築された ROS 2 に対して自作パッケージをクロスコンパイルすることも可能です。以下の変更を加えて、ステップは前述の Arm クロスコンパイルの章で示した例と似ています。
ROS 2 スタックをダウンロードする代わりに、自身のワークスペースにパッケージ(この場合は ros2 の例)とクロスコンパイルアセットを追加するだけです。
mkdir -p ~/cc_ws/ros2_ws/src cd ~/cc_ws/ros2_ws/src git clone https://github.com/ros2/examples.git git clone https://github.com/ros2/cross_compile.git cd ..
3. sysroot を準備するの説明に従って、ファイルシステムを生成してエクスポートします(ただし、提供されている Dockerfile_ubuntu_arm64_prebuilt
を使用します)。これらの_prebuilt
Dockerfile は、ソースからビルドするのではなく、バイナリパッケージを使用して ROS 2 をインストールします。
インストールディレクトリを指すように環境変数 ROS2_INSTALL_PATH
を変更します。
export ROS2_INSTALL_PATH=~/cc_ws/sysroot_docker/opt/ros/crystal
ターゲットファイルシステムのsetup.bash
スクリプトを読み込みます。
source $ROS2_INSTALL_PATH/setup.bash
次に、toolconin-file
を指定してColcon
でビルドを開始します。
colcon build \ --merge-install \ --cmake-force-configure \ --cmake-args \ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ -DCMAKE_TOOLCHAIN_FILE="$(pwd)/src/cross_compile/cmake-toolchains/generic_linux.cmake"
ターゲットで実行
ターゲットにファイルシステムをコピーするか、以前に作成したdockerイメージを使用します。
docker run -it --rm -v `pwd`/ros2_ws:/ros2_ws arm_ros2:latest
環境を取り込みます。
source /ros2_ws/install/local_setup.bash
C++ または python の例をいくつか実行します。
ros2 run demo_nodes_cpp listener & ros2 run demo_nodes_py talker