Skip to Content
中心となる概念運転と安全性

運転と安全性

Tracelet は生の位置情報と加速度計のストリームを 意味のあるものに変えることができます デバイスがどのように移動しているかに関するイベント — クラウドを使用せず、完全にデバイス上で 呼び出します。 3.3.0 で追加された、3 つの独立した機能があります。

|特集 |それがあなたに伝えること | | を使用して有効にします。 | で聞きます。 |---|---|---|---| | 運転イベント | 「ドライバーは急ブレーキをかけた / 急加速した / 急ハンドルを切った / スピードを出しました」 |非トランスレート |翻訳1遅れ | | トランスポートモード | 「ユーザーは現在、歩いたり、走ったり、自転車に乗ったり、乗り物に乗ったりしています。」 |非トランスレート |翻訳1遅れ | | 衝突と落下 | 「衝突(または落下)が起こったばかりかもしれません」 |非トランスレート |翻訳1遅れ |

ここでのすべてはデフォルトでオプトインおよびオフになっています。 機能を有効にしない場合は、 そのエンジンはまったく作成されていません。既存の追跡はまったく同じように動作します。 前に。必要なものだけをオンにします。


これは誰のためのものですか? (実際の例)

  • 使用量ベースの保険 / 車両の安全 → 運転イベントにより、旅行ごとに提供されます サーバー側を使用しない危険な運転(急ブレーキ、スピード違反)の画像 処理。
  • 配達 / フィールドサービス アプリ → 輸送モード により、各旅行にタグを付けることができます 運転 と 徒歩 (例: 「バンを降りてドアまで歩いた」)。
  • 単独労働者 / ライドシェア / 個人安全アプリ → 衝突と落下の検出 信頼できるトリガーを提供します(ユーザーの「大丈夫です」キャンセルウィンドウ付き)。 SOSフローを開始します。

任意の組み合わせを有効にすることができます。これらは独立しています。


1. 走行イベント(テレマティクス)

30秒バージョン

// 1. Turn it on (e.g. with a 50 km/h limit for speeding) await Tracelet.ready(Config( telematics: TelematicsConfig( enableDrivingEvents: true, speedLimitKmh: 50, ), )); // 2. Listen Tracelet.onDrivingEvent((event) { print('${event.kind} — severity ${event.severity}'); }); // 3. Start tracking as usual await Tracelet.start();

それでおしまい。デバイスが移動すると、次のようなイベントが発生します。

harsh_braking — severity 0.82 speeding — severity 0.40

各フィールドの意味

すべての DrivingEvent には次の機能があります。

フィールド意味
非トランスレートharsh_braking、harsh_acceleration、harsh_cornering、または speeding
非トランスレート0.0–1.0 — しきい値をどれだけ超えたか (スコアリングに便利)
非トランスレート測定された数値: 過酷なイベントの場合は G 力、スピード違反の場合は 制限を超えるkm/h**
非トランスレート現時点の速度 (m/s)
latitude / longitude / timestampどこで、いつ

しきい値の調整

すべてのしきい値は g 単位です (1 g ≈ 9.81 m/s²、重力の引力)。デフォルト 一般的な保険/車両の慣例に従ってください。変更する必要はほとんどありません。

オプションデフォルト何をするのか
非トランスレート翻訳1遅れこれより強くブレーキをかける → harsh_braking
非トランスレート翻訳1遅れこれ以上加速→ harsh_acceleration
非トランスレート翻訳1遅れこれより難しいコーナー → harsh_cornering
非トランスレート0 (オフ)制限速度; 0 は速度超過の検出を無効にします。
非トランスレート翻訳1遅れ制限を超える前に猶予を与えてください
非トランスレート翻訳1遅れこの長さは制限を超えている必要があります (短いブリップを避ける)
非トランスレート翻訳1遅れこの速度未満のイベント (駐車場の騒音) を無視します。

時々イベントが発生しないのはなぜですか? 運転イベントは GPS 速度から派生します。 更新は 1 秒に 1 回程度で、少しうるさいです。 Traletet は意図的に好意を示します 感度よりも精度 — 境界線のイベントを見逃すよりもむしろ見逃してしまいます。 オオカミを叫ぶ。最良の結果を得るには、実際に運転しながら (歩きながらではなく) 使用してください。


