PocketSDRすごい(pocket_trk編)

categories: gnss
tags: qzss sdr

はじめに

東京海洋大学の高須知二先生が、新しいPocketSDRのコードとサンプルデータを提供されました。これは、測位衛星の信号を追捕しながら、その航法データを復号するものです。

このコードはPythonで書かれていますが、今回、利用するpocket_trk.pyはC言語で書かれたRTKLIBとLIBFECの共有ライブラリを呼び出しています。PocketSDRには、これらの64ビットWindows用とLinux用の共有ライブラリも同梱されています。

私の利用しているMacbook Air(Intel CPU)でも、その航法データ復号コードを実行してみたいと思い、自らで必要な共有ライブラリをコンパイルしてみました。

ここでは、RTKLIBやLIBFECのmacOS上での共有ライブラリ作成手順と、pocket_trk.py実行例を示します。もうひとつのサンプルコードpocket_acq.py実行できていること、パッケージマネージャHomebrewがインストールされて、C言語での開発環境が整っていることを前提にしています。

Mac上でのRTKLIBとLIBFECの共有ライブラリ作成

RTKLIBは、高須知二先生が公開されている、測位衛星利用に関するC言語ライブラリとアプリケーションです。一方、LIBFECは、昔からのアマチュア無線家ならばご存知かもしれないKA9Q、Phil Karn氏が公開されている、前方誤り訂正(FEC: forward error correction)のC言語ライブラリ(のクローン)です。

以下は、ターミナルで操作します。私は、より使いやすいiTerm2をHomebrewにてインストールし、それを利用しています(brew install iterm2)。

はじめに、RTKLIBをGitHubからチェックアウトして、共有ライブラリ作成用のディレクトリを作成します。

git clone https://github.com/tomojitakasu/RTKLIB -b rtklib_2.4.3 rtklib
cd rtklib/app/consapp/
mkdir -p dylib/gcc/

現在のmacOSでは、シリアルポートのボーレートが230,400 bit/sまでですので、src/stream.cの348行目や361行目付近にある、460800や921600の文字をコメントアウトします。

そして、例えばstr2str/gccにあるmakefiledylib/gcc/にコピーして、共有ライブラリが作成されるよう、先頭部分を次のように書き換えました。

# makefile for str2str

BINDIR = /usr/local/bin
SRC    = ../../../../src

# for beagleboard
#CTARGET= -mfpu=neon -mfloat-abi=softfp -ffast-math
CTARGET=

OPTION = -DENAGLO -DENAGAL -DENAQZS -DENACMP -DENAIRN -DTRACE -DNFREQ=3 -DNEXOBS=3
#OPTION = -DENAGLO -DENAGAL -DENAQZS -DENACMP -DENAIRN -DTRACE -DNFREQ=5 -DNEXOBS=3 -DSVR_REUSEADDR
CFLAGS = -Wall -O3 -ansi -pedantic -fno-common -I$(SRC) $(OPTION) $(CTARGET) -g
LDLIBS  = -lm -lpthread #-lrt

all: librtk.dylib
librtk.dylib: stream.o rtkcmn.o solution.o sbas.o geoid.o
librtk.dylib: rcvraw.o novatel.o ublox.o ss2.o crescent.o skytraq.o javad.o
librtk.dylib: nvs.o binex.o rt17.o rtcm.o rtcm2.o rtcm3.o rtcm3e.o preceph.o
librtk.dylib: streamsvr.o septentrio.o
librtk.dylib  :
    $(CC) -dynamiclib -o librtk.dylib $(CFLAGS) \
        stream.o rtkcmn.o solution.o sbas.o geoid.o \
        rcvraw.o novatel.o ublox.o ss2.o crescent.o skytraq.o javad.o \
        nvs.o binex.o rt17.o rtcm.o rtcm2.o rtcm3.o rtcm3e.o preceph.o \
        streamsvr.o septentrio.o

stream.o   : $(SRC)/stream.c
    $(CC) -c $(CFLAGS) $(SRC)/stream.c

macOSにて共有ライブラリを作成するためには、コンパイル時に-fno-commonオプションを、リンク時に-dynamiclibオプションを指定すればよいようです(PowerPC CPUでの方法がIntel CPUでも利用できました)。

ここでmakeを実行すると、このディレクトリにlibrtk.dylibが作成されます。これをPocketSDRのlibディレクトリにコピーします。

次に、LIBFECの共有ライブラリを作成します。LIBFECをGitHubからチェックアウトし、configureスクリプトを実行して、makeコマンドを実行します。ターゲットCPUの自動判定に失敗するようですので、configureスクリプトにはターゲットCPUを指定するオプションが必要です。

git clone https://github.com/quiet/libfec
cd libfec
./configure --target=x86
make

最後に、ローダーコマンドの実行に失敗した旨のメッセージ(ld: unknown option: -soname=libfec.so)が現れます。そこで、手作業で共有ライブラリを作成します。

