Skip to content

Repository files navigation

aichallenge-toolkit

日本語版を先に、英語版はその後に続きます。 / Japanese section first, English follows.


日本語

1. 何ができるか

AWSIM/Autoware ベースの自動運転レースに向けた、ROS 不要のオフライン解析ツール集です。 ラップタイムやペナルティの検出、レース後のリプレイ生成、追い越し可能区間の可視化、 横方向オフセットの幾何計算などを、レコーディング済みの rosbag (mcap) だけを入力にして 行います。一つ一つのツールは小さく、依存も最小限です。

2. 30 秒で試す

pip install -e ".[bag]"
python -m bagkit.v2x your_race.mcap --out-dir out/
python -m replay.replay --bag your_race.mcap

サンプルの mcap は同梱していません(理由は samples/README.md と本ファイル末尾の 「限界と罠」を参照)。手元のレースの mcap ファイルをそのまま渡してください。

3. ツール一覧

追い越し可能区間マップ(trackgeo)と二乗余弦の横オフセット(lateral)は、決勝(9/19-20)の後に追加します。

各ツールについて、何をするか、1 コマンドでの実行例、実測値を 1 つずつ示します。

bagkit.v2x: V2X 位置配列のデコード

ROS を使わずに /v2x/vehicle_positions を CDR 手デコードし、車両ごとの CSV と統計 JSON を 書き出します。

python -m bagkit.v2x race.mcap --out-dir out/

実測: 466 秒のレースに対して 0.5 秒で完了。対象車両のサンプリングレートは 14.99 Hz (sigma 0.005)。

bagkit.trajectory: 発行された走行軌道のデコード

コントローラが実際に発行した /planning/scenario_planning/trajectory を CDR 手デコードします。

python -m bagkit.trajectory race.mcap

実測: デコーダ本体は約 20 行。外部の非公開モジュールへの依存はありません。

bagkit.penalty: 5.00 km/h プラトーからペナルティを検出

公開ボードの rosbag にはペナルティ用のトピックがありません。評価系がペナルティ中に v_max を厳密に 1.3889 m/s (5.00 km/h) にクランプすることを使い、そのプラトーからペナルティ 区間を検出します。

python -m bagkit.penalty --bag race.mcap --raceline line.csv

実測: 手元の 2 レースに対する検証で recall 2/2 および 3/3、誤検出 1 件、実行 6.3 秒。

replay: 1 台または 3 台レースの統合タイムライン

make eval などが出力するレースディレクトリ(または単体の mcap)から、10 Hz の統合 タイムライン、周回・停止統計、車間距離、ニアミス、ペナルティを含むイベントログを作ります。

python -m replay.replay --bag race.mcap

実測: 484 秒のレース、4,843 サンプルの処理に 3.3 秒。

presubmit: 提出前静的チェック

aichallenge_submit に対する 11 種類の静的チェック(ホストパス、DDS 設定、ビルド時の pip 実行、外部参照、環境変数のデフォルト値、C++ メンバー、単位の取り違えなど)を行います。

presubmit check --repo-root .

実測: 154 件のテストが通過。誤検出だったチェック(コメントや docstring 内の内部パス 参照を実コードと誤検出する問題)は既に修正済みで、自分たちの提出ツリーに対して実行した 結果は 0 FAIL / 5 WARN でした。

evalwrap: 実行結果の取り込みと比較

レースディレクトリを runs.csv に変換し、環境フィンガープリントを記録し、2 回の実行結果を 比較します。

python -m evalwrap ingest-race output/20260101-000000 --out runs.csv --run-id my-run

実測: 105 件のテストが通過。

racekit: バリアント構築・台帳・ロードブロック

YAML の上書き差分から提出用 tarball を作る variant.py、実行結果を順位付けする ledger.py、レーシングラインの途中で停止するオポーネント軌道を作る roadblock.py を 含みます。

python -m racekit.variant --spec variant.yaml --out submit/variant.tar.gz

実測: roadblock.py は指定した waypoint で速度列だけを 0 にランプダウンし、他の列は 1 バイトも変更しません(本リポジトリのテストで保証)。

opponents: 対戦相手ビルダー

