えいあーるれいの技術日記

ROS2やM5 Stack、Ubuntuについて書いています

Raspberry Pi4におけるROS2の環境構築 (Ubuntu22.04 + Rolling)

私は高専でROSの講習を昨年から行っています。それぞれ学生はRaspi4とSDカード、あとはカメラなどの講習に必要なものを渡されます。

さすがにコミュニティやバージョンの節目という状況でROS1の講習を継続は無理があると思っているので、今年度はROS2で講習を行う予定です。


昨年度はRaspberry Pi4にUbuntu20.04LTS-Serverを無理やりデスクトップ化させてそこにROS1-Noeticを入れていました。そもそもRaspberryPi-ImagerからDesktop版がインストールできなかったからです。

Ubuntu21.04はデスクトップに対応していたので、なんでーーと思いながら配布用イメージを自作していたのですが、今年リリースの22.04からその状況が改善しそうです。

なんと、Ubuntu-Desktopが対応しています。(ただし64bitでRaspi4のみです)


まだHumbleも出ていないのに今からお試し!は気が早い気もしますが、さらに使いやすくなっているUbuntu22.04の恩恵を受けるためにもRollingインストールを行ってみました。


環境

  • Raspberry Pi4 (4GB)
  • SDカード(TOSHIBAの速い方)
  • OS: Ubuntu22.04LTS
  • ROS2: ROS2-Rolling


環境構築

Raspberry Pi上にUbuntu22のインストール

以前からインストール方法はほとんど変わっていません。Imagerを用いてUbuntu22.04-Desktopを焼き、以下の記事の「パッケージの更新」まで同様の手順で行ってください。

Ubuntu22.04ではデスクトップ画面の何もないところで右クリック→Settingができません(項目自体が消えています)

zenn.dev

Ubuntuはデフォルトでは5分で画面がロックされます。Settings->Power->Screen blackNeverにしておきましょう。


ROS-Rollingのインストール

ROS-Rollingは最新のUbuntu-LTSで動作する常に最新のROSの機能を試せるバージョンです。これからリリースされるHumbleもRollingから枝分かれしているので、Rollingの挙動がHumbleの挙動に直結します。

ROS2-Rolling (Ubuntu22)のインストール手順は以下から

docs.ros.org

sudo apt update && sudo apt install curl gnupg lsb-release -y
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 ros-rolling-desktop


動作確認

source /opt/ros/rolling/setup.bash
ros2 launch demo_nodes_cpp talker_listener.launch.py


その他画像など

Ubuntu22.04はクラゲがデスクトップ画面になっています。Ubuntu20.04よりもさらに高機能になっています(Ubuntu20.04のときも高機能!と喜んでいたころが懐かしい)

Ubuntu22ではPython3.10が採用されています。最近までPython3.7とかだった気がするけど…?


スクショ機能が大幅アップグレードしており、PrintScreenボタン一つで録画もできるようになっています。Windowsに追いついています。


Rvizは結構重いです。Ubuntu20にlightdm入れていた頃のほうがまだマシかも…


TurtleSim。問題なく動作しました。


YOLOX-ROSについては、そもそもほとんどのPyPIパッケージがPython3.9までの対応のため動きません。そのうちonnxruntimeやtflite-runtimeが対応するようになれば動くと思います。

結論

初学者がUbuntu22.04+ROS2に手を出すには少し早すぎるかも!

Dockerを使わないのであれば、夏頃までは待ったほうが良さそうです。

Humble対応予定リスト(GitHub)

LinuxのLTSリリースされた年の5月は新しいバージョンのROSが公開される月です。

Galacticリリースの記事を書いてから既に1年経ちました。時間はあっという間ですね。


Foxy→Humble移行の注意点

Dashing→Foxyへのアップデートの際にAPIが大きく変更され、複数の機能が非推奨になりました。Galacticでは非推奨が廃止になっているものがあるため、Dashing以前とHumble以降は互換性がないパッケージがいくつかあります。

Foxyのリリース・変更点(ROS Documentation)

Humbleのリリース・変更点(ROS Documentation)

例えば、Hubmleのアップデート以降darknet_rosはそのままでは動きません。(launchにおいてnode_executableが使えないため)

また、多く使われるCUDAのバージョンが11に移行したことやAmpereアーキテクチャの登場で過去のプログラムでハードウェア依存があるものはメンテナンスなしでは動かないものが多いです。

そのため、昨年作製したリポジトリで引き続きHumbleに移行する(動作テストを行う)パッケージを示します。公式は全部対応すると思いますが、個人が管理しているリポジトリはアップデートされているかを確認するの大変ですからね…


対応リスト

以下はHumbleリリース後に動作確認を行い、適宜修正予定です。

⭐(総スター数)は2022年5月1日時点のものです。

