Kiro のワークフローで"自動車運転相棒AI"アプリを作ってみた(第2部:データで裏取りし、エッジで判定する)

Kiro のワークフローで"自動車運転相棒AI"アプリを作ってみた(第2部:データで裏取りし、エッジで判定する)

Kiro のワークフローで相棒AIアプリ「AI Co-Driver」を作る実践記の第2部です。 監視指標を揃え(M2)、走行ログを溜めて(M2.5)、机上で決めた閾値が実測とどれだけ ズレていたかをデータで突き合わせ、「いつ喋るか」を端末側で決定論的に判定する トリガーエンジン(M3)まで。主観でなく実データで基準を決め、安全の軸は人が握る 日々の業務で染み付いた姿勢がワークフローとどう噛み合ったかをお届けします。
2026.10.09

こんにちは。クラウド事業統括本部の Yoshi です。普段は TAM(テクニカルアカウントマネージャー)として、お客様のAWS活用のご支援をしています。

Kiro IDE の ワークフロー機能 で、車載データと会話する相棒AI「AI Co-Driver」を個人開発で作ってみた実践記の第2部です。第1部では、いきなり作らず「不確実性の高い順」にマイルストーンを並べ、最大の山である実車データ取得(M1)を最初に突破しました。

今回は、その土台の上に 「いつ・何を言うべきか」を端末側で判定する仕組み を作ります。ポイントは、判定の基準を 主観ではなく実データで決めた ことです。

目次

  • シリーズ構成
  • おさらい — ハイブリッド構成「判定はエッジ、言い回しだけクラウド」
  • M2:監視指標を揃える — 実機で「取れるか」を確かめる
  • M2.5:走行ログを溜める — 「やってみる」の投資
  • データが設計を正した — 机上の閾値は実測とズレていた
  • もう一度データで殴る — 文脈を変えて再検証
  • M3:エッジで決定論的に判定するトリガーエンジン
  • 層分離の恩恵 — 実車なしでロジックを検証できる
  • 業務感覚への接続 — 「データで基準を決める・安全の軸は人が握る」
  • 次回予告
  • まとめ

シリーズ構成

記事 位置づけ 内容
機能紹介編(別記事・公開済み) 土台 Kiro のワークフロー機能は何ができるのか
第1部(公開済み) 実践記 全体像を描いてから動く(構想 → 実車にデータ取得)
第2部(本記事) 実践記 データで裏取りし、エッジで判定する(PID拡充 → 走行ログ → トリガー判定)
第3部(近日) 実践記 言葉と声を与え、仕上げる(LLM連携 → 音声 → UI仕上げ、三部作の回収)

おさらい — ハイブリッド構成「判定はエッジ、言い回しだけクラウド」

第1部で触れた、この相棒AIのいちばん大事な設計判断をおさらいします。それは 「いつ・何を言うべきか」の判定は端末(エッジ)で完結させ、クラウドのLLMには「言い回しの生成」だけを任せる というハイブリッド構成です。

第2部でやるのは、この図の 左半分(エッジ側) です。LLM はまだ登場しません。「気づく」仕組みを、実データを根拠にして組み立てます。

M2:監視指標を揃える — 実機で「取れるか」を確かめる

M1 では水温と車速だけを通しました。M2 では、相棒AIが状況を語るのに必要な指標を揃えます。回転数、エンジン負荷、スロットル、吸気圧(MAP)、吸気温、大気圧。そして、スマホの加速度センサーから加速・減速・コーナリングのGも取り込みます。

ここでひとつ、やりたかった演出があります。ブースト圧です。私の車両はターボ車なので、「過給が立ち上がった」「ブースト最大」といった実況は相棒AIで実現したかった。ところが、標準のOBD-IIには「ブースト圧」そのものを返すPIDがありません。

そこで、こう設計しました。

ブースト圧(ゲージ) = 吸気圧(MAP) − 大気圧

正圧なら過給、負圧なら吸気負圧。これらを個別のPIDで取って引き算すれば、ブーストを算出できます。ただし「このPIDが自分の車で実際に取れるか」は、実機で確かめないと分かりません(第1部の油温のように、取れると思ったら取れた/取れないと思ったら取れた、は現場でしか決着しません)。

そこで、接続時に1回だけ 「この車で何が取れるか」を調べるスキャン を入れました。常時ポーリングには混ぜず(車のECUに負荷をかけないため)、接続直後に対応PIDの一覧だけ取得して記録します。

実機スキャンの結果、ブースト算出に必要なPIDはこうなりました。

試したPID 内容 結果
01 0B 吸気圧(MAP) 取れた
01 33 大気圧(Barometric) 取れた
01 70 ブースト圧制御(新しめの規格) 取れなかった

本命だと思っていた専用PID(01 70)は非対応でしたが、MAP と大気圧の両方が取れたので、引き算でブーストを正確に算出できることが確定しました(ADR-008/009)。この「現物で取得可否を確定させる」一手が、以降のトリガー設計と演出の土台になります。

M2.5:走行ログを溜める — 「やってみる」の投資

