Awesome PocketSDR (pocket_trk)

category: gnss
tags: pocketsdr qzss sdr

Introduction

Professor Tomoji Takasu of Tokyo University of Marine Science and Technology provided the new code and sample data of the Pocket SDR. This is to decode the navigation data while capturing the signal of the positioning satellite.

This code is written in Python and one of the code pocket_trk.py calls the shared libraries of RTKLIB and LIBFEC written both in C language. PocketSDR also ships with these 64-bit Windows and Linux shared libraries.

I wanted to execute the navigation data decryption code of PocketSDR on my Macbook Air (Intel CPU), therefore I compiled the shared library that pocket_trk.py requires.

Here, the procedure for creating a shared library for RTKLIB and LIBFEC on macOS and an execution example of pocket_trk.py are shown. It is assumed that another sample code pocket_acq.py can be executed, the package manager Homebrew is installed, and the development environment in C language is ready.

Creating a shared library of RTKLIB and LIBFEC on Mac

RTKLIB is a C language library and application related to the use of positioning satellites published by Professor Takasu. On the other hand, LIBFEC is (a clone of) the C language library of forward error correction (FEC) published by Phil Karn, KA9Q, who may be familiar to amateur radio operators from long ago.

The following are operated in the terminal. I have installed iTerm2, which is easier to use, with Homebrew(brew install iterm2)。

First, I checked out RTKLIB source code from GitHub and created a directory for making a shared library.

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

On current macOS, the serial port baud rate is up to 230,400 bit/s, therefore we need commenting out the characters 460800 and 921600 near lines 348 and 361 of the source code src/stream.c.

Then, I copied the makefile in, say, str2str/gcc to dylib/gcc/ and rewrote the beginning part as follows so that a shared library is created.

# 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

To create a shared library on macOS, specify the -fno-common option at compile time and the -dynamiclib option at link time.

Now running make will create librtk.dylib in this directory. I copied this to the PocketSDR lib directory.

Next, create a shared library for LIBFEC. I checked out LIBFEC from GitHub, ran the configure script, and ran the make command. It seems that the automatic determination of the target CPU fails, so the configure script needs an option to specify the target CPU.

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

Finally, a message (ld: unknown option: -soname = libfec.so) appeared while executed the loader. Therefore, I created a shared library manually.

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

At this point, libfec.dylib will be created, so I copied it to the PocketSDR lib directory as well.

Finally, I modified the beginning of sdr_rtk.py and sdr_fec.py in the PocketSDR python directory so that pocket_trk.py can load the shared library.

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')

Execution of pocket_trk.py

Refer to the file with the link extension in the sample directory of PocketSDR, download the sample data, and extract it with the unzip command. This is because the observation time needs to be about 30 seconds.

At this point, we can try pocket_trk.py in the PocketSDR’s python directory. There are many execution examples on Professor Takasu’s homepage, but what I found particularly fun was to track the satellite signal with a DLL (delay locked loop) and decode the signal. As an example, the navigation data is decoded while tracking the GPS L1 C/A signal of PRN 16.

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

The signal tracking, signal space diagram, waveform after despreading, and after a while, the decoding result of the navigation data will be displayed.

This is a lot of fun. I would like to see various satellite signals. The Python code shipped with PocketSDR can track not only L1 C/A signals, but also many other signals such as QZS’s L1S signal and new L1 C/B signal (sdr_code.py). We also decode the navigation messages such as LNAV (legacy navigation message), CNAV (civil navigation message), I/NAV (integrity navigation message), F/NAV (free navigation message), and SBAS (satellite-based augmentation system) (sdr_nav.py).

The usage and function specifications of pocket_trk.py are carefully described in the source code. I’m much more happy to be able to read the comments in the source code while searching, rather than tackle a thick manual.

If I make a generic library, I’ll also provide the shared library and the Python wrapper.

I haven’t tried it on a Mac with an M1 CPU yet. LIBFEC seems to assume the use with specific CPUs, so it may be difficult to create its shared library for Apple M1 CPU.

pocket_trk with Apple M1 CPU

(added on 2022-01-07)

I also tried it on a Mac with an Apple M1 CPU. I could create the RTKLIB shared library by the steps above. For LIBFEC, a shared library could be easily created executing the configure script without specifying the CPU architecture and simply executing the make command.

In the previous execution, I used 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.

On the other hand in this execution, I used Mac mini M1 2020, Apple M1 3.2 GHz, 16 GB LPDDR 4 unified memory, macOS Monterey 12.0.1.

PocketSDR is awesome. I would like to obtain MAX2771 and FX2LP to create PocketSDR hardware. I will prepare a reflow oven and learn how to use it.

Download shared libraries for macOS

The shared library I created is as follows. Please feel free to use it and at your own risk. There are one for Intel CPU and one for M1 CPU.


Related article(s):