2. トランスポートモード

ユーザーが still、walking、running、cycling、または vehicle、加速度計の動きと GPS 速度を組み合わせたもの。

await Tracelet.ready(Config( classifier: ClassifierConfig(enableFusedClassifier: true), )); Tracelet.onModeChange((event) { print('Now: ${event.mode} (confidence ${event.confidence})'); });
オプションデフォルト何をするのか
非トランスレート翻訳1遅れマスタースイッチ
非トランスレート翻訳1遅れtrue の場合、融合モードはバッテリー決定のための OS のアクティビティをオーバーライドします。 false (デフォルト) の場合、注釈を付けるだけで、OS の値が引き続き使用されます。
非トランスレート翻訳1遅れ新しいモードは、報告される (ちらつきが停止する) までに、これほど長く存続する必要があります。
非トランスレート翻訳1遅れこの下では、モードは unknown
非トランスレート翻訳1遅れtrue の場合、コミットモードでも位置フィルターが返されます。以下を参照

アノテーションとオーバーライド: デフォルトでは、分類子は セカンドオピニオン です。 はモードを報告しますが、Tracelet が GPS をサンプリングする方法は変更しません。ほとんどのアプリはこれを必要とします。 特に融合が必要な場合のみ fusedClassifierAuthoritative: true を設定してください 結果はバッテリー/サンプリング動作を駆動します。

位置フィルターの自動調整

3.8.0の新機能

距離を正確に追跡するには、異なるフィルターしきい値が必要です。 活動。歩行は困難なケースです。約 1.4 m/s では、GPS ノイズ フロアが大きくなります。 実際に移動した距離の一部であるため、緩いフィルタではジッターが次のように記録されます。 距離。車ではその逆が当てはまります - 敷居が狭いと現実が捨てられます 動き。

事前にセットアップを選択することはできません。ユーザーは「今ジョギング中です」とは宣言しません。 1 つのセッションには通常、登山口までの散歩、ランニング、そしてランニングが含まれます。 歩いて戻ります。したがって、分類器に次のことを決定させます。

