RinexNavigationParser.java
- /* Copyright 2002-2024 CS GROUP
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.orekit.files.rinex.navigation;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.Reader;
- import java.util.Arrays;
- import java.util.Collections;
- import java.util.InputMismatchException;
- import java.util.function.Function;
- import java.util.function.Predicate;
- import org.hipparchus.util.FastMath;
- import org.orekit.annotation.DefaultDataContext;
- import org.orekit.data.DataContext;
- import org.orekit.data.DataSource;
- import org.orekit.errors.OrekitException;
- import org.orekit.errors.OrekitInternalError;
- import org.orekit.errors.OrekitMessages;
- import org.orekit.files.rinex.utils.parsing.RinexUtils;
- import org.orekit.gnss.Frequency;
- import org.orekit.gnss.SatelliteSystem;
- import org.orekit.gnss.TimeSystem;
- import org.orekit.propagation.analytical.gnss.data.AbstractNavigationMessage;
- import org.orekit.propagation.analytical.gnss.data.BeidouCivilianNavigationMessage;
- import org.orekit.propagation.analytical.gnss.data.BeidouLegacyNavigationMessage;
- import org.orekit.propagation.analytical.gnss.data.BeidouSatelliteType;
- import org.orekit.propagation.analytical.gnss.data.CivilianNavigationMessage;
- import org.orekit.propagation.analytical.gnss.data.GLONASSNavigationMessage;
- import org.orekit.propagation.analytical.gnss.data.GPSCivilianNavigationMessage;
- import org.orekit.propagation.analytical.gnss.data.GPSLegacyNavigationMessage;
- import org.orekit.propagation.analytical.gnss.data.GalileoNavigationMessage;
- import org.orekit.propagation.analytical.gnss.data.IRNSSNavigationMessage;
- import org.orekit.propagation.analytical.gnss.data.LegacyNavigationMessage;
- import org.orekit.propagation.analytical.gnss.data.QZSSCivilianNavigationMessage;
- import org.orekit.propagation.analytical.gnss.data.QZSSLegacyNavigationMessage;
- import org.orekit.propagation.analytical.gnss.data.SBASNavigationMessage;
- import org.orekit.time.AbsoluteDate;
- import org.orekit.time.GNSSDate;
- import org.orekit.time.TimeScale;
- import org.orekit.time.TimeScales;
- import org.orekit.utils.Constants;
- import org.orekit.utils.units.Unit;
- /**
- * Parser for RINEX navigation messages files.
- * <p>
- * This parser handles RINEX version from 2 to 4.00.
- * </p>
- * @see <a href="https://files.igs.org/pub/data/format/rinex2.txt">rinex 2.0</a>
- * @see <a href="https://files.igs.org/pub/data/format/rinex210.txt">rinex 2.10</a>
- * @see <a href="https://files.igs.org/pub/data/format/rinex211.pdf">rinex 2.11</a>
- * @see <a href="https://files.igs.org/pub/data/format/rinex301.pdf"> 3.01 navigation messages file format</a>
- * @see <a href="https://files.igs.org/pub/data/format/rinex302.pdf"> 3.02 navigation messages file format</a>
- * @see <a href="https://files.igs.org/pub/data/format/rinex303.pdf"> 3.03 navigation messages file format</a>
- * @see <a href="https://files.igs.org/pub/data/format/rinex304.pdf"> 3.04 navigation messages file format</a>
- * @see <a href="https://files.igs.org/pub/data/format/rinex305.pdf"> 3.05 navigation messages file format</a>
- * @see <a href="https://files.igs.org/pub/data/format/rinex_4.00.pdf"> 4.00 navigation messages file format</a>
- *
- * @author Bryan Cazabonne
- * @since 11.0
- *
- */
- public class RinexNavigationParser {
- /** Converter for positions. */
- private static final Unit KM = Unit.KILOMETRE;
- /** Converter for velocities. */
- private static final Unit KM_PER_S = Unit.parse("km/s");
- /** Converter for accelerations. */
- private static final Unit KM_PER_S2 = Unit.parse("km/s²");;
- /** Converter for velocities. */
- private static final Unit M_PER_S = Unit.parse("m/s");
- /** Converter for clock drift. */
- private static final Unit S_PER_S = Unit.parse("s/s");
- /** Converter for clock drift rate. */
- private static final Unit S_PER_S2 = Unit.parse("s/s²");
- /** Converter for ΔUT₁ first derivative. */
- private static final Unit S_PER_DAY = Unit.parse("s/d");
- /** Converter for ΔUT₁ second derivative. */
- private static final Unit S_PER_DAY2 = Unit.parse("s/d²");
- /** Converter for square root of semi-major axis. */
- private static final Unit SQRT_M = Unit.parse("√m");
- /** Converter for angular rates. */
- private static final Unit RAD_PER_S = Unit.parse("rad/s");;
- /** Converter for angular accelerations. */
- private static final Unit RAD_PER_S2 = Unit.parse("rad/s²");;
- /** Converter for rates of small angle. */
- private static final Unit AS_PER_DAY = Unit.parse("as/d");;
- /** Converter for accelerations of small angles. */
- private static final Unit AS_PER_DAY2 = Unit.parse("as/d²");;
- /** System initials. */
- private static final String INITIALS = "GRECIJS";
- /** Set of time scales. */
- private final TimeScales timeScales;
- /**
- * Constructor.
- * <p>This constructor uses the {@link DataContext#getDefault() default data context}.</p>
- * @see #RinexNavigationParser(TimeScales)
- *
- */
- @DefaultDataContext
- public RinexNavigationParser() {
- this(DataContext.getDefault().getTimeScales());
- }
- /**
- * Constructor.
- * @param timeScales the set of time scales used for parsing dates.
- */
- public RinexNavigationParser(final TimeScales timeScales) {
- this.timeScales = timeScales;
- }
- /**
- * Parse RINEX navigation messages.
- * @param source source providing the data to parse
- * @return a parsed RINEX navigation messages file
- * @throws IOException if {@code reader} throws one
- */
- public RinexNavigation parse(final DataSource source) throws IOException {
- // initialize internal data structures
- final ParseInfo pi = new ParseInfo(source.getName());
- Iterable<LineParser> candidateParsers = Collections.singleton(LineParser.HEADER_VERSION);
- try (Reader reader = source.getOpener().openReaderOnce();
- BufferedReader br = new BufferedReader(reader)) {
- nextLine:
- for (String line = br.readLine(); line != null; line = br.readLine()) {
- ++pi.lineNumber;
- for (final LineParser candidate : candidateParsers) {
- if (candidate.canHandle.test(line)) {
- try {
- candidate.parsingMethod.parse(line, pi);
- candidateParsers = candidate.allowedNextProvider.apply(pi);
- continue nextLine;
- } catch (StringIndexOutOfBoundsException | NumberFormatException | InputMismatchException e) {
- throw new OrekitException(e,
- OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
- pi.lineNumber, source.getName(), line);
- }
- }
- }
- throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
- pi.lineNumber, source.getName(), line);
- }
- }
- if (!pi.headerParsed) {
- throw new OrekitException(OrekitMessages.UNEXPECTED_END_OF_FILE, source.getName());
- }
- pi.closePendingMessage();
- return pi.file;
- }
- /** Transient data used for parsing a RINEX navigation messages file. */
- private class ParseInfo {
- /** Name of the data source. */
- private final String name;
- /** Set of time scales for parsing dates. */
- private final TimeScales timeScales;
- /** The corresponding navigation messages file object. */
- private RinexNavigation file;
- /** Number of initial spaces in broadcase orbits lines. */
- private int initialSpaces;
- /** Flag indicating header has been completely parsed. */
- private boolean headerParsed;
- /** Flag indicating the distinction between "alpha" and "beta" ionospheric coefficients. */
- private boolean isIonosphereAlphaInitialized;
- /** Satellite system line parser. */
- private SatelliteSystemLineParser systemLineParser;
- /** Current global line number. */
- private int lineNumber;
- /** Current line number within the navigation message. */
- private int messageLineNumber;
- /** Container for GPS navigation message. */
- private GPSLegacyNavigationMessage gpsLNav;
- /** Container for GPS navigation message. */
- private GPSCivilianNavigationMessage gpsCNav;
- /** Container for Galileo navigation message. */
- private GalileoNavigationMessage galileoNav;
- /** Container for Beidou navigation message. */
- private BeidouLegacyNavigationMessage beidouLNav;
- /** Container for Beidou navigation message. */
- private BeidouCivilianNavigationMessage beidouCNav;
- /** Container for QZSS navigation message. */
- private QZSSLegacyNavigationMessage qzssLNav;
- /** Container for QZSS navigation message. */
- private QZSSCivilianNavigationMessage qzssCNav;
- /** Container for IRNSS navigation message. */
- private IRNSSNavigationMessage irnssNav;
- /** Container for GLONASS navigation message. */
- private GLONASSNavigationMessage glonassNav;
- /** Container for SBAS navigation message. */
- private SBASNavigationMessage sbasNav;
- /** Container for System Time Offset message. */
- private SystemTimeOffsetMessage sto;
- /** Container for Earth Orientation Parameter message. */
- private EarthOrientationParameterMessage eop;
- /** Container for ionosphere Klobuchar message. */
- private IonosphereKlobucharMessage klobuchar;
- /** Container for ionosphere Nequick-G message. */
- private IonosphereNequickGMessage nequickG;
- /** Container for ionosphere BDGIM message. */
- private IonosphereBDGIMMessage bdgim;
- /** Constructor, build the ParseInfo object.
- * @param name name of the data source
- */
- ParseInfo(final String name) {
- // Initialize default values for fields
- this.name = name;
- this.timeScales = RinexNavigationParser.this.timeScales;
- this.isIonosphereAlphaInitialized = false;
- this.file = new RinexNavigation();
- }
- /** Ensure navigation message has been closed.
- */
- void closePendingMessage() {
- if (systemLineParser != null) {
- systemLineParser.closeMessage(this);
- systemLineParser = null;
- }
- }
- }
- /** Parsers for specific lines. */
- private enum LineParser {
- /** Parser for version, file type and satellite system. */
- HEADER_VERSION(line -> RinexUtils.matchesLabel(line, "RINEX VERSION / TYPE"),
- (line, pi) -> {
- RinexUtils.parseVersionFileTypeSatelliteSystem(line, pi.name, pi.file.getHeader(),
- 2.0, 2.01, 2.10, 2.11,
- 3.01, 3.02, 3.03, 3.04, 3.05,
- 4.00);
- pi.initialSpaces = pi.file.getHeader().getFormatVersion() < 3.0 ? 3 : 4;
- },
- LineParser::headerNext),
- /** Parser for generating program and emitting agency. */
- HEADER_PROGRAM(line -> RinexUtils.matchesLabel(line, "PGM / RUN BY / DATE"),
- (line, pi) -> RinexUtils.parseProgramRunByDate(line, pi.lineNumber, pi.name, pi.timeScales, pi.file.getHeader()),
- LineParser::headerNext),
- /** Parser for comments. */
- HEADER_COMMENT(line -> RinexUtils.matchesLabel(line, "COMMENT"),
- (line, pi) -> RinexUtils.parseComment(pi.lineNumber, line, pi.file),
- LineParser::headerNext),
- /** Parser for ionospheric correction parameters. */
- HEADER_ION_ALPHA(line -> RinexUtils.matchesLabel(line, "ION ALPHA"),
- (line, pi) -> {
- pi.file.getHeader().setIonosphericCorrectionType(IonosphericCorrectionType.GPS);
- // Read coefficients
- final double[] parameters = new double[4];
- parameters[0] = RinexUtils.parseDouble(line, 2, 12);
- parameters[1] = RinexUtils.parseDouble(line, 14, 12);
- parameters[2] = RinexUtils.parseDouble(line, 26, 12);
- parameters[3] = RinexUtils.parseDouble(line, 38, 12);
- pi.file.setKlobucharAlpha(parameters);
- pi.isIonosphereAlphaInitialized = true;
- },
- LineParser::headerNext),
- /** Parser for ionospheric correction parameters. */
- HEADER_ION_BETA(line -> RinexUtils.matchesLabel(line, "ION BETA"),
- (line, pi) -> {
- pi.file.getHeader().setIonosphericCorrectionType(IonosphericCorrectionType.GPS);
- // Read coefficients
- final double[] parameters = new double[4];
- parameters[0] = RinexUtils.parseDouble(line, 2, 12);
- parameters[1] = RinexUtils.parseDouble(line, 14, 12);
- parameters[2] = RinexUtils.parseDouble(line, 26, 12);
- parameters[3] = RinexUtils.parseDouble(line, 38, 12);
- pi.file.setKlobucharBeta(parameters);
- },
- LineParser::headerNext),
- /** Parser for ionospheric correction parameters. */
- HEADER_IONOSPHERIC(line -> RinexUtils.matchesLabel(line, "IONOSPHERIC CORR"),
- (line, pi) -> {
- // ionospheric correction type
- final IonosphericCorrectionType ionoType =
- IonosphericCorrectionType.valueOf(RinexUtils.parseString(line, 0, 3));
- pi.file.getHeader().setIonosphericCorrectionType(ionoType);
- // Read coefficients
- final double[] parameters = new double[4];
- parameters[0] = RinexUtils.parseDouble(line, 5, 12);
- parameters[1] = RinexUtils.parseDouble(line, 17, 12);
- parameters[2] = RinexUtils.parseDouble(line, 29, 12);
- parameters[3] = RinexUtils.parseDouble(line, 41, 12);
- // Verify if we are parsing Galileo ionospheric parameters
- if (ionoType == IonosphericCorrectionType.GAL) {
- // We are parsing Galileo ionospheric parameters
- pi.file.setNeQuickAlpha(parameters);
- } else {
- // We are parsing Klobuchar ionospheric parameters
- // Verify if we are parsing "alpha" or "beta" ionospheric parameters
- if (pi.isIonosphereAlphaInitialized) {
- // Ionospheric "beta" parameters
- pi.file.setKlobucharBeta(parameters);
- } else {
- // Ionospheric "alpha" parameters
- pi.file.setKlobucharAlpha(parameters);
- // Set the flag to true
- pi.isIonosphereAlphaInitialized = true;
- }
- }
- },
- LineParser::headerNext),
- /** Parser for corrections to transform the system time to UTC or to other time systems. */
- HEADER_DELTA_UTC(line -> RinexUtils.matchesLabel(line, "DELTA-UTC: A0,A1,T,W"),
- (line, pi) -> {
- // Read fields
- final double a0 = RinexUtils.parseDouble(line, 3, 19);
- final double a1 = RinexUtils.parseDouble(line, 22, 19);
- final int refTime = RinexUtils.parseInt(line, 41, 9);
- final int refWeek = RinexUtils.parseInt(line, 50, 9);
- // convert date
- final SatelliteSystem satSystem = pi.file.getHeader().getSatelliteSystem();
- final AbsoluteDate date = new GNSSDate(refWeek, refTime, satSystem, pi.timeScales).getDate();
- // Add to the list
- final TimeSystemCorrection tsc = new TimeSystemCorrection("GPUT", date, a0, a1);
- pi.file.getHeader().addTimeSystemCorrections(tsc);
- },
- LineParser::headerNext),
- /** Parser for corrections to transform the GLONASS system time to UTC or to other time systems. */
- HEADER_CORR_SYSTEM_TIME(line -> RinexUtils.matchesLabel(line, "CORR TO SYSTEM TIME"),
- (line, pi) -> {
- // Read fields
- final int year = RinexUtils.parseInt(line, 0, 6);
- final int month = RinexUtils.parseInt(line, 6, 6);
- final int day = RinexUtils.parseInt(line, 12, 6);
- final double minusTau = RinexUtils.parseDouble(line, 21, 19);
- // convert date
- final SatelliteSystem satSystem = pi.file.getHeader().getSatelliteSystem();
- final TimeScale timeScale = satSystem.getObservationTimeScale().getTimeScale(pi.timeScales);
- final AbsoluteDate date = new AbsoluteDate(year, month, day, timeScale);
- // Add to the list
- final TimeSystemCorrection tsc = new TimeSystemCorrection("GLUT", date, minusTau, 0.0);
- pi.file.getHeader().addTimeSystemCorrections(tsc);
- },
- LineParser::headerNext),
- /** Parser for corrections to transform the system time to UTC or to other time systems. */
- HEADER_TIME(line -> RinexUtils.matchesLabel(line, "TIME SYSTEM CORR"),
- (line, pi) -> {
- // Read fields
- final String type = RinexUtils.parseString(line, 0, 4);
- final double a0 = RinexUtils.parseDouble(line, 5, 17);
- final double a1 = RinexUtils.parseDouble(line, 22, 16);
- final int refTime = RinexUtils.parseInt(line, 38, 7);
- final int refWeek = RinexUtils.parseInt(line, 46, 5);
- // convert date
- final SatelliteSystem satSystem = pi.file.getHeader().getSatelliteSystem();
- final AbsoluteDate date;
- if (satSystem == SatelliteSystem.GLONASS) {
- date = null;
- } else if (satSystem == SatelliteSystem.BEIDOU) {
- date = new GNSSDate(refWeek, refTime, satSystem, pi.timeScales).getDate();
- } else {
- // all other systems are converted to GPS week in Rinex files!
- date = new GNSSDate(refWeek, refTime, SatelliteSystem.GPS, pi.timeScales).getDate();
- }
- // Add to the list
- final TimeSystemCorrection tsc = new TimeSystemCorrection(type, date, a0, a1);
- pi.file.getHeader().addTimeSystemCorrections(tsc);
- },
- LineParser::headerNext),
- /** Parser for leap seconds. */
- HEADER_LEAP_SECONDS(line -> RinexUtils.matchesLabel(line, "LEAP SECONDS"),
- (line, pi) -> pi.file.getHeader().setNumberOfLeapSeconds(RinexUtils.parseInt(line, 0, 6)),
- LineParser::headerNext),
- /** Parser for DOI.
- * @since 12.0
- */
- HEADER_DOI(line -> RinexUtils.matchesLabel(line, "DOI"),
- (line, pi) -> pi.file.getHeader().setDoi(RinexUtils.parseString(line, 0, RinexUtils.LABEL_INDEX)),
- LineParser::headerNext),
- /** Parser for license.
- * @since 12.0
- */
- HEADER_LICENSE(line -> RinexUtils.matchesLabel(line, "LICENSE OF USE"),
- (line, pi) -> pi.file.getHeader().setLicense(RinexUtils.parseString(line, 0, RinexUtils.LABEL_INDEX)),
- LineParser::headerNext),
- /** Parser for stationInformation.
- * @since 12.0
- */
- HEADER_STATION_INFORMATION(line -> RinexUtils.matchesLabel(line, "STATION INFORMATION"),
- (line, pi) -> pi.file.getHeader().setStationInformation(RinexUtils.parseString(line, 0, RinexUtils.LABEL_INDEX)),
- LineParser::headerNext),
- /** Parser for merged files.
- * @since 12.0
- */
- HEADER_MERGED_FILE(line -> RinexUtils.matchesLabel(line, "MERGED FILE"),
- (line, pi) -> pi.file.getHeader().setMergedFiles(RinexUtils.parseInt(line, 0, 9)),
- LineParser::headerNext),
- /** Parser for the end of header. */
- HEADER_END(line -> RinexUtils.matchesLabel(line, "END OF HEADER"),
- (line, pi) -> {
- // get rinex format version
- final RinexNavigationHeader header = pi.file.getHeader();
- final double version = header.getFormatVersion();
- // check mandatory header fields
- if (header.getRunByName() == null ||
- version >= 4 && header.getNumberOfLeapSeconds() < 0) {
- throw new OrekitException(OrekitMessages.INCOMPLETE_HEADER, pi.name);
- }
- pi.headerParsed = true;
- },
- LineParser::navigationNext),
- /** Parser for navigation message space vehicle epoch and clock. */
- NAVIGATION_SV_EPOCH_CLOCK_RINEX_2(line -> true,
- (line, pi) -> {
- // Set the line number to 0
- pi.messageLineNumber = 0;
- // Initialize parser
- pi.closePendingMessage();
- pi.systemLineParser = SatelliteSystemLineParser.getParser(pi.file.getHeader().getSatelliteSystem(),
- null, pi, line);
- pi.systemLineParser.parseSvEpochSvClockLine(line, pi);
- },
- LineParser::navigationNext),
- /** Parser for navigation message space vehicle epoch and clock. */
- NAVIGATION_SV_EPOCH_CLOCK(line -> INITIALS.indexOf(line.charAt(0)) >= 0,
- (line, pi) -> {
- // Set the line number to 0
- pi.messageLineNumber = 0;
- if (pi.file.getHeader().getFormatVersion() < 4) {
- // Current satellite system
- final SatelliteSystem system = SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, 0, 1));
- // Initialize parser
- pi.closePendingMessage();
- pi.systemLineParser = SatelliteSystemLineParser.getParser(system, null, pi, line);
- }
- // Read first line
- pi.systemLineParser.parseSvEpochSvClockLine(line, pi);
- },
- LineParser::navigationNext),
- /** Parser for navigation message type. */
- EPH_TYPE(line -> line.startsWith("> EPH"),
- (line, pi) -> {
- final SatelliteSystem system = SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, 6, 1));
- final String type = RinexUtils.parseString(line, 10, 4);
- pi.closePendingMessage();
- pi.systemLineParser = SatelliteSystemLineParser.getParser(system, type, pi, line);
- },
- pi -> Collections.singleton(NAVIGATION_SV_EPOCH_CLOCK)),
- /** Parser for broadcast orbit. */
- BROADCAST_ORBIT(line -> line.startsWith(" "),
- (line, pi) -> {
- switch (++pi.messageLineNumber) {
- case 1: pi.systemLineParser.parseFirstBroadcastOrbit(line, pi);
- break;
- case 2: pi.systemLineParser.parseSecondBroadcastOrbit(line, pi);
- break;
- case 3: pi.systemLineParser.parseThirdBroadcastOrbit(line, pi);
- break;
- case 4: pi.systemLineParser.parseFourthBroadcastOrbit(line, pi);
- break;
- case 5: pi.systemLineParser.parseFifthBroadcastOrbit(line, pi);
- break;
- case 6: pi.systemLineParser.parseSixthBroadcastOrbit(line, pi);
- break;
- case 7: pi.systemLineParser.parseSeventhBroadcastOrbit(line, pi);
- break;
- case 8: pi.systemLineParser.parseEighthBroadcastOrbit(line, pi);
- break;
- case 9: pi.systemLineParser.parseNinthBroadcastOrbit(line, pi);
- break;
- default:
- // this should never happen
- throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
- pi.lineNumber, pi.name, line);
- }
- },
- LineParser::navigationNext),
- /** Parser for system time offset message model. */
- STO_LINE_1(line -> true,
- (line, pi) -> {
- pi.sto.setTransmissionTime(Unit.SECOND.toSI(RinexUtils.parseDouble(line, 4, 19)));
- pi.sto.setA0(Unit.SECOND.toSI(RinexUtils.parseDouble(line, 23, 19)));
- pi.sto.setA1(S_PER_S.toSI(RinexUtils.parseDouble(line, 42, 19)));
- pi.sto.setA2(S_PER_S2.toSI(RinexUtils.parseDouble(line, 61, 19)));
- pi.file.addSystemTimeOffset(pi.sto);
- pi.sto = null;
- },
- LineParser::navigationNext),
- /** Parser for system time offset message space vehicle epoch and clock. */
- STO_SV_EPOCH_CLOCK(line -> true,
- (line, pi) -> {
- pi.sto.setDefinedTimeSystem(TimeSystem.parseTwoLettersCode(RinexUtils.parseString(line, 24, 2)));
- pi.sto.setReferenceTimeSystem(TimeSystem.parseTwoLettersCode(RinexUtils.parseString(line, 26, 2)));
- final String sbas = RinexUtils.parseString(line, 43, 18);
- pi.sto.setSbasId(sbas.length() > 0 ? SbasId.valueOf(sbas) : null);
- final String utc = RinexUtils.parseString(line, 62, 18);
- pi.sto.setUtcId(utc.length() > 0 ? UtcId.parseUtcId(utc) : null);
- // TODO is the reference date relative to one or the other time scale?
- final int year = RinexUtils.parseInt(line, 4, 4);
- final int month = RinexUtils.parseInt(line, 9, 2);
- final int day = RinexUtils.parseInt(line, 12, 2);
- final int hours = RinexUtils.parseInt(line, 15, 2);
- final int min = RinexUtils.parseInt(line, 18, 2);
- final int sec = RinexUtils.parseInt(line, 21, 2);
- pi.sto.setReferenceEpoch(new AbsoluteDate(year, month, day, hours, min, sec,
- pi.sto.getDefinedTimeSystem().getTimeScale(pi.timeScales)));
- },
- pi -> Collections.singleton(STO_LINE_1)),
- /** Parser for system time offset message type. */
- STO_TYPE(line -> line.startsWith("> STO"),
- (line, pi) -> {
- pi.closePendingMessage();
- pi.sto = new SystemTimeOffsetMessage(SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, 6, 1)),
- RinexUtils.parseInt(line, 7, 2),
- RinexUtils.parseString(line, 10, 4));
- },
- pi -> Collections.singleton(STO_SV_EPOCH_CLOCK)),
- /** Parser for Earth orientation parameter message model. */
- EOP_LINE_2(line -> true,
- (line, pi) -> {
- pi.eop.setTransmissionTime(Unit.SECOND.toSI(RinexUtils.parseDouble(line, 4, 19)));
- pi.eop.setDut1(Unit.SECOND.toSI(RinexUtils.parseDouble(line, 23, 19)));
- pi.eop.setDut1Dot(S_PER_DAY.toSI(RinexUtils.parseDouble(line, 42, 19)));
- pi.eop.setDut1DotDot(S_PER_DAY2.toSI(RinexUtils.parseDouble(line, 61, 19)));
- pi.file.addEarthOrientationParameter(pi.eop);
- pi.eop = null;
- },
- LineParser::navigationNext),
- /** Parser for Earth orientation parameter message model. */
- EOP_LINE_1(line -> true,
- (line, pi) -> {
- pi.eop.setYp(Unit.ARC_SECOND.toSI(RinexUtils.parseDouble(line, 23, 19)));
- pi.eop.setYpDot(AS_PER_DAY.toSI(RinexUtils.parseDouble(line, 42, 19)));
- pi.eop.setYpDotDot(AS_PER_DAY2.toSI(RinexUtils.parseDouble(line, 61, 19)));
- },
- pi -> Collections.singleton(EOP_LINE_2)),
- /** Parser for Earth orientation parameter message space vehicle epoch and clock. */
- EOP_SV_EPOCH_CLOCK(line -> true,
- (line, pi) -> {
- final int year = RinexUtils.parseInt(line, 4, 4);
- final int month = RinexUtils.parseInt(line, 9, 2);
- final int day = RinexUtils.parseInt(line, 12, 2);
- final int hours = RinexUtils.parseInt(line, 15, 2);
- final int min = RinexUtils.parseInt(line, 18, 2);
- final int sec = RinexUtils.parseInt(line, 21, 2);
- pi.eop.setReferenceEpoch(new AbsoluteDate(year, month, day, hours, min, sec,
- pi.eop.getSystem().getObservationTimeScale().getTimeScale(pi.timeScales)));
- pi.eop.setXp(Unit.ARC_SECOND.toSI(RinexUtils.parseDouble(line, 23, 19)));
- pi.eop.setXpDot(AS_PER_DAY.toSI(RinexUtils.parseDouble(line, 42, 19)));
- pi.eop.setXpDotDot(AS_PER_DAY2.toSI(RinexUtils.parseDouble(line, 61, 19)));
- },
- pi -> Collections.singleton(EOP_LINE_1)),
- /** Parser for Earth orientation parameter message type. */
- EOP_TYPE(line -> line.startsWith("> EOP"),
- (line, pi) -> {
- pi.closePendingMessage();
- pi.eop = new EarthOrientationParameterMessage(SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, 6, 1)),
- RinexUtils.parseInt(line, 7, 2),
- RinexUtils.parseString(line, 10, 4));
- },
- pi -> Collections.singleton(EOP_SV_EPOCH_CLOCK)),
- /** Parser for ionosphere Klobuchar message model. */
- KLOBUCHAR_LINE_2(line -> true,
- (line, pi) -> {
- pi.klobuchar.setBetaI(3, IonosphereKlobucharMessage.S_PER_SC_N[3].toSI(RinexUtils.parseDouble(line, 4, 19)));
- pi.klobuchar.setRegionCode(RinexUtils.parseDouble(line, 23, 19) < 0.5 ?
- RegionCode.WIDE_AREA : RegionCode.JAPAN);
- pi.file.addKlobucharMessage(pi.klobuchar);
- pi.klobuchar = null;
- },
- LineParser::navigationNext),
- /** Parser for ionosphere Klobuchar message model. */
- KLOBUCHAR_LINE_1(line -> true,
- (line, pi) -> {
- pi.klobuchar.setAlphaI(3, IonosphereKlobucharMessage.S_PER_SC_N[3].toSI(RinexUtils.parseDouble(line, 4, 19)));
- pi.klobuchar.setBetaI(0, IonosphereKlobucharMessage.S_PER_SC_N[0].toSI(RinexUtils.parseDouble(line, 23, 19)));
- pi.klobuchar.setBetaI(1, IonosphereKlobucharMessage.S_PER_SC_N[1].toSI(RinexUtils.parseDouble(line, 42, 19)));
- pi.klobuchar.setBetaI(2, IonosphereKlobucharMessage.S_PER_SC_N[2].toSI(RinexUtils.parseDouble(line, 61, 19)));
- },
- pi -> Collections.singleton(KLOBUCHAR_LINE_2)),
- /** Parser for ionosphere Klobuchar message model. */
- KLOBUCHAR_LINE_0(line -> true,
- (line, pi) -> {
- final int year = RinexUtils.parseInt(line, 4, 4);
- final int month = RinexUtils.parseInt(line, 9, 2);
- final int day = RinexUtils.parseInt(line, 12, 2);
- final int hours = RinexUtils.parseInt(line, 15, 2);
- final int min = RinexUtils.parseInt(line, 18, 2);
- final int sec = RinexUtils.parseInt(line, 21, 2);
- pi.klobuchar.setTransmitTime(new AbsoluteDate(year, month, day, hours, min, sec,
- pi.klobuchar.getSystem().getObservationTimeScale().getTimeScale(pi.timeScales)));
- pi.klobuchar.setAlphaI(0, IonosphereKlobucharMessage.S_PER_SC_N[0].toSI(RinexUtils.parseDouble(line, 23, 19)));
- pi.klobuchar.setAlphaI(1, IonosphereKlobucharMessage.S_PER_SC_N[1].toSI(RinexUtils.parseDouble(line, 42, 19)));
- pi.klobuchar.setAlphaI(2, IonosphereKlobucharMessage.S_PER_SC_N[2].toSI(RinexUtils.parseDouble(line, 61, 19)));
- },
- pi -> Collections.singleton(KLOBUCHAR_LINE_1)),
- /** Parser for ionosphere Nequick-G message model. */
- NEQUICK_LINE_1(line -> true,
- (line, pi) -> {
- pi.nequickG.setFlags((int) FastMath.rint(RinexUtils.parseDouble(line, 4, 19)));
- pi.file.addNequickGMessage(pi.nequickG);
- pi.nequickG = null;
- },
- LineParser::navigationNext),
- /** Parser for ionosphere Nequick-G message model. */
- NEQUICK_LINE_0(line -> true,
- (line, pi) -> {
- final int year = RinexUtils.parseInt(line, 4, 4);
- final int month = RinexUtils.parseInt(line, 9, 2);
- final int day = RinexUtils.parseInt(line, 12, 2);
- final int hours = RinexUtils.parseInt(line, 15, 2);
- final int min = RinexUtils.parseInt(line, 18, 2);
- final int sec = RinexUtils.parseInt(line, 21, 2);
- pi.nequickG.setTransmitTime(new AbsoluteDate(year, month, day, hours, min, sec,
- pi.nequickG.getSystem().getObservationTimeScale().getTimeScale(pi.timeScales)));
- pi.nequickG.setAi0(IonosphereNequickGMessage.SFU.toSI(RinexUtils.parseDouble(line, 23, 19)));
- pi.nequickG.setAi1(IonosphereNequickGMessage.SFU_PER_DEG.toSI(RinexUtils.parseDouble(line, 42, 19)));
- pi.nequickG.setAi2(IonosphereNequickGMessage.SFU_PER_DEG2.toSI(RinexUtils.parseDouble(line, 61, 19)));
- },
- pi -> Collections.singleton(NEQUICK_LINE_1)),
- /** Parser for ionosphere BDGIM message model. */
- BDGIM_LINE_2(line -> true,
- (line, pi) -> {
- pi.bdgim.setAlphaI(7, Unit.TOTAL_ELECTRON_CONTENT_UNIT.toSI(RinexUtils.parseDouble(line, 4, 19)));
- pi.bdgim.setAlphaI(8, Unit.TOTAL_ELECTRON_CONTENT_UNIT.toSI(RinexUtils.parseDouble(line, 23, 19)));
- pi.file.addBDGIMMessage(pi.bdgim);
- pi.bdgim = null;
- },
- LineParser::navigationNext),
- /** Parser for ionosphere BDGIM message model. */
- BDGIM_LINE_1(line -> true,
- (line, pi) -> {
- pi.bdgim.setAlphaI(3, Unit.TOTAL_ELECTRON_CONTENT_UNIT.toSI(RinexUtils.parseDouble(line, 4, 19)));
- pi.bdgim.setAlphaI(4, Unit.TOTAL_ELECTRON_CONTENT_UNIT.toSI(RinexUtils.parseDouble(line, 23, 19)));
- pi.bdgim.setAlphaI(5, Unit.TOTAL_ELECTRON_CONTENT_UNIT.toSI(RinexUtils.parseDouble(line, 42, 19)));
- pi.bdgim.setAlphaI(6, Unit.TOTAL_ELECTRON_CONTENT_UNIT.toSI(RinexUtils.parseDouble(line, 61, 19)));
- },
- pi -> Collections.singleton(BDGIM_LINE_2)),
- /** Parser for ionosphere BDGIM message model. */
- BDGIM_LINE_0(line -> true,
- (line, pi) -> {
- final int year = RinexUtils.parseInt(line, 4, 4);
- final int month = RinexUtils.parseInt(line, 9, 2);
- final int day = RinexUtils.parseInt(line, 12, 2);
- final int hours = RinexUtils.parseInt(line, 15, 2);
- final int min = RinexUtils.parseInt(line, 18, 2);
- final int sec = RinexUtils.parseInt(line, 21, 2);
- pi.bdgim.setTransmitTime(new AbsoluteDate(year, month, day, hours, min, sec,
- pi.bdgim.getSystem().getObservationTimeScale().getTimeScale(pi.timeScales)));
- pi.bdgim.setAlphaI(0, Unit.TOTAL_ELECTRON_CONTENT_UNIT.toSI(RinexUtils.parseDouble(line, 23, 19)));
- pi.bdgim.setAlphaI(1, Unit.TOTAL_ELECTRON_CONTENT_UNIT.toSI(RinexUtils.parseDouble(line, 42, 19)));
- pi.bdgim.setAlphaI(2, Unit.TOTAL_ELECTRON_CONTENT_UNIT.toSI(RinexUtils.parseDouble(line, 61, 19)));
- },
- pi -> Collections.singleton(BDGIM_LINE_1)),
- /** Parser for ionosphere message type. */
- IONO_TYPE(line -> line.startsWith("> ION"),
- (line, pi) -> {
- pi.closePendingMessage();
- final SatelliteSystem system = SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, 6, 1));
- final int prn = RinexUtils.parseInt(line, 7, 2);
- final String type = RinexUtils.parseString(line, 10, 4);
- if (system == SatelliteSystem.GALILEO) {
- pi.nequickG = new IonosphereNequickGMessage(system, prn, type);
- } else {
- // in Rinex 4.00, tables A32 and A34 are ambiguous as both seem to apply
- // to Beidou CNVX messages, we consider BDGIM is the proper model in this case
- if (system == SatelliteSystem.BEIDOU && "CNVX".equals(type)) {
- pi.bdgim = new IonosphereBDGIMMessage(system, prn, type);
- } else {
- pi.klobuchar = new IonosphereKlobucharMessage(system, prn, type);
- }
- }
- },
- pi -> Collections.singleton(pi.nequickG != null ? NEQUICK_LINE_0 : (pi.bdgim != null ? BDGIM_LINE_0 : KLOBUCHAR_LINE_0)));
- /** Predicate for identifying lines that can be parsed. */
- private final Predicate<String> canHandle;
- /** Parsing method. */
- private final ParsingMethod parsingMethod;
- /** Provider for next line parsers. */
- private final Function<ParseInfo, Iterable<LineParser>> allowedNextProvider;
- /** Simple constructor.
- * @param canHandle predicate for identifying lines that can be parsed
- * @param parsingMethod parsing method
- * @param allowedNextProvider supplier for allowed parsers for next line
- */
- LineParser(final Predicate<String> canHandle, final ParsingMethod parsingMethod,
- final Function<ParseInfo, Iterable<LineParser>> allowedNextProvider) {
- this.canHandle = canHandle;
- this.parsingMethod = parsingMethod;
- this.allowedNextProvider = allowedNextProvider;
- }
- /** Get the allowed parsers for next lines while parsing Rinex header.
- * @param parseInfo holder for transient data
- * @return allowed parsers for next line
- */
- private static Iterable<LineParser> headerNext(final ParseInfo parseInfo) {
- if (parseInfo.file.getHeader().getFormatVersion() < 3) {
- // Rinex 2.x header entries
- return Arrays.asList(HEADER_COMMENT, HEADER_PROGRAM,
- HEADER_ION_ALPHA, HEADER_ION_BETA,
- HEADER_DELTA_UTC, HEADER_CORR_SYSTEM_TIME,
- HEADER_LEAP_SECONDS, HEADER_END);
- } else if (parseInfo.file.getHeader().getFormatVersion() < 4) {
- // Rinex 3.x header entries
- return Arrays.asList(HEADER_COMMENT, HEADER_PROGRAM,
- HEADER_IONOSPHERIC, HEADER_TIME,
- HEADER_LEAP_SECONDS, HEADER_END);
- } else {
- // Rinex 4.x header entries
- return Arrays.asList(HEADER_COMMENT, HEADER_PROGRAM,
- HEADER_DOI, HEADER_LICENSE, HEADER_STATION_INFORMATION, HEADER_MERGED_FILE,
- HEADER_LEAP_SECONDS, HEADER_END);
- }
- }
- /** Get the allowed parsers for next lines while parsing navigation date.
- * @param parseInfo holder for transient data
- * @return allowed parsers for next line
- */
- private static Iterable<LineParser> navigationNext(final ParseInfo parseInfo) {
- if (parseInfo.gpsLNav != null || parseInfo.gpsCNav != null || parseInfo.galileoNav != null ||
- parseInfo.beidouLNav != null || parseInfo.beidouCNav != null || parseInfo.qzssLNav != null ||
- parseInfo.qzssCNav != null || parseInfo.irnssNav != null || parseInfo.sbasNav != null) {
- return Collections.singleton(BROADCAST_ORBIT);
- } else if (parseInfo.glonassNav != null) {
- if (parseInfo.messageLineNumber < 3) {
- return Collections.singleton(BROADCAST_ORBIT);
- } else {
- // workaround for some invalid files that should nevertheless be parsed
- // we have encountered in the wild merged files that claimed to be in 3.05 version
- // and hence needed at least 4 broadcast GLONASS orbit lines (the fourth line was
- // introduced in 3.05), but in fact only had 3 broadcast lines. We think they were
- // merged from files in 3.04 or earlier format. In order to parse these files,
- // we accept after the third line either another broadcast orbit line or a new message
- if (parseInfo.file.getHeader().getFormatVersion() < 4) {
- return Arrays.asList(BROADCAST_ORBIT, NAVIGATION_SV_EPOCH_CLOCK);
- } else {
- return Arrays.asList(BROADCAST_ORBIT, EPH_TYPE, STO_TYPE, EOP_TYPE, IONO_TYPE);
- }
- }
- } else if (parseInfo.file.getHeader().getFormatVersion() < 3) {
- return Collections.singleton(NAVIGATION_SV_EPOCH_CLOCK_RINEX_2);
- } else if (parseInfo.file.getHeader().getFormatVersion() < 4) {
- return Collections.singleton(NAVIGATION_SV_EPOCH_CLOCK);
- } else {
- return Arrays.asList(EPH_TYPE, STO_TYPE, EOP_TYPE, IONO_TYPE);
- }
- }
- }
- /** Parsers for satellite system specific lines. */
- private enum SatelliteSystemLineParser {
- /** GPS legacy. */
- GPS_LNAV() {
- /** {@inheritDoc} */
- @Override
- public void parseSvEpochSvClockLine(final String line, final ParseInfo pi) {
- if (pi.file.getHeader().getFormatVersion() < 3.0) {
- parseSvEpochSvClockLineRinex2(line, pi.timeScales.getGPS(), pi.gpsLNav);
- } else {
- parseSvEpochSvClockLine(line, pi.timeScales.getGPS(), pi.gpsLNav);
- }
- }
- /** {@inheritDoc} */
- @Override
- public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.gpsLNav.setIODE(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.gpsLNav.setCrs(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.gpsLNav.setDeltaN(parseBroadcastDouble3(line, pi.initialSpaces, RAD_PER_S));
- pi.gpsLNav.setM0(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.gpsLNav.setCuc(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.gpsLNav.setE(parseBroadcastDouble2(line, pi.initialSpaces, Unit.NONE));
- pi.gpsLNav.setCus(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.gpsLNav.setSqrtA(parseBroadcastDouble4(line, pi.initialSpaces, SQRT_M));
- }
- /** {@inheritDoc} */
- @Override
- public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.gpsLNav.setTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.gpsLNav.setCic(parseBroadcastDouble2(line, pi.initialSpaces, Unit.RADIAN));
- pi.gpsLNav.setOmega0(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.gpsLNav.setCis(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.gpsLNav.setI0(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.gpsLNav.setCrc(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.gpsLNav.setPa(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.gpsLNav.setOmegaDot(parseBroadcastDouble4(line, pi.initialSpaces, RAD_PER_S));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
- // iDot
- pi.gpsLNav.setIDot(parseBroadcastDouble1(line, pi.initialSpaces, RAD_PER_S));
- // Codes on L2 channel (ignored)
- // RinexUtils.parseDouble(line, 23, 19)
- // GPS week (to go with Toe)
- pi.gpsLNav.setWeek((int) RinexUtils.parseDouble(line, 42, 19));
- pi.gpsLNav.setDate(new GNSSDate(pi.gpsLNav.getWeek(),
- pi.gpsLNav.getTime(),
- SatelliteSystem.GPS,
- pi.timeScales).getDate());
- }
- /** {@inheritDoc} */
- @Override
- public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.gpsLNav.setSvAccuracy(parseBroadcastDouble1(line, pi.initialSpaces, Unit.METRE));
- pi.gpsLNav.setSvHealth(parseBroadcastInt2(line, pi.initialSpaces));
- pi.gpsLNav.setTGD(parseBroadcastDouble3(line, pi.initialSpaces, Unit.SECOND));
- pi.gpsLNav.setIODC(parseBroadcastInt4(line, pi.initialSpaces));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.gpsLNav.setTransmissionTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.gpsLNav.setFitInterval(parseBroadcastInt2(line, pi.initialSpaces));
- pi.closePendingMessage();
- }
- /** {@inheritDoc} */
- @Override
- public void closeMessage(final ParseInfo pi) {
- pi.file.addGPSLegacyNavigationMessage(pi.gpsLNav);
- pi.gpsLNav = null;
- }
- },
- /** GPS civilian.
- * @since 12.0
- */
- GPS_CNAV() {
- /** {@inheritDoc} */
- @Override
- public void parseSvEpochSvClockLine(final String line, final ParseInfo pi) {
- parseSvEpochSvClockLine(line, pi.timeScales.getGPS(), pi.gpsCNav);
- }
- /** {@inheritDoc} */
- @Override
- public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.gpsCNav.setADot(parseBroadcastDouble1(line, pi.initialSpaces, M_PER_S));
- pi.gpsCNav.setCrs(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.gpsCNav.setDeltaN(parseBroadcastDouble3(line, pi.initialSpaces, RAD_PER_S));
- pi.gpsCNav.setM0(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.gpsCNav.setCuc(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.gpsCNav.setE(parseBroadcastDouble2(line, pi.initialSpaces, Unit.NONE));
- pi.gpsCNav.setCus(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.gpsCNav.setSqrtA(parseBroadcastDouble4(line, pi.initialSpaces, SQRT_M));
- }
- /** {@inheritDoc} */
- @Override
- public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.gpsCNav.setTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.gpsCNav.setCic(parseBroadcastDouble2(line, pi.initialSpaces, Unit.RADIAN));
- pi.gpsCNav.setOmega0(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.gpsCNav.setCis(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.gpsCNav.setI0(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.gpsCNav.setCrc(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.gpsCNav.setPa(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.gpsCNav.setOmegaDot(parseBroadcastDouble4(line, pi.initialSpaces, RAD_PER_S));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.gpsCNav.setIDot(parseBroadcastDouble1(line, pi.initialSpaces, RAD_PER_S));
- pi.gpsCNav.setDeltaN0Dot(parseBroadcastDouble2(line, pi.initialSpaces, RAD_PER_S2));
- pi.gpsCNav.setUraiNed0(parseBroadcastInt3(line, pi.initialSpaces));
- pi.gpsCNav.setUraiNed1(parseBroadcastInt4(line, pi.initialSpaces));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.gpsCNav.setUraiEd(parseBroadcastInt1(line, pi.initialSpaces));
- pi.gpsCNav.setSvHealth(parseBroadcastInt2(line, pi.initialSpaces));
- pi.gpsCNav.setTGD(parseBroadcastDouble3(line, pi.initialSpaces, Unit.SECOND));
- pi.gpsCNav.setUraiNed2(parseBroadcastInt4(line, pi.initialSpaces));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.gpsCNav.setIscL1CA(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.gpsCNav.setIscL2C(parseBroadcastDouble2(line, pi.initialSpaces, Unit.SECOND));
- pi.gpsCNav.setIscL5I5(parseBroadcastDouble3(line, pi.initialSpaces, Unit.SECOND));
- pi.gpsCNav.setIscL5Q5(parseBroadcastDouble4(line, pi.initialSpaces, Unit.SECOND));
- }
- /** {@inheritDoc} */
- @Override
- public void parseEighthBroadcastOrbit(final String line, final ParseInfo pi) {
- if (pi.gpsCNav.isCnv2()) {
- // in CNAV2 messages, there is an additional line for L1 CD and L1 CP inter signal delay
- pi.gpsCNav.setIscL1CD(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.gpsCNav.setIscL1CP(parseBroadcastDouble2(line, pi.initialSpaces, Unit.SECOND));
- } else {
- parseTransmissionTimeLine(line, pi);
- }
- }
- /** {@inheritDoc} */
- @Override
- public void parseNinthBroadcastOrbit(final String line, final ParseInfo pi) {
- parseTransmissionTimeLine(line, pi);
- }
- /** Parse transmission time line.
- * @param line line to parse
- * @param pi holder for transient data
- */
- private void parseTransmissionTimeLine(final String line, final ParseInfo pi) {
- pi.gpsCNav.setTransmissionTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.closePendingMessage();
- }
- /** {@inheritDoc} */
- @Override
- public void closeMessage(final ParseInfo pi) {
- pi.file.addGPSLegacyNavigationMessage(pi.gpsCNav);
- pi.gpsCNav = null;
- }
- },
- /** Galileo. */
- GALILEO() {
- /** {@inheritDoc} */
- @Override
- public void parseSvEpochSvClockLine(final String line, final ParseInfo pi) {
- parseSvEpochSvClockLine(line, pi.timeScales.getGPS(), pi.galileoNav);
- }
- /** {@inheritDoc} */
- @Override
- public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.galileoNav.setIODNav(parseBroadcastInt1(line, pi.initialSpaces));
- pi.galileoNav.setCrs(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.galileoNav.setDeltaN(parseBroadcastDouble3(line, pi.initialSpaces, RAD_PER_S));
- pi.galileoNav.setM0(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.galileoNav.setCuc(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.galileoNav.setE(parseBroadcastDouble2(line, pi.initialSpaces, Unit.NONE));
- pi.galileoNav.setCus(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.galileoNav.setSqrtA(parseBroadcastDouble4(line, pi.initialSpaces, SQRT_M));
- }
- /** {@inheritDoc} */
- @Override
- public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.galileoNav.setTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.galileoNav.setCic(parseBroadcastDouble2(line, pi.initialSpaces, Unit.RADIAN));
- pi.galileoNav.setOmega0(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.galileoNav.setCis(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.galileoNav.setI0(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.galileoNav.setCrc(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.galileoNav.setPa(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.galileoNav.setOmegaDot(parseBroadcastDouble4(line, pi.initialSpaces, RAD_PER_S));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
- // iDot
- pi.galileoNav.setIDot(parseBroadcastDouble1(line, pi.initialSpaces, RAD_PER_S));
- pi.galileoNav.setDataSource(parseBroadcastInt2(line, pi.initialSpaces));
- // GAL week (to go with Toe)
- pi.galileoNav.setWeek(parseBroadcastInt3(line, pi.initialSpaces));
- pi.galileoNav.setDate(new GNSSDate(pi.galileoNav.getWeek(),
- pi.galileoNav.getTime(),
- SatelliteSystem.GPS, // in Rinex files, week number is aligned to GPS week!
- pi.timeScales).getDate());
- }
- /** {@inheritDoc} */
- @Override
- public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.galileoNav.setSisa(parseBroadcastDouble1(line, pi.initialSpaces, Unit.METRE));
- pi.galileoNav.setSvHealth(parseBroadcastDouble2(line, pi.initialSpaces, Unit.NONE));
- pi.galileoNav.setBGDE1E5a(parseBroadcastDouble3(line, pi.initialSpaces, Unit.SECOND));
- pi.galileoNav.setBGDE5bE1(parseBroadcastDouble4(line, pi.initialSpaces, Unit.SECOND));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.galileoNav.setTransmissionTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.closePendingMessage();
- }
- /** {@inheritDoc} */
- @Override
- public void closeMessage(final ParseInfo pi) {
- pi.file.addGalileoNavigationMessage(pi.galileoNav);
- pi.galileoNav = null;
- }
- },
- /** Glonass. */
- GLONASS() {
- /** {@inheritDoc} */
- @Override
- public void parseSvEpochSvClockLine(final String line, final ParseInfo pi) {
- if (pi.file.getHeader().getFormatVersion() < 3.0) {
- pi.glonassNav.setPRN(RinexUtils.parseInt(line, 0, 2));
- // Toc
- final int year = RinexUtils.convert2DigitsYear(RinexUtils.parseInt(line, 3, 2));
- final int month = RinexUtils.parseInt(line, 6, 2);
- final int day = RinexUtils.parseInt(line, 9, 2);
- final int hours = RinexUtils.parseInt(line, 12, 2);
- final int min = RinexUtils.parseInt(line, 15, 2);
- final double sec = RinexUtils.parseDouble(line, 17, 5);
- pi.glonassNav.setEpochToc(new AbsoluteDate(year, month, day, hours, min, sec,
- pi.timeScales.getUTC()));
- // clock
- pi.glonassNav.setTauN(-RinexUtils.parseDouble(line, 22, 19));
- pi.glonassNav.setGammaN(RinexUtils.parseDouble(line, 41, 19));
- pi.glonassNav.setTime(fmod(RinexUtils.parseDouble(line, 60, 19), Constants.JULIAN_DAY));
- // Set the ephemeris epoch (same as time of clock epoch)
- pi.glonassNav.setDate(pi.glonassNav.getEpochToc());
- } else {
- pi.glonassNav.setPRN(RinexUtils.parseInt(line, 1, 2));
- // Toc
- pi.glonassNav.setEpochToc(parsePrnSvEpochClock(line, pi.timeScales.getUTC()));
- // clock
- pi.glonassNav.setTauN(-RinexUtils.parseDouble(line, 23, 19));
- pi.glonassNav.setGammaN(RinexUtils.parseDouble(line, 42, 19));
- pi.glonassNav.setTime(fmod(RinexUtils.parseDouble(line, 61, 19), Constants.JULIAN_DAY));
- // Set the ephemeris epoch (same as time of clock epoch)
- pi.glonassNav.setDate(pi.glonassNav.getEpochToc());
- }
- }
- /** {@inheritDoc} */
- @Override
- public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.glonassNav.setX(parseBroadcastDouble1(line, pi.initialSpaces, KM));
- pi.glonassNav.setXDot(parseBroadcastDouble2(line, pi.initialSpaces, KM_PER_S));
- pi.glonassNav.setXDotDot(parseBroadcastDouble3(line, pi.initialSpaces, KM_PER_S2));
- pi.glonassNav.setHealth(parseBroadcastDouble4(line, pi.initialSpaces, Unit.NONE));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.glonassNav.setY(parseBroadcastDouble1(line, pi.initialSpaces, KM));
- pi.glonassNav.setYDot(parseBroadcastDouble2(line, pi.initialSpaces, KM_PER_S));
- pi.glonassNav.setYDotDot(parseBroadcastDouble3(line, pi.initialSpaces, KM_PER_S2));
- pi.glonassNav.setFrequencyNumber(parseBroadcastDouble4(line, pi.initialSpaces, Unit.NONE));
- }
- /** {@inheritDoc} */
- @Override
- public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.glonassNav.setZ(parseBroadcastDouble1(line, pi.initialSpaces, KM));
- pi.glonassNav.setZDot(parseBroadcastDouble2(line, pi.initialSpaces, KM_PER_S));
- pi.glonassNav.setZDotDot(parseBroadcastDouble3(line, pi.initialSpaces, KM_PER_S2));
- if (pi.file.getHeader().getFormatVersion() < 3.045) {
- pi.closePendingMessage();
- }
- }
- /** {@inheritDoc} */
- @Override
- public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.glonassNav.setStatusFlags(parseBroadcastDouble1(line, pi.initialSpaces, Unit.NONE));
- pi.glonassNav.setGroupDelayDifference(parseBroadcastDouble2(line, pi.initialSpaces, Unit.NONE));
- pi.glonassNav.setURA(parseBroadcastDouble3(line, pi.initialSpaces, Unit.NONE));
- pi.glonassNav.setHealthFlags(parseBroadcastDouble4(line, pi.initialSpaces, Unit.NONE));
- pi.closePendingMessage();
- }
- /** {@inheritDoc} */
- @Override
- public void closeMessage(final ParseInfo pi) {
- pi.file.addGlonassNavigationMessage(pi.glonassNav);
- pi.glonassNav = null;
- }
- },
- /** QZSS legacy. */
- QZSS_LNAV() {
- /** {@inheritDoc} */
- @Override
- public void parseSvEpochSvClockLine(final String line, final ParseInfo pi) {
- parseSvEpochSvClockLine(line, pi.timeScales.getGPS(), pi.qzssLNav);
- }
- /** {@inheritDoc} */
- @Override
- public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.qzssLNav.setIODE(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.qzssLNav.setCrs(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.qzssLNav.setDeltaN(parseBroadcastDouble3(line, pi.initialSpaces, RAD_PER_S));
- pi.qzssLNav.setM0(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.qzssLNav.setCuc(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.qzssLNav.setE(parseBroadcastDouble2(line, pi.initialSpaces, Unit.NONE));
- pi.qzssLNav.setCus(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.qzssLNav.setSqrtA(parseBroadcastDouble4(line, pi.initialSpaces, SQRT_M));
- }
- /** {@inheritDoc} */
- @Override
- public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.qzssLNav.setTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.qzssLNav.setCic(parseBroadcastDouble2(line, pi.initialSpaces, Unit.RADIAN));
- pi.qzssLNav.setOmega0(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.qzssLNav.setCis(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.qzssLNav.setI0(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.qzssLNav.setCrc(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.qzssLNav.setPa(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.qzssLNav.setOmegaDot(parseBroadcastDouble4(line, pi.initialSpaces, RAD_PER_S));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
- // iDot
- pi.qzssLNav.setIDot(parseBroadcastDouble1(line, pi.initialSpaces, RAD_PER_S));
- // Codes on L2 channel (ignored)
- // RinexUtils.parseDouble(line, 23, 19)
- // GPS week (to go with Toe)
- pi.qzssLNav.setWeek(parseBroadcastInt3(line, pi.initialSpaces));
- pi.qzssLNav.setDate(new GNSSDate(pi.qzssLNav.getWeek(),
- pi.qzssLNav.getTime(),
- SatelliteSystem.GPS, // in Rinex files, week number is aligned to GPS week!
- pi.timeScales).getDate());
- }
- /** {@inheritDoc} */
- @Override
- public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.qzssLNav.setSvAccuracy(parseBroadcastDouble1(line, pi.initialSpaces, Unit.METRE));
- pi.qzssLNav.setSvHealth(parseBroadcastInt2(line, pi.initialSpaces));
- pi.qzssLNav.setTGD(parseBroadcastDouble3(line, pi.initialSpaces, Unit.SECOND));
- pi.qzssLNav.setIODC(parseBroadcastInt4(line, pi.initialSpaces));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.qzssLNav.setTransmissionTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.qzssLNav.setFitInterval(parseBroadcastInt2(line, pi.initialSpaces));
- pi.closePendingMessage();
- }
- /** {@inheritDoc} */
- @Override
- public void closeMessage(final ParseInfo pi) {
- pi.file.addQZSSLegacyNavigationMessage(pi.qzssLNav);
- pi.qzssLNav = null;
- }
- },
- /** QZSS civilian.
- * @since 12.0
- */
- QZSS_CNAV() {
- /** {@inheritDoc} */
- @Override
- public void parseSvEpochSvClockLine(final String line, final ParseInfo pi) {
- parseSvEpochSvClockLine(line, pi.timeScales.getGPS(), pi.qzssCNav);
- }
- /** {@inheritDoc} */
- @Override
- public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.qzssCNav.setADot(parseBroadcastDouble1(line, pi.initialSpaces, M_PER_S));
- pi.qzssCNav.setCrs(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.qzssCNav.setDeltaN(parseBroadcastDouble3(line, pi.initialSpaces, RAD_PER_S));
- pi.qzssCNav.setM0(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.qzssCNav.setCuc(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.qzssCNav.setE(parseBroadcastDouble2(line, pi.initialSpaces, Unit.NONE));
- pi.qzssCNav.setCus(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.qzssCNav.setSqrtA(parseBroadcastDouble4(line, pi.initialSpaces, SQRT_M));
- }
- /** {@inheritDoc} */
- @Override
- public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.qzssCNav.setTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.qzssCNav.setCic(parseBroadcastDouble2(line, pi.initialSpaces, Unit.RADIAN));
- pi.qzssCNav.setOmega0(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.qzssCNav.setCis(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.qzssCNav.setI0(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.qzssCNav.setCrc(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.qzssCNav.setPa(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.qzssCNav.setOmegaDot(parseBroadcastDouble4(line, pi.initialSpaces, RAD_PER_S));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.qzssCNav.setIDot(parseBroadcastDouble1(line, pi.initialSpaces, RAD_PER_S));
- pi.qzssCNav.setDeltaN0Dot(parseBroadcastDouble2(line, pi.initialSpaces, RAD_PER_S2));
- pi.qzssCNav.setUraiNed0(parseBroadcastInt3(line, pi.initialSpaces));
- pi.qzssCNav.setUraiNed1(parseBroadcastInt4(line, pi.initialSpaces));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.qzssCNav.setUraiEd(parseBroadcastInt1(line, pi.initialSpaces));
- pi.qzssCNav.setSvHealth(parseBroadcastInt2(line, pi.initialSpaces));
- pi.qzssCNav.setTGD(parseBroadcastDouble3(line, pi.initialSpaces, Unit.SECOND));
- pi.qzssCNav.setUraiNed2(parseBroadcastInt4(line, pi.initialSpaces));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.qzssCNav.setIscL1CA(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.qzssCNav.setIscL2C(parseBroadcastDouble2(line, pi.initialSpaces, Unit.SECOND));
- pi.qzssCNav.setIscL5I5(parseBroadcastDouble3(line, pi.initialSpaces, Unit.SECOND));
- pi.qzssCNav.setIscL5Q5(parseBroadcastDouble4(line, pi.initialSpaces, Unit.SECOND));
- }
- /** {@inheritDoc} */
- @Override
- public void parseEighthBroadcastOrbit(final String line, final ParseInfo pi) {
- if (pi.qzssCNav.isCnv2()) {
- // in CNAV2 messages, there is an additional line for L1 CD and L1 CP inter signal delay
- pi.qzssCNav.setIscL1CD(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.qzssCNav.setIscL1CP(parseBroadcastDouble2(line, pi.initialSpaces, Unit.SECOND));
- } else {
- parseTransmissionTimeLine(line, pi);
- }
- }
- /** {@inheritDoc} */
- @Override
- public void parseNinthBroadcastOrbit(final String line, final ParseInfo pi) {
- parseTransmissionTimeLine(line, pi);
- }
- /** Parse transmission time line.
- * @param line line to parse
- * @param pi holder for transient data
- */
- private void parseTransmissionTimeLine(final String line, final ParseInfo pi) {
- pi.qzssCNav.setTransmissionTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.closePendingMessage();
- }
- /** {@inheritDoc} */
- @Override
- public void closeMessage(final ParseInfo pi) {
- pi.file.addQZSSCivilianNavigationMessage(pi.qzssCNav);
- pi.qzssCNav = null;
- }
- },
- /** Beidou legacy. */
- BEIDOU_D1_D2() {
- /** {@inheritDoc} */
- @Override
- public void parseSvEpochSvClockLine(final String line, final ParseInfo pi) {
- parseSvEpochSvClockLine(line, pi.timeScales.getBDT(), pi.beidouLNav);
- }
- /** {@inheritDoc} */
- @Override
- public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.beidouLNav.setAODE(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.beidouLNav.setCrs(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.beidouLNav.setDeltaN(parseBroadcastDouble3(line, pi.initialSpaces, RAD_PER_S));
- pi.beidouLNav.setM0(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.beidouLNav.setCuc(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.beidouLNav.setE(parseBroadcastDouble2(line, pi.initialSpaces, Unit.NONE));
- pi.beidouLNav.setCus(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.beidouLNav.setSqrtA(parseBroadcastDouble4(line, pi.initialSpaces, SQRT_M));
- }
- /** {@inheritDoc} */
- @Override
- public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.beidouLNav.setTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.beidouLNav.setCic(parseBroadcastDouble2(line, pi.initialSpaces, Unit.RADIAN));
- pi.beidouLNav.setOmega0(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.beidouLNav.setCis(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.beidouLNav.setI0(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.beidouLNav.setCrc(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.beidouLNav.setPa(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.beidouLNav.setOmegaDot(parseBroadcastDouble4(line, pi.initialSpaces, RAD_PER_S));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
- // iDot
- pi.beidouLNav.setIDot(parseBroadcastDouble1(line, pi.initialSpaces, RAD_PER_S));
- // BDT week (to go with Toe)
- pi.beidouLNav.setWeek(parseBroadcastInt3(line, pi.initialSpaces));
- pi.beidouLNav.setDate(new GNSSDate(pi.beidouLNav.getWeek(),
- pi.beidouLNav.getTime(),
- SatelliteSystem.BEIDOU,
- pi.timeScales).getDate());
- }
- /** {@inheritDoc} */
- @Override
- public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.beidouLNav.setSvAccuracy(parseBroadcastDouble1(line, pi.initialSpaces, Unit.METRE));
- // TODO SatH1
- pi.beidouLNav.setTGD1(parseBroadcastDouble3(line, pi.initialSpaces, Unit.SECOND));
- pi.beidouLNav.setTGD2(parseBroadcastDouble4(line, pi.initialSpaces, Unit.SECOND));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.beidouLNav.setTransmissionTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.beidouLNav.setAODC(parseBroadcastDouble2(line, pi.initialSpaces, Unit.SECOND));
- pi.closePendingMessage();
- }
- /** {@inheritDoc} */
- @Override
- public void closeMessage(final ParseInfo pi) {
- pi.file.addBeidouLegacyNavigationMessage(pi.beidouLNav);
- pi.beidouLNav = null;
- }
- },
- /** Beidou-3 CNAV. */
- BEIDOU_CNV_123() {
- /** {@inheritDoc} */
- @Override
- public void parseSvEpochSvClockLine(final String line, final ParseInfo pi) {
- parseSvEpochSvClockLine(line, pi.timeScales.getBDT(), pi.beidouCNav);
- }
- /** {@inheritDoc} */
- @Override
- public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.beidouCNav.setADot(parseBroadcastDouble1(line, pi.initialSpaces, M_PER_S));
- pi.beidouCNav.setCrs(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.beidouCNav.setDeltaN(parseBroadcastDouble3(line, pi.initialSpaces, RAD_PER_S));
- pi.beidouCNav.setM0(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.beidouCNav.setCuc(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.beidouCNav.setE(parseBroadcastDouble2(line, pi.initialSpaces, Unit.NONE));
- pi.beidouCNav.setCus(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.beidouCNav.setSqrtA(parseBroadcastDouble4(line, pi.initialSpaces, SQRT_M));
- }
- /** {@inheritDoc} */
- @Override
- public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.beidouCNav.setTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.beidouCNav.setCic(parseBroadcastDouble2(line, pi.initialSpaces, Unit.RADIAN));
- pi.beidouCNav.setOmega0(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.beidouCNav.setCis(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.beidouCNav.setI0(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.beidouCNav.setCrc(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.beidouCNav.setPa(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.beidouCNav.setOmegaDot(parseBroadcastDouble4(line, pi.initialSpaces, RAD_PER_S));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.beidouCNav.setIDot(parseBroadcastDouble1(line, pi.initialSpaces, RAD_PER_S));
- pi.beidouCNav.setDeltaN0Dot(parseBroadcastDouble2(line, pi.initialSpaces, RAD_PER_S2));
- switch (parseBroadcastInt3(line, pi.initialSpaces)) {
- case 0 :
- pi.beidouCNav.setSatelliteType(BeidouSatelliteType.RESERVED);
- break;
- case 1 :
- pi.beidouCNav.setSatelliteType(BeidouSatelliteType.GEO);
- break;
- case 2 :
- pi.beidouCNav.setSatelliteType(BeidouSatelliteType.IGSO);
- break;
- case 3 :
- pi.beidouCNav.setSatelliteType(BeidouSatelliteType.MEO);
- break;
- default:
- throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
- pi.lineNumber, pi.name, line);
- }
- pi.beidouCNav.setTime(parseBroadcastDouble4(line, pi.initialSpaces, Unit.SECOND));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.beidouCNav.setSisaiOe(parseBroadcastInt1(line, pi.initialSpaces));
- pi.beidouCNav.setSisaiOcb(parseBroadcastInt2(line, pi.initialSpaces));
- pi.beidouCNav.setSisaiOc1(parseBroadcastInt3(line, pi.initialSpaces));
- pi.beidouCNav.setSisaiOc2(parseBroadcastInt4(line, pi.initialSpaces));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
- if (pi.beidouCNav.getSignal() == Frequency.B1C) {
- pi.beidouCNav.setIscB1CD(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- // field 2 is spare
- pi.beidouCNav.setTgdB1Cp(parseBroadcastDouble3(line, pi.initialSpaces, Unit.SECOND));
- pi.beidouCNav.setTgdB2ap(parseBroadcastDouble4(line, pi.initialSpaces, Unit.SECOND));
- } else if (pi.beidouCNav.getSignal() == Frequency.B2A) {
- // field 1 is spare
- pi.beidouCNav.setIscB2AD(parseBroadcastDouble2(line, pi.initialSpaces, Unit.SECOND));
- pi.beidouCNav.setTgdB1Cp(parseBroadcastDouble3(line, pi.initialSpaces, Unit.SECOND));
- pi.beidouCNav.setTgdB2ap(parseBroadcastDouble4(line, pi.initialSpaces, Unit.SECOND));
- } else {
- parseSismaiHealthIntegrity(line, pi);
- }
- }
- /** {@inheritDoc} */
- @Override
- public void parseEighthBroadcastOrbit(final String line, final ParseInfo pi) {
- if (pi.beidouCNav.getSignal() == Frequency.B2B) {
- pi.beidouCNav.setTransmissionTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.closePendingMessage();
- } else {
- parseSismaiHealthIntegrity(line, pi);
- }
- }
- /** {@inheritDoc} */
- @Override
- public void parseNinthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.beidouCNav.setTransmissionTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- // field 2 is spare
- // field 3 is spare
- pi.beidouCNav.setIODE(parseBroadcastInt4(line, pi.initialSpaces));
- pi.closePendingMessage();
- }
- /** {@inheritDoc} */
- @Override
- public void closeMessage(final ParseInfo pi) {
- pi.file.addBeidouCivilianNavigationMessage(pi.beidouCNav);
- pi.beidouCNav = null;
- }
- /**
- * Parse the SISMAI/Health/integrity line.
- * @param line line to read
- * @param pi holder for transient data
- */
- private void parseSismaiHealthIntegrity(final String line, final ParseInfo pi) {
- pi.beidouCNav.setSismai(parseBroadcastInt1(line, pi.initialSpaces));
- pi.beidouCNav.setHealth(parseBroadcastInt2(line, pi.initialSpaces));
- pi.beidouCNav.setIntegrityFlags(parseBroadcastInt3(line, pi.initialSpaces));
- pi.beidouCNav.setIODC(parseBroadcastInt4(line, pi.initialSpaces));
- }
- },
- /** SBAS. */
- SBAS() {
- /** {@inheritDoc} */
- @Override
- public void parseSvEpochSvClockLine(final String line, final ParseInfo pi) {
- // parse PRN
- pi.sbasNav.setPRN(RinexUtils.parseInt(line, 1, 2));
- // Time scale (UTC for Rinex 3.01 and GPS for other RINEX versions)
- final int version100 = (int) FastMath.rint(pi.file.getHeader().getFormatVersion() * 100);
- final TimeScale timeScale = (version100 == 301) ? pi.timeScales.getUTC() : pi.timeScales.getGPS();
- pi.sbasNav.setEpochToc(parsePrnSvEpochClock(line, timeScale));
- pi.sbasNav.setAGf0(parseBroadcastDouble2(line, pi.initialSpaces, Unit.SECOND));
- pi.sbasNav.setAGf1(parseBroadcastDouble3(line, pi.initialSpaces, S_PER_S));
- pi.sbasNav.setTime(parseBroadcastDouble4(line, pi.initialSpaces, Unit.SECOND));
- // Set the ephemeris epoch (same as time of clock epoch)
- pi.sbasNav.setDate(pi.sbasNav.getEpochToc());
- }
- /** {@inheritDoc} */
- @Override
- public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.sbasNav.setX(parseBroadcastDouble1(line, pi.initialSpaces, KM));
- pi.sbasNav.setXDot(parseBroadcastDouble2(line, pi.initialSpaces, KM_PER_S));
- pi.sbasNav.setXDotDot(parseBroadcastDouble3(line, pi.initialSpaces, KM_PER_S2));
- pi.sbasNav.setHealth(parseBroadcastDouble4(line, pi.initialSpaces, Unit.NONE));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.sbasNav.setY(parseBroadcastDouble1(line, pi.initialSpaces, KM));
- pi.sbasNav.setYDot(parseBroadcastDouble2(line, pi.initialSpaces, KM_PER_S));
- pi.sbasNav.setYDotDot(parseBroadcastDouble3(line, pi.initialSpaces, KM_PER_S2));
- pi.sbasNav.setURA(parseBroadcastDouble4(line, pi.initialSpaces, Unit.NONE));
- }
- /** {@inheritDoc} */
- @Override
- public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.sbasNav.setZ(parseBroadcastDouble1(line, pi.initialSpaces, KM));
- pi.sbasNav.setZDot(parseBroadcastDouble2(line, pi.initialSpaces, KM_PER_S));
- pi.sbasNav.setZDotDot(parseBroadcastDouble3(line, pi.initialSpaces, KM_PER_S2));
- pi.sbasNav.setIODN(parseBroadcastDouble4(line, pi.initialSpaces, Unit.NONE));
- pi.closePendingMessage();
- }
- /** {@inheritDoc} */
- @Override
- public void closeMessage(final ParseInfo pi) {
- pi.file.addSBASNavigationMessage(pi.sbasNav);
- pi.sbasNav = null;
- }
- },
- /** IRNSS. */
- IRNSS() {
- /** {@inheritDoc} */
- @Override
- public void parseSvEpochSvClockLine(final String line, final ParseInfo pi) {
- parseSvEpochSvClockLine(line, pi.timeScales.getIRNSS(), pi.irnssNav);
- }
- /** {@inheritDoc} */
- @Override
- public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.irnssNav.setIODEC(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.irnssNav.setCrs(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.irnssNav.setDeltaN(parseBroadcastDouble3(line, pi.initialSpaces, RAD_PER_S));
- pi.irnssNav.setM0(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.irnssNav.setCuc(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.irnssNav.setE(parseBroadcastDouble2(line, pi.initialSpaces, Unit.NONE));
- pi.irnssNav.setCus(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.irnssNav.setSqrtA(parseBroadcastDouble4(line, pi.initialSpaces, SQRT_M));
- }
- /** {@inheritDoc} */
- @Override
- public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.irnssNav.setTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.irnssNav.setCic(parseBroadcastDouble2(line, pi.initialSpaces, Unit.RADIAN));
- pi.irnssNav.setOmega0(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.irnssNav.setCis(parseBroadcastDouble4(line, pi.initialSpaces, Unit.RADIAN));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.irnssNav.setI0(parseBroadcastDouble1(line, pi.initialSpaces, Unit.RADIAN));
- pi.irnssNav.setCrc(parseBroadcastDouble2(line, pi.initialSpaces, Unit.METRE));
- pi.irnssNav.setPa(parseBroadcastDouble3(line, pi.initialSpaces, Unit.RADIAN));
- pi.irnssNav.setOmegaDot(parseBroadcastDouble4(line, pi.initialSpaces, RAD_PER_S));
- }
- /** {@inheritDoc} */
- @Override
- public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
- // iDot
- pi.irnssNav.setIDot(parseBroadcastDouble1(line, pi.initialSpaces, RAD_PER_S));
- // IRNSS week (to go with Toe)
- pi.irnssNav.setWeek(parseBroadcastInt3(line, pi.initialSpaces));
- pi.irnssNav.setDate(new GNSSDate(pi.irnssNav.getWeek(),
- pi.irnssNav.getTime(),
- SatelliteSystem.GPS, // in Rinex files, week number is aligned to GPS week!
- pi.timeScales).getDate());
- }
- /** {@inheritDoc} */
- @Override
- public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.irnssNav.setURA(parseBroadcastDouble1(line, pi.initialSpaces, Unit.METRE));
- pi.irnssNav.setSvHealth(parseBroadcastDouble2(line, pi.initialSpaces, Unit.NONE));
- pi.irnssNav.setTGD(parseBroadcastDouble3(line, pi.initialSpaces, Unit.SECOND));
- }
- /** {@inheritDoc} */
- @Override
- public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
- pi.irnssNav.setTransmissionTime(parseBroadcastDouble1(line, pi.initialSpaces, Unit.SECOND));
- pi.closePendingMessage();
- }
- /** {@inheritDoc} */
- @Override
- public void closeMessage(final ParseInfo pi) {
- pi.file.addIRNSSNavigationMessage(pi.irnssNav);
- pi.irnssNav = null;
- }
- };
- /** Get the parse for navigation message.
- * @param system satellite system
- * @param type message type (null for Rinex 3.x)
- * @param parseInfo container for transient data
- * @param line line being parsed
- * @return the satellite system line parser
- */
- private static SatelliteSystemLineParser getParser(final SatelliteSystem system, final String type,
- final ParseInfo parseInfo, final String line) {
- switch (system) {
- case GPS :
- if (type == null || type.equals(LegacyNavigationMessage.LNAV)) {
- parseInfo.gpsLNav = new GPSLegacyNavigationMessage();
- return GPS_LNAV;
- } else if (type.equals(CivilianNavigationMessage.CNAV)) {
- parseInfo.gpsCNav = new GPSCivilianNavigationMessage(false);
- return GPS_CNAV;
- } else if (type.equals(CivilianNavigationMessage.CNV2)) {
- parseInfo.gpsCNav = new GPSCivilianNavigationMessage(true);
- return GPS_CNAV;
- }
- break;
- case GALILEO :
- if (type == null || type.equals("INAV") || type.equals("FNAV")) {
- parseInfo.galileoNav = new GalileoNavigationMessage();
- return GALILEO;
- }
- break;
- case GLONASS :
- if (type == null || type.equals("FDMA")) {
- parseInfo.glonassNav = new GLONASSNavigationMessage();
- return GLONASS;
- }
- break;
- case QZSS :
- if (type == null || type.equals(LegacyNavigationMessage.LNAV)) {
- parseInfo.qzssLNav = new QZSSLegacyNavigationMessage();
- return QZSS_LNAV;
- } else if (type.equals(CivilianNavigationMessage.CNAV)) {
- parseInfo.qzssCNav = new QZSSCivilianNavigationMessage(false);
- return QZSS_CNAV;
- } else if (type.equals(CivilianNavigationMessage.CNV2)) {
- parseInfo.qzssCNav = new QZSSCivilianNavigationMessage(true);
- return QZSS_CNAV;
- }
- break;
- case BEIDOU :
- if (type == null ||
- type.equals(BeidouLegacyNavigationMessage.D1) ||
- type.equals(BeidouLegacyNavigationMessage.D2)) {
- parseInfo.beidouLNav = new BeidouLegacyNavigationMessage();
- return BEIDOU_D1_D2;
- } else if (type.equals(BeidouCivilianNavigationMessage.CNV1)) {
- parseInfo.beidouCNav = new BeidouCivilianNavigationMessage(Frequency.B1C);
- return BEIDOU_CNV_123;
- } else if (type.equals(BeidouCivilianNavigationMessage.CNV2)) {
- parseInfo.beidouCNav = new BeidouCivilianNavigationMessage(Frequency.B2A);
- return BEIDOU_CNV_123;
- } else if (type.equals(BeidouCivilianNavigationMessage.CNV3)) {
- parseInfo.beidouCNav = new BeidouCivilianNavigationMessage(Frequency.B2B);
- return BEIDOU_CNV_123;
- }
- break;
- case IRNSS :
- if (type == null || type.equals("LNAV")) {
- parseInfo.irnssNav = new IRNSSNavigationMessage();
- return IRNSS;
- }
- break;
- case SBAS :
- if (type == null || type.equals("SBAS")) {
- parseInfo.sbasNav = new SBASNavigationMessage();
- return SBAS;
- }
- break;
- default:
- // do nothing, handle error after the switch
- }
- throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
- parseInfo.lineNumber, parseInfo.name, line);
- }
- /**
- * Parse the SV/Epoch/Sv clock of the navigation message.
- * @param line line to read
- * @param timeScale time scale to use
- * @param message navigation message
- */
- protected void parseSvEpochSvClockLineRinex2(final String line, final TimeScale timeScale,
- final AbstractNavigationMessage message) {
- // PRN
- message.setPRN(RinexUtils.parseInt(line, 0, 2));
- // Toc
- final int year = RinexUtils.convert2DigitsYear(RinexUtils.parseInt(line, 2, 3));
- final int month = RinexUtils.parseInt(line, 5, 3);
- final int day = RinexUtils.parseInt(line, 8, 3);
- final int hours = RinexUtils.parseInt(line, 11, 3);
- final int min = RinexUtils.parseInt(line, 14, 3);
- final double sec = RinexUtils.parseDouble(line, 17, 5);
- message.setEpochToc(new AbsoluteDate( year, month, day, hours, min, sec, timeScale));
- // clock
- message.setAf0(RinexUtils.parseDouble(line, 22, 19));
- message.setAf1(RinexUtils.parseDouble(line, 41, 19));
- message.setAf2(RinexUtils.parseDouble(line, 60, 19));
- }
- /**
- * Parse the SV/Epoch/Sv clock of the navigation message.
- * @param line line to read
- * @param timeScale time scale to use
- * @param message navigation message
- */
- protected void parseSvEpochSvClockLine(final String line, final TimeScale timeScale,
- final AbstractNavigationMessage message) {
- // PRN
- message.setPRN(RinexUtils.parseInt(line, 1, 2));
- // Toc
- message.setEpochToc(parsePrnSvEpochClock(line, timeScale));
- // clock
- message.setAf0(RinexUtils.parseDouble(line, 23, 19));
- message.setAf1(RinexUtils.parseDouble(line, 42, 19));
- message.setAf2(RinexUtils.parseDouble(line, 61, 19));
- }
- /** Parse epoch field of a Sv/epoch/clock line.
- * @param line line to parse
- * @param timeScale time scale to use
- * @return parsed field
- */
- protected AbsoluteDate parsePrnSvEpochClock(final String line, final TimeScale timeScale) {
- final int year = RinexUtils.parseInt(line, 4, 4);
- final int month = RinexUtils.parseInt(line, 9, 2);
- final int day = RinexUtils.parseInt(line, 12, 2);
- final int hours = RinexUtils.parseInt(line, 15, 2);
- final int min = RinexUtils.parseInt(line, 18, 2);
- final int sec = RinexUtils.parseInt(line, 21, 2);
- return new AbsoluteDate(year, month, day, hours, min, sec, timeScale);
- }
- /** Parse double field 1 of a broadcast orbit line.
- * @param line line to parse
- * @param initialSpaces number of initial spaces in the line
- * @param unit unit to used for parsing the field
- * @return parsed field
- */
- protected double parseBroadcastDouble1(final String line, final int initialSpaces, final Unit unit) {
- return unit.toSI(RinexUtils.parseDouble(line, initialSpaces, 19));
- }
- /** Parse integer field 1 of a broadcast orbit line.
- * @param line line to parse
- * @param initialSpaces number of initial spaces in the line
- * @return parsed field
- */
- protected int parseBroadcastInt1(final String line, final int initialSpaces) {
- return (int) FastMath.rint(RinexUtils.parseDouble(line, initialSpaces, 19));
- }
- /** Parse double field 2 of a broadcast orbit line.
- * @param line line to parse
- * @param initialSpaces number of initial spaces in the line
- * @param unit unit to used for parsing the field
- * @return parsed field
- */
- protected double parseBroadcastDouble2(final String line, final int initialSpaces, final Unit unit) {
- return unit.toSI(RinexUtils.parseDouble(line, initialSpaces + 19, 19));
- }
- /** Parse integer field 2 of a broadcast orbit line.
- * @param line line to parse
- * @param initialSpaces number of initial spaces in the line
- * @return parsed field
- */
- protected int parseBroadcastInt2(final String line, final int initialSpaces) {
- return (int) FastMath.rint(RinexUtils.parseDouble(line, initialSpaces + 19, 19));
- }
- /** Parse double field 3 of a broadcast orbit line.
- * @param line line to parse
- * @param initialSpaces number of initial spaces in the line
- * @param unit unit to used for parsing the field
- * @return parsed field
- */
- protected double parseBroadcastDouble3(final String line, final int initialSpaces, final Unit unit) {
- return unit.toSI(RinexUtils.parseDouble(line, initialSpaces + 38, 19));
- }
- /** Parse integer field 3 of a broadcast orbit line.
- * @param line line to parse
- * @param initialSpaces number of initial spaces in the line
- * @return parsed field
- */
- protected int parseBroadcastInt3(final String line, final int initialSpaces) {
- return (int) FastMath.rint(RinexUtils.parseDouble(line, initialSpaces + 38, 19));
- }
- /** Parse double field 4 of a broadcast orbit line.
- * @param line line to parse
- * @param initialSpaces number of initial spaces in the line
- * @param unit unit to used for parsing the field
- * @return parsed field
- */
- protected double parseBroadcastDouble4(final String line, final int initialSpaces, final Unit unit) {
- return unit.toSI(RinexUtils.parseDouble(line, initialSpaces + 57, 19));
- }
- /** Parse integer field 4 of a broadcast orbit line.
- * @param line line to parse
- * @param initialSpaces number of initial spaces in the line
- * @return parsed field
- */
- protected int parseBroadcastInt4(final String line, final int initialSpaces) {
- return (int) FastMath.rint(RinexUtils.parseDouble(line, initialSpaces + 57, 19));
- }
- /**
- * Parse the SV/Epoch/Sv clock of the navigation message.
- * @param line line to read
- * @param pi holder for transient data
- */
- public abstract void parseSvEpochSvClockLine(String line, ParseInfo pi);
- /**
- * Parse the "BROADCASTORBIT - 1" line.
- * @param line line to read
- * @param pi holder for transient data
- */
- public abstract void parseFirstBroadcastOrbit(String line, ParseInfo pi);
- /**
- * Parse the "BROADCASTORBIT - 2" line.
- * @param line line to read
- * @param pi holder for transient data
- */
- public abstract void parseSecondBroadcastOrbit(String line, ParseInfo pi);
- /**
- * Parse the "BROADCASTORBIT - 3" line.
- * @param line line to read
- * @param pi holder for transient data
- */
- public abstract void parseThirdBroadcastOrbit(String line, ParseInfo pi);
- /**
- * Parse the "BROADCASTORBIT - 4" line.
- * @param line line to read
- * @param pi holder for transient data
- */
- public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
- // this should never be called (except by some tests that use reflection)
- throw new OrekitInternalError(null);
- }
- /**
- * Parse the "BROADCASTORBIT - 5" line.
- * @param line line to read
- * @param pi holder for transient data
- */
- public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
- // this should never be called (except by some tests that use reflection)
- throw new OrekitInternalError(null);
- }
- /**
- * Parse the "BROADCASTORBIT - 6" line.
- * @param line line to read
- * @param pi holder for transient data
- */
- public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
- // this should never be called (except by some tests that use reflection)
- throw new OrekitInternalError(null);
- }
- /**
- * Parse the "BROADCASTORBIT - 7" line.
- * @param line line to read
- * @param pi holder for transient data
- */
- public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
- // this should never be called (except by some tests that use reflection)
- throw new OrekitInternalError(null);
- }
- /**
- * Parse the "BROADCASTORBIT - 8" line.
- * @param line line to read
- * @param pi holder for transient data
- */
- public void parseEighthBroadcastOrbit(final String line, final ParseInfo pi) {
- // this should never be called (except by some tests that use reflection)
- throw new OrekitInternalError(null);
- }
- /**
- * Parse the "BROADCASTORBIT - 9" line.
- * @param line line to read
- * @param pi holder for transient data
- */
- public void parseNinthBroadcastOrbit(final String line, final ParseInfo pi) {
- // this should never be called (except by some tests that use reflection)
- throw new OrekitInternalError(null);
- }
- /**
- * Close a message as last line was parsed.
- * @param pi holder for transient data
- */
- public abstract void closeMessage(ParseInfo pi);
- /**
- * Calculates the floating-point remainder of a / b.
- * <p>
- * fmod = a - x * b
- * where x = (int) a / b
- * </p>
- * @param a numerator
- * @param b denominator
- * @return the floating-point remainder of a / b
- */
- private static double fmod(final double a, final double b) {
- final double x = (int) (a / b);
- return a - x * b;
- }
- }
- /** Parsing method. */
- @FunctionalInterface
- private interface ParsingMethod {
- /** Parse a line.
- * @param line line to parse
- * @param parseInfo holder for transient data
- */
- void parse(String line, ParseInfo parseInfo);
- }
- }