パッケージ (GitHubへのリンク) 概要 Foxy Galactic
darknet_ros_fps16 darknetをベースにした物体検出パッケージ 18
YOLOX-ROS YOLOXをベースにした物体検出パッケージ 105
motpy_ros Motpyをベースにした物体追跡パッケージ 5
ps_ros2_common PS3/PS4/PS5コントローラの配置変換ライブラリ 12
YOLOv5-ROS YOLOv5をベースにした物体検出パッケージ 10
YouTube-publisher-ROS2 Youtube-dlのROSラッパー 2
rclshark2 IPアドレスとユーザネームの探索用サーバー 0


このリストに掲載していないパッケージであっても対応したバージョンへのプルリクエストやメンテナンスの必要性が出てきた時にアップデートしていく予定です。

YAMLでComposableNodeを起動する(ROS2・launch_yaml)

ここでは、あまり注目されていない?launch.yamlの記法について説明します。


最近ROS2のlaunch記法のうちの一つにYAMLがあることを知りました。

docs.ros.org

launchとは、ROSのプログラムを同時に起動するときに使われるツールですが、基本Pythonで書かれることが多いです。ROS2の豊富な機能やリソースを全て使い切るためにはLaunchのAPIを直叩きするのが最も手っ取り早いです。(ROS2は機能のほとんどがPythonベースになっています。)

冗長なPythonによる設定よりもはるかに見やすいYAMLによる設定の方を初心者向けには推したいところですが、ドキュメントが本当に少なく、ハードルはxmlpython記法よりも高い気がします。


今年度もROSの勉強会なるものを現在計画しています。やはり、できる限り円滑な講習の運営のためにはより分かりやすい文で書けるようにしたほうがいいと思っています。なぜならlaunchファイルはプログラミングではなく設定として扱われることが多いからです。

そこで、今回は多くの開発者が多用しているComposableNodeの書き方について示したいと思います。私が調べた限りではComposableNodeをlaunch_yamlで記載している記事を見たことがないです。

書き方

最初に見慣れたPythonの書き方を示します。demo_nodes_cpp talker_listener.launch.pyをComposableNodeで記述したプログラムです

import launch
from launch_ros.actions import ComposableNodeContainer
from launch_ros.descriptions import ComposableNode


def generate_launch_description():
    container = ComposableNodeContainer(
            name='image_container',
            namespace='',
            package='rclcpp_components',
            executable='component_container',
            composable_node_descriptions=[
                ComposableNode(
                    package='demo_nodes_cpp',
                    plugin='demo_nodes_cpp::Talker',
                    name='node_talker',
                    remappings=[('/chatter', '/talker_listener')]),
                ComposableNode(
                    package='demo_nodes_cpp',
                    plugin='demo_nodes_cpp::Listener',
                    name='node_listener',
                    remappings=[('/chatter', '/talker_listener')])
            ],
    )

    return launch.LaunchDescription([container])

次にYAMLの書き方を示します。コマンドラインからの応答を元に記述しているため、ほかにも使える機能があるかもしれません。

launch:
  - node_container:
      pkg: "rclcpp_components"
      exec: "component_container"
      name: "my_container"
      namespace: ""
      composable_node:
        -
          pkg: "demo_nodes_cpp"
          plugin: "demo_nodes_cpp::Talker"
          name: "node_talker"
          remap:
          -
            from: /chatter
            to: /talker_listener
        -
          pkg: "demo_nodes_cpp"
          plugin: "demo_nodes_cpp::Listener"
          name: "node_listener"
          remap:
          -
            from: /chatter
            to: /talker_listener

