org.gogpsproject.parser.rinex.RinexNavigation.java Source code

Java tutorial

Introduction

Here is the source code for org.gogpsproject.parser.rinex.RinexNavigation.java

Source

/*
 * Copyright (c) 2011 Eugenio Realini, Mirko Reguzzoni, Cryms sagl - Switzerland. All Rights Reserved.
 *
 * This file is part of goGPS Project (goGPS).
 *
 * goGPS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3
 * of the License, or (at your option) any later version.
 *
 * goGPS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with goGPS.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package org.gogpsproject.parser.rinex;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.SimpleTimeZone;
import java.util.TimeZone;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.gogpsproject.Coordinates;
import org.gogpsproject.EphGps;
import org.gogpsproject.IonoGps;
import org.gogpsproject.NavigationProducer;
import org.gogpsproject.Observations;
import org.gogpsproject.StreamResource;
import org.gogpsproject.Time;
import org.gogpsproject.SatellitePosition;
import org.gogpsproject.util.UncompressInputStream;

/**
 * @author Lorenzo Patocchi, cryms.com
 *
 * This class retrieve RINEX file on-demand from known server structures
 *
 */
public class RinexNavigation implements NavigationProducer {

    public final static String GARNER_NAVIGATION_AUTO = "ftp://garner.ucsd.edu/pub/nav/${yyyy}/${ddd}/auto${ddd}0.${yy}n.Z";
    public final static String IGN_MULTI_NAVIGATION_DAILY = "ftp://igs.ign.fr/pub/igs/data/campaign/mgex/daily/rinex3/${yyyy}/${ddd}/brdm${ddd}0.${yy}p.Z";
    public final static String GARNER_NAVIGATION_ZIM2 = "ftp://garner.ucsd.edu/pub/nav/${yyyy}/${ddd}/zim2${ddd}0.${yy}n.Z";
    public final static String IGN_NAVIGATION_HOURLY_ZIM2 = "ftp://igs.ensg.ign.fr/pub/igs/data/hourly/${yyyy}/${ddd}/zim2${ddd}${h}.${yy}n.Z";

    /** cache for negative answers */
    private Hashtable<String, Date> negativeChache = new Hashtable<String, Date>();

    /** Folder containing downloaded files */
    public String RNP_CACHE = "./rnp-cache";

    private boolean waitForData = true;

    /**
     * @param args
     */
    public static void main(String[] args) {

        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, 2011);
        c.set(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 9);
        c.set(Calendar.HOUR_OF_DAY, 1);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        c.setTimeZone(new SimpleTimeZone(0, ""));

        Time t = new Time(c.getTimeInMillis());

        System.out.println("ts: " + t.getMsec() + " " + (new Date(t.getMsec())));
        System.out.println("week: " + t.getGpsWeek());
        System.out.println("week sec: " + t.getGpsWeekSec());
        System.out.println("week day: " + t.getGpsWeekDay());
        System.out.println("week hour in day: " + t.getGpsHourInDay());

        System.out.println("ts2: " + (new Time(t.getGpsWeek(), t.getGpsWeekSec())).getMsec());

        RinexNavigation rn = new RinexNavigation(IGN_NAVIGATION_HOURLY_ZIM2);
        rn.init();
        //      SatellitePosition sp = rn.getGpsSatPosition(c.getTimeInMillis(), 2, 0, 0);
        Observations obs = new Observations(new Time(c.getTimeInMillis()), 0);
        SatellitePosition sp = rn.getGpsSatPosition(obs, 2, 'G', 0);

