みつきんのメモ

組み込みエンジニアです。Interface誌で「Yocto Projectではじめる 組み込みLinux開発入門」連載中

Yocto標準SDKでROS2ノードをビルド〜YoctoでROS2に入門する(その3)

はじめに

YoctoでROS2入門シリーズ

  1. YoctoでROS2に入門する(その1)
  2. YoctoでROS2に入門する(その2)

前回作成したscarthgap+humbleの環境向けに標準SDKを作成してROS2ノードをビルドできるようにする。

全体の流れ

ROS2ノードのためのワークスペースなどを作成するためにホストPCにもROS2環境をインストールする必要がある。1 そのため全体の流れとしては以下のようになる。

  1. ホストPCのROS2セットアップ
  2. 標準SDKのビルド
  3. ROS2ワークスペースの作成
  4. ROS2ノードの作成
  5. ターゲットでの動作確認

ホスト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ノードをクロスコンパイルできることがわかった。

  1. ホストPCにROSのインストールは必要
  2. TOOLCHAIN_HOST_TASK/TOOLCHAIN_TARGET_TASKに追加が必要

  1. SDKのホスト側のsysrootに入らないかいろいろ試したけど断念した。