PocketSDRすごい(スナップショット測位編)

categories: gnss
tags: pocketsdr qzss sdr

はじめに

2022年2月21日の測位航法学会高精度衛星測位研究委員会にて、東京海洋大学の高須知二先生がAn Open Source GNSS SDR: Develepment and Applicationsと題した講演をされました。内容は、PocketSDRのハードウェア、L6帯信号受信、スナップショット測位、そして今後の14素子アレイアンテナを備える受信機の展望に関するものです。どれも簡単には到達できない、すごい内容ですが、一方で、ソースコードやサンプルデータが公開されていて、誰でも試せるようになっています。

この中で、私が今まで知らなかったスナップショット測位を試してみました。

スナップショット測位

衛星測位は、複数衛星からの電波の同時受信により達成されます。受信機が座標計算に必要な情報は、

  1. 信号観測を要する情報(擬似距離)と、
  2. 信号観測を要しないが座標計算のために復号する情報(衛星位置、衛星時刻、電離層遅延補正、補強情報など)とに

大別されます。

信号観測を要しない情報は、例えば6秒や12分のオーダーで伝送される情報なので、この間は信号途絶のないように受信することが求められます。しかし、この情報は、必ずしも自らが受信しなくてもよく、例えば、セルラー回線やインターネット回線から得ることも可能です。

したがって、信号観測を要する情報のみを観測すれば、原理的には座標を得られるはずです。この信号観測期間は、短くてもよく、例えば100ミリ秒間程度の観測でも座標を得られると考えるのがスナップショット測位です。

高須先生の講演資料の13ページには、1分間に1回、20ミリ秒間だけ受信するスナップショット間欠受信機の構成が例示されています。これは、CR2032ボタン電池1個にて1年以上にわたり動作し、この期間の座標計算に資する情報を32GBのSDカード1枚に記録できるものです。この消費電力には、受信モジュールMAX2769Bの電力消費、マイコンSTM32L4の動作時とディープスリープ時の電力消費、SDカード動作の電力消費も含まれています。

Snapshot GNSS receiver configurationAn Open Source GNSS SDR: Develepment and Applicationsの13ページより抜粋)

そこで、PocketSDRに含まれているサンプルデータとPythonコードを用いて、このスナップショット測位を試してみました。

L1帯での100ミリ秒観測データ

ここで用いる観測データは、PocketSDRにあるsample/L1_20211125_004000_12MHz_I.binです。readme.txtファイルによる諸元は次の通りです。

File Path   : L1_20211125_0040000_12MHz_I.bin
Date Time   : 2021-11-25 00:40:00 UTC
Duration    : 100 ms
Conf File   : pocket_L1L6.conf
Channel     : 1
F_LO        : 1572.420 MHz
F_ADC       : 12.000 MHz
Sampling    : I
F_IF        : 3.0 MHz
BW_IF       : 4.2 MHz

この設定において、PocketSDRは、1回の標本で1バイトを要し、1秒間に12メガサンプル取得するレートで100ミリ秒間だけデータ記録しますので、ファイルサイズは1.2メガバイトです。

ls -l ../sample/L1_20211125_004000_12MHz_I.bin
-rw-r--r-- 1 sat staff 1200000  1 19 19:51 ../sample/L1_20211125_004000_12MHz_I.bin

標本化周波数を1/2にするとファイルサイズも1/2になり、観測期間を1/5にするとファイルサイズもまた1/5になります。

この100ミリ秒観測データに含まれるGPS信号を確認するために、pythonディレクトリにあるpocket_acq.pyを利用します。私はMacbook Air(Early 2015, Intel Core i7-5650U 2.2 GHz)を用いました。

./pocket_acq.py -f 12 -fi 3 ../sample/L1_20211125_004000_12MHz_I.bin -prn 1-32

PocketSDR signal acquisition

多くのGPS衛星信号が観測されています。しかし、観測期間がとても短いので、例えば、ここで信号の強力なPRN 5番衛星信号であっても、信号追尾ができません。

./pocket_acq.py -f 12 -fi 3 ../sample/L1_20211125_004000_12MHz_I.bin -prn 5
TIME = 0.261 s

PocketSDR signal tracking with very short measurement

スナップショット座標計算

スナップショット座標計算には、観測データのほかに航法データが必要です。後者は、信号観測を要しない情報で、衛星位置や衛星時刻などが記述されています。この航法データの入手にはいろいろな方法がありますが、ここでは広島でのNovAtel OEM729受信機を用いた観測データを利用します。この観測時刻を含む、2021年11月25日00:00:00 UTC(世界協定時: coordinated universal time)から01:00:00 UTCまでの1時間の生データをダウンロードします。

curl https://phys.info.hiroshima-cu.ac.jp/gnss/oem7/202111/20211125a.gps -o 20211125a.gps

次に、RTKLIBのアプリケーションconvbinを用いて、このOEM729受信機生データから航法データ20211125a.navと観測データ20211125a.obsを抽出します。

convbin 20211125a.gps
input file  : 20211125a.gps (NovAtel OEM7)
->rinex obs : 20211125a.obs
->rinex nav : 20211125a.nav
->sbas log  : 20211125a.sbs