自分たちの aichallenge_submit のコピーから、stock / pp-slow / pacer / blocker の 4 種類のオポーネント tarball を作ります。

opponents/build-opponent.sh pp-slow --speed-kmh 15

実測: 82 件のテストが通過。shellcheck もクリーンです。

mpcdebug: MPC の infeasible 原因診断

コントローラのログから [MPCInfeasibleDiag] 系の診断行を読み取り、どの仮説がどれだけの 事象を説明するかを、レース全体に対して検証します。オフラインの QP レプリカも含みます。

python -m mpcdebug.infeasible_verdict controller.log

実測: 「corridor の行だけが infeasible の原因になりうる」という仮説について、 not_lateral に分類される事象が 1 件でもあれば、その仮説と矛盾することを機械的に 検出します。

4. AWSIM で実測した事実

  • V2X は 15 Hz(50 ms クロックの 3 スロットのうち 2 スロット)、位置ノイズは概ね 1 cm。
  • ペナルティ中の速度プラトーは厳密に 1.3889 m/s(5.00 km/h)。
  • 実測されたカート同士の横方向接触距離は約 1.50 m(中心間)。
  • MPC のホライズンは「ステップ数 × 解像度」で決まり、狭いのはコースではなく設定。
  • 追い越し可能区間の判定は、lanelet2 の全レーンレット多角形の和集合を使うべきで、 占有格子地図(OGM)や境界線の点群最近傍だけでは過大・過小評価する。

5. 限界と罠

  • どのツールもサーキット固有のデータ(ラインやマップ)を前提にしています。別のコースに そのまま使うと数値は再検証が必要です。
  • HART(軌道予測、v0.2 で公開予定)は 15 Hz の生データをそのまま渡すと速度推定が 約 25% 低く出ます。内部で 20 Hz にリサンプルしてから使ってください。
  • 横方向オフセットの計算はコリドーに振幅をクリップされて 0 になった瞬間、所要時間も 0 と評価されるため、速度則と組み合わせる際はゼロ振幅のケースを明示的にガードする 必要があります(決勝後に追加する lateral モジュールで説明します)。
  • 追い越しのシミュレーションは初期条件に敏感で、1 回の実行では意味のある比較になりません。 ペアテストで少なくとも 15 回の実行が必要でした。

6. 貢献・ライセンス

Apache-2.0 ライセンスです。コードの一部は AI アシスタント(Claude)の支援を受けて 作成・整理されました。追い越し可能区間の考え方や横方向オフセットの手法について、 fis-teria, topse, iASL, NITS の公開された取り組みから着想を得た部分があります。この場を 借りて感謝します。


English

1. What it does

A collection of ROS-free, offline analysis tools for AWSIM/Autoware-based autonomous racing. Lap and penalty detection, post-race replay, overtake-window visualisation, all driven from a recorded rosbag (mcap) alone. Each tool is small and has minimal dependencies.

2. Try it in 30 seconds

pip install -e ".[bag]"
python -m bagkit.v2x your_race.mcap --out-dir out/
python -m replay.replay --bag your_race.mcap

No sample mcap ships with this release (see samples/README.md and "Limits and traps" below for why). Point these commands at a bag from your own local race.

3. Tools

The overtake-window map (trackgeo) and the raised-cosine lateral offset (lateral) will be added after the finals (9/19-20).

One command and one measured number per tool.

bagkit.v2x: decode the V2X position array

Hand-decodes /v2x/vehicle_positions CDR without ROS, writing a per-car CSV and a stats JSON.

python -m bagkit.v2x race.mcap --out-dir out/

Measured: 0.5 s on a 466 s race. The recorded vehicle's sampling rate was 14.99 Hz (sigma 0.005).

bagkit.trajectory: decode the published trajectory

Hand-decodes /planning/scenario_planning/trajectory, the line the controller actually published.

python -m bagkit.trajectory race.mcap

Measured: the decoder itself is about 20 lines, with no dependency on a private internal module.

bagkit.penalty: detect penalties from the 5.00 km/h plateau

Public board bags carry no penalty topic. The evaluator clamps v_max to exactly 1.3889 m/s (5.00 km/h) for a penalty's duration, and this looks for that plateau.

