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

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

ロボットタクシーに乗ってきました

ティア某(ティアフォー・TIER IV, Inc.)の自動運転技術を活用したタクシー「ロボットタクシー」の試乗会に参加する機会を頂き、試乗しました🚕

米・中から遅れを取っているとしばしば言われる日本ですが、自動運転はもうすでに来ているんだなぁと感じさせられる試乗会でした。


なぜ乗れたのか?

イベントのプレゼントキャンペーンに「ロボットタクシー試乗券」があり、これに当選して乗ることができました。

medium.com

オープンソースな自動運転ソフトウェアをベースに、その技術・実装力に注目が集まっているティアフォーは昨年10月に自動運転「レベル4」の認可を受けました。イベントは、このプレスリリースに関連したものです。

prtimes.jp


レベル4

国土交通省の資料によると、レベル4は「特定条件下においてシステムが全ての運転タスクを実施」と位置付けられており、レベル4での運転中は人による介入が発生しません。

レベル3と異なり、開発・製造側の責任が非常に大きいことや認証プロセスが非常に難化するため、技術・法整備両面でこれを支えなければなりません。

4が実用化されたケースはとても少なく、日本でも2023年の4月施行の改正道路交通法によって認証を通せるようになったばかりです。


他の景品も魅力的なものばかりでしたが、体験はプライスレス。お台場に向かいました。


いざ試乗🚕

平日のお台場のタクシー発着所でタクシーを待つことに。

この日は晴天でした。最高のタクシー日和ですね(?)

お台場のタクシー停留所にて

タクシーの外観、点群が大量に出ていそうなタクシーです。

一番上に載っているLiDARは上下方向に128ライン取得可能だそうです。

社内モニタには見たことあるような車両ステータスと周辺環境の画面が映っていました。

画面上ではリアルタイムに交通状況や車両の状態が分かるそうです。

運転経路を指定したら、自動でハンドルやアクセル・ブレーキを操作して運転してくれます。


特にすごいなぁと感じたのは、右折時の対応です。

右折時に対向車の動きを見て的確に右折を行っているようです。

対向車が見えなくなって動こうとしたところ、バイクが接近してくることがあったのですが、これにもしっかりと対応してブレーキを踏んでいました。

右折時

ただ、対向車が非常に多い状況下では右折中に赤信号になってしまうケースがあり、この時は詰んでしまいます。

地域特性や混雑を避けた運転など工夫が必要そうですね。


早くロボットタクシーで移動できる時代来ないかな🤤

今回の試乗を通して、結構「安心感」がありました。

タクシーは意外と飛ばしてくれたりすることを考えるとロボットタクシーは結構慎重な方です。

しかし、無人だとそちらの方がかえって安心感を得られる気がしますね。


自動運転は既に技術としては確立しており、あとは法整備など含めて、社会がどう受け入れるかにかかってる気がします。

自動運転が一家に一台になる日は来るのでしょうか?来てほしいなぁ🤤

CoRE-1の近況報告

ほぼ1ヶ月投稿しておらず申し訳ないです🥲

CoRE-1というロボットコンテストの募集から5ヶ月、ついに大会直前です。

ar-ray.hatenablog.com

ここ1ヶ月間は(仕事以外の)書類作成タスクや届いたハードウェアに組み込む作業で全く時間が取れていませんでした…😭


ちなみに、大会が終わっても書類タスクが山積…😇

入門書も書く!と宣言しているだけにまだまだ忙しくなりそうです🥺

週一ペースで投稿とXのプロフィールに堂々と書いていますが、ここ数ヶ月は厳しいなぁと。

ただ、トータルの文章量はブログと同じ(もしかしたらそれよりも多いかもしれない)なので、公開された時はぜひご覧ください🙏


今のコンディション

1ヶ月ほど前にロボットが届いて実装開始!とXでは言いつつ実はかなりやばかったりするのですが、開発自体は着々と進めています。

画像処理

大会の規定上、ソフトウェアの全ての部分にROS 2が使用されています。

ROSはそのままでも割とソフトウェアを切り分けやすいのですが、画像処理部分ではpluginlibを使用してさらにノード内を通信部分とアルゴリズム部分を切り分けています。

