MADOCALIB version 1.4

category: gnss

Introduction

MADOCALIB (MADOCA-PPP test library) version 1.4 has been released. It is a software that handles MADOCA-PPP (muti-GNSS advanced orbit and clock augmentation) messages, one of the high-precision positioning messages from the Quasi-Zenith Satellite, Michibiki. Version 1.2 was reported in article,High-Precision GPS Positioning with MADOCALIB. This new version has been improved to handle phase information and multiple wide-area ionospheric information.

In addition, this new version 1.4 includes sample files for precise point positioning (PPP), PPP-AR, which adds ambiguity resolution (AR) to PPP in relation to the code and phase, and a batch file that handles the wide-area ionospheric information that will be broadcast from the upcoming Michibiki 6 and 7 satellites.

This MADOCALIB is an application for Windows. Here, I will build MADOCALIB version 1.4 on a Mac and run this sample. I think this method can also be applied to Linux PC and Raspberry Pi.

Building rnx2rtkp

First, build the post-processing program rnx2rtkp. Download MADOCALIB using git or similar (git clone https://github.com/QZSS-Strategy-Office/madocalib) and create the following file by modifying the existing makefile. For lines that start with a space, all of those spaces are tab characters. The path has been modified and the Windows-related defines have been deleted.

app/consapp/rnx2rtkp/gcc_mingw/makefile.linux

# makefile for MADOCALIB rnx2rtkp.exe
# Rev.2024/07/01

BINDIR  = ../../../../bin
SRC     = ../../../../src

CC      = gcc
OPTS    = -DTRACE -DENAGLO -DENAQZS -DENAGAL -DENACMP -DENAIRN -DNFREQ=5 -DNEXOBS=5
CFLAGS  = -Wall -O3 -ansi -pedantic -Wno-unused-but-set-variable -I$(SRC) $(OPTS) -g
LDLIBS  =
OBJS    = rnx2rtkp.o rtkcmn.o rinex.o rtkpos.o postpos.o solution.o lambda.o geoid.o sbas.o preceph.o pntpos.o ephemeris.o options.o ppp.o ppp_ar.o ppp_iono.o rtcm.o rtcm2.o rtcm3.o rtcm3e.o ionex.o tides.o mdccssr.o mdciono.o

rnx2rtkp : $(OBJS)
	$(CC) -o rnx2rtkp $(OBJS) $(LDLIBS)
rnx2rtkp.o : ../rnx2rtkp.c
	$(CC) -c $(CFLAGS) ../rnx2rtkp.c
rtkcmn.o   : $(SRC)/rtkcmn.c
	$(CC) -c $(CFLAGS) $(SRC)/rtkcmn.c
rinex.o    : $(SRC)/rinex.c
	$(CC) -c $(CFLAGS) $(SRC)/rinex.c
rtkpos.o   : $(SRC)/rtkpos.c
	$(CC) -c $(CFLAGS) $(SRC)/rtkpos.c
postpos.o  : $(SRC)/postpos.c
	$(CC) -c $(CFLAGS) $(SRC)/postpos.c
solution.o : $(SRC)/solution.c
	$(CC) -c $(CFLAGS) $(SRC)/solution.c
lambda.o   : $(SRC)/lambda.c
	$(CC) -c $(CFLAGS) $(SRC)/lambda.c
geoid.o    : $(SRC)/geoid.c
	$(CC) -c $(CFLAGS) $(SRC)/geoid.c
sbas.o     : $(SRC)/sbas.c
	$(CC) -c $(CFLAGS) $(SRC)/sbas.c
preceph.o  : $(SRC)/preceph.c
	$(CC) -c $(CFLAGS) $(SRC)/preceph.c
pntpos.o   : $(SRC)/pntpos.c
	$(CC) -c $(CFLAGS) $(SRC)/pntpos.c
ephemeris.o: $(SRC)/ephemeris.c
	$(CC) -c $(CFLAGS) $(SRC)/ephemeris.c
options.o  : $(SRC)/options.c
	$(CC) -c $(CFLAGS) $(SRC)/options.c
ppp.o      : $(SRC)/ppp.c
	$(CC) -c $(CFLAGS) $(SRC)/ppp.c
ppp_ar.o   : $(SRC)/ppp_ar.c
	$(CC) -c $(CFLAGS) $(SRC)/ppp_ar.c
ppp_iono.o : $(SRC)/ppp_iono.c
	$(CC) -c $(CFLAGS) $(SRC)/ppp_iono.c
rtcm.o     : $(SRC)/rtcm.c
	$(CC) -c $(CFLAGS) $(SRC)/rtcm.c
rtcm2.o    : $(SRC)/rtcm2.c
	$(CC) -c $(CFLAGS) $(SRC)/rtcm2.c
rtcm3.o    : $(SRC)/rtcm3.c
	$(CC) -c $(CFLAGS) $(SRC)/rtcm3.c
rtcm3e.o   : $(SRC)/rtcm3e.c
	$(CC) -c $(CFLAGS) $(SRC)/rtcm3e.c
ionex.o    : $(SRC)/ionex.c
	$(CC) -c $(CFLAGS) $(SRC)/ionex.c
tides.o    : $(SRC)/tides.c
	$(CC) -c $(CFLAGS) $(SRC)/tides.c
mdccssr.o  : $(SRC)/mdccssr.c
	$(CC) -c $(CFLAGS) $(SRC)/mdccssr.c
mdciono.o  : $(SRC)/mdciono.c
	$(CC) -c $(CFLAGS) $(SRC)/mdciono.c
rnx2rtkp.o : $(SRC)/rtklib.h
rtkcmn.o   : $(SRC)/rtklib.h
rinex.o    : $(SRC)/rtklib.h
rtkpos.o   : $(SRC)/rtklib.h
postpos.o  : $(SRC)/rtklib.h
solution.o : $(SRC)/rtklib.h
lambda.o   : $(SRC)/rtklib.h
geoid.o    : $(SRC)/rtklib.h
sbas.o     : $(SRC)/rtklib.h
preceph.o  : $(SRC)/rtklib.h
pntpos.o   : $(SRC)/rtklib.h
ephemeris.o: $(SRC)/rtklib.h
options.o  : $(SRC)/rtklib.h
ppp.o      : $(SRC)/rtklib.h
ppp_ar.o   : $(SRC)/rtklib.h
ppp_iono.o : $(SRC)/rtklib.h
rtcm.o     : $(SRC)/rtklib.h
rtcm2.o    : $(SRC)/rtklib.h
rtcm3.o    : $(SRC)/rtklib.h
rtcm3e.o   : $(SRC)/rtklib.h
ionex.o    : $(SRC)/rtklib.h
tides.o    : $(SRC)/rtklib.h
mdccssr.o  : $(SRC)/rtklib.h
mdciono.o  : $(SRC)/rtklib.h

install :
	cp rnx2rtkp $(BINDIR)

clean :
	rm *.o
	rm rnx2rtkp

To actually build, pass this file as an argument to the make command. This will generate rnx2rtkp in the bin directory.

make -f makefile.linux
make -f makefile.linux install

Building cssr2ssr

Next, build the program cssr2ssr that converts the MADOCA-PPP message format CSSR (compact state space representation) to the widely used RTCM (Radio Technical Commission for Maritime Services) SSR (state space representation) format. As with rnx2rtkp, copy the existing makefile and modify it as follows:

app/consapp/cssr2ssr/gcc_mingw/makefile.linux

# makefile for MADOCALIB cssr2ssr.exe
# Rev.2024/09/03

BINDIR  = ../../../../bin
SRC     = ../../../../src

CC      = gcc
OPTS    = -DTRACE -DENAGLO -DENAQZS -DENAGAL -DENACMP -DENAIRN -DNFREQ=5 -DNEXOBS=5
CFLAGS  = -Wall -O3 -ansi -pedantic -Wno-unused-but-set-variable -I$(SRC) $(OPTS) -g
LDLIBS  =
OBJS    = cssr2ssr.o cssr.o rtkcmn.o rtcm.o rtcm2.o rtcm3.o rtcm3e.o

cssr2ssr.exe : $(OBJS)
	$(CC) -o cssr2ssr $(OBJS) $(LDLIBS)
cssr2ssr.o : ../cssr2ssr.c
	$(CC) -c $(CFLAGS) ../cssr2ssr.c
cssr.o     : ../cssr.c
	$(CC) -c $(CFLAGS) ../cssr.c
rtkcmn.o   : $(SRC)/rtkcmn.c
	$(CC) -c $(CFLAGS) $(SRC)/rtkcmn.c
rtcm.o     : $(SRC)/rtcm.c
	$(CC) -c $(CFLAGS) $(SRC)/rtcm.c
rtcm2.o    : $(SRC)/rtcm2.c
	$(CC) -c $(CFLAGS) $(SRC)/rtcm2.c
rtcm3.o    : $(SRC)/rtcm3.c
	$(CC) -c $(CFLAGS) $(SRC)/rtcm3.c
rtcm3e.o   : $(SRC)/rtcm3e.c
	$(CC) -c $(CFLAGS) $(SRC)/rtcm3e.c
cssr2ssr.o : $(SRC)/rtklib.h
cssr.o     : $(SRC)/rtklib.h
rtkcmn.o   : $(SRC)/rtklib.h
rtcm.o     : $(SRC)/rtklib.h
rtcm2.o    : $(SRC)/rtklib.h
rtcm3.o    : $(SRC)/rtklib.h
rtcm3e.o   : $(SRC)/rtklib.h

install :
	cp cssr2ssr $(BINDIR)

clean :
	rm cssr2ssr
	rm *.o

Just like building rnx2rtkp, pass this file as an argument to the make command. This will generate cssr2ssr in the bin directory.

make -f makefile.linux
make -f makefile.linux install

Running the sample

The rnx2rtkp created in this way can be executed using command line arguments, just like in High-precision GPS positioning with MADOCALIB, but here we will convert the batch file in the sample_data directory into a bash shell script and execute it.

Move to the sample_data directory and create exec_ppp.sh, exec_pppar.sh and exec_pppar_ion.sh corresponding to exec_ppp.bat, exec_pppar.bat and exec_pppar_ion.bat as follows. For shell scripts that do not specify the antenna phase center file igs20.atx, add the file specification with the -ant option.

sample_data/exec_ppp.sh

#!/bin/bash
# This is a sample BAT file that executes ppp from 00min00sec to 59min30sec every hour

BIN=../bin/rnx2rtkp
CONF=../app/consapp/rnx2rtkp/gcc_mingw/sample.conf
OBS=./TSK200JPN_S_20241620000_01D_30S_MO.rnx
NAV=./TSK200JPN_S_20241620000_01D_MN.rnx
L6E=./2024162all.204.l6
ANT=./igs20.atx
OUT=./result

mkdir -p $OUT

for H in {00..23}; do
    $BIN -k $CONF -ts 2024/06/10 $H:00:00 -te 2024/06/10 $H:59:30 $OBS $NAV $L6E -o $OUT/ppp_20240610$H.pos -ant $ANT -x 2
done

sample_data/exec_pppar.sh

#!/bin/bash
# This is a sample BAT file that executes ppp-ar from 00min00sec to 59min30sec every hour

BIN=../bin/rnx2rtkp
CONF=../app/consapp/rnx2rtkp/gcc_mingw/sample_pppar.conf
OBS=./TSK200JPN_S_20241620000_01D_30S_MO.rnx
NAV=./TSK200JPN_S_20241620000_01D_MN.rnx
L6E=./2024162all.204.l6
ANT=./igs20.atx
OUT=./result

mkdir -p $OUT

for H in {00..23}; do
    $BIN -k $CONF -ts 2024/06/10 $H:00:00 -te 2024/06/10 $H:59:30 -ant $ANT $OBS $NAV $L6E -o $OUT/pppar_20240610$H.pos -x 2
done

sample_data/exec_pppar_ion.sh

#!/bin/bash
# This is a sample BAT file that executes ppp-ar with ionospheric correction
# from 00min00sec to 59min30sec every hour

BIN=../bin/rnx2rtkp
CONF=../app/consapp/rnx2rtkp/gcc_mingw/sample_pppar_iono.conf
OBS=./TSK200JPN_S_20241620000_01D_30S_MO.rnx
NAV=./TSK200JPN_S_20241620000_01D_MN.rnx
L6E=./2024162all.204.l6
ANT=./igs20.atx
OUT=./result

# for Japan and Eastern Australia Region
L6D2=./2024162all.201.l6

# for Southeast Asia and Western Australia Region
L6D1=./2024162all.200.l6

mkdir -p $OUT

for H in {00..23}; do
    $BIN -k $CONF -ts 2024/06/10 $H:00:00 -te 2024/06/10 $H:59:30 $OBS $NAV $L6E -mdciono $L6D1 -mdciono $L6D2 -ant $ANT -o $OUT/pppar_ion_20240610$H.pos -x 2
done

After creating these files, grant them permission to run by running chmod 755 exec_ppp.sh exec_pppar.sh exec_pppar_ion.sh. For example, executing ./exec_ppp.sh, we will obtain the results in the result directory.

Let us try another application cssr2ssr. We try to convert the CSSR file 2024162all.204.l6 in this sample to the RTCM SSR file 2024162all.rtcm.

../bin/cssr2ssr 2024162all.204.l6 -o 2024162all.rtcm
cssr2ssr  (0487):
reading... 2024162all.204.l6
finished

First, we will try to perform single positioning using the satellite orbit file TSK200JPN_S_20241620000_01D_MN.rnx and the observation file TSK200JPN_S_20241620000_01D_30S_MO.rnx found here.

../bin/rnx2rtkp -p 0 TSK200JPN_S_20241620000_01D_*
% program   : rnx2rtkp ver.2.4.3 b34
% inp file  : TSK200JPN_S_20241620000_01D_30S_MO.rnx
% inp file  : TSK200JPN_S_20241620000_01D_MN.rnx
% satantfile:
% rcvantfile:
% obs start : 2024/06/10 00:00:00.0 GPST (week2318  86400.0s)
% obs end   : 2024/06/10 23:59:30.0 GPST (week2318 172770.0s)
%
% (lat/lon/height=WGS84/ellipsoidal,Q=1:fix,2:float,3:sbas,4:dgps,5:single,6:ppp,ns=# of satellites)
%  GPST          latitude(deg) longitude(deg)  height(m)   Q  ns   sdn(m)   sde(m)   sdu(m)  sdne(m)  sdeu(m)  sdun(m) age(s)  ratio
2318  86400.000   36.105582210  140.087105580    87.6496   5  12   4.4032   3.7796  10.3945   0.4904  -2.0305  -4.8329   0.00    0.0
2318  86430.000   36.105576871  140.087101426    89.7484   5  12   4.4158   3.7734  10.4132   0.4356  -1.9986  -4.8626   0.00    0.0
...

Single positioning was completed. Next, we will try to perform PPP positioning using the RTCM SSR file 2024162all.rtcm created here.

../bin/rnx2rtkp -k ../app/consapp/rnx2rtkp/gcc_mingw/sample.conf -ant igs20.atx -p 6 -x 2 TSK200JPN_S_20241620000_01D_* 2024162all.rtcm
processing : 2024/06/10 00:00:00 Q=0
2 no ssr orbit correction: 2024/06/10 00:00:00 sat= 2
2 no ssr orbit correction: 2024/06/10 00:00:00 sat= 3
2 no ssr orbit correction: 2024/06/10 00:00:00 sat= 7
...
2 no ssr orbit correction: 2024/06/10 00:00:00 sat=102
2 00:00:00.00: point pos error (lack of valid sats ns=5)
processing : 2024/06/10 00:00:30 Q=0
2 no ssr orbit correction: 2024/06/10 00:00:30 sat= 2
...

I created an RTCM SSR file and ran PPP positioning, but no solution was found. It seems that the RTCM SSR file was not loaded correctly. I will look into this further.

Also, in the process of loading this 2024162all.rtcm with rtcmread.py in the QZS L6 Tool, I found a bug in rtcmread.py. I will fix this as well.

Conclusion

I built MADOCALIB version 1.4 on a Mac and ran rnx2rtkp. I also ran a sample. I confirmed that it is possible to run not only PPP, but also PPP-AR and PPP using wide-area ionospheric information. I will look into how to use cssr2ssr.