PocketSDRすごい(L6信号デコード編)
はじめに
PocketSDRがアップデートされ、v.0.6になりました。みちびきL6帯信号の復号機能が追加されたので、今回は私のパソコンにてL6E(MADOCA)メッセージを読み出してみました。PocketSDRすごいです。
共有ライブラリ作成
このバージョンから低密度パリティ検査(LDPC: low density parity check)の共有ライブラリが必要になります。PocketSDRには、WindowsとLinuxに対する共有ライブラリが同梱されていますので、これらの環境ではこのステップは不要です。
macOSでは、自ら共有ライブラリを作成しなければなりませんが、PocketSDRのlib/ldpc
フォルダにMakefileがありますので、容易にこのライブラリを作成できます。出力ファイルの拡張子を.so
から.dylib
にすることと、共有ライブラリ作成オプションを-shared
から-dynamiclib
に変更するだけです。私の作成したmacOS向け共有ライブラリは次の通りです。ご自由にお使いください。
pocketsdr_maclib.zip
(2022-02-19更新: PocketSDR version 0.7に合わせて更新しました。)
このZIPファイルを解凍すると、フォルダdarwin_arm
とdarwin_x86
が現れます。前者がM1 Mac用で、後者がIntel Mac用です。これらのフォルダをPocketSDRのlib
ディレクトリにおいてください。
macOSのセキュリティ機能により、ダウンロードしたファイルをそのままでは実行できないかもしれません。Finderにてこれらの共有ライブラリファイルを「2本指クリック」して「開く」を実行して、実行許可を与えてください。
次に、PocketSDRのPythonコードから、これらの共有ライブラリを扱えるようにします。その方法はPocketSDRすごい(pocket_trk編)と同様ですが、今回はplatform
モジュールにより自動機種判定を行うようにしました。PocketSDRのpythonフォルダにある次の3ファイルの先頭部分を次のように書き換えてください。
sdr_fec.py
# load LIBFEC ([1]) ------------------------------------------------------------
dir = os.path.dirname(__file__)
import platform
environment = platform.platform()
if 'Windows' in environment:
libfec = cdll.LoadLibrary(dir + '/../lib/win32/libfec.so')
elif 'Linux' in environment:
libfec = cdll.LoadLibrary(dir + '/../lib/linux/libfec.so')
elif 'macOS' in environment and 'x86_64' in environment:
libfec = cdll.LoadLibrary(dir + '/../lib/darwin_x86/libfec.dylib')
elif 'macOS' in environment and 'arm' in environment:
libfec = cdll.LoadLibrary(dir + '/../lib/darwin_arm/libfec.dylib')
sdr_ldpc.py
# load library of LDPC-codes ([1],[2]) -----------------------------------------
dir = os.path.dirname(__file__)
import platform
environment = platform.platform()
if 'Windows' in environment:
libldpc = cdll.LoadLibrary(dir + '/../lib/win32/libldpc.so')
elif 'Linux' in environment:
libldpc = cdll.LoadLibrary(dir + '/../lib/linux/libldpc.so')
elif 'macOS' in environment and 'x86_64' in environment:
libldpc = cdll.LoadLibrary(dir + '/../lib/darwin_x86/libldpc.dylib')
elif 'macOS' in environment and 'arm' in environment:
libldpc = cdll.LoadLibrary(dir + '/../lib/darwin_arm/libldpc.dylib')
sdr_rtk.py
# load RTKLIB ([1]) ------------------------------------------------------------
dir = os.path.dirname(__file__)
import platform
environment = platform.platform()
if 'Windows' in environment:
librtk = cdll.LoadLibrary(dir + '/../lib/win32/librtk.so')
elif 'Linux' in environment:
librtk = cdll.LoadLibrary(dir + '/../lib/linux/librtk.so')
elif 'macOS' in environment and 'x86_64' in environment:
librtk = cdll.LoadLibrary(dir + '/../lib/darwin_x86/librtk.dylib')
elif 'macOS' in environment and 'arm' in environment:
librtk = cdll.LoadLibrary(dir + '/../lib/darwin_arm/librtk.dylib')
サンプルデータの復号
PocketSDRのsample
フォルダを開き、.link
拡張子ファイルに書かれたURLから、ZIP形式サンプルデータを取得します。これらをunzip
などで解凍して、このフォルダに置きます。今回、使用するサンプルデータはL6_20211226_082212_12MHz_IQ.bin
です。
はじめに、このサンプルデータ中にて観測できるL6D信号(CLAS: centimeter level augmentation service)を確認します。python
フォルダにあるpocket_rtk.py
を実行します。オプションの意味はpocket_acq.pyのものと同様です。
python3 pocket_trk.py ../sample/L6_20211226_082212_12MHz_IQ.bin -prn 193-199 -f 12 -sig L6D
TIME(s) SIG PRN STATE LOCK(s) C/N0 (dB-Hz) COFF(ms) DOP(Hz) ADR(cyc) SYNC #NAV #ERR #LOL NER
0.02 L6D 193 IDLE 0.00 0.0 0.0000000 0.0 0.0 --- 0 0 0 0
0.05 L6D 194 LOCK 0.03 43.2 |||||||| 3.8254181 -104.9 -3.7 --- 0 0 0 0
0.05 L6D 195 LOCK 0.03 40.9 ||||||| 0.7774230 -250.6 -8.0 --- 0 0 0 0
0.02 L6D 196 IDLE 0.00 0.0 0.0000000 0.0 0.0 --- 0 0 0 0
0.02 L6D 197 IDLE 0.00 0.0 0.0000000 0.0 0.0 --- 0 0 0 0
0.02 L6D 198 IDLE 0.00 0.0 0.0000000 0.0 0.0 --- 0 0 0 0
0.05 L6D 199 LOCK 0.03 40.9 ||||||| 2.0844222 -153.7 -4.4 --- 0 0 0 0
みちびき2号機(PRN 194)、3号機(PRN 199)、4号機(PRN 195)のL6D信号が観測できました。積算デルタレンジ(ADR)も表示されていて、このL6D信号を測位に利用できることも期待できます。ここでは、みちびき2号機を対象に信号追尾します。
python3 pocket_trk.py ../sample/L6_20211226_082212_12MHz_IQ.bin -prn 194 -f 12 -sig L6D -p
次に、L6E信号(MADOCA: multi-GNSS advanced demonstration tool for orbit and clock analysis)を復号します。みちびき2号機L6D信号のPRN番号に10を加えたPRN 204が、このL6E信号に相当します。
python3 pocket_trk.py ../sample/L6_20211226_082212_12MHz_IQ.bin -prn 204 -f 12 -sig L6E -p
L6D信号のものと同様に表示できることを確認しましたので、この復号データをログファイルpocket.log
に保存します。
python3 pocket_trk.py ../sample/L6_20211226_082212_12MHz_IQ.bin -prn 204 -f 12 -sig L6E -log pocket.log
L6E信号解読
L6D信号やL6E信号のメッセージは、1秒間に1データパートと呼ばれるメッセージ単位が伝送されます。
ここで、L6E信号を対象にするのは、メッセージが1つのデータパート内に完結しているからです。L6D信号については、30秒に1度だけ放送されるサブタイプ1を解読できないと他のメッセージを読み出すことができず、またメッセージが複数データパートにまたがることもあるので、その解読のハードルが高いです。
このログファイルには、信号追尾状況と復号データがカンマ区切りで保存されています。このL6E信号メッセージは、先頭が$L6FRM
ではじまる行の6列目に16進テキスト形式で書かれています。これをバイナリ形式化するプログラムを作成しました。
pksdr2l6.py
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
line = sys.stdin.readline().strip()
while (line):
if line[0:6] != "$L6FRM":
line = sys.stdin.readline().strip()
continue
t_data = line.split(',')[5]
sys.stdout.buffer.write(bytes.fromhex(t_data))
sys.stdout.flush()
line = sys.stdin.readline().strip()
そして、L6メッセージからペイロードを抽出してRTCM 3(Radio Technical Commission for Maritime Services version 3)メッセージに変換するコードshowqzsl6.pyqzsl62rtcm.py
と、RTCM 3メッセージの内容を表示するコードshowrtcm.py
を用いて、このL6Eメッセージを読み出します。このshowqzsl6.py
とshowrtcm.py
は、まだ未完成ではありますが、近日中に公開します公開しました。(2022-02-03公開し、コード名をshowqzsl6.py
からqzsl62rtcm.py
に変更しました)
はじめに、このL6Eメッセージを解読します。
cat pocket.log | ./pksdr2l6.py | qzsl62rtcm.py > /dev/null
204 Hitachi-Ota:0* 2021-12-26 08:21:58 1059(24)
204 Hitachi-Ota:0* 2021-12-26 08:22:00 1062(24) 1068(17)
204 Hitachi-Ota:0* 2021-12-26 08:22:00 1059(2)
204 Hitachi-Ota:0* 2021-12-26 08:22:02 1062(24) 1068(17)
204 Hitachi-Ota:0* 2021-12-26 08:22:02 1065(19)
204 Hitachi-Ota:0* 2021-12-26 08:22:04 1062(24) 1068(17)
204 Hitachi-Ota:0* 2021-12-26 08:22:04
204 Hitachi-Ota:0* 2021-12-26 08:22:06 1062(24) 1068(17)
204 Hitachi-Ota:0* 2021-12-26 08:22:06
204 Hitachi-Ota:0* 2021-12-26 08:22:08 1062(24) 1068(17)
204 Hitachi-Ota:0* 2021-12-26 08:22:08
204 Hitachi-Ota:0* 2021-12-26 08:22:10 1062(24) 1068(17)
204 Hitachi-Ota:0* 2021-12-26 08:22:10
204 Hitachi-Ota:0* 2021-12-26 08:22:12 1062(24) 1068(17)
204 Hitachi-Ota:0* 2021-12-26 08:22:12 1057(8) 1061(8)
204 Hitachi-Ota:0* 2021-12-26 08:22:14 1062(24) 1068(17)
204 Hitachi-Ota:0* 2021-12-26 08:22:14 1057(8) 1061(8)
204 Hitachi-Ota:0* 2021-12-26 08:22:16 1062(24) 1068(17)
204 Hitachi-Ota:0* 2021-12-26 08:22:16 1057(8) 1061(8)
204 Hitachi-Ota:0* 2021-12-26 08:22:18 1062(24) 1068(17)
204 Hitachi-Ota:0* 2021-12-26 08:22:18
204 Hitachi-Ota:0* 2021-12-26 08:22:20 1062(24) 1068(17)
204 Hitachi-Ota:0* 2021-12-26 08:22:20 1063(8) 1067(8)
204 Hitachi-Ota:0* 2021-12-26 08:22:22 1062(24) 1068(17)
204 Hitachi-Ota:0* 2021-12-26 08:22:22 1063(8) 1067(8)
204 Hitachi-Ota:0* 2021-12-26 08:22:24 1062(24) 1068(17)
204 Hitachi-Ota:0* 2021-12-26 08:22:24 1063(1) 1067(1)
204 Hitachi-Ota:0* 2021-12-26 08:22:26 1062(24) 1068(17)
204 Hitachi-Ota:0* 2021-12-26 08:22:26
これは、1行に1データパートの内容を示しています。それぞれの行には、PRN番号、管制局(常陸太田または神戸)と系統番号(0または1)、アラートフラグ状態(アスタリスクはアラートオン状態です)、UTC日時、RTCMメッセージ番号と補強対象衛星数が含まれます。ひとつのデータパートに、2つのRTCMメッセージを含むこともあれば、メッセージを含まないこともありました。次に、このRTCM 3メッセージを解読します。
cat pocket.log | ./pksdr2l6.py | qzsl62rtcm.py 2> /dev/null | showrtcm.py
実行結果の一部は次の通りです。この30秒間に観測できたすべてのRTCM 3メッセージをpocket.rtcm3.txtに置きます。
RTCM 1059 G SSR code bias G01 G02 G03 G05 G06 G07 G08 G09 G10 G12 G13 G15 G16 G17 G19 G20 G21 G22 G24 G25 G26 G27 G29 G30 (nsat=24 iod=4 cont.)
RTCM 1062 G SSR hr clock G01 G02 G03 G05 G06 G07 G08 G09 G10 G12 G13 G15 G16 G17 G19 G20 G21 G24 G25 G26 G29 G30 G31 G32 (nsat=24 iod=4)
RTCM 1068 R SSR hr clock R01 R02 R03 R04 R05 R07 R08 R12 R13 R14 R15 R17 R18 R19 R20 R21 R22 (nsat=17 iod=5)
RTCM 1059 G SSR code bias G31 G32 (nsat=2 iod=4)
RTCM 1062 G SSR hr clock G01 G02 G03 G05 G06 G07 G08 G09 G10 G12 G13 G15 G16 G17 G19 G20 G21 G24 G25 G26 G29 G30 G31 G32 (nsat=24 iod=4)
RTCM 1068 R SSR hr clock R01 R02 R03 R04 R05 R07 R08 R12 R13 R14 R15 R17 R18 R19 R20 R21 R22 (nsat=17 iod=5)
RTCM 1065 R SSR code bias R01 R02 R03 R04 R05 R07 R08 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 (nsat=19 iod=5)
無事、RTCM形式の補強情報が復号できました!
MADOCAでは、G
(GPS)、R
(Glonass)、J
(みちびき、ただし初号機のみ)の3衛星システムが補強対象です。SSR(space state representation)空間情報表現とは、誤差を要因別にわけて、それぞれの補正情報を伝送する方法です。MADOCAでは、衛星内部時計と衛星軌道を補強します。そのメッセージのひとつである、High rate clock(高速時刻補正)が頻繁に伝送されていることがわかります。L6E信号のMADOCAでは、メッセージをデータパート内に納めるため、異なるデータパートに同じメッセージ番号で続き(continue)を伝送することがあります。例えば、この1行目内容の続きが4行目内容です。nsat
は補強対象衛星数を、iod
(issue of data)とはSSRメッセージ発行番号を、それぞれ表します。
このRTCMメッセージに、「時刻補正情報」を付加すれば、MADOCAによる補強ができる見込みです。
昨年11月頃から、L6E信号でのみちびきの補強情報が来なくなりました。みちびき初号機の状態がよくないので、補強情報も来なくなったのだと推測しています。これはAllystarの受信モジュールを用いた受信でも確認しています。はやくみちびき初号機が元気になることを望んでいます。
PocketSDRの誤り訂正後メッセージ解読画面の行頭に、16進数でのL6信号ヘッダ1a
cf
fc
1d
がありますので、正しく復号されていることは明らかですが、ここではそのメッセージを読み出してみました。
少し前まで、L6信号メッセージを抽出できる受信機は、例えばJavad DELTA-G3TにみちびきオプションとL6オプションをつけた高性能受信機しかなく、大変高価でした。これはとてもすごいことです。
おわりに
PocketSDRのコードがアップグレードされ、L6信号をも復号できるようになりました。サンプルデータから、RTCMメッセージと補強対象衛星まで確認できました。とても楽しかったです。
PocketSDRのコードを読みましたが、準同期検波から同期を引き込む方法として、一般的に用いられるコスタスループを使用していないようです。PocketSDRは、動作とコードの両方が楽しめ、1粒で2度美味しいグリコのようです。
関連記事
- Pocket SDRすごい(リアルタイム測位機能) 13th October 2024
- Pocket SDRを用いたGalileo E6B信号の受信 27th January 2023
- リフローでやらかしました 19th January 2023
- Pocket SDRハードウェア製作(第3報) 30th September 2022
- Pocket SDRハードウェア製作(第2報) 14th September 2022
- Pocket SDRハードウェア製作(第1報) 4th September 2022
- PocketSDRすごい(パーツ購入編) 9th April 2022
- PocketSDR APにてbladeRFを使いたい(その2) 16th March 2022
- PocketSDR APにてbladeRFを使いたい 5th March 2022
- PocketSDRすごい(スナップショット測位編) 23rd February 2022
- PocketSDRすごい(FFTWによる高速化) 19th February 2022
- PocketSDRすごい(pocket_trk編) 28th December 2021
- PocketSDRすごい(pocket_acq編) 4th December 2021