0から始まる自動運転チャレンジ
この記事はUEC Advent Calender 2024の1日めの記事になります。
1日目から遅れてしまい申し訳ありません...
2日目の記事は、UdonさんのWeb Audio APIを使ってみたです。
私もiCCD2を受けていたので、無事にプロジェクトが完成することを応援してます!
はじめに
始めました。UEC21のぼいどと申します。某サークル等でインフラをやったりしています。
最近は自動運転をする板を作ってるのですが、その中でなんもわからんの状態から学んだ技術的なまとめ記事です。
自動運転やつくばチャレンジなど興味のある方に刺されば幸いです。
動くいたProject
学内でもしかしたら謎の板が走っているのを見かけたことがある人もいるかもしれません。
動くいたProjectとは、自動運転をする板の形状をしたモビリティを開発するプロジェクトです。iCCDという授業をきっかけに、約5名のメンバーで昨年から開発を進めています。
一応の目標としては、
近年、AGV(Automated Guided Vehicle)と呼ばれる自律走行型の荷物運搬ロボットが倉庫など幅広い分野で活用されています。しかし、既存のAGVは倉庫での運搬、飲食物のデリバリー、工場の建物間運搬など、それぞれの用途に特化して提供されています。ハードウェアの基本的な機能は共通しているにもかかわらず、他の用途への転用が難しい状況です。
我々の「動く板Project」は、こうした課題を解決するべく、特定の用途に縛られず、様々なシステムやハードウェアと容易に連携・拡張が可能なIoTスマートデバイス「動く板NEO」を開発しています。
という建前があるのですが、どちらかというと何かモビリティを作りたいというモチベーションで進めてます。
最近は某PoCなどに出展していたりします。今の所の目標としては、来年のつくばチャレンジに参加することを目標にしています。
ハードウェア構成
ハードウェア周りに関しては、主にチームメンバーのやえさんというハードウェアのプロが設計をしてくれています。ハードがないとソフトウェアは動かせないので、頭が上がりません。感謝!
2年間の中で少しずつハードウェアも進化しているので、その変遷を踏まえてご紹介します。
Ugokuita初代
一番初めの機体です。
LiDARには中華で2万円ほどのYD-LiDARを採用し、制御はJetson Nanoを利用しています。
この機体でセンサーの値測定などしてみたのですが、以下のような課題が出てきました。
- 2D Lidarで位置が低いため、車などの障害物を検知できない
- 地面が凸凹で揺れるため値が安定しない
Ugokuita v2
初代の課題を解決すべく、v2では3D LiDARを採用しました。やはり、屋外での安全な自動走行となるとある程度ちゃんとしたものが必要になってきそうなので、LivoxのMID-70というLiDARを導入しました。
また、拡張性などの関係でJetson NanoからAsrockのN100 Mini-ITXマザーボードに変更となりました。メモリは16GBでSSD512GBぐらいです。
また、IoT連携機能の開発のためにNVR700Wを追加したり、フロントライトの追加などが行われています。(なお、NVR700Wは3G/LTEにしか対応したなかったため結局は楽天のMobile Routerになりました)
現在は主にこちらの機体でデバッグを進めています。
Ugokuita NEO
現在開発中の最新鋭の機体です。
LiDARがMID-70からMID-360に変更され、さらにフレームもより頑丈になりました。
また、そのほかに細かい部分でも色々とグレードアップされています。
現在はこの機体を改良しつつ、つくばチャレンジに対応した機能などを追加開発しているところです。
開発費用はハードウェアだけで約30万円ほどかかりました....
自動運転に何が必要?
これを始めた当時はROSや自動運転に必要な技術など何もわからない状態からのスタートでした。
そこで、自動運転を始めようとなった時に何が必要なのかと思い色々と調べてみました。
まず初めに登場したのが、Autowareと呼ばれるOSSの自動運転プラットフォームです。最初はこれを使おうと思ったのですが、当時は知識がほぼなかったので起動することすら苦戦して諦めました...
とりあえずは、ROS2というロボット開発のためのミドルウェアがあるのでそれを使って板を動かすというところに注力して、自動運転に関しては少し停滞していました。
その後色々あり、今年の夏のMFT2024でSONYのブースで太田さんという方がやっている「Spresenseとmicro-ROSではじめるSLAMとNavigation」というプレゼンを見たのですが、これがとても参考になりました。丁寧に必要な要素について解説してあり、資料を何回も読ませていただきました。
また、つくばチャレンジ参加者の方の記事も非常に参考になりました。
自動運転に必要な要素まとめ
色々な記事を読んだり試したりする中で必要な要素が見えてきました。以下は私が理解した範囲でのまとめなので、誤っている場合があるのでご注意ください。
センサー
- LiDAR
点群データを取得するためのセンサー。2Dでも3Dでも良いが、3Dの方が精度は高い。
2Dの場合はsensor_msgs/LaserScan.msg
、3Dの場合はsensor_msgs/PointCloud2.msg
というフォーマットで出力する。 - IMU
機体の姿勢を推定したり、自己位置推定に利用する。基本的には9軸加速度センサーが必要。
sensor_msgs/Imu.msg
というフォーマットで出力する。 - モーションセンサー
オドメトリ情報を出力する。オドメトリとは、車輪やステアリングの回転角度を累積計算して、ロボットの位置や速度、移動距離などを推定する手法のことで、今回の場合は両輪の速度差から計算。
開始した地点から、実際にロボットがどの方向にどれだけ進んだのかを累積していき、現在の位置を推定する。今回の場合は、ホイールに内属されたホールセンサーの情報を利用した。
Odometryでは、nav_msgs/Odometry.msg
というフォーマットで現在の座標と車両の向きを出力。
TF(TransForm)
ROS2をやっている中で最も苦労した概念がこれです。
まず、ROSにはFrameIDという座標系を指定するためのIDが存在します。
Rviz2など可視化するときに、fixed frame
で指定したりします。
そして、複数の座標系(FrameID)でその親子関係を構成するのがTFです。
現在の動く板では以下のような座標系が存在します。
- base_link
ロボットの基準位置座標 - base_footprint
地上のbase_linkの投影 - scan_link
LiDARの位置 - imu_link
IMUの位置 - map
ロボットが位置するワールド座標 - odom
オドメトリと真のワールド座標のずれ
また親子関係がここでは、以下のような状況になっています。 - map
- odom
- base_link
- base_footprint
- scan_link
- imu_link
また、TFがPublishされるTopicには主に以下の2種類があります。
- base_link
- odom
- /tf
主に変化するTF(odomやmapなど) - /tf_static
変化しないTF(base_linkに対するimu_linkなどロボットのハードウェア構成)
今回は実際の機体の設計データをもとにしてTFを出力しています。
UDRF
ロボットのモデルを表現するためのXML。
ボディの形や車輪であったりIMUなどを定義して、Gazebo上のシミュレーションやNavigationで利用する。
あまり詳しくは理解していないけど、おそらく経路計画の時にどの幅なら通れるとかをやってるのかな...?
例:TE-YoshinoriOota/Spresense-microROS-Seminar2より引用
ソフトウェア
- SLAM
各種センサーの情報をもとにしてロボットの現在の位置を推論する仕組みで、事前に相応する場所に対してマッピングを行い地図を作成する。
2Dと3Dの両方の種類のものがあり、いくつか選択肢がある模様。実際に試してみたものだと、LIO-SAMやCartgrapherなどがあったが、パラメータ調整の項目などが多くあまり芳しく動作しなかった。
以下の記事が参考になりました。
https://qiita.com/rsasaki0109/items/493c1059ffe3178166bc
今回はglimと呼ばれる日本の産総研で作られているOSSのSLAMを活用して、3Dマップを作成する。
選定理由としては、日本人の方が開発しておりサポート・開発もしっかりされていること、さらに今回利用するLivox MID-70やMID-360での動作実績があることが大きいです。
- Navigation
SLAMで作成した地図を用いて、ロボットの自己位置を推論しつつ、新たな障害物などの情報を踏まえた上で目的地までの適切なルートを作成してくれる経路計画の仕組み。
今回は代表的なものとして、Navigation2というフレームワークを利用する。
事前にマッピングした2D地図と周囲の点群情報から自己位置推定をしつつ、障害物などを回避する経路を生成してくれるも。ロボットへの指示は、geometry_msgs/Twist.msg
で行われる。
必要なTopicを用意
GLIMでマップを作るために最低限必要なデータは以下の3つです。
- PointCloud
- IMU
これらのデータに加えて、OdometryなどNavigationに必要な情報も用意します。
Odometry情報の生成
モータードライバ側でホールセンサーの値から各車輪の実速度がわかるので、その値をシリアル通信経由でROS2のNodeが取り込み、それを定期的にOdom_publisherが受け取ってます。
速度と受信する周期から初期位置からの車輪の移動、車輪の速度差から車体の向きがそれぞれ分かるので、これらの情報を累積していって現在の位置と向きを計算しています。
必要なデータを全て取得したRviz2上で可視化してみると、マップ上で実際にロボットが初期位置から移動し、LiDARの向きに追従した方向で点群が取得できていることを確認できました。わーい!
地図の作成
以下の記事などを参考にしつつ、ロボットが自己位置推定するために必要な3Dマップの作成を行います。
3次元の点群地図のデータは.pcd
という形式で、2次元の地図情報は.pgm
という形式です。
今回は3次元の地図を自己位置推定、2次元の地図を経路計画に利用します。
地図作成の流れとしては、
- rosbagでセンサーの値を記録しながらロボットを走らせる
- rosbagで記録したトピック再生しながらマップを作る
といった流れがあります。2の処理が非常に重いので、板とは別のGPUがある環境で動かします。
とりあえずはGLIMを動かしてみようと必要なトピック情報を指定して起動してみたのですが、なんか荒ぶってますね
原因として考えられることとしては、LiDARとIMUのタイムスタンプが合っていないといったことが考えられるので、一度rosのトピックをrosbagで記録してから再生すれば比較的マシになりそうかなと思い試行錯誤中です...
Navigation
地図の作成の部分で詰まっているので、まだNavigationまで手をつけられていないのですが、3D地図を作成した後の流れについて検討しました。以下の記事が参考になりました。
検討している構成は以下のとおりです。
ここでは、3D LiDARからの自己位置推定にAutowareのLocalizationを使ってみようかなと検討しています。Localizationで自己位置等を推定した後で、その情報をNavigation2に流してそこで経路計画をするという算段です。
最初から3D LiDARの情報をスライスしてLaserScanにもできるのですが、せっかくの3D LiDARなのに情報量が減ってしまうのは残念なので3Dのままで自己位置推定をする方法を模索しています。
問題点 どうやってPGMに変換するのか?
今回Navigationに利用しようとしているNavigation2は主に2Dのマップしか対応していません。そのため、作成したpcdのマップをpgmに変換する必要があります。
何やら以下のようなツールを使えばいけそう...?
何かうまい方法をご存知の方いたら知りたいです
まとめ
最初は自動運転という曖昧な目標でしたが、約2年間色々と調べていくうちに具体的にどんな技術の組み合わせで実現されているのかを知ることができてきました。自動車の自動運転なんかでは、これ以外にも画像認識など多数のコンポーネントがあるようですが、基本的な仕組みは自己位置推定と経路計画という認識です。(最初からAutowareという膨大なComponentが詰まったシステムを理解しようとするのは無謀でした...)
現在は3Dマップの作成の部分まで進めてきましたが、ここからNavigationの部分まで完成させ直近で電通大の中での自律走行したいと思ってます。
最後にちょっとした宣伝ですが、動く板NEOは12/14にあるGUGEN2024に参加予定なので興味のある方いたら来場お待ちしてます。
Discussion