python -m bagkit.penalty --bag race.mcap --raceline line.csv

Measured: on two local validation runs, recall 2/2 and 3/3, one false positive, 6.3 s to run.

replay: a merged timeline for a 1- or 3-car race

Turns a race output directory (or a single bare mcap) into a synced 10 Hz timeline, per-car lap/stop stats, pairwise distances, near-contacts, and a merged penalty/event log.

python -m replay.replay --bag race.mcap

Measured: 3.3 s to process a 484 s race, 4,843 samples.

presubmit: static pre-submit checks

11 static checks against aichallenge_submit: host paths, DDS settings, build-time pip installs, references outside the submitted tree, empty environment-variable defaults, C++ member issues, unit-confusion traps, and more.

presubmit check --repo-root .

Measured: 154 tests pass. A false-positive class (a check that flagged internal-path references sitting inside comments or docstrings, not real code) has already been fixed; running it against our own tree gives 0 FAIL / 5 WARN.

evalwrap: ingest and compare run results

Turns a race directory into runs.csv, records an environment fingerprint, and compares two runs.

python -m evalwrap ingest-race output/20260101-000000 --out runs.csv --run-id my-run

Measured: 105 tests pass.

racekit: variant builds, a ledger, and a roadblock opponent

variant.py builds a submission tarball from a YAML override diff, ledger.py ranks run results, and roadblock.py builds an opponent trajectory that stops dead partway around the line.

python -m racekit.variant --spec variant.yaml --out submit/variant.tar.gz

Measured: roadblock.py ramps only the speed column to zero at the requested waypoint and changes not a single other column (checked by this repository's own tests).

opponents: build local sparring partners

Builds stock / pp-slow / pacer / blocker opponent tarballs from a copy of your own aichallenge_submit.

opponents/build-opponent.sh pp-slow --speed-kmh 15

Measured: 82 tests pass, and shellcheck is clean on the build script.

mpcdebug: diagnose why an MPC went infeasible

Reads [MPCInfeasibleDiag]-style diagnostic lines from a controller log and tests a set of candidate causes against every infeasible event in the race, not a hand-picked sample. Includes an offline QP replica.

python -m mpcdebug.infeasible_verdict controller.log

Measured: if a hypothesis claims the corridor rows are the only possible source of infeasibility, this mechanically flags any event classified not_lateral as a direct contradiction of that hypothesis.

4. Measured facts from AWSIM

  • V2X arrives at 15 Hz (2 of 3 slots of a 50 ms clock), with roughly 1 cm of position noise.
  • The penalty speed plateau is exactly 1.3889 m/s (5.00 km/h).
  • Measured centre-to-centre lateral contact distance between karts is about 1.50 m.
  • The MPC horizon is horizon steps times resolution; a narrow corridor is a configuration fact, not a track fact.
  • Overtake-window feasibility should be computed from the union of every lanelet2 lanelet polygon; an occupancy-grid raytrace or a nearest-point search over boundary polylines both over- or under-estimate it.

5. Limits and traps

  • Every tool here assumes circuit-specific data (a line, a map). Re-verify the numbers before reusing them on a different track.
  • HART (the trajectory predictor, planned for v0.2) under-estimates speed by about 25% if fed raw 15 Hz data directly; resample to 20 Hz first.
  • The lateral-offset time law has a zero-amplitude trap: once the corridor clips a live manoeuvre's amplitude to zero, the time-to-build calculation also reads zero. A speed law built on top of it needs to guard that case explicitly (see the docstring on the lateral module, added after the finals).
  • Overtake simulations are sensitive to initial conditions; a single run is not a meaningful comparison. Paired testing needed at least 15 runs per side before a result was trustworthy.

6. Contributing and license

Apache-2.0. Some of this code was written and organised with the help of an AI assistant (Claude). The overtake-window approach and the lateral-offset method were informed by public work from fis-teria, topse, iASL, and NITS; thanks to all of them.

About

ROS-free tools for AWSIM/Autoware racing bags and pre-submit checks (JSAE AI Challenge 2026) / 自動運転AIチャレンジ向けツール

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages