エクスポートしたシナリオに対して受信機を実行する
実験室用 GNSS シミュレーターを所有する受信機メーカーは、Kshana シナリオの車両の動きをそれで再生し、試験対象の受信機の動作を記録し、そのログを実行前に定めたイベントと照らして kshana receiver-trust で採点できます。Kshana が提供するのは、動き、イベントの時刻、採点です。信号は一切書き出しません。ここでエクスポートされるものは、無線周波数やベースバンドの波形を合成、モデル化、送信するものではなく、エクスポートされたイベントはラベル付きの時間区間であって、干渉を生成するための手順ではありません。信号はシミュレーターとその運用者が用意し、運用者は、許可された場所(シミュレーター自身の安全上の指示に従った、ケーブル接続またはシールドされた環境)でのみ実行する責任を負います。
このページは手法の説明です。結果は公表しません。
1. エクスポート#
kshana bench-export scenarios/gnss-ins.toml --out run1 --epoch 2025-03-01T10:00:00Z
対象は gnss-ins カインド(姿勢を伴う走行プロファイル。航法状態の途絶がイベントです)、および jamming と gnss-sim(シナリオの継続時間のあいだ静止している受信機。jamming シナリオのジャマーは、実行全体にわたる 一つのイベントです)です。それ以外のカインドには、車両の軌跡がない理由が示されます。--epoch は動きの時刻ゼロにあたる UTC 時刻です(既定は 2024-01-01T00:00:00Z)。シナリオ自体には、車両の動きに関する暦日付がありません。実在する UTC 時刻で、YYYY-MM-DDTHH:MM:SS(末尾の Z も受け付けます)の形式、年は 2000 から 2099 の範囲、すべてのフィールドが範囲内でなければならず、それ以外は拒否されます。同じシナリオとエポックであれば、出力はバイト単位で同一です。
| ファイル | 内容 |
|---|---|
run1.motion.csv |
サンプルごとに一行:time_s、地球固定の x_m,y_m,z_m、vx_m_s,vy_m_s,vz_m_s、測地の lat_deg,lon_deg,h_m、heading_deg,pitch_deg,roll_deg、utc、kshana_row |
run1.motion.json |
その CSV のエポック、座標系、単位、列、往復の許容差 |
run1.nmea |
サンプルごとの NMEA 0183 の GGA 文と RMC 文(チェックサム付き) |
run1.waypoints.txt |
RESOLUTION: <ms> 行に続く longitude,latitude,altitude の各行(すべてのサンプル間隔が同じ整数ミリ秒のときにのみ書き出されます。省かれた場合は、コマンドが標準エラー出力でその理由を示します) |
run1.events.csv |
label,kind,onset_s,end_s,description |
run1.events.toml |
receiver-trust シナリオ向けの、[[events]] ブロックとして書いた同じイベント |
run1.conditions.json |
receiver-log 記録向けの kshana.test-conditions/1 ドキュメントとしての実行内容:イベントは既知の真値として記載し、recording.path、recording.sha256、receiver.*、各イベントの type と電力は、実験室が記入するよう空欄のままにします |
座標系と規約#
- 位置:WGS 84、地球固定(ECEF:
xは本初子午線上の赤道を通り、zは極を通ります)。lat_deg、lon_deg、h_mは同じ位置を測地座標で表したもので、h_mは楕円体からの高さです。 - 速度:地球固定の軸で、地球に対する相対速度です。
- Attitude:
heading_degは真北から時計回りで [0, 360) の範囲、pitch_degは機首上げが正、roll_degは右翼下げが正です。ローカルの北・東・下方向の座標系から、x が前方、y が右、z が下の機体軸へのヨー・ピッチ・ロール(3-2-1)です。静止した発生源ではゼロが書き込まれます。NMEA とウェイポイントのテキストには姿勢が含まれません。 - 方位は機体のヨーであり、進行方向ではありません。
gnss-ins走行プロファイルでは、速度が追従するなか機体は矩形波状にヨー運動するため、方位と対地針路は数十度異なることがあります(同梱のautomotive-urban-canyonシナリオでは最大約 77 度)。NMEA のRMCの針路は対地針路、つまり速度ベクトルの向きです。そのため、動きのファイルから方位を読むシミュレーターと、NMEA ファイルから針路を読むシミュレーターでは、異なる角度が見えます。CSV の対地針路は、速度を北・東・下方向に回転させたもののatan2(v_east, v_north)です。 - 高さはシナリオに従います。
gnss-insでは、h_mはこのカインド自身の接平面ステッピングによる真値であり、一定には保たれません(automotive-urban-canyonの 180 秒間で約 7 m)。これはシナリオの動きをそのまま書き出したものです。 - NMEA の
GGAのプレースホルダー。測位品質(1)、使用衛星数(12)、HDOP(1.0)は、文の形式を整えるためだけに書き込まれます。シナリオのジオメトリや受信機の状態については何も示しません。 - Time: エポックからの
time_s、UTC、うるう秒はモデル化していません。 - NMEA の高さは楕円体高です。
GGAの高度には楕円体高が入り、ジオイド分離は 0.0 として書き込まれます。高度を平均海面からの高さとして扱うシミュレーターでは、車両の位置が現地のジオイド起伏の分だけずれます。 - 往復の許容差(各ファイルを読み戻して試験):CSV の位置 0.1 mm、緯度と経度 1e-9 度、速度 0.1 mm/s、角度 1e-6 度。NMEA の水平位置 5 mm、高さ 1 mm、速力 0.001 ノット、針路 0.001 度。
ファイルをシミュレーターに読み込む#
実験室用シミュレーターは製品ごとに異なり、このリポジトリはどのシミュレーターのマニュアルも再現しません。上記の形式のうちどれを使用しているシミュレーターが読めるか、またその要件を確認してください。
- 多くの動きのインポーターは、一定の更新レート(一般的には 10 Hz)を想定しています。
gnss-insシナリオは 0.1 秒刻みです。静止シナリオでは、[time] step_sをシミュレーターが求めるレートに設定してください。 - インポーターによっては、整数秒の間にあるサンプルを読み飛ばしたり、時刻の列を無視して行の順序を使ったりします。動きは整数秒から開始し、格子を規則的に保ってください。
- 列を対応付けられる CSV インポーターであれば、
run1.motion.csvを直接読み込めます。地球固定の列か測地の列を選び、その単位はrun1.motion.jsonに従って設定してください。小数部を切り捨てると偽の加速度が生じるため、書き出された精度を保ってください。 - このファイルは動きのみを含みます。コンステレーション、干渉、受信機のフロントエンドはシミュレーターで設定し、
run1.events.csvのイベントに合わせてタイミングを設定してください。
Kshana はベンダー固有のスクリプトインターフェースを書き出しません。
オープンソースのシミュレーター一つのリーダーで確認
gps-sdr-sim(MIT、コミット 28ca29a6)の動きのリーダーに、同梱の八つのシナリオのエクスポートを与えました。どのリーダーも、エクスポートされた軌跡を返しました(tests/testbench_gpssdrsim_oracle.rs、xval/testbench-gpssdrsim/PREREGISTRATION.md で事前登録)。
| gps-sdr-sim のオプション | 与えるもの | CSV との最大の差 |
|---|---|---|
-g(NMEA GGA) |
書き出したままの run1.nmea |
1.2 mm |
-x(時刻、緯度、経度、高さ) |
tail -n +2 run1.motion.csv | cut -d, -f1,8,9,10 |
0.15 mm |
-u(時刻、x、y、z) |
tail -n +2 run1.motion.csv | cut -d, -f1-4 |
完全一致 |
-uに動きの CSV 全体を与えてはいけません。そのリーダーは 行ごとに 100 文字を保持しますが、CSV の一行は約 160 文字あるため、各行が 二つのサンプルとして読まれます。ヘッダー行は、数値を含まないサンプルがもう一つあるものとして読まれます。- gps-sdr-sim が保持できるサンプルは最大 3000 個、固定の 10 Hz で 300 秒分であり、時刻の列は無視されます。
gnss-insのエクスポートはちょうど 0.1 秒刻みです。20 分間のgnss-ins-maritimeのようにそれより長いシナリオは、最初の 300 秒分しか読み込まれません。 - これは、ファイルが書かれたとおりに読み込まれることを確認するものです。シナリオの物理や、シミュレーターが送信する内容を確認するものではありません。
2. 実行前に採点対象を明記する#
イベントファイルには、シナリオが定義する区間が記載されています。run1.events.toml を receiver-trust シナリオにコピーし、確認したい予測があれば追加し、監視のしきい値と許容差を受信機の実行前に固定してください。ログを見たあとに調整してはいけません。シナリオ、しきい値、ログの SHA-256 はすべて、結果のハッシュに含まれます。
kind = "receiver-trust"
name = "bench session 1"
[log]
format = "ubx" # ubx, rinex, android or nmea
path = "receiver-log.ubx"
[monitors]
calibration_s = 60.0
# paste run1.events.toml here, and shift onsets by the log offset (step 4)
[[events]]
label = "gnss-denied-1"
kind = "other"
onset_s = 100.0
end_s = 160.0
エクスポートされるイベントには、シナリオ自身の kind が入ります。jamming シナリオのジャマーは jamming、航法状態の途絶は other です。シナリオが述べているのは GNSS が利用できなかったことであり、その方法ではないためです。kind は、シミュレーターに設定する内容に合わせて変更してください。
3. 受信機を実行する#
受信機とそのロガーを起動し、動きのファイルを使ってシミュレーターのシナリオを開始し、実行がキャリブレーション区間、すべてのイベント、そして最後のイベントのあとの余裕時間を含むようにします。受信機自身のログ(UBX、RINEX 3 観測、Android ロガーの CSV、または衛星状態文を含む NMEA)を保存してください。衛星ごとの信号強度がないログでも、受信機自身の位置については採点できますが、搬送波対雑音比の監視にはそれが必要です。
4. 時計を揃える#
receiver-trust は、イベント時刻を受信機のログの最初のエポックから数えます。動きのファイルは最初のサンプルから数えます。ログが動きの最初のサンプルより d 秒前に始まる場合は、すべての onset_s と end_s に d を加えてください。誤ったオフセットはすべての採点結果を動かすため、オフセットとその測り方を記録し、シナリオの name またはコメントに明記してください。イベント時刻だけからはオフセットは分かりません。シミュレーターのシナリオ開始マーカーか、受信機自身のタイムスタンプを使ってください。
5. 採点する#
kshana receiver-trust bench-session.toml
bench-session.result.json、.trust.csv、.trust.svg を書き出します。各イベントについて、結果には、開始前の誤警報、最初の警報とその監視、遅延、結果(detected、late、missed、not-evaluable)が示され、予測を明記した場合は、予測された搬送波対雑音比の低下と観測された低下も示されます。不一致は報告され、調整して消されることはありません。RECEIVER-TRUST.md を参照してください。
このセッションが裏付けとなる証拠を提供する公開フレームワークの行を確認するには、次のようにします。
kshana compliance-report bench-session.result.json
compliance/README.md を参照してください。このレポートは、与えた実行に含まれる証拠を記述するものであり、受信機やいかなるフレームワークについても判定を下しません。
6. 往復全体を一つの署名付きパックにまとめる#
採点後、kshana evidence round-trip が 四つの記録、すなわちエクスポートしたシナリオ、実験室の試験条件、受信機のログ、採点結果を結び付けます。run1.conditions.json(ログのパスと SHA-256、試験対象の受信機、各イベントの種類と明記した電力)に記入してから、次を実行します。
kshana evidence keygen --out lab.key
kshana evidence round-trip bench-session.toml --scenario scenarios/gnss-ins.toml \
--conditions run1.conditions.json --from 0 --to 180 --key lab.key --out round-trip-pack
kshana evidence verify round-trip-pack --pubkey <signer public key>
round-trip-pack/config.json には、scenario_sha256、conditions_hash、log_sha256、および採点結果(評価可能なうち検出されたイベント数、最初の警報)を含む round_trip ブロック(kshana.round-trip/1)が入っており、マニフェストのハッシュと署名で保護されています。このコマンドは、条件と採点対象イベントが食い違うパック、または記載されたログのハッシュがログ自体のハッシュと一致しないパックを拒否します。すべてのエビデンスパックと同様、これは技術的な記録であり、法的な見解ではありません。
実例:gps-sdr-sim によるファイルの書き出し#
この例では、オープンソースのシミュレーター gps-sdr-sim を、エクスポートした動きからベースバンドファイルを書き出すためだけに使います。Kshana は送信を行わず、このページのどの内容も、そのファイルを無線機で再生する作業を自動化しません。実験室がそのようなファイルを受信機に再生する場合、それは運用者の責任であり、許可された場所(シミュレーターと無線機自身の安全上の指示に従った、ケーブル接続またはシールドされた環境)でのみ行うものです。Kshana はそれを文書化することも、ラップすることもしません。
kshana bench-export scenarios/gnss-ins.toml --out run1 --epoch 2025-03-01T10:00:00Z
tail -n +2 run1.motion.csv | cut -d, -f1-4 > run1.xyz # time, x, y, z (see above)
gps-sdr-sim -e brdc0600.25n -u run1.xyz -b 8 -o run1.iq # writes a file, nothing else
実験室が run1.iq をその後どう扱うかは、Kshana の外で行われます。入手方法を問わず、受信機自身のログが、手順 5 で採点され、手順 6 で結び付けられるものです。Kshana 自身のエクスポートに対するファイルと確認は、合成データのみで試験されており(tests/round_trip_pack.rs)、ここでは実験室での実行は主張しません。
この手法が行わないこと#
- 信号は生成せず、シミュレーターがどの干渉を生成すべきかも示しません。イベントが示すのは「いつ」であり、「何を」ではありません。
- 一回のセッションは一つのデータ点にすぎません。結果が記述するのはその構成でのそのログであり、他の受信機、ファームウェア、アンテナ、実際の干渉については何も示しません。
- 高さ、レート、時刻の整合は、運用者がシミュレーターに照らして確認するものです。エクスポートは自らの規約と許容差を示すだけで、それ以上は示しません。