        if (sp != null) {
            System.out
                    .println("found " + (new Date(sp.getUtcTime())) + " " + (sp.isPredicted() ? " predicted" : ""));
        } else {
            System.out.println("Epoch not found " + (new Date(c.getTimeInMillis())));
        }

    }

    /** Template string where to retrieve files on the net */
    private String urltemplate;
    private HashMap<String, RinexNavigationParser> pool = new HashMap<String, RinexNavigationParser>();

    /**
     * Instantiates a new RINEX navigation retriever and parser.
     *
     * @param urltemplate the template URL where to get the files on the net.
     */
    public RinexNavigation(String urltemplate) {
        this.urltemplate = urltemplate;

    }

    /* (non-Javadoc)
     * @see org.gogpsproject.NavigationProducer#getGpsSatPosition(long, int, double)
     */
    public SatellitePosition getGpsSatPosition(Observations obs, int satID, char satType,
            double receiverClockError) {

        long unixTime = obs.getRefTime().getMsec();
        double range = obs.getSatByIDType(satID, satType).getPseudorange(0);

        RinexNavigationParser rnp = getRNPByTimestamp(unixTime);
        if (rnp != null) {
            if (rnp.isTimestampInEpocsRange(unixTime)) {
                return rnp.getGpsSatPosition(obs, satID, satType, receiverClockError);
            } else {
                return null;
            }
        }

        return null;
    }

    public EphGps findEph(long unixTime, int satID, char satType) {
        long requestedTime = unixTime;
        EphGps eph = null;
        int maxBack = 12;
        while (eph == null && (maxBack--) > 0) {

            RinexNavigationParser rnp = getRNPByTimestamp(requestedTime);

            if (rnp != null) {
                if (rnp.isTimestampInEpocsRange(unixTime)) {
                    eph = rnp.findEph(unixTime, satID, satType);
                }
            }
            if (eph == null)
                requestedTime -= (1L * 3600L * 1000L);
        }

        return eph;
    }

    private RinexNavigationParser getRNPByTimestamp(long unixTime) {

        RinexNavigationParser rnp = null;
        long reqTime = unixTime;
        boolean retrievable = true;

        do {
            // found none, retrieve from urltemplate
            Time t = new Time(reqTime);
            //System.out.println("request: "+unixTime+" "+(new Date(t.getMsec()))+" week:"+t.getGpsWeek()+" "+t.getGpsWeekDay());

            String url = t.formatTemplate(urltemplate);

            if (url.startsWith("ftp://")) {
                try {
                    if (pool.containsKey(url)) {
                        //System.out.println(url+" from memory cache.");
                        rnp = pool.get(url);
                    } else {
                        rnp = getFromFTP(url);
                    }
                    if (rnp != null) {
                        pool.put(url, rnp);
                        return rnp;
                    }
                    System.out.println("Try in 10s");
                    try {
                        Thread.sleep(1000 * 10);
                    } catch (InterruptedException ee) {
                    }
                } catch (FileNotFoundException e) {
                    //System.out.println("Try with previous time by 1h");
                    reqTime = reqTime - (1L * 3600L * 1000L);
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("Try in 10s");
                    try {
                        Thread.sleep(1000 * 10);
                    } catch (InterruptedException ee) {
                    }
                }

            } else {
                // no way to get out
                retrievable = false;
            }
        } while (retrievable && waitForData && rnp == null);

        return null;
    }

    private RinexNavigationParser getFromFTP(String url) throws IOException {
        RinexNavigationParser rnp = null;

        String origurl = url;
        if (negativeChache.containsKey(url)) {
            if (System.currentTimeMillis() - negativeChache.get(url).getTime() < 60 * 60 * 1000) {
                throw new FileNotFoundException("cached answer");
            } else {
                negativeChache.remove(url);
            }
        }

        String filename = url.replaceAll("[ ,/:]", "_");
        if (filename.endsWith(".Z"))
            filename = filename.substring(0, filename.length() - 2);
        File rnf = new File(RNP_CACHE, filename);

        if (!rnf.exists()) {
            System.out.println(url + " from the net.");
            FTPClient ftp = new FTPClient();

            try {
                int reply;
                System.out.println("URL: " + url);
                url = url.substring("ftp://".length());
                String server = url.substring(0, url.indexOf('/'));
                String remoteFile = url.substring(url.indexOf('/'));
                String remotePath = remoteFile.substring(0, remoteFile.lastIndexOf('/'));
                remoteFile = remoteFile.substring(remoteFile.lastIndexOf('/') + 1);

                ftp.connect(server);
                ftp.login("anonymous", "info@eriadne.org");

                System.out.print(ftp.getReplyString());

                // After connection attempt, you should check the reply code to
                // verify
                // success.
                reply = ftp.getReplyCode();

                if (!FTPReply.isPositiveCompletion(reply)) {
                    ftp.disconnect();
                    System.err.println("FTP server refused connection.");
                    return null;
                }

                System.out.println("cwd to " + remotePath + " " + ftp.changeWorkingDirectory(remotePath));
                System.out.println(ftp.getReplyString());
                ftp.setFileType(FTP.BINARY_FILE_TYPE);
                System.out.println(ftp.getReplyString());

                System.out.println("open " + remoteFile);
                InputStream is = ftp.retrieveFileStream(remoteFile);
                InputStream uis = is;
                System.out.println(ftp.getReplyString());
                if (ftp.getReplyString().startsWith("550")) {
                    negativeChache.put(origurl, new Date());
                    throw new FileNotFoundException();
                }

                if (remoteFile.endsWith(".Z")) {
                    uis = new UncompressInputStream(is);
                }

                rnp = new RinexNavigationParser(uis, rnf);
                rnp.init();
                is.close();

                ftp.completePendingCommand();

                ftp.logout();
            } finally {
                if (ftp.isConnected()) {
                    try {
                        ftp.disconnect();
                    } catch (IOException ioe) {
                        // do nothing
                    }
                }
            }
        } else {
            System.out.println(url + " from cache file " + rnf);
            rnp = new RinexNavigationParser(rnf);
            rnp.init();
        }
        return rnp;
    }

    /* (non-Javadoc)
     * @see org.gogpsproject.NavigationProducer#getIono(int)
     */
    @Override
    public IonoGps getIono(long unixTime) {
        RinexNavigationParser rnp = getRNPByTimestamp(unixTime);
        if (rnp != null)
            return rnp.getIono(unixTime);
        return null;
    }

    /* (non-Javadoc)
     * @see org.gogpsproject.NavigationProducer#init()
     */
    @Override
    public void init() {

    }

    /* (non-Javadoc)
     * @see org.gogpsproject.NavigationProducer#release()
     */
    @Override
    public void release(boolean waitForThread, long timeoutMs) throws InterruptedException {
        waitForData = false;
    }

}