roadrunner-convert-lanelet2-to-rrhd について
このスキルは、MATLAB を使う地図ワークフロー向けに Lanelet2 OSM を RoadRunner HD Map(.rrhd)へ変換する手順を示します。道路形状、トポロジー、意味情報を処理し、書き込み前に検証します。
主な機能
- 01Lanelet2 OSM のノード、ウェイ、関係の解析
- 02座標投影と地理参照への対応
- 03レーン、交差点、道路の意味情報の構築
- 04書き込み前の整列、空間整合性、完全性の検査
活用シーン
- 01Lanelet2 .osm マップを .rrhd に変換
- 02レーン関係を含むマップを RoadRunner に取り込む
- 03OSM から標識、バリア、速度制限を含むマップを作成
MCP 対応
生成した MATLAB 変換コードを mcp__matlab__evaluate_matlab_code 経由で実行し、run_matlab_file でスクリプトを動かす手順を示します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ matlab/ matlab-agentic-toolkit --skill roadrunner-convert-lanelet2-to-rrhdインストール後、Claude Code で/roadrunner-convert-lanelet2-to-rrhdを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
manifest.yamlreferences/buildRRHD.mddetectGeoReference.mddiscoverRelations.mdenforcementGate.mdextractGeometry.mdextractJunctions.mdextractLanelets.mdextractNonLaneElements.mdextractSemantics.mdextractTopology.mdimportIntoRoadRunner.mdlatlon2enu.mdmapLanelet2SignCode.mdplacedObjects.mdreadOSM.mdsignCodeMapping.mdsnapEndpoints.mdsplitClosedRoads.mdscripts/discoverWayTypes.mparseOSM.m詳細
Lanelet2 から RRHD への変換ツール
Lanelet2 の .osm ファイルを RoadRunner HD Map の .rrhd 形式に変換します。
使用する場面
- Lanelet2 の
.osmファイルを RoadRunner HD Map の.rrhd形式に変換する場合 - MATLAB 経由で Lanelet2 マップを RoadRunner にインポートする場合
type=laneletリレーションを含む.osmソースから RRHD を構築する場合- パース、ジオメトリ、トポロジ、セマンティクス、交差点、バリア、標識、路面標示を含む完全なパイプラインが必要な場合
使用しない場面
- 入力が標準の OpenStreetMap ファイルである場合(
type=laneletリレーションを含まない highway=* ウェイ) - 入力が OpenDRIVE
.xodrの場合 —roadrunner-import-sceneから直接インポートしてください - ソースファイルなしで RRHD を一から構築する場合 —
roadrunner-rrhd-authoringを使用してください - アセットパスの検索だけが必要な場合 —
roadrunner-asset-mappingを使用してください
重要なルール
- コードを実行する場合は、必ず .m ファイルに記述してください。
evaluate_matlab_codeに複数行の MATLAB コードを直接記述しないでください。.m ファイルに記述し、run_matlab_fileで実行し、エラーが発生したら編集してください。例外:ユーザーが「パターンを示して」または「実行しないで」と依頼した場合は、ファイルに書き込まず、コードをインラインで示してください。 - パイプラインの全ステップが必須です。 車線/境界を書き込んだだけで終了しないでください。交差点、曲線標示、バリア、標識、制限速度をすべて構築する必要があります。
- 境界ジオメトリは変更不可です。 境界点を反転、再サンプリング、投影、変更しないでください。
- ウェイごとに境界オブジェクトを1つ作成してください。
wayToBndIDマップで重複を排除してください。 - すべての車線の整列方向を検出してください。 すべての境界に
"Forward"をハードコードしないでください。 - 中心線の密度は最低でも1メートルあたり1点にしてください。
max(10, round(avgLen), nLeft, nRight)を使用してください。 write()の前に強制チェックゲートを実行してください。 整列、空間、拡張、完全性のチェックは必須です。- 関数をネストして定義しないでください。 コードはスクリプトコンテキストで実行されます。すべてのロジックをインラインまたは無名関数で記述してください。
動作
以下に説明する変換パイプラインを実行する MATLAB コードを生成します。mcp__matlab__evaluate_matlab_code 経由で実行してください。事前作成済みスクリプトや addpath の呼び出しは不要です。Claude はこれらの指示に基づき、すべてのコードを実行時に生成します。
必須:すべてのステップを実行してください。 車線/境界を書き込んだだけで終了しないでください。交差点、曲線標示(停止線と横断歩道)、バリア、標識、制限速度がなければ、パイプラインは未完了です。OSM 内で見つかったすべての要素が、出力 RRHD に含まれている必要があります。
必須:ステップ 3b と 3c(検出)は、ステップ 3a と同じコードブロック内で実行してください。 これらは任意の後処理ではなく、パースの一部です。検出ループのコードはステップ 3 にインラインで記載されています。3b/3c を省略すると、ステップ 9 の完全性ゲートでアサーションエラーが発生します。
対象範囲: このスキルがサポートするのは Lanelet2 OSM のみ です。入力が標準の OpenStreetMap ファイル(type=lanelet リレーションを含まない highway=* ウェイ)の場合、変換を試みないでください。代わりにユーザーへ次のように伝えてください。「このファイルは Lanelet2 マップではなく、標準の OpenStreetMap 道路ネットワークのようです。このスキルがサポートするのは Lanelet2 OSM から RRHD への変換のみです。」
関連スキル(変換中に自動的に呼び出す):
| スキル | 呼び出すタイミング | 目的 |
|---|---|---|
roadrunner-rrhd-authoring | ステップ 9(RRHD オブジェクトの構築) | roadrunner.hdmap.* クラス/プロパティのリファレンスと構築パターンを提供します |
roadrunner-asset-mapping | ステップ 8(セマンティクスの抽出) | 路面標示のサブタイプ、標識コード、バリアの種類を RoadRunner のアセットパスに対応付けます |
これらのスキルは必要に応じて読み込まれます。RRHD 構築コードを生成するとき、またはアセットパスを解決するときに、それぞれのリファレンスを確認してください。
スキルの担当範囲: このスキルは Lanelet2 固有の処理(OSM パース、ノード参照トポロジ、turn_direction によるクラスタリング、対向境界の検出)をすべて担当します。RRHD オブジェクトの構築パターン(整列アルゴリズム、中心線の生成、交差点ポリゴン、API リファレンス)については、roadrunner-rrhd-authoring を参照してください。
座標系
Lanelet2 の OSM ノードでは、次のいずれかを使用できます。
local_x/local_yタグ — すでにローカルメートル単位のため、ジオメトリの X/Y としてそのまま使用しますlat/lon属性のみ — 地理座標のため、ローカルメートル単位に必ず投影する必要があります
ステップ 1:map_projector_info.yaml を確認する
Lanelet2 のデータセットには通常、.osm ファイルと同じディレクトリに map_projector_info.yaml ファイルが含まれています。このファイルには、投影法と地図の原点が指定されています。
ProjectorType: TransverseMercator
VerticalDatum: WGS84
MapOrigin:
Latitude: 42.300945
Longitude: -83.698205
Altitude: 0
必ず最初にこのファイルを探してください。 ファイルを解析して ProjectorType と MapOrigin を取得します。
projFile = fullfile(fileparts(osmFile), "map_projector_info.yaml");
if isfile(projFile)
txt = fileread(projFile);
latMatch = regexp(txt, 'Latitude:\s*([-\d.]+)', 'tokens');
lonMatch = regexp(txt, 'Longitude:\s*([-\d.]+)', 'tokens');
if ~isempty(latMatch) && ~isempty(lonMatch)
originLat = str2double(latMatch{1}{1});
originLon = str2double(lonMatch{1}{1});
end
end
MapOrigin が [0, 0] の場合、原点は暗黙的です。その場合は、すべてのノードの重心を使用します。
ステップ 2:座標モードを判定する
- ノードに
local_x/local_yがある → そのまま使用し、map_projector_info.yamlの MapOrigin(yaml がない場合はノードの lat/lon)からgeoRefを設定します - ノードに
lat/lonのみがある → yaml の原点(またはフォールバックとしてノードの重心)を使用して、ローカル ENU メートル単位に投影します
ステップ 3:lat/lon をローカルメートル単位に投影する(必要な場合)
% Origin from map_projector_info.yaml or centroid fallback
geoRef = [originLat, originLon];
% For each node, convert to local meters:
dLat = node.lat - originLat;
dLon = node.lon - originLon;
metersPerDegLat = 111132.92;
metersPerDegLon = 111132.92 * cosd(originLat);
x = dLon * metersPerDegLon; % East
y = dLat * metersPerDegLat; % North
z = node.ele; % Up (elevation)
rrMap.GeoReference = [originLat, originLon] を設定して、RoadRunner が地図の地理的位置を認識できるようにします。
重要: この投影は、ノードの解析時に 1 回だけ行われます。以降のすべてのジオメトリ(境界、中心線、バリア、標識)には、投影済みのローカル座標を使用します。以下の「境界ジオメトリは不変」というルールは、投影済みの座標を指します。初回の解析後に再投影したり変更したりしないでください。
ジオメトリの不変条件(必ず適用 — 違反すると RRHD が壊れます)
これらのルールは絶対に守ってください。すべての変換で必ず従ってください。
-
境界ジオメトリは不変です。 way のノード座標(ローカル座標または投影済み座標)は、解析時に計算されたとおりに正確に格納します。初回の座標割り当て後に、境界点を反転、再サンプリング、変更してはいけません。反対方向の車線が共有する境界に手を加えると、データが破損します。代わりに
Alignment="Backward"を使用してください。 -
way ごとに境界オブジェクトを 1 つだけ作成します。
wayToBndIDマップを使用して重複を除去します。複数の車線から、異なるアラインメントで同じ境界を参照します。 -
左/右の内積と近接性テストでアラインメントを判定します。
dp = dot(leftDir, rightDir)(全体の方向を正規化した値 — しきい値判定にはこれが適切です)を計算します。dp >= -0.3の場合、両方の境界は Forward です。dp < -0.3の場合、境界は互いに逆向きです。近接性(d_ls_re = norm(leftStart - rightEnd)とd_ls_rs = norm(leftStart - rightStart)の比較)を使って、どちらを Backward にするかを判定します。d_ls_re < d_ls_rsの場合、right は Backward、left は Forward です。(注:ステップ 9 の「全体の方向を絶対に使わない」という警告は、複数サンプルを使った空間的な検証ステップに適用されるものであり、この dp のしきい値判定には適用されません。) -
中心線の密度は最低でも 1 メートルあたり 1 点にします。
nPts = max(10, round(avgBoundaryLength), nLeftPts, nRightPts)を使用します。点が少なすぎると、pchip 補間で真の中点からずれが生じます。 -
中心線の端点のみを直交させます。 接線ブレンディングを使って、中心線の始点と終点を垂直にします。境界の端点を投影してはいけません。
MATLAB スクリプトの制約
コードは mcp__matlab__evaluate_matlab_code で実行されます。これはスクリプトコンテキストであり、関数ファイルではありません。
- 入れ子関数の定義は禁止 — すべてのロジックをインラインで記述するか、無名関数を使用してください
function ... endブロックは禁止 — 「Function definitions are not supported in this context」というエラーが発生します- 型付き空配列 —
[]ではなくClassName.emptyを使用してください(例:roadrunner.hdmap.AlignedReference.empty) - Name=Value コンストラクター —
RelativeAssetPath、AlignedReferenceでは Name=Value 構文が必要です:% CORRECT: rap = roadrunner.hdmap.RelativeAssetPath(AssetPath="Assets/Markings/StopLine.rrlms"); ar = roadrunner.hdmap.AlignedReference(Reference=ref, Alignment="Forward"); % WRONG (will error with "A name is expected"): rap = roadrunner.hdmap.RelativeAssetPath("Assets/Markings/StopLine.rrlms"); ar = roadrunner.hdmap.AlignedReference(bndID, "Forward"); containers.Mapへの空値の代入 —map(key) = []は使用しないでください。map(key) = zeros(1,0)を使うか、空でない値のみを代入してください()の連結は禁止 —geomMap(key)(:,1)は「Using parentheses directly after parentheses is disallowed」というエラーが発生します。先に一時変数に代入してください:% WRONG: min(geomMap(k)(:,1)) % CORRECT: pts = geomMap(k); minX = min(pts(:,1));- セル配列に対する
unique()—unique(cellArray)には cellstr(char ベクトルのセル)が必要です。string 配列にはunique(stringArray)を直接使用してください。型が混在するセルにはunique(string(cellArray))を使用してください。 containers.Mapの値には明示的な型キャストが必要 —containers.Mapから取得した値は数値型が失われることがあります。cosd()、sind()などに渡す前に必ずキャストしてください(例:double(geoRef(1)))- セル配列の構造体フィールドへの代入 —
cellArray{end+1} = x; cellArray{end}.field = val;は使用しないでください(「dot indexing not supported for double」というエラーが発生します)。代わりに、構造体を先に作成してから追加してください:% WRONG: stopLineWays{end+1} = w; stopLineWays{end}.wayID = wid; % CORRECT: w.wayID = wid; stopLineWays{end+1} = w; % OR: store IDs in a separate parallel cell array
パイプライン(順番に実行)
ステップ 1:OSM を解析する
references/readOSM.md および scripts/parseOSM.m を参照してください。
doc = xmlread(osmFile);
% Parse nodes: id, lat, lon, ele, local_x, local_y (from tags)
% Parse ways: id, nodeRefs[], tags (containers.Map)
% Parse relations: id, members[], tags (containers.Map)
ステップ 2:形式を検証する
少なくとも 1 つの relation に type=lanelet があることを確認してください。見つからない場合は、そのファイルが Lanelet2 形式ではないことを明示するエラーメッセージを表示してください。
hasLanelet = false;
relKeys = relations.keys;
for i = 1:numel(relKeys)
rel = relations(relKeys{i});
if rel.tags.isKey('type') && strcmp(rel.tags('type'), 'lanelet')
hasLanelet = true; break;
end
end
if ~hasLanelet
error('UNSUPPORTED FORMAT: This converter supports Lanelet2 OSM files only.');
end
ステップ 3:Lanelet を抽出し、すべての非 Lanelet 要素を検出する
このステップには必須のサブステップが 3 つあります。すべて実行してください。
ステップ 3a:Lanelet を抽出する
type=lanelet の relation をフィルターしてください。references/extractLanelets.md を参照してください。
% For each relation with type=lanelet:
% leftWayID = member with role="left"
% rightWayID = member with role="right"
% subtype, one_way, speed_limit, turn_direction from tags
ステップ 3b:すべての Way タイプを検出する(必須 — 3a の直後に実行)
参考実装については scripts/discoverWayTypes.m を参照してください。
ホワイトリストは使用しないでください。 すべての way を走査し、複合タイプには strsplit(wType, '/') を使用して、type タグに基づいて分類してください:
stopLineWays = {}; pedestrianMarkingWays = {}; zebraMarkingWays = {};
bikeMarkingWays = {}; zigzagWays = {};
fenceWays = {}; guardRailWays = {}; jerseyBarrierWays = {};
wallWays = {}; curbstoneWays = {};
trafficSignWays = {}; trafficLightWays = {};
unmappedWays = containers.Map;
wayKeys = ways.keys;
for i = 1:numel(wayKeys)
w = ways(wayKeys{i});
if ~w.tags.isKey('type'), continue; end
wType = w.tags('type');
typeParts = strsplit(wType, '/');
baseType = typeParts{1};
switch baseType
case 'stop_line', stopLineWays{end+1} = w;
case 'pedestrian_marking', pedestrianMarkingWays{end+1} = w;
case 'zebra_marking', zebraMarkingWays{end+1} = w;
case 'bike_marking', bikeMarkingWays{end+1} = w;
case {'zig-zag','zig_zag'}, zigzagWays{end+1} = w;
case 'fence', fenceWays{end+1} = w;
case 'guard_rail', guardRailWays{end+1} = w;
case 'jersey_barrier', jerseyBarrierWays{end+1} = w;
case 'wall', wallWays{end+1} = w;
case 'curbstone', curbstoneWays{end+1} = w;
case 'traffic_sign', trafficSignWays{end+1} = w;
case 'traffic_light', trafficLightWays{end+1} = w;
case {'line_thin','line_thick','virtual','road_border','rail','keepout','symbol'}
% Lane boundary types — handled via lanelet extraction
otherwise
if unmappedWays.isKey(wType), unmappedWays(wType) = unmappedWays(wType)+1;
else, unmappedWays(wType) = 1; end
end
end
ステップ 3c:すべての Relation タイプを検出する(必須 — 3b の直後に実行)
分類ループの詳細については references/discoverRelations.md を参照してください。すべての非 Lanelet relation を、trafficSignRels、speedLimitRels、rightOfWayRels、trafficLightRels、multipolygonRels(.building、.parking、.vegetation、.traffic_island、.walkway、.exit、.keepout を持つ構造体)、および unmappedRels(件数を格納する containers.Map)に分類します。
検出結果の概要と未マッピングの要素を出力してください。 要素を黙って破棄しないでください。
ステップ 4:ジオメトリの構築
ノードからウェイのジオメトリを解決します。必須の実装パターンについては、references/extractGeometry.md を参照してください。
GeoReference の自動検出: local_x/local_y タグが存在しない場合は、すべてのノードの緯度・経度から重心を計算します。[0 0] は使用しないでください。references/detectGeoReference.md を参照してください。
優先順位: 利用可能な場合は、ノードの local_x/local_y タグを使用します。利用できない場合は、緯度・経度から ENU に変換します(references/latlon2enu.md を参照):
east = (lon - geoRef(2)) * 111320 * cosd(geoRef(1));
north = (lat - geoRef(1)) * 110540;
必須:方向を検出する前に、閉ループ境界を処理してください。 両方の境界が閉ループ(始点と終点の間隔が 1.0m 未満)である場合、全体の方向ベクトルはほぼゼロになり、dot(leftOverall, rightOverall) の信頼性が低くなります(約 0)。これにより誤った反転が発生し、トラックの内側を横切る中心線が生成されます(例:「幅」が 6.5m ではなく 136m になる)。閉ループ境界の処理アルゴリズム全体(局所的な方向検出+始点の位置合わせ)については、roadrunner-rrhd-authoring スキルの references/splitClosedGeometry.md を参照してください。
必須の中心線合成パイプライン — コードを含むアルゴリズム全体については、roadrunner-rrhd-authoring スキルの references/synthesizeCenterLine.md を参照してください。概要:
- 反対方向の境界を検出: 閉ループを考慮した検出を使用します(上記の
splitClosedGeometry.mdを参照) - 弧長
pchipを使用して、密度ベースの点数に再サンプリング:max(10, round(avgLen), nLeft, nRight) - 再サンプリングした境界を平均して中心線を作成
- 直交する端点を強制します(接線の 50% ブレンドを使用。閉ループレーンではスキップ)
- 境界ジオメトリは変更しないでください — 代わりに
Alignmentプロパティを使用します
重要:境界ジオメトリに直交する端点への射影を適用しないでください。 境界は、反対方向のレーンを含む複数のレーンで共有されています。あるレーンの中心線の方向に合わせて共有境界の端点を変更すると、同じ境界を参照する他のレーンでジオメトリが破損します。方向の関係は Alignment プロパティで処理します。
境界ジオメトリのルール: OSM ノードから取得した元のウェイジオメトリを常に保存します。堅牢な複数サンプルアルゴリズムを使用してアラインメントを計算します(roadrunner-rrhd-authoring/references/alignmentRules.md を参照)。全体の方向の単純なドット積は使用しないでください — 曲線ジオメトリでは機能しません。
すべてのジオメトリは Nx3 形式(ele タグの Z 値を含み、既定値は 0)である必要があります。
ステップ 5:閉じた道路を分割する
RoadRunner は自己閉鎖ジオメトリをレンダリングできません。汎用的な N 方向直交分割アルゴリズムについては、references/splitClosedRoads.md と roadrunner-rrhd-authoring スキルの references/splitClosedGeometry.md を参照してください。
閉鎖部を含むすべての接合部で、垂直断面への射影を使用して分割します。N 方向アルゴリズム全体については、roadrunner-rrhd-authoring/references/orthogonalSplit.md を参照してください。
ステップ 6:トポロジーの抽出
主な方法として境界端点のノードマッチングを使用し、フォールバックとしてジオメトリの近接性(しきい値 1.0m)を使用します。references/extractTopology.md を参照してください。
重要なルール:
- ノードのマッチング時には、反対方向の境界を考慮します(dp のしきい値に -0.3 を使用し、後退方向の右側レーンでは近接性テストを使用)
- 実効的な走行方向を使用して反対方向フィルターを適用します(後退方向の右側レーンでは、生の方向を反転します)
- より適切な代替候補がある場合は、左境界の間隔が 3m を超える誤った後続レーンを除外するため、左側の間隔によるフィルタリングを適用します
ステップ 7:交差点を検出する
アルゴリズムの全容とコードについては、references/extractJunctions.mdを参照してください。
主な方法: turn_direction タグ(straight、left、right)を交差点の車線を示す指標として使用します。
フォールバック:(先行ノードの後続ノードが1つより多い)または(後続ノードの先行ノードが1つより多い)場合、その車線を交差点の車線とします。
重要なルール:
- 8m のしきい値を使用した BFS クラスタリング — union-find は使用しないでください(遠く離れた交差点間で推移的な連結が発生します)。後処理フィルター:各メンバーがクラスタの重心から 12m 以内にあることを確認します。
- ポリゴン形状には
boundary(pts,0.7)を使用 — 良好な曲線ポリゴンが生成されます。boundary()の凹形状によって車線が除外される交差点では、convhullを選択的に使用します。 - クラスタごとに最低 2 車線(3 車線のしきい値では検出できない小さな T 字路も検出できます)
- フォールバック:カバーされていないファンイン/ファンアウトノード — 主なクラスタリングの後、交差点のカバー範囲がない、終端車線が 2 つ以上かつ開始車線が 2 つ以上のノードを検出します。これらのノードにある
turn_direction車線から交差点を追加します。 - 交差点のトポロジーノードを通過する場合、既存の交差点に非ターン車線を追加します(ポリゴンのカバー範囲が向上します)。
- すべての交差点車線境界から標示を取り除きます(ParametricAttributes を割り当てないでください)。
- **安全なフォールバック:**検出の信頼性が低い場合は、交差点を完全にスキップします — インポート時のビルドオプションで
UseLaneGroups=trueを使用してください。
ステップ 8:セマンティクスを抽出する
references/extractSemantics.mdを参照してください。
| Lanelet2 境界サブタイプ | RRHD Marking ID | アセットパス |
|---|---|---|
solid | SolidWhite | Assets/Markings/SolidSingleWhite.rrlms |
dashed | DashedWhite | Assets/Markings/DashedSingleWhite.rrlms |
solid_solid | SolidDoubleYellow | Assets/Markings/SolidDoubleYellow.rrlms |
dashed_solid | DashedSolidYellow | Assets/Markings/DashedSolidYellow.rrlms |
solid_dashed | DashedSolidYellow | Assets/Markings/DashedSolidYellow.rrlms(+ FlipLaterally=true) |
| Lanelet2 サブタイプ | RRHD LaneType |
|---|---|
road、highway、bus_lane | Driving |
crosswalk、walkway | CurveMarking(車線ではありません) |
bicycle_lane | Biking |
emergency_lane | Shoulder |
parking | Parking |
走行方向:
turn_directionタグがある →"Forward"(常に一方通行)one_way=yes→"Forward"- 歩道/縁石 →
"Undirected" - それ以外 →
"Bidirectional"
ステップ 8b:車線リストから横断歩道/歩道を除外する
RRHD 車線オブジェクトを構築する前に、サブタイプごとに lanelet を分けます。
subtype=crosswalkまたはsubtype=walkway→ CurveMarkings に振り分けます(ジオメトリには中心線を使用し、タイプはSimpleCrosswalkにします)- それ以外のすべてのサブタイプ → RRHD Lanes として構築します
**横断歩道/歩道の lanelet に対して、Lane オブジェクトを作成してはいけません。**これらは CurveMarking インスタンスになります。
CurveMarkingType の拡張 — 混同しないでください:
- 停止線 →
.rrlms(車線標示のスタイル):Assets/Markings/StopLine.rrlms - 横断歩道 →
.rrcws(横断歩道のスタイル):Assets/Markings/SimpleCrosswalk.rrcws
停止線に .rrcws を使用すると、インポート時に「アセットファイルが見つかりません」というエラーが発生します。
ステップ 9:RRHD オブジェクトを構築する
完全な構築パターンについては、references/buildRRHD.md を参照してください。
重要なルール:
rrMap = roadrunnerHDMap;を最初に実行する必要があります(名前空間を読み込みます)。警告: システムによっては、roadrunnerHDMapが RoadRunner のバックグラウンドインスタンスを起動する場合があります。インポートスキルの接続ロジックでは、再試行によってこの問題に対処します。roadrunner-import-sceneを参照してください。roadrunnerHDMapがすでにインスタンスを起動している場合は、別途roadrunner(InstallationFolder=...)を呼び出さないでください。- すべての
roadrunner.hdmap.*オブジェクトには、作成してから代入するパターンを使用します。 - ジャンクションの車線境界から区画線を除去します(ParametricAttributes を代入しないだけです)。
- 境界ジオメトリは決して変更しないでください — 元の OSM way のノード座標をそのまま保存します。境界は複数の車線(反対方向の車線を含む)で共有されます。反転、端点の投影、再サンプリングなどを行うと、他の車線の境界が破損します。
- way ごとに境界は 1 つ —
wayToBndIDマップを使用して重複を除去します。way を参照する最初の lanelet が境界を作成し、他の lanelet はすべて alignment を介して共有します。 - すべての車線で境界の alignment を検出します。
roadrunner-rrhd-authoringスキルのreferences/alignmentRules.md にある堅牢なマルチサンプルアルゴリズムを使用してください。すべての境界でalignment = "Forward"をハードコードしないでください — 不正なシーンが生成される最大の原因です。空間検証に全体方向(geom(end,:)-geom(1,:))を使わないでください — 曲率の高いセグメント(進行方向を弦の方向で表せない、分割された半楕円など)では正しく機能しません。このアルゴリズムは 2 つのステップで構成されます。(1)近接性に基づく方向検出、(2)多数決を用いた複数サンプルの局所接線による空間検証。
確認済みプロパティ名: 完全なクラス/プロパティ一覧については、roadrunner-rrhd-authoring スキルのreferences/apiReference.md を参照してください。わかりにくい主な対応関係:CurveMarking.MarkingTypeReference(CurveMarkingTypeID ではありません)、Barrier.BarrierTypeReference(BarrierTypeID ではありません)、Sign.Geometry(BoundingBox ではなく GeoOrientedBoundingBox)、SpeedLimit.Value と .VelocityUnit="Kph"、ParametricAttribution.Span=[0 1](StartFraction/EndFraction ではありません)、MarkingReference.MarkingID には数値ではなく Reference オブジェクトを指定します。
重要: 書き込む前に、自己参照トポロジ(自分自身を指す車線の predecessor/successor)をフィルターで除外してください。インポート時に RoadRunner が「connectedLane.Object != this」エラーを返します。
ステップ 10:後処理(必須 — 省略しないでください)
接続された端点をスナップする — successor の始点は predecessor の終点と一致する必要があります(車線と境界)。pred→succ の各ペアについて、ギャップが 1.0m 未満の場合は、succ の始点を pred の終点にスナップします。references/snapEndpoints.md と roadrunner-rrhd-authoring スキルのスクリプトを参照してください。
高さの競合解決(必須): 同じ Z にある、接続されていない重複車線は芝生のアーティファクトを引き起こします。グラフ彩色を使い、幅の狭い車線を Z レベルごとに +0.05m 持ち上げます。roadrunner-rrhd-authoring スキルのスクリプトを参照してください。
境界の重複除去(必須): Lanelet2 の反対方向の車線は、ジオメトリが反転した同じ内容を持つ異なる way ID を参照している場合があります。way ごとの wayToBndID による重複除去で検出できるのは同じ way の再利用のみです。ジオメトリに基づく重複除去では、反転した重複を検出します。アルゴリズムについては、roadrunner-rrhd-authoring スキルのreferences/deduplicateBoundaries.md を参照してください。
ステップ 11:組み立てて書き込む
すべての配列(Lanes、LaneBoundaries、LaneMarkings、SpeedLimits、Junctions、CurveMarkingTypes、CurveMarkings、BarrierTypes、Barriers、SignTypes、Signs)を rrMap に割り当て、rrMap.GeoReference = geoRef(1x2 の [lat, lon])を設定します。write(rrMap, outputFile) を呼び出します。references/buildRRHD.md を参照してください。
Junctions は任意です: Junction 検出を省略した場合は、rrMap.Junctions を省略します(デフォルトは空です)。インポート時のビルドオプションでは UseLaneGroups=true を使用してください。
ステップ 9 のサブステップ — レーン以外の RRHD オブジェクトをすべて構築する
ステップ 9 では、ステップ 3b/3c のレーン以外の要素をすべて構築する必要があります。コードパターンについては references/extractNonLaneElements.md を参照してください。サブステップ:9a CurveMarkings(停止線、横断歩道、自転車用標示)、9b Barriers(フェンス、ガードレール、コンクリート製防護柵、壁、縁石)、9c Signs(way と relation の両方から。標識タイプの解決については references/signCodeMapping.md と references/mapLanelet2SignCode.md を参照)、9d SpeedLimits、9e 配置オブジェクト(カスタム relation の解析については references/placedObjects.md を参照)。
強制チェックゲート(必須 — write() の前に実行)
references/enforcementGate.md の検証ブロックを必ず実行してください。このブロックでは、変換で最もよく発生する 3 つのエラー(整列、空間的な正確さ、アセットの拡張子、完全性)を検出します。省略したり簡略化したりしないでください。
書き込み後
マッピングされなかった要素の数(インポートできない建物、植生、信号)を出力します。その後、roadrunner-import-scene スキルを使用してインポートします。ビルドオプションについては references/importIntoRoadRunner.md を参照してください。
主要な関数
| 関数 | 目的 |
|---|---|
xmlread(osmFile) | OSM XML を DOM ドキュメントに解析する |
roadrunnerHDMap | HD Map オブジェクトを作成する(名前空間を読み込む) |
write(rrMap, file) | HD Map を .rrhd ファイルに書き込む |
containers.Map | 解析したノード、way、relation を格納する |
pchip / interp1 | 中心線を弧長で再サンプリングする |
vecnorm | クラスタリングと近接性の距離を計算する |
strsplit | 複合型タグ(type/subtype)を解析する |
規約
- 元の OSM way のノード座標は、解析したとおりに正確に保持します。境界のジオメトリは決して変更しません。
- インデックス付きのすべての検索(ノード、way、relation、ジオメトリ)に
containers.Mapを使用します。 - すべてのジオメトリは Nx3 とし、Z には
eleタグの値を使用します(デフォルトは 0)。 - Junction のクラスタリングには近接性に基づく BFS を使用します(しきい値 8m +重心フィルター 12m)。union-find は決して使用しません。
- Junction のポリゴンには
boundary(pts,0.7)を使用します。全体をカバーする必要がある小さな Junction にはconvhullを選択的に使用します。 - 解析後に検出結果の概要を出力し、マッピングされなかった要素を黙って破棄しないでください。
- 複数パネルの図には
tiledlayout/nexttileを使用します(subplotは使用しません)。
Copyright 2026 The MathWorks, Inc.