Skip to content

Develop: PilotNet (Camera-based End-to-End)

このドキュメントでは、NVIDIA PilotNet (DAVE-2) を AI Challenge 環境で学習・デプロイする手順を説明します。

tiny_lidar_net との主な違い:

tiny_lidar_net pilot_net
入力 2D LiDAR スキャン フロントカメラ画像 (66x200)
教師 Autoware の経路追従コマンド MPC エキスパートの制御コマンド
推論 NumPy NumPy
入力前処理 距離正規化 上部 37.5% クロップ → 66x200 リサイズ → YUV 変換

Setup

AI Challenge のドキュメントに従って、

までを実施してください。

PilotNet の学習手順

PilotNet の学習には Autoware から取得した rosbag が必要です。本セクションでは、rosbag の取得から学習・デプロイまでの手順を説明します。

Step 1. コンテナの操作 (rocker で起動)

このステップでは、4 つの Terminal を使います。1つ目は ./docker_run.sh devrocker により新しいコンテナを起動し、残りは ./docker_exec.sh既存コンテナに docker exec で入る運用です。ホスト側のコマンドはすべて ~/aichallenge-racingkart で実行する前提ですが、必要に応じて変更してください。

cd ~/aichallenge-racingkart

各 Terminal でコンテナに入ったら、ROS 2 の source を実行してください:

source /opt/ros/humble/setup.bash
source /autoware/install/setup.bash
source /aichallenge/workspace/install/setup.bash

Terminal 1: AWSIM の起動

pwd
./docker_run.sh dev
./run_simulator.bash

PilotNet は単独走行を前提に動作確認するため、起動画面では 1人プレイ を選択してください。

Terminal 2: Autoware1 の起動

./docker_exec.sh
./run_autoware.bash awsim 1

Initial pose を設定します。Rviz の view を ThirdPersonFollower から TopdownOrtho に切り替えてから設定してください。

設定したら、AWSIM 画面右上の Control ボタンで Manual → Autonomous に切り替えます。

Terminal 3: ROS topic の確認 (任意)

./docker_exec.sh
export ROS_DOMAIN_ID=1
ros2 topic list

/sensing/camera/image_raw/control/command/control_cmd の双方が存在することを確認してください。

Terminal 4: rosbag の記録開始

./docker_exec.sh
export ROS_DOMAIN_ID=1
cd /aichallenge/ml_workspace
./record_data.bash

record_data.bash/sensing/camera/image_raw/control/command/control_cmd を含む形で record_data.bash 内に定義されているので、tiny_lidar_net と同じスクリプトでカメラデータも収集できます。

走行が終わったら Ctrl+C で記録を停止します。記録された rosbag は /aichallenge/ml_workspace/rawdata/$(date +%Y%m%d-%H%M%S) に保存されます。

検証データを別に取るのが理想ですが、まずは動作を掴むために訓練・検証ともに同じデータを使います:

cp -r /aichallenge/ml_workspace/rawdata/* /aichallenge/ml_workspace/train
cp -r /aichallenge/ml_workspace/rawdata/* /aichallenge/ml_workspace/val
※ teleop で手動収集する場合 Terminal 2 で `./run_autoware.bash awsim 1` の代わりに
export ROS_DOMAIN_ID=1
ros2 launch teleop_manager teleop_manager.launch.xml
を実行すると、Joycon 等で手動走行できます。

Step 2. Dataset conversion

rosbag を学習用 dataset に変換します。

cd /aichallenge/ml_workspace/pilot_net/
python3 /aichallenge/ml_workspace/pilot_net/extract_data_from_bag.py \
    --bags-dir /aichallenge/ml_workspace/train/ \
    --outdir /aichallenge/ml_workspace/pilot_net/dataset/train/

trainだけでなく、validation setも変換しておきましょう。

cd /aichallenge/ml_workspace/pilot_net/
python3 /aichallenge/ml_workspace/pilot_net/extract_data_from_bag.py \
    --bags-dir /aichallenge/ml_workspace/val/ \
    --outdir /aichallenge/ml_workspace/pilot_net/dataset/val/

このコマンドは内部で以下を実行します:

  1. rosbag から /sensing/camera/image_raw/control/command/control_cmd を時刻同期して取得
  2. 各画像の上部 37.5% をクロップ (空・遠景を除外)
  3. 66x200 にリサイズして images.npy (uint8) として保存
  4. ステアリングと加速度を steers.npy / accelerations.npy に保存

以下のような出力が得られたら成功です:

[INFO] [PID:99328] Found 1 bags. Starting processing with 1 workers.
[INFO] [PID:99356] Saved rosbag2_autoware: 413 samples (Total: 0.13s)
[INFO] [PID:99328] All processing finished in 0.34 seconds.

まずはこのまま Step 3 に進んでください。精度を上げたい場合は後述の オプション: train/val 分割と augmentation を参照。

Step 3. Model training

python3 /aichallenge/ml_workspace/pilot_net/train.py

CPU で学習を回したい場合や、RTX 50 シリーズなどで CUDA がこの環境に対応していない場合は次を実行してください:

CUDA_VISIBLE_DEVICES="" python3 /aichallenge/ml_workspace/pilot_net/train.py

学習ログ (TensorBoard) は logs/ 配下、checkpoint は checkpoints/ 配下に保存されます。best_model.pth が val loss 最良のモデルです。

ステアのみ学習したい場合 (アクセル学習が不安定なときに推奨):

python3 /aichallenge/ml_workspace/pilot_net/train.py train.loss.accel_weight=0.0

Step 4. Model deployment

.pth から .npy に変換します:

python3 convert_weight.py \
    --ckpt /aichallenge/ml_workspace/pilot_net/checkpoints/best_model.pth \
    --output /aichallenge/ml_workspace/pilot_net/weights/pilotnet_weights.npy

以下のような出力が得られれば成功です:

Loaded checkpoint: /aichallenge/ml_workspace/pilot_net/checkpoints/best_model.pth
Saved NumPy weights to: /aichallenge/ml_workspace/pilot_net/weights/pilotnet_weights.npy

作成した pilotnet_weights.npy を ROS 2 package 内の ckpt ディレクトリにコピーします:

cp /aichallenge/ml_workspace/pilot_net/weights/pilotnet_weights.npy \
   /aichallenge/workspace/src/aichallenge_submit/pilot_net_controller/ckpt/pilotnet_weights.npy

Step 5. Run PilotNet Sample ROS Node

reference.launch.xmlにおけるcontrol methodを、rule_basedからpilot_netに変更しましょう。

Step 1 でコンテナを既に起動している場合は、そのまま Terminal を再利用できます。コンテナを停止していた場合はホスト側で再度 ./docker_run.sh dev (Terminal 1) と ./docker_exec.sh (Terminal 2 以降) で入り直してください。

Terminal 1: AWSIM の起動確認

./run_simulator.bash

Terminal 2: Autoware1 の起動確認

./docker_exec.sh
./run_autoware.bash awsim 1

アクセル制御の追加

pilot_net_node.param.yamlcontrol_mode をデフォルトでは "ai" にしています。"fixed" に変更すると、ステアのみネットワークが推論し、アクセルは acceleration パラメータで指定した固定値を使います。

control_mode アクセル ステアリング
ai NN 出力 NN 出力
fixed acceleration パラメータ (固定値) NN 出力

output_dim=1 で学習した場合 (ステアのみ学習) は自動的に fixed 相当の動作になります。

オプション: train/val 分割と augmentation

extract_data_from_bag.py の出力 (./dataset/train/) のままでも学習は開始できますが、汎化性能を上げたい場合は train/val 分割と水平反転 augmentation を行ってから train.py を実行してください:

cd /aichallenge/ml_workspace/pilot_net/
python3 prepare_data.py

dataset/train/merged/dataset/val/merged/ が生成され、train.py がこちらを優先して読み込みます。

ワンショット実行 (run_pipeline.bash)

extract → prepare → train → convert を一気に実行できます:

cd /aichallenge/ml_workspace/pilot_net
./run_pipeline.bash /aichallenge/ml_workspace/train

引数で解像度・色空間・出力次元・クロップ比率を変更できます:

./run_pipeline.bash <bag_dir> <image_height> <image_width> <color_space> <output_dim> <crop_top_ratio>

例: ステアのみ (output_dim=1):

./run_pipeline.bash /aichallenge/ml_workspace/train 66 200 yuv 1 0.375

Notes

  • 入力解像度を変える場合は学習側 (run_pipeline.bash の引数 または train.yaml) と推論側 (pilot_net_node.param.yaml) を必ず揃えてください。 ずらすと flatten dim 不一致でモデルが読めません。
  • 複数台走行データの収集・学習は将来拡張です。詳細は tiny_lidar_net の Overtake セクション を参照。
  • Rviz で camera topic を表示する場合は QoS を Reliable から BestEffort に変更してください。
  • 推論性能: 66x200 でも 40Hz は CPU 推論で厳しい場合があります。必要なら ONNX Runtime への移行を検討してください。