参考サイト(xml

launch.xmlのComposableNode対応

github.com

launchの3構文

docs.ros.org

そのほか

APIを呼ぶキーの割当てが定義されているファイルが見つかりませんでした…どこにあるか誰か教えてください

キーの指定方法がわからなかったので、エラー文から動作するプログラムを推測しました。

microROS-ArduinoのM5Atom用設定(ESP32・ROS2)

本当はもう少しあとにしようかなとか思っていたのですが、後輩に「先輩の記事見たんですが、ros2arduinoを使ったほうがいいのかなーー」と言われてしまい焦ったので、とりあえず今のうちからmicroROSを推しておこうと思います。


…なぜ知っているし。

microROSとは

microROSとは、実質公式のマイコン向けROS2です。

ArduinoやSTM32CubeMX、Raspberry Pi Picoなどのさまざまなプラットフォームに対応しており、(Agentサーバが必要になりますが)ネットワーク内のデバイスと自由に相互通信することができるようになります。

microROSはrclc-client libraryをベースにしてさまざまなミドルウェアを統合したライブラリです。マイコンによるUDPTCPを使ったDDS通信をサポートするMicroXRCE-DDSや、POSIXベースのRTOSに対応しています。

ros2arduinoからの乗り換え

およそ1年半前にROS2をはじめて触った頃にマイコン向けのROS2で探したところ使いやすかったライブラリがros2arduinoでした。見てわかるとおり現在はほとんど開発されていませんが…

github.com

microROSと比べても記法がC++寄りで分かりやすく、自分がほしかった機能を満たすくらいには使えたので1年くらいはこのライブラリを使っていました。

ただ、sensor_msgs/Imu型のデータがどうしても送れなかったりpub-subを増やしすぎると動かなくなったりしたので、これらの悩みを解決できるmicroROSに乗り換えました。

mROS2というagentなしのすごいマイコン向けROS2もあるようなのでマイコンが手に入れば使ってみたいですね。

micoROS-Arduino + ESP32の使いかた

microROSはさまざまなボードをサポートしているため、ボードの数だけチュートリアルがありますが、ここではM5Atom(ESP32-Pico)とPlatformIOを使った開発例を紹介したいと思います。

BugC + PS5の組み合わせもこのチュートリアルにしたがって作成できます。近いうちにレシピを公開したいです。

環境

1. PlatformIOを開く

次の画面は、ExtensionsからPlatfomIOをインストールしてVSCodeのリロードが終わったあとの画面です。

f:id:Ray_ar:20220407095755p:plain

プロジェクトの新規作成を行います。

  • ① PlatformIOのアイコンをクリック
  • ② PIO Home/Openをクリック
  • ③ + New Projecttをクリック

f:id:Ray_ar:20220407095955p:plain

すると、上のような画像が表示されます。Project Wizardに次の内容を記入します。

  • Name:プロジェクト名
  • Board:対象ボード。M5Atomは対象に含まれていないもののCPUがM5Stick-Cと同じなので、M5Stick-Cを選択する。
  • Framework:言語。Arduino言語を使用するため、Arduino Frameworkを選択する。
  • Location:ファイルが格納される場所

すべて記載したらFinishボタンを押してプロジェクトが作成されるまで待つ。

2. platformio.iniの設定

microROS-Arduinoにはライブラリの組み合わせがあるようで、すべて最新でOK!…とはいきません。そこで、PlatformIOの利点であるビルド時にライブラリを自動インストールする機能を使います。

f:id:Ray_ar:20220407104326p:plain

プロジェクトウィザード終了後にplatformio.iniが開くので次のコードをコピペします。

gist.github.com

もしかしたら、Git由来のライブラリがアップデートされた場合にコンパイルに失敗する可能性もあるかもしれないので、その場合は適宜修正してください。

コメントアウトしている箇所は、ESP32-devとM5Stick-Cの場合のライブラリを使いたいとき用です。その場合、M5Atom依存のライブラリをコメントアウトして対象のライブラリのコメントアウトを外してください。

3. main.cppの編集

MPU6886のimuの内容を送信するサンプルプログラムを以下に示します。

※ROS2のエラー処理については簡単のために省略しています。

#include <Arduino.h>
#include "WiFi.h"

#include <M5Atom.h>

// microros ===================================================================
#include <micro_ros_arduino.h>

#include <stdio.h>
#include <rcl/rcl.h>
#include <rcl/error_handling.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>

#include <sensor_msgs/msg/imu.h>

rclc_executor_t executor;
rcl_publisher_t publisher;
sensor_msgs__msg__Imu msg;
rclc_support_t support;
rcl_allocator_t allocator;
rcl_node_t node;
rcl_timer_t timer;

void timer_callback(rcl_timer_t *timer, int64_t last_call_time)
{
  RCLC_UNUSED(last_call_time);

  float linear_acceleration_x = 0.0;
  float linear_acceleration_y = 0.0;
  float linear_acceleration_z = 0.0;
  float angular_velocity_x = 0.0;
  float angular_velocity_y = 0.0;
  float angular_velocity_z = 0.0;

  M5.IMU.getGyroData(&angular_velocity_x, &angular_velocity_y, &angular_velocity_z);
  M5.IMU.getAccelData(&linear_acceleration_x, &linear_acceleration_y, &linear_acceleration_z);

  msg.linear_acceleration.x = linear_acceleration_x;
  msg.linear_acceleration.y = linear_acceleration_y;
  msg.linear_acceleration.z = linear_acceleration_z;
  msg.angular_velocity.x = angular_velocity_x;
  msg.angular_velocity.y = angular_velocity_y;
  msg.angular_velocity.z = angular_velocity_z;

  rcl_publish(&publisher, &msg, NULL);
}

void setup()
{
  M5.begin(true, true, true);
  M5.IMU.Init();

  // int agent_id = 2000;
  // set_microros_wifi_transports("ssid", "pass", "ip", agent_id);
  set_microros_transports();

  delay(2000);

  allocator = rcl_get_default_allocator();

  // create init_options
  rclc_support_init(&support, 0, NULL, &allocator);
  rclc_node_init_default(&node, "micro_ros_node", "", &support);
  rclc_publisher_init_default(&publisher, &node, ROSIDL_GET_MSG_TYPE_SUPPORT(sensor_msgs, msg, Imu), "pub_imu");

  const unsigned int timer_timeout = 1000;
  rclc_timer_init_default(&timer, &support, RCL_MS_TO_NS(timer_timeout), timer_callback);
  rclc_executor_init(&executor, &support.context, 1, &allocator);
  rclc_executor_add_timer(&executor, &timer);
}

void loop()
{
  delay(100);
  rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100));
}

あとは左下付近にあるUploadボタンを押してアップロードします。Permission Errorの場合は管理者権限を与えるとうまく動きます。

/dev/ttyUSB0に接続されている場合、大体はsudo chmod 777 /dev/ttyUSB0で解決します。(dockerの場合も同様です。)

4. microROS-agentの起動

micorROS-agentはDockerを使った起動が最も楽です。ここではUSBポート経由のシリアル接続の場合の実行コマンドを示します。

docker run -it --rm -v /dev:/dev --privileged --net=host microros/micro-ros-agent:galactic serial --dev /dev/ttyUSB0 --baud 115200

他のインタフェースを使用する際はこのページを参考にコマンドを入力してください。


接続に成功すると次のようなログ画面になります。

f:id:Ray_ar:20220407104455p:plain

あとは別のターミナルでros2 topic echo /pub_imuを入力してトピックを受信すれば、1秒ごとにIMUのデータが流れてきます。

ブログ3年目。

このブログは開設から2年経過しました。これまでで135本の記事、閲覧数3万のブログ記事となりました。いつもご覧頂きありがとうございます。

2年前の記事→初投稿 - えいあーるれいの技術日記

1年前の記事→ブログ開設1年。これまでとこれからについて - えいあーるれいの技術日記

ソフトウェアな1年

この1年を振り返ってみれば、「最初にソフトウェア、中ソフトウェア、最後もソフトウェア」な1年でした。ちょうど1年前の記事ではオープンソースのロボットプロジェクト「ar-ray-robot(仮称)」や画像処理のROS実装の検討についても進めていきます。と書いていたのですが、ロボットについてほとんど触っていませんでした。

しかし、ROS2の特殊な使用例や画像処理との組み合わせについてはなかなか良い成果が出たのかなと思います。
2021年4月→2022年4月までの画像処理+ROS2ソフトウェア

github.com

ウマ娘」との出会い

秋ごろから多忙によりずっと不調だった私に強い影響を与えたプロジェクトに「urara-challenge」があります。これが私にいくつかのプロジェクトをもたらし、スキルアップに繋がりました。

github.com

「馬の判定根拠は背景に依存する」ことがこのプロジェクトを通して分かりましたが、実は背景との誤認識を利用したプロダクトもあるそうです👀

wired.jp

現在の物体検出プログラムというのはCOCOデータセットを基に学習を行い検証を行うことが多いですが、これだけでは不十分なんだなーと感じる良い機会でした。

現在もランキング作成も兼ねてぼちぼちとウマ娘を進めていますが、既に例のツイートから4ヶ月も経過して注目されなくなっているのでだいぶ後回しになると思います。課金すればだいぶ進むと思いますが(他に買いたいモノがたくさんあるので)…
またこういった人気コンテンツに関連したプロジェクトをネタ程度に楽しむのもいいなぁと思います。

収益

昨年の記事では執筆した記事で収入が欲しいとも考えていますなんてことを書いていました。あれからAmazon associateやGoogle AdsenseGitHub sponsorsなどの収益化方法を試しています。

  • Amazon associate:500円程度(現在は中止)
  • Google Adsense:2000円程度(報酬未発生)
  • GitHub sponsors:$10(2人のスポンサー❗感謝🙏🙏🙏)
  • A8 netバナー:20〜30円程度(報酬未発生)

そもそもこのブログ自体が収益化を目的にしていないため報酬に対するモチベが低かったというのはありますが、リンクを貼るのがとにかく大変でした…

GitHubではできるかぎりプログラムのメンテナンスを継続していきたいと思っているので支援頂けると幸いです。

あと1年

今年度は学生最後の1年です。そしてこれまでの学生生活の中でも最も多くの自由な時間が与えられる年でもあります。これまで通り気まぐれでプロジェクトを立ち上げることはもちろん続けていきたいですが、長期間かけてしっかりと作り込むことにも挑戦していきたいなーと思います。

まずは現在取り組んでいるPyamlQtをしっかり作り込んでいきたいです。

おわりに

 2020年4月1日から今日(3月31日現在)までの2年間で総PV数が30427件となりました。前年比30倍です。本当にありがとうございます。これからも頑張って投稿を続けたいと思います。