await Tracelet.ready(Config( classifier: ClassifierConfig( enableFusedClassifier: true, // required autoTuneFromTransportMode: true, ), ));

モードが コミットすると、Tracelet は 4 つのしきい値をそれに適した値に交換します。

ファッション非トランスレート翻訳1遅れodometerAccuracyThresholdNOTRANS3LATE
非トランスレート25メートル15メートル10メートル3m/秒
非トランスレート8メートル15メートル10メートル4m/秒
非トランスレート12メートル25メートル15メートル9m/秒
非トランスレート20メートル30メートル20メートル20m/秒
非トランスレート30メートル50メートル30メートル60m/秒
非トランスレート設定した値が復元されました

ジョギングには意図的に漕ぎはありません。running 帯域 (6 ~ 20 km/h) 内に収まります。 まさにこれが、ユーザー向けの「ジョギング プリセット」がフィクションである理由です。

予測可能性を維持する方法:

  • 再調整は、コミットされたモード変更の場合にのみ発生します - すでに信頼度ゲート型です modeSwitchDwellMs によってデバウンスされます — センサー読み取りごとではないため、しきい値は おしゃべりはできません。
  • しきい値はその場で交換されます。走行距離計は一定期間にわたって継続します。 セグメントを失うのではなく、モードを変更します。
  • 適用された値は onModeChange イベントおよびデバッグ ログに到着します。 オートチューンは決して静かではありません。
  • unknown は、設定したものをすべて復元します。 Tracelet はそれがいつ起こるかを推測しません わかりません。
  • autoTuneFromTransportMode (または enableFusedClassifier) を オフ にします ランタイムは構成されたしきい値をすぐに復元します。この機能は決して復元しません。 スイッチをオフにすると、その効果が残ります。

何が適用されたのかを見ると、

ModeChangeEvent.appliedTuning は、設定された 4 つのしきい値を保持します。 力。オートチューニングOFF時、モードがunknownの場合はnullとなります。 (独自の値を復元します):

Tracelet.onModeChange((event) { final tuning = event.appliedTuning; if (tuning == null) { print('${event.mode} — your configured thresholds are in force'); } else { print('${event.mode} → distanceFilter ${tuning.distanceFilter} m, ' 'odometerAccuracyThreshold ${tuning.odometerAccuracyThreshold} m'); } });

debug: true と logLevel: verbose では、同じ値がログに表示されます。

auto-tune: 'walking' → distanceFilter=8.0m trackingAccuracy=15m odometerAccuracy=10m maxImpliedSpeed=4m/s

現在有効な内容を読む

onModeChange は、モードがコミットされた「瞬間」について通知します。どういうことかと聞くと、 フィルタは、モード変更が発生していない場合を含め、任意の時点で使用されています。 時間 — Tracelet.getCurrentLocationTuning() を使用します。

final tuning = await Tracelet.getCurrentLocationTuning(); print('in force: distanceFilter ${tuning?.distanceFilter} m, ' 'trackingAccuracyThreshold ${tuning?.trackingAccuracyThreshold} m');

これは、設定からではなく**、ネイティブの位置プロセッサから読み取ります。 セット。この違いが重要です。Tracelet.activeConfig は Dart 側のミラーです。 最後に渡した Config なので、何を要求したかではなく、何を要求したかが報告されます。 フィルターは実際に使用しています - そして自動調整をまったく表示できません。 自動調整により、設定呼び出しを行わずにしきい値が変更されます。

追跡セッションがプロセッサを構築する前に null を返し、常に Web 上の null。同等のフィルター状態がありません。

これは、設定した geo.distanceFilter および geo.filter.* 値を上書きします。 モードがコミットされている限り。それがこの機能のポイントですが、 設定したしきい値が実行時に有効ではないことを意味します — 呼び出し getCurrentLocationTuning() を使用して実際の内容を確認してください。 false のままにしておきます ( デフォルト)正確な値を尊重する必要がある場合。


3. 衝突・落下検知

実稼働対応。 クラッシュ検出には、安定したオンデバイス パイプラインが付属しています。 ルール エンジン (デフォルト)、およびオプションのライセンス付き AI クラッシュ モデル トレーニング済み CC0 / パブリックドメイン クラッシュ データセット上 - したがって、商用利用が許可されています 実稼働アプリで。転倒検出はオプトインおよびベストエフォートのままです。進行中の追跡 問題 #183  の精度調査。

衝突の可能性(移動中の強い衝撃)、またはオプションで衝突を検出します。 個人的な秋。誤報はコストがかかるため、検出は裏付けられています (大きな衝撃だけでは決して十分ではありません)、ユーザーに キャンセルまでのカウントダウンを与えます。

await Tracelet.ready(Config( impact: ImpactConfig( enableCrashDetection: true, confirmWindowMs: 15000, // 15s for the user to say "I'm fine" ), )); Tracelet.onImpact((event) async { if (event.isPotential) { // Show a big "Are you OK?" countdown screen. // If the user taps "I'm fine": await Tracelet.cancelImpact(event.id); // If they tap "Get help now": // await Tracelet.confirmImpact(event.id); } else { // event.kind == 'crash' (or 'fall') — confirmed. // The user didn't cancel in time → start your SOS flow. } });

流れの仕組み

  1. 高速移動中の強い衝撃 → potential_crash イベントが発生します。 非トランスレート。
  2. カウントダウン UI を表示します。ユーザーは キャンセル (cancelImpact) または 今すぐ確認できます (翻訳されていません)。
  3. 期限までに何もしなかった場合 → 確認された crash イベントが発生します。
オプションデフォルト何をするのか
非トランスレート翻訳1遅れ車両衝突検知
非トランスレート翻訳1遅れ個人的な転倒 (ベストエフォート — 誤警報が増加)
非トランスレート翻訳1遅れ衝突としてカウントされる衝撃強度 (g)。大規模な現場データ調査に基づいて 3.0 から引き下げられました (3.0 g は実際の衝突事故の約半分を逃しました)。キャンセルカウントダウンによって誤ったアラームが検出されるため、リコールが優先されます。プロンプトが多すぎる場合は調整してください。
非トランスレート翻訳1遅れこんなに速く動いていたに違いない (裏付け)
非トランスレート翻訳1遅れカウントダウンの長さをキャンセル
非トランスレート翻訳1遅れ信頼性の低い候補者を抑制する

Tracelet は トリガーとキャンセル ウィンドウを提供します。電話をかけることはありません 緊急サービスに電話または連絡します。実際のSOS/緊急フローの構築は、 あなたのアプリの責任(そしてあなたがUXと合法的なコピーを制御することを可能にします)。

確認はアプリが強制終了されても存続します

暴力的な衝撃は、多くの場合、OS によるアプリの強制終了で終わります。つまり、携帯電話が投げられたり、 車両が停止すると、デバイスは Doze 状態になります。キャンセルカウントダウンの場合 メモリ内にのみ存在するため、確認された crash/fall は黙って起動されません。 Tracelet はカウントダウンを プロセスデスセーフ にします。 potential_crash/potential_fall が発生すると、ディスクに永続化され、 ウェイクアップは締め切り直後に備えてあります。アプリがまだ生きている場合は、 正常に確認し、ウェイクアップを解除します。殺されたら目覚める 確認されたイベントを新しいプロセスから再発行するため、SOS フローは引き続き実行されます。

プラットフォームメカニズム
アンドロイド正確な AlarmManager アラーム (setExactAndAllowWhileIdle、Doze 中でも発生) は、確認されたイベントを再配信する受信機を起動します。
iOS期限にスケジュールされたローカル通知は、アプリが停止している間でもユーザーに警告します。確認されたイベントは、次回 SDK を実行するときに (バックグラウンドでの再起動またはフォアグラウンドで) 再配信されます。ユーザー向けアラートに対する通知権限を付与します。再配信はどちらの方法でも機能します。

ユーザーがキャンセルすると、永続化された候補が削除され、ウェイクアップが解除されます。 キャンセルされた候補は、再起動後に再確認されることはありません。

実際の衝突や落下を裏付ける追加の手がかり

大きな衝撃だけでは十分ではありません。それは、誤報が多すぎる原因となります。 したがって、Tracelet は、通常、現実世界の現実世界で発生する追加の手がかりを探します。 衝突または落下。手がかりが多ければ多いほど、その確信度は高まります。これらの手がかりは、 Tracelet は さらに 自信を持っていただけます。実際のイベントは決してキャンセルされません。

  • 携帯電話が落ちていた - 誰かが携帯電話を落としたり、携帯電話を盗んだりする直前 落下すると、携帯電話は一時的に無重力状態になります。フォールをさらに盛り上げるスポッティング 信じられる。
  • その後はすべてが静止しました — 実際に転倒した後、その人と電話は 通常は動きを停止します。その突然の静けさは強い兆候です。
  • 車が突然停止した — 実際の衝突では、車両は高速から停止します。 1、2秒でほとんど止まりました。速度の急激な低下は衝突を後押しします。
  • 圧力による「ポップ」 — 重大な衝突(またはエアバッグの作動)により、急速な衝撃が発生します。 車内の気圧の変化。圧力センサーを備えた携帯電話では、 これに注目してください。これがない携帯電話では、このチェックをスキップするだけで、デメリットはありません。

オプション: ライセンス付き AI クラッシュ モデル

デフォルトでは、衝突検出は ルール エンジン (G しきい値 + 速度) を使用します。 上記の裏付け) — 追加のセットアップは不要で、そのまま使用できます。より高い精度を目指して AI クラッシュ モデル を有効にできます。これは、ゲート クラッシュを学習したモデルです。 固定閾値の代わりに学習された確率。

オプトインでオンデマンドでダウンロード (決して埋め込まれない) なので、基本 SDK サイズ は変わっていない。これを有効にするには、ライセンス キーを取得し、設定でそれを指定します。

await Tracelet.ready(Config( impact: ImpactConfig( enableCrashDetection: true, crashModelUnlockUrl: 'https://unlock.ikolvi.com/unlock', crashModelLicenseKey: '<your license key>', crashModelThreshold: 0.5074, // rf_probability_threshold from training ), ));
オプションデフォルト何をするのか
非トランスレート翻訳1遅れモデルをアクティブ化するライセンス エンドポイント。 null ⇒ 純粋なルールエンジン
非トランスレート翻訳1遅れライセンス キー ([ライセンスの取得] ページから)
非トランスレート翻訳1遅れモデルがクラッシュのフラグを立てる確率

何らかの理由(オフライン、無効なキー)でモデルをアクティブ化できない場合、SDK 自動的にルール エンジンにフォールバックします - アプリは動作し続けます。

ライセンスを取得する

ライセンスの取得 ページからキーを取得します。サインインし、パスワードを入力します。 アプリケーション ID を入力し、すぐに貼り付けられるキー (または完全な ImpactConfig) をコピーします。 スニペット)。

  • 開発ライセンス — デバッグ ビルドとエミュレータ用。アプリ ID だけで、追加のものはありません 設定。
  • 製品ライセンス — 出荷されたアプリ用。アプリの署名証明書も必要です SHA-256 (Play Console → アプリの整合性 → アプリ署名、または ./gradlew signingReport)。

ポータルには、発行されたキーのリストも表示され、キーを即座に取り消すことができます。


4. 旅行のアイデンティティ: すべてを結びつける

場所、運転イベント、旅行の概要は、同じ旅の 3 つの視点です。 trip_id はそれらに加わるものです。

旅行が開始されると、SDK は UUIDv4 を作成し、旅行が終了するまで記録されたすべての場所と運転イベントにそれをスタンプします。同じ ID が旅行の概要に表示されるため、「このドライブでどのような急ブレーキが発生しましたか?」再構築ではなく検索です。

旅行の開始時期を知る

トリップは、デバイスが静止状態から移動状態に移行したときに始まります。 onTripStart はその時点で起動され、それ以降に記録されるすべての ID が次のようになります。

Tracelet.onTripStart((trip) { print('Trip ${trip.tripId} started at ${trip.startedAt}'); // Tag your own data with the same key. analytics.beginDrive(tripId: trip.tripId); }); Tracelet.onTrip((trip) { print('Trip ${trip.tripId} covered ${trip.distance} m'); print('From ${trip.startedAt} to ${trip.endedAt}'); });

また、どの時点でどの旅行が実行されているかを尋ねることもできます。

final id = Tracelet.currentTripId; // null between trips

トリップ ID が出荷される前は、トリップは 終了 して初めて観察可能になりました。onTrip はトリップ終了時に起動され、それ以前のシグナルはありませんでした。レコードを旅行ごとにグループ化する必要があるアプリは、onMotionChange から境界を再導出する必要がありました。これは、背後にあるデバウンスとしきい値が認識されないため、SDK 自体の検出からドリフトします。

読み返してみると

trip_id は行に保存されるため、保存された履歴や同期するものには残ります。

final events = await Tracelet.getTelematicsEvents(50); final thisDrive = events.where((e) => e.tripId == someTripId);
どこフィールド
非トランスレートtripId、startedAt、startLocation
TripEvent (onTrip から)tripId、startedAt、endedAt、および既存の距離/期間/ウェイポイント
非トランスレート翻訳1遅れ
ペイロードの同期各位置およびテレマティクス レコードの trip_id — Tracelet Sync

知っておくべきルール

  • これは不透明です。 UUIDv4 には情報が含まれず、時系列に並べ替えられません。決して解析したり、それによって注文したりしないでください。startedAt によって旅行を注文します。
  • 再利用されることはありません。 トリップ終了では ID が破棄されます。次の旅行では新しいものが鋳造されます。同じ ID を 2 番目の旅行に渡すことができる「前の旅行を再開する」パスはありません。
  • 行が書き込まれるときに書き込まれます。 旅行中に記録された場所は、数時間後に別の旅行が実行されているときにアップロードされた場合でも、その旅行の ID を保持します。これにより、オフライン バックログが正しくなります。
  • トリップの開始付近のいくつかのポイントでは null が設定されています。 トリップの検出はモーション トランジションに続くため、一部の修正は SDK がトリップの開始を宣言する前に適用されます。これらはバックフィルされません。値は書き込み時の状態を記録します。
  • null は正常です。 旅行の外部で記録されたものには旅行 ID がありません。旅行 ID が出荷される前のバージョンで書き込まれた行や旅行も同様です。

旅行 概要 は依然として onTrip() 経由でのみ配信されます。SQLite に書き込まれず、同期もされません。 trip_id は例外です。trip_id は場所と運転イベントに保持されるため、概要がバックエンドに到達しない場合でも、同期された行から旅行を再構築できます。


運転せずに試してみる(シミュレーション)&データベースアクセス

Tracelet には、テレマティクス イベントと一連の診断 API を保存する専用のデータベース テーブルが含まれています。これらは Tracelet Doctor 診断オーバーレイによって頻繁に使用されますが、物理的に車を運転したり衝突させたりすることなく、アプリ内で直接使用してカスタム診断画面を構築したり、安全フローをテストしたりすることもできます。

データベースからテレマティクスを取得する

すべての運転イベントと衝撃イベントは、ローカル SQLite データベースに自動的に保存されます。これらの構造化された記録を取得して、危険な運転行為の履歴を表示できます。

// Fetch the 50 most recent telematics events from the database final events = await Tracelet.getTelematicsEvents(50); for (final event in events) { print('Event Type: \${event.eventType}'); // e.g. harsh_braking, crash print('Severity: \${event.severity}'); print('Location: \${event.latitude}, \${event.longitude}'); }

イベントは新しい順で返され、同期してもイベントは削除されません。

無傷。

バックエンドに送信する

HttpConfig.syncTelematics: true を設定すると、非同期イベントが通常のイベントに乗ります。 location sync — 同じ POST 上のルートレベルの telematics 配列、または独自の配列 HttpConfig.telematicsUrl を設定するときにリクエストします。アップロードに失敗するとイベントが保持される ドロップするのではなくキューに入れます。ワイヤー スキーマの場合、バッチ処理の境界と 別のエンドポイントのトレードオフについては、を参照してください。 テレマティクス同期 📖。

イベントのシミュレーション

模擬テレマティクス イベントをネイティブ追跡エンジンに直接挿入できます。これは、アプリの反応 (クラッシュ時に SOS 画面を表示するなど) をテストしたり、UI コンポーネントをテストしたりするのに最適です。サンプル アプリの 運転と安全性 ページと Tracelet Doctor オーバーレイは、この API を使用して、開発者がボタン経由でイベントをトリガーできるようにします。

// Simulate a harsh braking event (named arguments) await Tracelet.simulateTelematicsEvent( eventType: 'harsh_braking', severity: 0.85, // 0.0 to 1.0 latitude: 37.422, longitude: -122.084, );

データベースのクリア

診断状態をリセットする必要がある場合、またはローカル データベースからテレマティクス イベントの履歴をクリアする必要がある場合は、キューをパージできます。

await Tracelet.destroyTelematicsEvents();

自動テストでは、Dart から直接エンジンを駆動することもできます (flutter_rust_bridge 経由で公開されます)。example/integration_test/behavior_simulation_test.dart を参照してください。


権限

  • 運転イベントには、すでに使用している位置情報の許可のみが必要です 追跡 — 余分なものは何もありません。
  • 輸送モード と 衝突/落下 は加速度センサーを使用します。 Android では、 モーション検出のためにすでに実行されています (新しい権限はありません)。 iOS では、 モーションとフィットネス の使用説明により、精度が向上します。を参照してください。 iOS および Android の設定ページ。

知っておいてよかった

  • オンデバイス & 決定的 — すべての検出は共有 Rust コアで実行されます。いいえ ネットワーク、クラウド モデルなし、Android と iOS で同じ結果。
  • ドライビング イベントは Web でも機能します (GPS から派生したものです)。
  • サイドチャネル — これらのイベントは通常のイベントと並行して配信されます onLocation ストリーム;あなたの場所や走行距離計を変更することはありません。 syncTelematics をオプトインした場合にのみ、同期ペイロードに参加します。
Last updated on