こんにちは、ティアフォーでベクターマップの作成ツールの開発をしている浦本と申します。今回は、Autowareで使われている地図の中でも、特にベクターマップとその作成ツールについてお話しようと思います。
なお、ティアフォーでは、「自動運転の民主化」をともに実現していく様々なエンジニア・リサーチャーを募集しています。もしご興味があればカジュアル面談も可能ですので以下のページからコンタクトいただければと思います。
自動運転の地図
点群地図とベクターマップについて
Autowareで使われる地図には、自己位置推定のための点群地図と、その地図上の走行可能領域や信号・標識などを定義したベクターマップがあります。
Autowareは、道路や周囲の環境の形状を持っている点群地図と、走行中に取得したスキャンデータが最もマッチする重ね合わせから、車両の位置や向きを推定しています。この仕組みをスキャンマッチングといいます。スキャンマッチングについての詳細はこちらをご覧ください。
ベクターマップには、走行可能領域や信号・標識以外にも、速度制限、優先道路などの交通ルールや注意が必要なエリアのような情報を入れることができ、これらの情報を適切に設定することで、車両がその場所に適した走行をできるようにしています。
Autowareは現在、このベクターマップのフォーマットとしてLanelet2を採用しており、このフォーマットをAutoware用に一部拡張して使っています(これ以降、この記事ではLanelet2はAutoware用に拡張したものを指します)。ティアフォーで開発中のベクターマップ作成ツール、Vector Map Builder (VMB)もこのAutoware拡張のLanelet2の地図作成が可能です。以下の画像はこのツール上で地図を表示している例です。白い点群地図と色がついているベクターマップを重ねています。
Lanelet2について
ここでは、Lanelet2の詳細について説明したいと思います。
Lanelet2はOpenStreetMap(OSM)形式を拡張したもので、拡張子は.osm、ファイルに出力する際にはXML形式となります。Lanelet2は以下の基本オブジェクトで構成されますが、出力時にはOSMに合わせてnode、way、relationの3種類に分類されます。各基本オブジェクトの説明とファイルに出力した際のサンプルは以下のとおりです。なお、画像はVMBでの表示例です。
Point
- 一番基本となるオブジェクトで、座標や信号の色情報などを持ちます。
- OSMのnodeに分類されます。z座標はeleというタグで表されます。
- ローカル座標を使いたい場合は、local_x、local_yというタグを設定することもできます。
- lat/lonは緯度経度、local_x、local_y、eleの単位はメートルです。
<node id="1" lat="35.0000" lon="139.0000"> <tag k="ele" v="19.000"/> </node>
LineString
- Pointのリストを順番に線で結んだオブジェクト。LineString2つでLaneletを構成したり、信号機や一時停止線に使われます。
- OSMのwayに分類されます。
- 構成要素のPointをndタグで持ちます。
- 一時停止線はtypeをstop_line、点線はsubtypeをdashedにすることで表します。Laneletの境界線のLineStringをdashedにすると隣接レーンに車線変更が可能になるなど、タグの付け方を変えることで様々な設定が可能です。詳細はこちらをご覧ください。
<way id="1"> <nd ref="1"/> <nd ref="2"/> <nd ref="3"/> <nd ref="4"/> <tag k="type" v="line_thin"/> <tag k="subtype" v="solid"/> </way>
Polygon
- Pointで囲まれた領域を表します。障害物検知領域を表すDetectionAreaなどで使われます。
- OSMのwayに分類され、area=yesというタグをつけます。
<way id="1"> <nd ref="1"/> <nd ref="2"/> <nd ref="3"/> <nd ref="4"/> <tag k="type" v="detection_area"/> <tag k="area" v="yes"/> </way>
Lanelet
- 左右にLineStringを1つずつ持ち、その間の領域を表します。向きを持っており、車線や横断歩道などに使われます。
- OSMのrelationに分類され、type=laneletというタグをつけます。
- 左右のLineStringをmemberとして持ちます。
- その車線で守る必要のある交通ルール(RegulatoryElement)がある場合は、それもmemberとして持ちます。
- 制限速度や通行対象(車や歩行者など)、一方通行かどうかなどの情報を持てます。
<relation id="1"> <member type="way" role="left" ref="1"/> <member type="way" role="right" ref="2"/> <member type="relation" role="regulatory_element" ref="2"/> <tag k="type" v="lanelet"/> <tag k="subtype" v="road"/> <tag k="speed_limit" v="50"/> <tag k="location" v="urban"/> <tag k="participant:vehicle" v="yes"/> <tag k="one_way" v="yes"/> </relation>
Area
- LineStringで囲まれた領域を表します。車両や人の通行領域を表す場合によく使われますが、Laneletと違って向きは持ちません。
- OSMのrelationに分類され、type=multipolygonというタグをつけます。
- 構成要素のLineStringをmemberとして時計回りの順番に持ちます。
<relation id="1"> <member type="way" role="outer" ref="1"/> <member type="way" role="outer" ref="2"/> <tag k="type" v="multipolygon"/> </relation>
※Polygonとの見た目の違いは、周囲がLineStringで囲まれているかどうかです。
RegulatoryElement
- 一時停止、信号、優先道路などの種類があり、それらがどの車線や一時停止線、信号機と紐付いているのかという情報を持っています。オブジェクト間の紐付けとルール情報を持つだけなので地図上に表示されるものではなく、画像はありません。
- OSMのrelationに分類されます。type=regulatory_elementというタグをつけます。
- subtypeでルールの種類を指定します(例:traffic_lightは信号、right_of_wayは優先道路)。
<relation id="1"> <member type="way" role="refers" ref="1"/> <member type="way" role="light_bulbs" ref="2"/> <member type="way" role="ref_line" ref="3"/> <tag k="type" v="regulatory_element"/> <tag k="subtype" v="traffic_light"/> </relation>
RegulatoryElementはルールの種類によってmemberの数や種類も変わってきます。例としてサンプルにも記載している信号を説明します。信号のmemberは3つで、refers、ref_line、light_bulbsがあります。それぞれtypeがwayとなっているので、LineStringがPolygonを表すのですが、信号に紐付くのは全てLineStringです。
まずはrefersですが、これは信号の外形を表します。ファイルに出力すると以下のwayのようになるのですが、ndの2と3は画像の丸(Point)の部分で信号機の幅を表し、heightタグで高さを表します。
<way id="1"> <nd ref="2"/> <nd ref="3"/> <tag k="type" v="traffic_light"/> <tag k="height" v="0.450000"/> </way>
次にlight_bulbsは、以下のwayのようになり、traffic_light_idは信号機の外形のLineStringのidを表しています。ndの4から6はPointで、以下のidが4のnodeのような形でそれぞれcolorタグで信号の色情報を持ちます(画像の信号の場合はred、yellow、greenの3つ)。
<way id="2"> <nd ref="4"/> <nd ref="5"/> <nd ref="6"/> <tag k="type" v="light_bulbs"/> <tag k="traffic_light_id" v="1"/> </way> <node id="4" lat="35.0000" lon="139.0000"> <tag k="ele" v="19.546"/> <tag k="color" v="red"/> </node>
最後にref_lineですが、信号のref_lineは信号が赤だった時に停止する停止線を表すため、以下のwayのように、stop_lineというtypeを設定します。
<way id="3"> <nd ref="7"/> <nd ref="8"/> <tag k="type" v="stop_line"/> </way>
このようなオブジェクトを組み合わせて、ベクターマップを作っています。
Vector Map Builderの紹介
これまで説明してきたようなベクターマップを作成するためのツールとして、ティアフォーではVMBを開発しています。ブラウザで動作するツールで、TypeScript、React、Three.jsを主に使っています。
リンクはこちらになりますが、最初にティアフォーアカウントを作成いただいてからログインが可能となります。
ここでは、地図を作りやすくするために実装しているVMBの機能を一部紹介します。
1つ目は、点群地図の表示範囲指定機能です。この機能を使うケースとして、例えば屋内のベクターマップを作成するときに、点群に屋根が入ってしまっていてそのままでは屋内の形状が見にくいというものがあります。そういう場合は、この機能で不要な屋根部分の点群をカットし、見たい範囲の点群だけを見えるようにすることで、地図作成がしやすくなります。他にも、下の画像のように木が邪魔で車線が見づらい場合にも使えたり、上下の高さを指定できるので、ビルのような複数階を含む点群があったときには、見たい階だけを残して作業することも可能です。
2つ目は、地図のリアルタイムチェック機能です。車線や交通ルールが増えて地図が複雑になると、作成・編集時にミスが起こりやすくなり、チェックも大変になります。ミスが残ってしまっていても、地図作成後はシミュレータで動作チェックを実施するため、想定外の挙動をする場合はそこでわかるのですが、複数箇所が間違っているとVMBに戻って該当箇所を修正→走行チェックという作業を何度か繰り返さなければいけない場合があります。
VMBではそのような作業を少しでも減らすため、フォーマットとして間違っている点に加え、ティアフォーのこれまでの地図作成経験からリストアップしたチェック項目を作成作業中にチェックするようにしています。問題のある設定をすると、その設定を行った直後に問題のあるオブジェクトとその詳細を表示し、修正を促します。また、修正をしないまま地図の保存を行った場合は、問題点が残っていることを表示し、問題点に気づかずに保存してしまうことをできるだけ避けられるようにしています。
画像は設定している制限速度を超えたLaneletが存在する場合の例です。何が問題なのかという説明とIDを表示しており、IDをクリックすることで該当オブジェクトの設定が確認できるようになっています。
チェックすべき項目は、現在も実証実験等から問題を吸い上げたりしながら増やしており、今以上に充実させていく予定です。
まとめ
今回は、Autowareで使われている地図の中でも、特にベクターマップについてお話しました。自動運転車がどのような地図を使って走行しているのか、イメージできたでしょうか。
ベクターマップは精度が求められるので作成時は細かな作業が多く、持たせる情報も多いことから設定とチェックに時間がかかります。これらの問題を解消し、より安全な地図をより早く作ることができるツール・仕組みの開発をこれからも進めていきます。