M2 で指標が揃ったところで、本来なら次は「どの値になったら喋らせるか(閾値)」を決める M3 に進みます。でも、ここで一歩寄り道をしました。

走行中の全データを、CSVに記録する機能 を先に作りました(M2.5)。理由はシンプルで、閾値を自分の頭の中(机上)で決めたくなかった からです。「水温が何℃を超えたら警告」なんて、実際の自分の車がどんな温度で走っているかを知らずに決めても、たぶん外すだろう。だったら先に実データを溜めて、それを見てから決めよう、という判断です。

走行ログを溜めて、PC側(手元のpandas)で分布やイベント候補を集計する——という小さなパイプラインを足しました。アプリ側のCSV書き出しと、PC側の分析スクリプトは、カラムの並びがズレると意味が壊れる ので、カラム定義を1つの「契約」として扱い、3か所(書き出し・分析スクリプト・README)で完全一致させました。

# CSVカラム契約(この並びを3か所で一致させる)
timestamp_ms, speed_kmh, rpm, coolant_c, oil_c, load_pct,
throttle_pct, map_kpa, boost_bar, intake_c, long_g, lat_g

データが設計を正した — 机上の閾値は実測とズレていた

実際に走ってログを溜め、分析してみて——これが面白いくらいに、机上の想定が実測とズレていました。

当初ざっくり考えていた閾値は「水温が105℃を超えたら警告」「エンジン負荷が80%を超え続けたら高負荷」といったものでした。ところが実データはこう語りました。

当初の想定(机上) 実測で分かったこと どう直したか
水温 >105℃ で警告 この車は走行中ふつうに103℃前後。105℃も日常域 警告を >108℃、危険を >112℃ に引き上げ
エンジン負荷 >80% 継続で高負荷 全開でも負荷は最大45%止まり(ターボ車では過小評価される) 負荷単体の判定は不使用。ブースト×回転数で代替
ブースト(感覚で設定) 正圧が出ているのは走行時間のわずか数%、ピークは実測値で確定 立ち上がり/全開の 2段 を実測ピークから設定

一番驚いたのは水温です。「105℃=危険」という素朴な直感は、この車にとっては完全な誤りでした。105℃はこの車の"日常"です。もし机上の値のまま作っていたら、相棒AIは普通に走っているだけで「警告」を連発する、うるさいだけのアプリになっていました。データが設計を正してくれた 瞬間です。

負荷の件も象徴的でした。「負荷80%で高負荷」は、全開でも45%にしか届かないこの車では永遠に発火しない「死にトリガー」でした。ターボ車の計算上のエンジン負荷は実際の加速感より小さく出る、という特性が実データではっきり見えたので、負荷単体はやめて、ブーストと回転数の組み合わせで「全開で踏んでいる」を捉えることにしました。

もう一度データで殴る — 文脈を変えて再検証

ただ、1本のログで決めた閾値には不安が残ります。「たまたまその走り方だっただけでは?」という疑いです。そこで、わざと走り方を変えた追加ログ をもう3本録って、同じ閾値で殴り直しました。

  • ワインディング(コーナーの多い道)
  • 長時間の市街地(アイドリングを跨ぐ)
  • 冷間始動(エンジンが冷えた状態から)

結果、閾値は どれも誤発火せず、変更不要 でした。むしろ、新しい発見がいくつも拾えました。

  • 横G:最初のログでは薄かったコーナリングのGが、ワインディングで明確なピークを記録。「コーナリング検知」の閾値が妥当だと裏取りできました。
  • 暖機の挙動:冷間始動のログで、油温は水温より遅れて温まることが実測で見えました(物理的に筋が通る)。これは第3部で触れる「暖機中の声かけ」の素材になります。
  • 油温の一時欠損:長時間ログで油温が一時的に取れなくなる場面がありました。「値が取れないときに嘘の数字を出さない」フォールバックが要る、という設計上の宿題が見つかりました。

1本で決めた基準が、文脈の違う3本でも破綻しなかった。保守的なマージンを取ってデータドリブンで決めた設計が、追加データで確証に変わりました。

M3:エッジで決定論的に判定するトリガーエンジン

実データで基準が固まったので、いよいよ トリガーエンジン(M3)を作ります。これが「いつ・何を言うべきか」を端末側で判定する心臓部です。まだLLMは使いません。喋りもしません。「このタイミングで、この種類のイベントが発生した」というところまでを、決定論的に(=同じ入力なら必ず同じ結果になるように)判定してログに出します。

やっていることはシンプルです。

  • 定期報告のタイマーで「状態レポート」のイベントを出す
  • 水温・油温が閾値を超えたら「警告」「危険」のイベントを出す
  • 加速・減速・コーナリングのGが閾値を超えたらイベントを出す
  • 同じイベントが連発しないよう、クールダウン(待ち時間)を設ける
  • モード(おだやか/スポーツ)で閾値のセットが切り替わる

ここで大事なのは、安全に関わる判定を全部ここ(エッジ・決定論的)に閉じ込めた ことです。「危険かどうか」をLLMに尋ねたりはしません。LLM は後(第3部)で、ここで確定した事実を自然な言葉にするだけに使います。確率的に揺れうるものに安全判断を任せない、というADR-004の思想を、実装で担保した形です。