GitHub - StrayedCats/detector2d: Detection2d node for CoRE-1 2024

pluginlibは、文字列を引数に渡すことでROSに登録されているモジュールを動的に読み込ませることができる機能です。インタフェース部分は確定しているけどその中身を入れ替えたい時に使用できます。

RvizやRqtで使用されていたりするので、実はROSに欠かせない機能だったりします。

TensorRTのdetectorを作りたい!と思った時は別リポジトリプラグインだけ作って後付けロードが可能なので、依存関係を隔離できるのも嬉しいポイント。

開発者はC++コードとして開発してもらって後でplugin仕様に合わせてライブラリを作ってもらえるので、円滑に開発が進むだろうなぁーと。

xmlのエラーに気づきにくかったりするのは罠かもしれないですね。

そういえば、C++でバリバリ(趣味として)開発する人ってどれくらいいるのでしょうか?Rustの方が受けが良かったりするんですかね?


ハードウェアとの繋ぎ込み

チーム結成当初は、「ハードウェアインタフェースで繋ぐぞ!」と意気込んでいたのですが、現実はそうではありませんでした…

GitHub - scramble-robot/CoRE_AutoRobot_2024_raspberrypi

通信相手をEthernetが付いているマイコンだと思っていたのですが、まさかのラズパイ4でした。(なんなら中で私が作ったdpkgが動いているw🙃)

この大会、ラズパイをしばいた方がいいのでは?と思いつつ開発方針を変更しました。rosbagを取りやすいのはいいですね。


行動計画

BehaviorTree (4) を使っています…が、ちょっとまだ作りこめていないので頑張ります…


開発ツール:AprilTag

特定の画像を使って絶対自己位置を推定する手法(TagSLAM)に使われるAprilTagというものがあるのですが、これをパネルに貼り付けて実験しています。

うまく動かない時に何が間違っているのかが一目で分かるので結構重宝しています。


3/24京都で会いましょう👋

まとまりのない文章ですが、近況報告でした。


3/23に予選・3/24に準決勝・決勝があり、私たちのチームは3/24に参加する予定です。

当日まで非常に忙しくなりますが、ラストスパート頑張ります🏃🔥


ROCK5のNPUで遊ぶ(Ubuntu22・rknn・YOLOX)

先週から今週にかけてAIに関するニュース(Gemini Pro・Chat with RTX・Sora)が飛び込んできて、再びLLM・生成AIの話題が沸騰中みたいです。

別方面ではありますが、まだまだAIへの投資と進化は止まらなさそうです。手元のPCで動く日が来るかもしれないと思うと楽しみですね✨


エッジAIだとラズパイ5の日本上陸も重大トピックの1つでしょう。

3倍速いと言われるCPUとPCIeのコネクタ実装によって新しい使い方ができるようですね。


