matlab-cosimulate-sumo-simulink について
Automated Driving Toolbox Interface for Eclipse SUMOを使い、Eclipse SUMOとSimulinkの同期交通コシミュレーションを構築するスキルです。車両状態の取得、制御、動的な追加・削除を扱います。
主な機能
- 01SUMO ServerとClientブロックの設定
- 02SUMOとSimulinkのシミュレーション同期
- 03車両状態とシミュレーション情報の取得
- 04車両の速度と位置の制御
- 05車両の動的な追加と削除
活用シーン
- 01ADASまたはADコントローラーのテスト
- 02Simulinkで車両の位置と速度を取得
- 03コントローラーからSUMO車両を操作
- 04ルートファイルなしで背景交通を生成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ matlab/ matlab-agentic-toolkit --skill matlab-cosimulate-sumo-simulinkインストール後、Claude Code で/matlab-cosimulate-sumo-simulinkを入力して読み込まれたか確認します。
同梱ファイルmanifest.yaml
詳細
SUMO と Simulink の協調シミュレーションを構築する
Automated Driving Toolbox Interface for Eclipse SUMO Traffic Simulator の SumoInterfaceLibrary ブロックを使用して、Eclipse SUMO と同期した協調シミュレーションを実行する Simulink モデルを作成します。
使用する場面
- Eclipse SUMO に接続する Simulink モデルを構築する
- ADAS/AD コントローラーのテスト用に交通の協調シミュレーションを設定する
- SUMO から Simulink に車両の状態(位置、速度)を読み込む
- Simulink コントローラーから SUMO 内の自車両を制御する
- シミュレーション中に車両を動的に生成または削除する
- ルートファイルを作成せずにランダムな背景交通を生成する
使用しない場面
- Simulink を使わない SUMO 単独のシミュレーション(SUMO の CLI または Python TraCI を直接使用してください)
- 車両ダイナミクスのモデリング(Vehicle Dynamics Blockset を使用してください)
- Driving Scenario Designer によるシナリオ設計(異なるワークフローです)
前提条件
SUMO_HOME環境変数を設定して Eclipse SUMO をインストールしていること- 「Automated Driving Toolbox Interface for Eclipse SUMO Traffic Simulator」サポートパッケージをインストールしていること
- Windows:
SUMO_HOMEの末尾に区切り文字を追加すること — Server ブロックのランチャーは、区切り文字を補わずにSUMO_HOME + "bin\..."を連結します。SUMO_HOMEの末尾に\または/がないと、SUMO が正しくインストールされていても、すべてのsim()が「Failed to launch Eclipse SUMO simulator」エラーで失敗します。モデルを作成またはシミュレーションする前に、必ず次を実行してください。
if ~endsWith(getenv('SUMO_HOME'), filesep)
setenv('SUMO_HOME', [getenv('SUMO_HOME') filesep]);
end
- 確認:
getenv('SUMO_HOME')が区切り文字で終わる有効なパスを返す必要があります。
推奨する構築方法
mcp__matlab__model_edit(SATK)が利用可能な場合は、生の add_block/add_line よりも優先して使用してください。各編集後に自動レイアウトが適用され、重なりのない整った配線が作成されます。また、同じ呼び出し内で ref を使って新しく追加したブロックを参照できます。以下のパターンはそのまま適用できます。1 つの JSON ペイロード内で add_block/connect/configure 操作として表現してください。SATK が利用できない場合、またはスキーマで表現できない操作(例:sfroot を使った MATLAB Function の Script の設定)に限り、add_block/add_line を使用してください。
注:新規作成した Enabled Subsystem の既定の In1/Out1 を削除した後に EnablePort を配線する場合、model_edit は Enable ポートを解決できません。回避策として、add_line(model, 'Source/1', 'SubsystemName/Enable', 'autorouting','smart') を使用してください。
ワークフロー
冪等なビルド用テンプレート
modelName = 'sumo_cosim';
workDir = fileparts(mfilename('fullpath'));
% SUMO_HOME workaround (Windows)
sh = getenv('SUMO_HOME');
if ~endsWith(sh, filesep), setenv('SUMO_HOME', [sh filesep]); end
% Idempotent rebuild
if bdIsLoaded(modelName), close_system(modelName, 0); end
slxPath = fullfile(workDir, [modelName '.slx']);
if isfile(slxPath), delete(slxPath); end
new_system(modelName);
open_system(modelName);
set_param(modelName, 'StopTime','100', 'SolverType','Fixed-step', 'FixedStep','0.1');
% ... build model ...
save_system(modelName, slxPath);
1. SUMO シナリオファイルを準備する
ユーザーに既存の .sumocfg を尋ねてください。新しいファイルを生成するのは、明示的に依頼された場合に限ります。簡易ネットワークには netgenerate を使用してください。
sumoHome = getenv('SUMO_HOME');
cmd = sprintf('"%s" --grid --grid.number 2 --grid.length 200 --output-file "%s"', ...
fullfile(sumoHome,'bin','netgenerate'), fullfile(pwd,'network.net.xml'));
system(cmd);
最小限の .sumocfg(EnableRandomTraffic を使用する場合、route-files は省略可能です):
<configuration>
<input><net-file value="network.net.xml"/></input>
<time><begin value="0"/><end value="100"/><step-length value="0.1"/></time>
</configuration>
ルートファイルの規則:すべての <vehicle>、<person>、<personFlow> エントリは、depart 時刻(フローの場合は begin)の順に並べる必要があります。順序が正しくないエントリは、警告なしで無視されます。Actor ブロックで使用するルートは、<flow> に埋め込まず、単独の <route> 要素にしてください。
OpenDRIVE のインポート:netconvert --opendrive-files file.xodr -o network.net.xml を使用してください。注:SUMO は netOffset を適用します(.net.xml の <location> 要素に表示されます)。すべての SUMO 座標は、OpenDRIVE 座標に netOffset を加えた値です。
2. Server と Client を作成する
add_block('SumoInterfaceLibrary/Server', [modelName '/SUMO Server']);
set_param([modelName '/SUMO Server'], 'ServerFile',fullfile(pwd,'cosim.sumocfg'), ...
'ServerPort','8813', 'ServerNumClients','1', 'EnablePacing','on', ...
'PacingRate','1', 'SampleTime','0.1');
add_block('SumoInterfaceLibrary/Client', [modelName '/SUMO Client']);
set_param([modelName '/SUMO Client'], 'ClientAddress','127.0.0.1', ...
'ClientPort','8813', 'ClientOrder','1', 'SampleTime','0.1');
重要:ClientPort は ServerPort と同じ値にしてください。FixedStep は SUMO の step-length と一致させてください。ペーシング(EnablePacing='on')を有効にして、GUI が 2 秒で一気に表示されるのを防いでください。
3~6. リーダー、ライター、Actor を追加し、保存して実行する
以下の「ブロックリファレンス」および「パターン」セクションを参照してください。モデルをプログラムから変更した場合は、必ず sim(modelName) の前に save_system(modelName) を実行してください。
ブロックリファレンス
サーバーブロック
| パラメーター | 用途 | デフォルト |
|---|---|---|
ServerFile | .sumocfg へのパス | — |
ServerPort | TraCI ポート | '8813' |
ServerNumClients | クライアント数 | '1' |
EnableRandomTraffic | ルートファイルなしで車両を生成 | 'off' |
RandomTraffic | ランダム交通が有効な場合の車両数 | '0' |
EnablePacing | リアルタイムのペーシング(デモに推奨) | 'off' |
PacingRate | ペーシング倍率 | '1' |
SampleTime | ステップ間隔 | '-1' |
注: SUMO のデフォルトは time-to-teleport=300s です。300 秒を超えて停止した車両はテレポートされます。バス停で意図的に自車を停止させる場合、予期しない動作になることがあります。
クライアントブロック
| パラメーター | 用途 | デフォルト |
|---|---|---|
ClientAddress | サーバー IP | '127.0.0.1' |
ClientPort | ServerPort と一致させる必要があります | '8813' |
ClientOrder | クライアントの優先度 | '1' |
リーダーブロック — 車両トピック
対象の車両が存在しない場合、すべての車両トピックのリーダーとライターはクラッシュします。 車両が t=0 より後に出現する場合は、有効なサブシステムで制御してください。Safe Vehicle State Access を参照してください。
| トピック | 入力 | 出力 |
|---|---|---|
Speed | 車両 ID | 速度(スカラー) |
Position | 車両 ID | 位置 [x, y] |
Position3D | 車両 ID | 位置 [x, y, z] |
Acceleration | 車両 ID | 加速度 |
Angle | 車両 ID | 進行方向(度、0=北、時計回り) |
車両 ID の入力には String Constant ブロックを使用してください。他のリーダーの出力は使用しないでください。
リーダーブロック — シミュレーショントピック(入力ポートなし)
| トピック | 出力 |
|---|---|
ID list | 車両 ID 文字列 |
ID count | スカラー数 |
Arrived list | 目的地に到着した ID |
Departed list | ネットワークに進入した ID |
ライターブロック — 車両トピック
対象の車両が存在しない場合、ライターはクラッシュします。リーダーと同じ障害が発生します。出現が遅れる車両は、有効なサブシステムで制御してください。
| トピック | 入力ポート | 備考 |
|---|---|---|
Speed | 車両 ID、速度 | 希望速度を設定します。SUMO の追従制御では、先行車に応じて引き続きブレーキがかかります |
Position(RouteFlag オフ) | 車両 ID、X、Y、角度 | — |
Position(RouteFlag オン) | 車両 ID、Edge ID、Lane Index、X、Y、角度、Keep Route | 下記の型の表を参照 |
Min gap | 車両 ID、間隔 | — |
Speed mode | 車両 ID、モード | — |
Writer(Vehicle/Position, RouteFlag=on) のポート型 — 型が一致しない場合、エラーは通知されずに失敗します。
| ポート | 信号 | 型 |
|---|---|---|
| 1 | 車両 ID | string |
| 2 | Edge ID | string |
| 3 | Lane Index | int32 |
| 4 | X | double |
| 5 | Y | double |
| 6 | 角度 | double(度) |
| 7 | Keep Route | uint8(uint8(1) を使用) |
警告: Writer(Vehicle/Position) は衝突チェックを行いません。他の車両の近くにテレポートさせると、車両が積み重なることがあります。生成する車両は近くの交通とは別の車線に配置してください。
ライターブロック — 可視化トピック
GUITopic パラメーターとともに TopicCategory='Visualization' を使用してください。可視化コマンドの設定は保持されます。SUMO が Schema/Track/Zoom を受信すると、その設定を保持します。必ずワンショットの有効なサブシステムで囲んでください。毎ステップ実行したままにしないでください。
| GUITopic | 入力ポート | 有効な値 |
|---|---|---|
Track Vehicle | View Id、Vehicle Id | — |
Zoom factor | View Id、Zoom | — |
Schema | View Id、Schema | "standard"、"real world"、"fast standard"、"fast real world" |
すべての可視化トピックでは、ポート 1 に View Id の入力が必要です。SUMO GUI のデフォルトのビュー名は "View #0" です。必ずこの文字列をそのまま使用してください。
% Track Vehicle example (one-shot): camera follows ego
add_block('SumoInterfaceLibrary/Writer', [subsysPath '/Track Writer'], ...
'TopicCategory','Visualization', 'GUITopic','Track Vehicle', 'SampleTime','0.1');
add_block('simulink/String/String Constant', [subsysPath '/View Id'], ...
'String','"View #0"'); % Default SUMO GUI view — always "View #0"
add_block('simulink/String/String Constant', [subsysPath '/Vehicle Id'], ...
'String','"ego_vehicle"');
add_line(subsysPath, 'View Id/1', 'Track Writer/1');
add_line(subsysPath, 'Vehicle Id/1', 'Track Writer/2');
% Wrap in one-shot Enabled Subsystem (Constant(0)->IC(1)->Enable)
% Schema example (one-shot): switch GUI to "real world"
add_block('SumoInterfaceLibrary/Writer', [modelName '/Set Schema'], ...
'TopicCategory','Visualization', 'GUITopic','Schema', 'SampleTime','0.1');
add_block('simulink/String/String Constant', [modelName '/View Id'], ...
'String','"View #0"'); % Default SUMO GUI view — always "View #0"
add_block('simulink/String/String Constant', [modelName '/Schema Name'], ...
'String','"real world"');
% Wrap in one-shot Enabled Subsystem (Constant(0)->IC(1)->Enable)
Actor ブロック
| パラメーター | 用途 |
|---|---|
VehicleState | 'Add' または 'Remove' |
SpawnMethod | 'Lane'(こちらを使用)または 'Position'(動作しません — 既知の問題を参照) |
departLane | 'random'、'free'、'allowed'、'first'、'best' |
departSpeed | 'max'(推奨)、'random'、'desired'、'speedLimit' |
enableRouteID | 'on'/'off' |
routeID | .rou.xml のルート ID(enableRouteID='on' が必要) |
typeID | 車両タイプ ID(デフォルト:'DEFAULT_VEHTYPE') |
Actor ブロックは必ず Enabled Subsystems 内に配置してください。Spawn サブシステムには Priority='1' を設定し、Readers(Priority='10')より先に実行されるようにしてください。
パターン
単発トリガー
| トリガー | パターン |
|---|---|
| t=0 のときのみスポーン | Constant(0) -> IC(Value=1) -> Enabled Subsystem |
| シミュレーション時間 T にスポーン | Clock -> MATLAB Function (persistent fired) -> Enabled Subsystem |
| T 以降、継続的に実行(例:速度ライター) | Clock -> Compare To Constant (>=T) -> Enabled Subsystem |
| 条件が真になったときにスポーン | Clock/センサー -> MATLAB Function (persistent fired) で条件をチェック |
時間ベースの単発処理(t=1.2 にスポーン):
% MATLAB Function code:
% function pulse = fcn(t)
% %#codegen
% persistent fired
% if isempty(fired), fired = false; end
% if (t >= 1.2) && ~fired, pulse = 1.0; fired = true;
% else, pulse = 0.0; end
% end
自車両の制御(ルートファイル方式 — 推奨)
Reader が t=0 から動作するよう、.rou.xml で depart="0" を指定して自車両を定義します。
<routes>
<vType id="ego_type" accel="2.6" decel="4.5" sigma="0" length="5" maxSpeed="25"/>
<route id="ego_route" edges="B1B2 B2B3 B3B4 B4B1 B1B2 B2B3 B3B4 B4B1"/>
<vehicle id="ego_veh" type="ego_type" route="ego_route" depart="0"
departLane="free" departSpeed="max"/>
</routes>
Simulink が Writer(Vehicle/Speed) で縦方向の制御を行う場合、自車両のルートに <stop> 節を含めないでください。SUMO の停止指令が Speed Writer を上書きします。
遅延スポーン車両向けのゲート付き Writer(Vehicle/Speed)
% Latched enable: HIGH from t >= spawnTime onwards
% Clock -> Compare To Constant (relop='>=', const=spawnTime) -> Enable
% Inside Enabled Subsystem:
% String Constant("veh_1") -> Writer(Vehicle/Speed) port 1
% Constant(desiredSpeed) -> Writer(Vehicle/Speed) port 2
ワンショットではなく Compare To Constant >= spawnTime(HIGH のまま維持)を使用してください。車両が存在する間、速度を継続的に適用する必要があります。
車両ごとに異なるルート(動的スポーン)
<routes>
<route id="ego_route" edges="A0A1 A1A2 A2B2 B2C2 C2C1 C1C0"/>
<route id="veh_1_route" edges="A1B1 B1B2 B2C2 C2C1 C1C0 C0B0"/>
<route id="veh_2_route" edges="B0B1 B1A1 A1A2 A2B2 B2C2 C2C1"/>
</routes>
% Per Actor block: set_param(actorPath, 'routeID', sprintf('veh_%d_route', k));
スポーン後にテレポート(位置指定の回避策)
SpawnMethod='Position' は動作しないため(既知の問題を参照)、次の 2 ステップのパターンを使用します。
Step N: Actor(Add, SpawnMethod='Lane', routeID=...) -> vehicle at edge start
Step N+1: Writer(Vehicle/Position, RouteFlag=on) with (VehId, EdgeId, int32(LaneIdx),
X, Y, Angle, uint8(1)) -> vehicle teleports to (X,Y)
Spawn と Move の間に 1 ステップの遅延が必須です。イネーブル信号に Unit Delay を使用してください。Actor の発火から 1 ステップ後まで、SUMO 側には車両が存在しません。
移動する基準点の近くで定期的に一括スポーン
Clock -> PulseGen (persistent, fires every 5s, increments batch id)
-> SpawnBatch (Enabled SS, Priority=1): N IDGen -> N Actor(Add)
-> [Unit Delay z^-1]
-> MoveBatch (Enabled SS, Priority=10): N Writer(Vehicle/Position)
Reader(Vehicle/Position) on ego feeds PosGen so batch lands at egoPos + offset.
文字列出力を持つ MATLAB Function
動的に生成される車両 ID(例:"dyn_" + string(batch) + "_1")の場合:
chart = sf.find('-isa','Stateflow.EMChart','Path',chartPath);
chart.ChartUpdate = 'DISCRETE';
chart.SampleTime = '0.1';
outData = chart.find('-isa','Stateflow.Data','Scope','Output');
outData.DataType = 'string';
outData.Props.Array.Size = '1';
安全な車両状態へのアクセス
Vehicle トピックの Reader と Writer はすべて、各ステップで Vehicle Id を参照します。車両が存在しない場合、クラッシュします。これは Reader(Vehicle/...)、Writer(Vehicle/...)、および Writer(Visualization/Track Vehicle) に適用されます。
t=0 より後にスポーンする車両は、Enabled Subsystem 内でゲートしてください。
% Clock -> Compare To Constant (>= spawnTime) -> Enabled Subsystem
% Inside: String Constant + Reader/Writer blocks
depart="0" を指定して .rou.xml で定義した自車両には、ゲートは不要です。
ランダム交通のクイックスタート
set_param([modelName '/SUMO Server'], 'EnableRandomTraffic','on', 'RandomTraffic','10');
<route-files> は不要です。ランダム車両の名前は SpawnedVehicle_1、SpawnedVehicle_2 のようになります。
既知の問題(サポートパッケージのバグ)
| 問題 | 影響 | 回避策 |
|---|---|---|
SUMO_HOME の末尾に区切り文字がない → 起動失敗(Windows) | P0 ブロッカー | setenv('SUMO_HOME', [getenv('SUMO_HOME') filesep]) |
SpawnMethod='Position' は内部の moveToXY で誤った RouteFlag を渡す | 車両が指定位置ではなく、エッジの始点に配置される | スポーン後にテレポートするパターンを使用(Actor + Unit Delay + Writer(Vehicle/Position)) |
よくある間違い
| 間違い | 失敗する理由 | 修正方法 |
|---|---|---|
| 車両がまだ存在しない状態で Reader/Writer を使用する | mdlOutputs で S-function がクラッシュします | Enabled Subsystem 内で実行を制御します。自車両には depart="0" を使用します |
| Reader の出力を Reader の入力に接続する | ID List は可変長であり、Vehicle reader には単一の文字列が必要です | Vehicle Id には String Constant を使用します |
| ClientPort != ServerPort | クライアントが接続できません | 両方を一致させます(デフォルトは '8813') |
| 可変ステップソルバー | SUMO ではロックステップが必要です | 固定ステップを使用し、step-length と一致させます |
| Actor が繰り返し起動する | 「Vehicle already exists」 | ワンショットロジックを備えた Enabled Subsystem を使用します |
| 遅延スポーン車両の Writer(Vehicle/Speed) が実行制御されていない | t=0 でクラッシュします | Clock >= spawnTime の条件で実行を制御します |
| Visualization Writer が毎ステップ実行される | シミュレーション時間を浪費し、車両が存在しない場合はクラッシュします | ワンショットの Enabled Subsystem を使用します |
| ルートエントリーが depart 時刻順に並んでいない | 警告なしに破棄されます | すべてのエントリーを depart/begin 順に並べます |
<flow> 内にルートを埋め込む | Actor がルートを見つけられません | 独立した <route> 要素を定義します |
自車両のルートに <stop> があり、Speed Writer も使用する | SUMO の stop が Writer より優先されます | <stop> を削除し、Simulink の速度プロファイルを使用します |
| Clock ブロックが複数ある | 配線が煩雑になり、すべて同じ時刻を出力します | Clock を 1 つだけ使用し、すべてのコンシューマーに分岐させます |
Writer の Lane Index または Keep Route に double を使用する | 型の不一致により拒否されます | int32(laneIdx)、uint8(keepRoute) を使用します |
| 占有されている車線にテレポートする | 車両が積み重なり、動けなくなります | 周囲の交通とは別の車線にテレポートします |
sim の前に save_system を実行しない | 「Unapplied changes」マスクエラーが発生します | プログラムによる変更後は必ず保存します |
自車両の depart="2" と t=0 の Reader を併用する | 車両が未定義のため、無効なデータやクラッシュが発生します | 自車両の depart="0" を設定します |
| FixedStep=1.0 で小数時刻にスポーンする | ソルバーが目標時刻に到達しません | FixedStep、step-length、すべての SampleTime を一致させます |
規則
- 常に、ステップサイズを SUMO の
step-lengthおよびすべてのブロックのSampleTimeに合わせた固定ステップソルバーを使用します - プログラムによる変更後は、
sim(modelName)の前に必ずsave_system(modelName)を実行します - 常に
ClientPortとServerPortを一致させます - モデルルートで Clock を 1 つだけ使用し、すべての比較器/パルスジェネレーターに分岐させます
- Actor ブロックよりも、
.rou.xmlでdepart="0"を指定して自車両を定義する方法を優先します - シミュレーション途中で車両が削除されないよう、自車両に長いルートまたは循環ルートを設定します
- 動きながらスポーンさせる車両には、実用上のデフォルトとして
departSpeed='max'を使用します - Writer(Speed) は希望速度を設定します。車間距離の維持は SUMO が追従走行によって処理します
- デモではペーシング(
EnablePacing='on')を有効にして、GUI が瞬時に進んでしまわないようにします - Visualization writer(Track、Schema、Zoom)は、ワンショットの Enabled Subsystem で囲みます。これらの設定は保持されます
- Actor ブロックは必ず Enabled/Triggered Subsystem 内に配置します
- 動的にスポーンする車両には、それぞれ一意の ID と有効な独立ルートが必要です
- Simulink で使用する前に SUMO CLI で
.sumocfgを検証します:system(sprintf('"%s" -c "%s" --end 0.1', sumoExe, cfgFile)) mcp__matlab__model_editを使用する際、Enable ポートの配線にはadd_lineを代わりに使用します
著作権 2026 The MathWorks, Inc.