scanning: 2021/11/25 01:00:18 GREJCI
2021/11/24 23:59:30-11/25 01:00:29: O=3639 N=173 E=17

ここで得た20211125a.navを、例えば、観測データと同じsampleディレクトリに置きます。

この観測データファイルの観測期間は100ミリ秒間ですが、pocket_snap.pyでの初期値では、先頭から20ミリ秒間の観測データを座標推定に用います。

./pocket_snap.py -f 12 -fi 3 -nav ../sample/20211125a.nav ../sample/L1_20211125_004000_12MHz_I.bin -ts 2021/11/25-00:40:00
2021/11/25 00:40:39.722    35.87xxxxxxx  138.38xxxxxxx     1xxx.xxx    5    8
TIME (s) = 14.863

すごい!たった20ミリ秒間の観測で座標が推定できてしまいました。結果表記はRTKLIB形式であり、座標の後の5は単独測位解を、その後の8は測位に用いた衛星数を表します。観測時刻も40秒だけ後方に自動修正されています。なお、座標の一部を伏せています。

この座標推定方法では、大まかな時刻を与えることが必要です。pocket_snap.pyでは、観測ファイル名から時刻が自動設定されるようになっていますが、ここではコードがファイル名時刻を読み取れなかったようでしたので、-tsオプションにて明示的に時刻を指定しました。引数には、UTCでの年月日時分秒を:/-のいずれかの記号で区切って与えます。

大まかな座標が既知であると、より短時間にて座標が推定できます。ここで-posオプションにて大まかな座標を与えたら、計算時間が大幅に削減されました。

./pocket_snap.py -f 12 -fi 3 -nav ../sample/20211125a.nav ../sample/L1_20211125_004000_12MHz_I.bin -ts 2021/11/25-00:40:00 -pos 35.87,138.38,1000
2021/11/25 00:40:39.723    35.87xxxxxxx  138.38xxxxxxx     1xxx.xxx    5    8
TIME (s) = 0.650

正しいと思われる時刻から数分以内の差であれば、座標推定できました。これは、すでに得た時刻から1分40秒だけ進めた時刻を与えた結果です。

./pocket_snap.py -f 12 -fi 3 -nav ../sample/20211125a.nav ../sample/L1_20211125_004000_12MHz_I.bin -ts 2021/11/25-00:39:00 -pos 35.87,138.38,1000
2021/11/25 00:40:39.723    35.87xxxxxxx  138.38xxxxxxx     1xxx.xxx    5    8
TIME (s) = 0.557

さらに-outオプションを用い、引数に出力ファイルを指定すると、ヘッダーや諸元とともに座標が記録されます。

% SNAPSHOT POSITION by POCKET_SNAP.PY
% INPUT FILE    : ../sample/L1_20211125_004000_12MHz_I.bin
% SAMPLING TIME : 20.0 ms / SNAPSHOT
% SAMPLING FREQ : 12.000 MHz
%  UTC                    latitude(deg) longitude(deg)    height(m)    Q   ns
2021/11/25 00:40:39.723    35.87xxxxxxx  138.38xxxxxxx     1xxx.xxx    5    8

また、この観測ファイルには100ミリ秒間の信号が記録されていますので、-tintオプションにて観測期間を100ミリ秒まで延ばしてみました。

./pocket_snap.py -f 12 -fi 3 -nav ../sample/20211125a.nav ../sample/L1_20211125_004000_12MHz_I.bin -ts 2021/11/25-00:40:00 -pos 35.87,138.38,1000 -tint 100 -out aaa.pos
TIME (s) = 3.236

より計算時間がかかり、また、座標値が多少、変化しました。スナップショット測位は、後に記録データを解析するので、この計算時間はあまり問題にはならないと考えます。

これまではGPSのみを利用していましたが、PocketSDRはマルチGNSS対応ですので、-sysオプションにて、GPS G、みちびきJ、Galileo E、北斗Cも座標推定に用いることができます。スナップショット測位は、解析時に対象衛星の追加や削除ができ、とても便利です。

./pocket_snap.py -f 12 -fi 3 -nav ../sample/20211125a.nav ../sample/L1_20211125_004000_12MHz_I.bin -ts 2021/11/25-00:40:00 -pos 35.87,138.38,1000 -sys G,J,E,C
2021/11/25 00:40:39.725    35.87xxxxxxx  138.38xxxxxxx     1xxx.xxx    5   23
TIME (s) = 5.191

座標推定にかかる時間が長くなりましたが、使用衛星数が23に増えました。

今度は自らの受信データでこのスナップショット測位を試してみたいです!

おわりに

スナップショット測位をPocketSDRのサンプルデータとPythonコードで試しました。たった20ミリ秒間の信号観測と、小さな外部情報で座標が推定できて、楽しかったです。

L6帯信号受信の話題も興味深かったです。信号追尾は、既知のビットパターンと受信したビットパターンとがより多く一致する時刻を見出すことにより行います。このPocketSDRでのL6帯信号受信のキーアイディアは、この相関計算と「たたみ込み」計算とで負号が異なるだけの類似性と、フーリエ変換によりたたみ込み演算が積演算に変換される性質を、固定情報が伝送されるプリアンブルに適用することにあると理解しました。この資料とコードを読み、L6信号受信についても考えてみます。


関連記事