goGPS-Project/goGPS_Java

UnhealthyEph and UnhealthySat, breaking change!

Closed this issue · 7 comments

I've started merging a lot of my changes so please bear with me.

A problem I had was that when a satellite is marked as unhealthy, its ephemeris was returned as null, the same if the ephemeris wasn't simply available.
To mark a satellite as unhealthy, I've created two singletons: one for the ephemeris and one for the satellite, so instead of returning null, I return that singleton. See these changes:

0213dd2

2c142cb

That certainly requires some changes in the rest of the code, so please check and see what you think.

Example usage in satelectSatellitesStandalone

      pos[i] = goGPS.getNavigation()
          .getGpsSatPosition( roverObs, id, 'G', this.getReceiverClockError() );
      
      if(  pos[i] == SatellitePosition.UnhealthySat ) {
        pos[i] = null;
        continue;
      }
      
      if( pos[i] == null  || Double.isNaN(pos[i].getX() )) {
//        if(debug) System.out.println("Not useful sat "+roverObs.getSatID(i));
        if( i == 0 || satAvail.size()> 0 )
          continue;
        else {
          status = Status.EphNotFound;
          return;
        }
      }

Here I know why the returned pos was null, because a satellite was marked unhealthy, vs Ephmeris not found. We could similarly create a singleton to mark EphNotFound, I'm just trying to move away from simply returning null.
Throwing an exception could be another option but I'm not a big fan

Hello, I'm a navigation student and I'm trying to use the Java version of goGPS to process my GPS readings.
I'm trying to get my readings exported to KML. I've downloaded Rinex observation (ftp://data-out.unavco.org/pub/rinex/obs/2017/) and navigation files (ftp://igs.bkg.bund.de/EUREF/BRDC/2017/), but both parsers seem to fail. They crash with NullPointerExceptions at some point (mostly because of calling methods on objects that are null at that point of execution for some reason). Guarding these assignments with ternary operators didn't help, as it means that the parsers just fail due to these objects being null. Could this be related to this issue or does it seem like another issue entirely?

Hi @MartaBanach

sorry about that, it's likely to be because of this change, and thank you for spotting it.
Can you post here the stack trace, and attach the needed files, and a code snippet to run if you can?
Thanks

package com.marta;

import org.gogpsproject.GoGPS;
import org.gogpsproject.NavigationProducer;
import org.gogpsproject.Observations;
import org.gogpsproject.ObservationsProducer;
import org.gogpsproject.parser.rinex.RinexNavigationParser;
import org.gogpsproject.parser.rinex.RinexObservationParser;
import org.gogpsproject.parser.ublox.DecodeRXMRAWX;
import org.gogpsproject.parser.ublox.UBXException;
import org.gogpsproject.parser.ublox.UBXFileReader;
import org.gogpsproject.producer.KmlProducer;

import java.io.*;

public class Main {

    public static void main(String[] args) {

        ObservationsProducer roverIn = new UBXFileReader(new File("./data/ublox.ubx"));
        ObservationsProducer masterIn = new RinexObservationParser(new File("./data/vrs.17o"));
        NavigationProducer navigationIn = new RinexNavigationParser(new File("./data/vrs.17n"));

        double goodDopThreshold = 3.0; // Threshold - próg graniczny
        int TimeSampleDelaySec = 30;
        String outPath = "./out.kml";
        // should be tuned according to the dataset;
        // use '0' to disable timestamps in the KML String outPath = "./test/out.kml";
        try {
            KmlProducer kml = new KmlProducer(outPath, goodDopThreshold, TimeSampleDelaySec);

            navigationIn.init();
            roverIn.init();
            masterIn.init();

            int dynamicModel = GoGPS.DYN_MODEL_STATIC; //may be also set to constant acceleration or static
            GoGPS goGPS = new GoGPS(navigationIn, roverIn, masterIn);
            goGPS.addPositionConsumerListener(kml);
            goGPS.setDynamicModel(dynamicModel);
            goGPS.runKalmanFilterCodePhaseDoubleDifferences();

            roverIn.release(true, 10000);
            masterIn.release(true, 10000);
            navigationIn.release(true, 10000);
            int a = 1;
        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}

I've modified a bit of the library, but the NPEs are still an issue. There might be some before this one.
The stack trace is

java.lang.NullPointerException
	at org.gogpsproject.parser.rinex.RinexNavigationParser.findEph(RinexNavigationParser.java:1142)
	at org.gogpsproject.parser.rinex.RinexNavigationParser.getGpsSatPosition(RinexNavigationParser.java:1249)
	at org.gogpsproject.ReceiverPosition.selectSatellitesStandalone(ReceiverPosition.java:1017)
	at org.gogpsproject.GoGPS.runKalmanFilterCodePhaseDoubleDifferences(GoGPS.java:609)
	at com.marta.Main.main(Main.java:40)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

and these are the files
data.zip

Hello @MartaBanach

Thank you for sending that, I've created a unit test and addressed the null pointer exception (4b98f1b).

Also, I've managed to create an output from your rover file by (1) setting the elevation cutoff to 0, (2) using the Rinex file from NASA and running goGPS in either code or code&phase standalone mode:
out.zip

Also, it's necessary to wait at the end of the procedure for all threads to finish: 9ae37f6

Not sure why the CodePhaseDoubleDifference mode is failing, maybe @ege010 can suggest an idea.

Hope that helps

Hi @MartaBanach
I've post-processed your RINEX files with goGPS MATLAB and I've noticed three issues:

  1. the u-blox data show a worse quality than usual; it might be due to the quality of the antenna you were using, and/or its position and "sky visibility" (i.e. unobstructed view towards the satellites);

  2. the base station data comes from a station in California; you need to use a base station nearby your rover receiver, e.g. at less than ~10 km of distance, to mitigate the atmospheric effects sufficiently (for typical navigation applications); the closest permanent station I've found, belonging to EPN (http://epncb.oma.be/_networkdata/stationmaps.php) is about 65 km away from your rover (http://epncb.oma.be/_networkdata/siteinfo4onestation.php?station=LAMA00POL). You could check if there are other GNSS networks with open data in Poland;

  3. the navigation file (vrs.17n) contains data for the 14th of March, while the other two files have observations for the 15th of March.

Eugenio

Thank you very, very much. It worked!

Great! Let us know if you need further help, or if you get "strange" results... the code is continuously evolving, so it might have glitches here and there. Cheers!