gcc -dynamiclib -o libfec.dylib cpu_mode_unknown.o fec.o viterbi27.o viterbi27_port.o viterbi29.o viterbi29_port.o viterbi39.o viterbi39_port.o viterbi615.o viterbi615_port.o encode_rs_char.o encode_rs_int.o encode_rs_8.o decode_rs_char.o decode_rs_int.o decode_rs_8.o init_rs_char.o init_rs_int.o ccsds_tab.o encode_rs_ccsds.o decode_rs_ccsds.o ccsds_tal.o dotprod.o dotprod_port.o peakval.o peakval_port.o sumsq.o sumsq_port.o -lc

ここで、libfec.dylibが作成されますので、これもPocketSDRのlibディレクトリにコピーします。

最後に、PocketSDRのpythonディレクトリにある、sdr_rtk.pysdr_fec.pyの先頭部分を修正して、ここで作成した共有ライブラリをpocket_trk.pyにて読み込めるようにします。

sdr_rtk.py

# load RTKLIB ([1]) ------------------------------------------------------------
dir = os.path.dirname(__file__)
#try:
#    librtk = cdll.LoadLibrary(dir + '/../lib/win32/librtk.so')
#except:
#    librtk = cdll.LoadLibrary(dir + '/../lib/linux/librtk.so')
librtk = cdll.LoadLibrary(dir + '/../lib/librtk.dylib')

sdr_fec.py

# load LIBFEC ([1]) ------------------------------------------------------------
dir = os.path.dirname(__file__)
#try:
#    libfec = cdll.LoadLibrary(dir + '/../lib/win32/libfec.so')
#except:
#    libfec = cdll.LoadLibrary(dir + '/../lib/linux/libfec.so')
libfec = cdll.LoadLibrary(dir + '/../lib/libfec.dylib')

pocket_trk.pyの実行

PocketSDRのsampleディレクトリにある、link拡張子のファイルを参照して、サンプルデータをダウンロードし、unzipコマンドで展開しておきます。観測時間が30秒程度は必要だからです。

ここまでできたら、PocketSDRのpythonディレクトリにあるpocket_trk.pyを試すことができます。高須先生のホームページに多数の実行例がありますが、私が特に楽しいと思ったのは、DLL(delay locked loop)にて衛星信号を追尾しながら、信号を復号するものです。一例として、PRN16のGPS L1 C/A信号を追尾しながら、その航法データを復号します。

python3 pocket_trk.py L1_20211226_082212_12MHz_I.bin -prn 16 -f 12 -fi 3 -p

その動画をキャプチャーしてみました。信号追尾、信号空間ダイヤグラム、逆拡散後の波形、そして、しばらく待つと航法データの復号結果が表示されます。

これはとても楽しいです。色々な衛星信号を見てみたいです。PocketSDRに添付されているPythonコードは、L1 C/A信号だけでなく、みちびきのL1S信号や新信号のL1 C/B信号をはじめとする多数の多数の信号を追尾でき(sdr_code.py)、LNAV(legacy navigation message、航空機の航法LNAVとは別ものです)、CNAV(civil navigation message)、I/NAV(integrity navigation message)、F/NAV(free navigation message)、SBAS(satellite-based augmentation system)の航法メッセージを復号できます(sdr_nav.py)。

pocket_trk.pyの使い方や関数仕様は、そのソースコード中に丁寧に記述されています。分厚いマニュアルよりも、ソースコード中のコメントの方が、検索しながら読むことができて、ずっと嬉しいです。

もし私が汎用的なライブラリを作ることがあるならば、その共有ライブラリとPythonラッパーも提供しようと思います。

まだ、M1 CPUのMacでは試していません。LIBFECは、特定CPUの利用を想定しているようですので、その共有ライブラリ作成は困難かもしれません。

Apple Silicon CPUでのpocket_trk

(2022-01-07追記)

Apple M1 CPUのMacでも試しました。RTKLIBの共有ライブラリは、上述の手順により作成できました。また、LIBFECについては、configureスクリプト実行時のCPUアーキテクチャを指定することなく、makeコマンド実行だけで、簡単に共有ライブラリが作成できました。

前述の実行では、Macbook Air 13-inch Early 2015, Intel Core i7-5650U 2.2 GHz, 8 GB 1600 MHz DDR 3, macOS Big Sur 11.6.2を使いました。

一方、この実行では、Mac mini M1 2020, Apple M1 3.2 GHz, 16 GB LPDDR 4 unified memory, macOS Monterey 12.0.1を使いました。

PocketSDRすごいです。私もPocketSDRハードウェアを作成すべく、MAX2771とFX2LPの獲得競争に参加しようと思います。これからリフロー炉を準備して、使い方を学びます。

macOS用共有ライブラリダウンロード

私の作成した共有ライブラリは以下の通りです。ご自由にご利用ください。自己責任でお願いします。Intel CPU向けと、M1 CPU向けとがあります。


この記事には一連の関連記事があります。