今回は このRaspberryPi ROCK5内蔵のNPUで遊ぼう思います🙃(おい


ROCK5とは?

ROCK5はシングルボードコンピュータを開発・製造しているRadxaのボードです。AとBがあり、私が使っているのはRaspberryPi Bに形状が似たAタイプです。

RaspberryPi 5 ModelBと形状が似ており、他の製品についてもほとんどRaspberryPiのCPU以外は全部パクリと言ってもいいでしょう。

ROCK5にはARM-CPU(Cortex-A76とCortex-A55のbig.LITTLE構成)が搭載されており、m.2が差せるところもあります。また、ラズパイらしい配置のUSBコネクタやGPIO・カメラコネクタも備えているので、もう実質RaspberryPi5と行ったところでしょう。


実は1ヶ月ほど前に入手して、CPU性能まわりを軽く調べていました。

Ubuntu-Desktopのリッチなグラフィックスも余裕で動かすくらいのGPU性能とCPU8コアの物量があるので、CPU性能だけに目を向ければラズパイはおろか、周辺のミニPCともいい勝負ができるでしょう。

ar-ray.hatenablog.com


内蔵AIアクセラレーション(NPU)は?

CPUは別にROCK5 (RK3588) 以外にもいくらでも選択肢があるわけで、ここまで読む限りではRaspberryPiでもよくね?となるかもしれません。

ここからはハードウェアアクセラレーションも軽く試してみることにします。

RockchipのRK3588には、最大6TOPsのAI推論用のチップ(NPU)が搭載されています。

AI推論といえばGPU (NVIDIA-CUDA・cuDNN) の使用が浮かびますが、NPUはAI推論に必要な機能に絞っているため、小型・低消費電力でありながら高速に処理することができます。とにかく小型・省電力なので、最近ではスマートフォンやノートPCにNPUを搭載するモデルも増えているようです。

外付けデバイス無し・2万弱でこの性能は嬉しいですね。


YOLOXのアクセラレーション

Rockchipのnpu (rknpu)を使用したAI推論例はrknn_model_zooに揃っています。

github.com

私が公開しているリポジトリにYOLOX-ROSというものがありますが、現時点ではx86前提のものが多いので、新たにrknpu向けに機能を追加したいなと思っています。

なお、今回の記事で紹介する実装については既にGitHubに上げています。

2種類以上同時に動かすと(多分設定の不具合で)プロセスが落ちる場合があるので、API操作が間違っているなどあればissue・PRお待ちしています🙇

github.com


モデル変換

Rockchipのnpuでモデルを動かす場合はNPU向けの量子化(拡張子:.rknn)が必要です

airockchip/rknn_model_zooのyolox/python/convert.py でonnxモデルを変換します。

モデル構造がNPU向けに最適化されているので Megvii-BaseDetection/YOLOX で配布されているonnxは使用しないでください。


x86-64環境にAI用変換ツール(rknn-tookit2)の環境を構築した上でonnxを変換スクリプトで変換します。

python3 convert.py <path to yolox_s.onnx> rk3588


ROS 2との統合

とりあえずROS 2と統合していろいろなデバイスでお試しできるようにしました。

github.com

YOLOXのrknn実装はC言語で書かれておりrknn_model_zooにもOpenCVのC実装が入っていますが、これを使うとなぜかうまく実行できなかったので、毎度OpenCVのMat型からimage_buffer型に変換しています。

該当箇所

cv::Mat3b YOLOX::image_buffer_to_mat3b(image_buffer_t* image_buffer)
{
    cv::Mat3b mat(image_buffer->height, image_buffer->width);
    memcpy(mat.data, image_buffer->virt_addr, image_buffer->size);
    return mat;
}

image_buffer_t YOLOX::mat3b_to_image_buffer(cv::Mat3b* mat)
{
    image_buffer_t image_buffer;
    memset(&image_buffer, 0, sizeof(image_buffer_t));
    image_buffer.width = mat->cols;
    image_buffer.height = mat->rows;
    image_buffer.width_stride = mat->cols;
    image_buffer.height_stride = mat->rows;
    image_buffer.format = IMAGE_FORMAT_RGB888;
    image_buffer.size = mat->cols * mat->rows * 3;
    image_buffer.virt_addr = (unsigned char*)malloc(image_buffer.size);
    memcpy(image_buffer.virt_addr, mat->data, image_buffer.size);
    return image_buffer;
}

パフォーマンスを大きく落としてはいないので今のところはこれでよしとしています。


依存環境

OSはこちらを使用しました。

github.com

使用するボードを確認してimgを選択してください。SDカードやemmc、SSDなどに焼きます。

emmcやSSDだと設定を色々いじる必要がありそうです。

「SDカード不安定」と言われていますが、私は気にせずに使ってます。


Ubuntu22.04をインストールしたら ros-humble-desktopをインストールします。

Ubuntu (Debian packages) — ROS 2 Documentation: Humble documentation


librealsenseを使いたい場合は、Ar-Ray-code/installerのREADME_Raspbian内にある 2.54.2:v4l2debパッケージをダウンロードしてインストールします。

cd
wget https://s3.ap-northeast-1.wasabisys.com/download-raw/dpkg/librealsense/debian/bookworm/librealsense-v4l2-backend-app-bookworm-2-54-2-arm64.deb -O ./librealsense.deb # 2.54.2 (v4l2) / bookworm
sudo apt install ./librealsense.deb

sudo curl https://raw.githubusercontent.com/IntelRealSense/librealsense/master/config/99-realsense-libusb.rules --output /etc/udev/rules.d/99-realsense-libusb.rules
sudo udevadm control --reload-rules
sudo udevadm trigger

realsense_rosを使用する場合はlibrealsenseに対応したバージョンのブランチを切って後述の yolox_rk3588_ros と一緒にビルドします。


ビルド方法

mkdir -p ~/ros2_ws/src
cd  ~/ros2_ws/src
git clone https://github.com/Ar-Ray-code/yolox_rk3588_ros.git
bash yolox_rk3588_cpp/install.sh # パスワード入力

cd ..
colcon build

install.shlibrknnrt.solibrga.so/usr/local/lib にコピーするためのコマンドです。


実行方法

事前にimage_publisher など画像送信トピックを起動します。

モデルは yolox_s.rknn とします。

export TARGET_RKNN=./yolox_s.rknn
source ~/ros2_ws/install/setup.bash
taskset -c 4,5,6,7 ros2 run yolox_rk3588_ros yolox_rk3588_ros_node --ros-args -p model_path:=${TARGET_RKNN}

ros2 run の前に付いてる taskset -c 4,5,6,7 は、タスクを指定したCPUコア番号で使用することを指定しています。

0~3番目はCortex-A55、4~7番目がCortex-A76に割り当てられているため、後者の方がちょっとスピードが速いです。

あと、pub-subどちらも同じコアに割り当ててください。異なると動かなくなったりパフォーマンスが落ちることがあります。 (pub側が0~3のコアだったらsub側も0~3のコア)


以下、実行時の様子

yolox-m (INT8) まだまだ余裕ありそう

パフォーマンスはYOLOX-Mで12~14fps程度 (preprocess・postprocess含む) です。参考元のリポジトリの通りの性能が出ていることは確認できました。

量子化の影響か、tinyやnanoなど416x416の入力の推論だとガクッと精度が落ちてしまうので、sやm推奨です。

電力は測っていないのですが、RaspberryPi用の15WのACアダプタでも動いています。


まとめ

ビルドの過程でいろいろ試行錯誤したので、情報がまとまっておらず雑に書いていますが、省電力AIチップ何かないかなーと探している人には結構選択肢に入るのかなと思い書きました。

本当はハードウェアエンコードやカメラも試して1話完結させたかったですが、今後もちまちまと書いていこうと思います。

バスの降車ボタンで楽しいLチカライフ💡🚎(電子工作日記)

久々のほのぼの回(?)🙃


いつもの通りXを眺めていたら、日本AI界隈のインフルエンサー(裏の顔はからあげ帝国のトップであり闇のエンジニア)であるからあげ先生が秋葉原でなにかしら見つけたようで、話題になっています。

え、バスのボタンが売ってる…だと!?


秋葉原といったら電子部品のジャンク品も売っている電気街ですが、このようなジャンク品を見たのは初めてでした。(自転車やPCのジャンクは結構見かけますが…)

こんな楽しそうなパーツを見たのは久しぶりだったので次の日に買いに行くことにしました🏃


どこで売ってる?

秋葉原書泉ブックタワー5階にあります。

電子部品のジャンクコーナーかなと思ったら、鉄道・バスの書籍・ファン向けグッズの売り場の一角にあります。

他にも(本物の)吊り革や運転席にありそうな装置が置いてあったりと結構本格的なパーツ揃いです。

見た感じだとバスのボタンのみ電子工作に使えそうなので、これを2つ買うことにしました。

乗ってたバスから引きちぎってないですよ!!!

いつのタイミングで追加されるのかは分かりませんが、定期的に見に行こうと思います。

新たな楽しみができて嬉しいです。私も昔は鉄道にハマっていたので、その頃に行きたかったなぁと思いつつ書店をあとにしました。


とりあえず仕様確認

とりあえず分解しました。

売り場には「転売はしないでください」と書いてありましたが、「リバースエンジニアリングしないでください」とは書いていなかったので、申し訳なく思いながら分解することにしました(というか特殊ネジでもなかった)

タクトスイッチ側には51Ωの抵抗が入っており、LED側は1つのダイオードと5つのLED、1.5kΩの抵抗が入っていました。

ダイオードは1個あたり0.7Vくらい降下、LEDは1個あたり2Vくらい降下で10.7Vくらい降下するので、24Vくらいの電圧をかける必要があります。

ちなみに、何も知らずに12Vを入れましたが光りましたw(おい)🙃

配線は黒がGND、緑がスイッチ用の接点(単純なGNDへの接点)、白がLEDのアノードということになります。

XHコネクタを取り付けてLet's 電子工作!!


Arduinoで楽しい電子工作!

シンプルなLチカ回路を作成しました。

パーツは次の通り

これらのパーツで回路を作りました。

ArduinoのBlinkを動かします。

not回路になっているので、ArduinoのLEDが消えたタイミングで降車ボタンが光り、LEDが点いた時に消えます。

これまでのどのLチカよりも楽しかったですね。

こういう面白いパーツがあればどんどん買っていきたいですね😀

ラズピコWではじめるROS 2(micro-ROS・RaspberryPi Pico W)

クリスマスプレゼントにぴったり?なメカナムロボットを買った(電子工作日記) - えいあーるれいの技術日記の続きです。

今回は、Wi-Fiに繋がるRaspberryPi PicoWにmicro-ROSを載せちゃおうという試みです。


RaspberryPi Pico

RaspberryPi PicoはRaspberryPi財団が開発したマイコンチップ「RP2040」を搭載したボードです。

チップ自体はCortex-M0+という低価格・省電力重視仕様ですが、デュアルコアでベースクロック133MHzからさらにスピードを上げることができます。

突き詰めれば色々と遊べますね。

(実際、1GHzまでOCする強者も…🔥)

www.raspberrypi.com

ちなみに、「RaspberryPi(ラズパイ)」はシングルボードコンピュータを指すため、区別してラズピコと呼んでいます。


Pico W

RaspberryPi Pico W (ラズピコW)は、ラズピコに無線チップ「CYW43439」を外付けしたモデルです。

Wi-Fi (2.4GHz) とBluetoothに繋げられるモデルですが、1200円くらいするので、ESP32チップ単体と比べるとなかなか悩ましい価格です。

プラットフォームや消費電力で比較することになりそうです。


micro-ROSとは?

micro-ROSとは、ROS2ノードとマイコンを接続するプロジェクトです。

他のROS2↔︎マイコンのプロジェクトと比較すると、幅広くプラットフォーム・デバイスをサポートしており比較的構築が簡単です。

ROS2との接続には、ホストPC上にmicro-ros-agentというROS2ノードを立ち上げる必要があります。

micro.ros.org

micro-ROS自体はプラットフォーム非依存のライブラリなので、ArduinoだけでなくESP-idfやRaspberryPi-Pico SDKでも使えます。


ラズピコ自体はmicro-ROSでサポートされていますが、UARTのみとなっていました。

github.com

Wi-Fiは自分でサポートしないといけないのかなと思ってフォーク先を漁っていたら、ありました!ラズピコW用のリポジトリ🤩

github.com

これだと少々使いにくかったので、コードを整理してUARTとWi-Fiを切り替えられるようにしました↓

github.com

これで、rpi-pico-de-hajimeru-ros2ができますね😉


使い方(4輪メカナムロボットの場合)

リポジトリは以下のURLより

github.com

TwistでデータをsubscribeしてTimerを回してデータが来ていない場合は速度をゼロにするだけの簡単なプログラムです。

analogWriteで全てを解決してきた自分としては、クロックからPWM生成とか訳わからんすぎでしたね。(PWMの部分(自分用)


ちなみに、動作確認についてですが、動きはしたもののモータの回転速度が全然違ったり唐突に接続が切れたりでちょっとキレそうになっていました…

フィードバックがない上に制御よわよわなのでちょっと今の状態では厳しいかも‥と思い、一旦諦めです😖

もしかしたらXに動画上げるかも

進捗(特になしw)

モータをDynamixelに変更して再挑戦ですね‥(原型留めていないのでは?