ADR-004(抜粋): LLMは運転判断をしない
 ・安全に関わる判定(閾値超え検知)はエッジのルールで決定論的に行う
 ・LLMが使えないとき(圏外・エラー)も、定型文で機能を止めない
 ・ポーリングは厳選したPIDを安全なレートに抑え、ECUに負荷をかけない

層分離の恩恵 — 実車なしでロジックを検証できる

M3 を作るとき、この相棒AIの設計でいちばん効いた判断が姿を見せます。それは、第1部でも少し触れた 「コア層」と「アダプタ層」の分離(ADR-002)です。

  • コア層:PIDの計算、閾値判定、モード切替、ブースト算出。これらは Android の部品を一切使わない純粋なロジック にしてあります。
  • アダプタ層:Bluetooth通信、センサー読み取り、音声出力、LLM呼び出し。こちらは Android 固有です。

この分け方の何がうれしいか。コア層は実車もスマホも無しで、PCだけでテストできる のです。M2.5 で記録した走行ログをコア層に流し込めば、「このログを再生したとき、意図したタイミングで意図したイベントが出るか」を、車に乗らずに単体テストで確かめられます。

層 中身 テスト方法
コア層 PID計算・閾値判定・モード・ブースト算出 PC上の単体テスト(走行ログを再生)
アダプタ層 Bluetooth・センサー・音声・LLM呼び出し 実機テスト(最終ゲート)

トリガーエンジンは判定ロジックの塊なので、ほぼコア層に収まります。おかげで M3 は、実車に乗らずとも大部分を検証できました。「どこを実車で確かめ、どこをPCで確かめるか」をあらかじめ設計で分けておいたことが、ここで効いてきます。

業務感覚への接続 — 「データで基準を決める・安全の軸は人が握る」

第2部でやったことを、普段の業務の言葉に置き換えると、こうなります。

  • 思い込みでなく実データで基準を決めた。「105℃=危険」という直感を、1本の走行ログが正してくれた。机上の値のまま進めていたら、使いものにならないアプリになっていた。
  • 一度決めた基準を、文脈を変えて殴り直した。1本で満足せず、ワインディング・市街地・冷間始動で再検証して、初めて「この基準で大丈夫」と言えた。
  • 安全・判断の軸は自分(人)で握った。何を危険とみなすか、どう判定するかはエッジに決定論で閉じ込め、LLMには委ねなかった。

これも、日々の業務でやっていることとそのまま重なりました。お客様の環境でも、「たぶんここがボトルネックだろう」という当たりだけで動かず、メトリクスやログの実データで裏を取ってから手を打ちます。そして、可用性やセキュリティのような外せない軸は、便利なツールに丸投げせず自分で握る。この姿勢が、ワークフローでアプリを作るときにもそのまま効きました。手を動かすのはワークフロー、基準とデータで決める判断は人、という分担です。

次回予告

第3部では、ついに 「言葉と声を与え、仕上げる」 話をします。ここまで端末側で確定させた「事実」を、LLM(Gemini)に渡して自然な一言に変え(M4)、それを音声で鳴らして相棒AIとして完成させ(M5)、運転中に一瞥できるUIを実機で見ながら仕上げます。

そしてこの第3部が、三部作でいちばん正直に「うまくいかなかった話」を書く回になります。**「静的レビューはAPPROVED、でも実機ビルドは通らない」**この切り分けを、権限漏れ・型推論の循環・画面を貫くゲージの暴発といった実際のつまずきとともにお届けします。三部作全体の回収も第3部で行います。

記事 位置づけ 内容
機能紹介編(公開済み) 土台 Kiro のワークフロー機能の紹介
第1部(公開済み) 実践記 全体像を描いてから動く
第2部(本記事) 実践記 データで裏取りし、エッジで判定する
第3部(公開済み) 実践記 言葉と声を与え、仕上げる(三部作の回収)

まとめ

  • 相棒AIの心臓部「いつ・何を言うか」の判定を、端末側(エッジ)で決定論的に 組んだ。LLM はまだ使わない。安全判断はエッジに閉じる(ADR-003/004)。
  • 監視指標を揃え(M2)、標準PIDに無いブースト圧は MAP − 大気圧 で算出。取得可否は実機スキャンで確定した(ADR-008/009)。
  • 閾値を机上で決めず、走行ログを溜めて実データで裏取りした(M2.5)。「105℃=危険」という机上の直感は誤りで、データが設計を正した。
  • 1本で満足せず、文脈を変えた追加ログで再検証。閾値は誤発火せず、横G・暖機挙動・油温欠損という新しい素材まで拾えた。
  • コア層とアダプタ層の分離(ADR-002)のおかげで、トリガー判定は実車なしでPC上の単体テストで検証できた。
  • この進め方は、業務でやっている「実データで基準を決める・安全の軸は人が握る」とそのまま重なった。手を動かすのはワークフロー、データで決める判断は人。

この記事が誰かのお役に立てれば幸いです。以上 Yoshi でした。

参考

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事