はじめに
YoctoでROS2入門シリーズ
前回作成したscarthgap+humbleの環境向けに標準SDKを作成してROS2ノードをビルドできるようにする。
全体の流れ
ROS2ノードのためのワークスペースなどを作成するためにホストPCにもROS2環境をインストールする必要がある。1 そのため全体の流れとしては以下のようになる。
ホストPCのROS2セットアップ
ホストPCにはUbuntu 22.04を使用しているので以下のコマンドを実行してROS2(humble)の環境をインストールする。
$ sudo apt update $ sudo apt install -y curl gnupg lsb-release $ sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(source /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null $ sudo apt update $ sudo apt install -y ros-humble-desktop $ sudo apt install -y python3-colcon-common-extensions
標準SDKのビルド
下記のコマンドで標準SDKをビルドする。
$ cd ~/yocto/ros $ source poky/oe-init-build-env $ bitbake ros-image-core -c populate_sdk
SDKのインストール
下記のコマンドで標準SDKをインストールする。
$ cd tmp-glibc/deploy/sdk/ $ oecore-ros-image-core-humble-x86_64-cortexa57-qemuarm64-toolchain-nodistro.0.sh
インストール先
Yocto Project標準のPokyとは異なりデフォルトのインストール先が「/usr/local/oecore-x86_64」となっている。 そのままでも良いが消すときに見つけづらいので「/opt/yocto-ros」に変更する。
Robot Operating System 2 (ROS 2) with OpenEmbedded Linux SDK installer version nodistro.0 ========================================================================================= Enter target directory for SDK (default: /usr/local/oecore-x86_64): /opt/yocto-ros
インストール完了時にSDKを使用する際には、下記を実行するようにというメッセージが表示される。
Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g. $ . /opt/yocto-ros/environment-setup-cortexa57-oe-linux
「. /opt/yocto-ros/environment-setup-cortexa57-oe-linux」は下記に置き換えることもできる。
$ source /opt/yocto-ros/environment-setup-cortexa57-oe-linux
ROS2ワークスペースの作成
ROS2プログラミング入門 #2 Hello worldを参考にワークスペースを作成する。このページでfoxyを使用しているのでhumbleに読み替えて作業する。
空のパッケージの作成
新しい端末を開いて操作する。
SDKを有効化するために下記を実行する。これはROS2の有効化の前に行う必要がある。
$ source /opt/yocto-ros/environment-setup-cortexa57-oe-linux
ROS2を有効化するために下記を実行する。
$ source /opt/ros/humble/setup.bash
上記ページを参考にワークスペースとパッケージを作成する。
$ mkdir -p ~/dev_ws/src $ cd ~/dev_ws/src/ $ ros2 pkg create --build-type ament_cmake my_first_package $ cd ~/dev_ws/ $ colcon build
エラー
しっかりとエラーが発生する。このエラーはmeta-rosとYoctoを使用した場合にはよく出てくるエラーらしくGoogle先生に聞くとよく引っかかる。
Starting >>> my_first_package
--- stderr: my_first_package
CMake Error at /opt/yocto-ros/sysroots/cortexa57-oe-linux/opt/ros/humble/share/ament_cmake/cmake/ament_cmake_export_dependencies-extras.cmake:5 (find_package):
By not providing "Findament_cmake_libraries.cmake" in CMAKE_MODULE_PATH
this project has asked CMake to find a package configuration file provided
by "ament_cmake_libraries", but CMake did not find one.
Could not find a package configuration file provided by
"ament_cmake_libraries" with any of the following names:
ament_cmake_librariesConfig.cmake
ament_cmake_libraries-config.cmake
Add the installation prefix of "ament_cmake_libraries" to CMAKE_PREFIX_PATH
or set "ament_cmake_libraries_DIR" to a directory containing one of the
above files. If "ament_cmake_libraries" provides a separate development
package or SDK, be sure it has been installed.
Call Stack (most recent call first):
/opt/yocto-ros/sysroots/cortexa57-oe-linux/opt/ros/humble/share/ament_cmake/cmake/ament_cmakeConfig.cmake:41 (include)
CMakeLists.txt:9 (find_package)
---
Failed <<< my_first_package [0.48s, exited with code 1]
Summary: 0 packages finished [2.62s]
1 package failed: my_first_package
1 package had stderr output: my_first_package
しかし、解決方法がほとんど出ていない。
エラーの内容としては、下記の通りビルド時にament-cmake-librariesパッケージが見つからないというものになる。
Could not find a package configuration file provided by
"ament_cmake_libraries" with any of the following names:
ament_cmake_librariesConfig.cmake
ament_cmake_libraries-config.cmake
Yocto 標準SDKの環境においては、ターゲット向けのsysrootである「/opt/yocto-ros/sysroots/cortexa57-oe-linux/」に にament-cmake-librariesパッケージが見つからないというエラーになる。
回避方法
通常populate_sdkタスクは、ターゲットにインストールされるパッケージについては自動的にターゲットのsysrootにインストールするようになっている。しかし、ビルド時に依存するがイメージにインストールされないパッケージについてはTOOLCHAIN_TARGET_TASK変数に追加しておかないとSDKには含まれない。
PokyなどのYocto Project由来のDISTROの場合は割とよしなになってくれるが、meta-rosのDISTROではあまりそこはケアされていないようだ。
応急処置として、local.confに下記を追加する。
TOOLCHAIN_HOST_TASK:append = " \ nativesdk-python3-catkin-pkg \ " TOOLCHAIN_TARGET_TASK:append = " \ ament-cmake \ ament-cmake-pytest \ ament-cmake-google-benchmark \ ament-cmake-core \ ament-cmake-test \ ament-cmake-vendor-package \ ament-cmake-export-dependencies \ ament-cmake-python \ ament-cmake-auto \ ament-cmake-gmock \ ament-cmake-export-interfaces \ ament-cmake-export-definitions \ ament-cmake-export-libraries \ ament-cmake-nose \ ament-cmake-gen-version-h \ ament-cmake-export-link-flags \ ament-cmake-include-directories \ ament-cmake-version \ ament-cmake-gtest \ ament-cmake-export-include-directories \ ament-cmake-export-targets \ ament-cmake-libraries \ ament-cmake-target-dependencies \ ament-lint-cmake \ ament-lint-auto \ ament-lint \ ament-lint-common \ fastrtps-cmake-module \ foonathan-memory-staticdev \ " SDKPATHINSTALL = "/opt/yocto-ros"
ビルドプロセスでホスト側でcatkin-pkgのモジュールを参照するためTOOLCHAIN_HOST_TASKで「nativesdk-python3-catkin-pkg」を追加している。
「SDKPATHINSTALL = "/opt/yocto-ros」は必須ではないがSDKのインストーラのインストール先の初期値を変更している。
再作成したSDKでビルド
新規に端末を再度開き、下記を実行しSDKを再インストールする。
$ sudo rm -rf /opt/yocto-ros $ cd ~/yocto/ros $ source poky/oe-init-build-env $ bitbake ros-image-core -c populate_sdk $ cd tmp-glibc/deploy/sdk/ $ ./oecore-ros-image-core-humble-x86_64-cortexa57-qemuarm64-toolchain-nodistro.0.sh
更に新規に端末を開き、再度パッケージをビルドする。
$ source /opt/yocto-ros/environment-setup-cortexa57-oe-linux $ source /opt/ros/humble/setup.bash $ cd ~/dev_ws/ $ colcon build
下記のメッセージが表示されればビルドは成功。
Starting >>> my_first_package Finished <<< my_first_package [0.72s] Summary: 1 package finished [0.92s]
ROS2ノードの作成
パッケージをビルドした端末で作業する。
hello.cppの作成
~/dev_ws/src/my_first_package/src/hello.cppを下記の内容で作成する。
#include "rclcpp/rclcpp.hpp" int main(int argc, char** argv) { rclcpp::init(argc, argv); auto node = rclcpp::Node::make_shared("hello"); RCLCPP_INFO(node->get_logger(), "Hello, ROS2 with Yocto world!"); rclcpp::shutdown(); return 0; }
CMakeLists.txtの修正
~/dev_ws/src/my_first_package/CMakeLists.txtに下記の内容を追加する。
find_package(rclcpp REQUIRED) add_executable(hello src/hello.cpp) ament_target_dependencies(hello rclcpp) install(TARGETS hello DESTINATION lib/${PROJECT_NAME})
ROS2ノードのビルド
ROS2ノードのソースコードを追加した状態で再びパッケージをビルドする。
$ cd ~/dev_ws/
$ colcon build
ビルドされたROS2ノードがクロスコンパイルされていることを確認する。
$ file install/my_first_package/lib/my_first_package/hello hello: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=d89cc90d624f8028c3d6b7bf9bc367d7ea6a1ae3, for GNU/Linux 5.15.0, with debug_info, not stripped
動作確認
ターゲットにワークスペースを転送してROS2ノードの動作を確認する。
QEMUの起動
下記を実行してQEMUを起動する。
$ cd ~/yocto/ros $ source poky/oe-init-build-env $ runqemu nographic
ワークスペースの転送
QEMUとは別の端末で下記を実行する。
$ scp -r ~/dev_ws root@192.168.7.2:/root
ROS2ノードの実行
QEMUの端末で下記を実行する。
$ source /opt/ros/humble/setup.bash $ source ~/dev_ws/install/setup.bash $ ros2 run my_first_package hello [INFO] [1727630879.487773420] [hello]: Hello, ROS2 with Yocto world!
実行できることが確認できる。
まとめ
Yocto標準SDKでROS2ノードをビルドした。下記の点に注意が必要だが、問題なくROS2ノードをクロスコンパイルできることがわかった。
- ホストPCにROSのインストールは必要
- TOOLCHAIN_HOST_TASK/TOOLCHAIN_TARGET_TASKに追加が必要