public override void updateMeasurements(GnssMeasurementsEvent evento) { lock (this) { visibleButNotUsed = 0; observedSatellites.Clear(); unusedSatellites.Clear(); GnssClock gnssClock = evento.Clock; long TimeNanos = gnssClock.TimeNanos; timeRefMsec = new Time(JavaSystem.CurrentTimeMillis()); double BiasNanos = gnssClock.BiasNanos; double galileoTime, pseudorangeTOW, pseudorangeE1_2nd, tTxGalileo; // Use only the first instance of the FullBiasNanos (as done in gps-measurement-tools) if (!fullBiasNanosInitialized) { FullBiasNanos = gnssClock.FullBiasNanos; fullBiasNanosInitialized = true; } // Start computing the pseudoranges using the raw data from the phone's GNSS receiver foreach (GnssMeasurement measurement in evento.Measurements) { if (measurement.ConstellationType != constellationId) { continue; } if (measurement.HasCarrierFrequencyHz) { if (!approximateEqual(measurement.CarrierFrequencyHz, E1a_FREQUENCY, FREQUENCY_MATCH_RANGE)) { continue; } } long ReceivedSvTimeNanos = measurement.ReceivedSvTimeNanos; double TimeOffsetNanos = measurement.TimeOffsetNanos; // Galileo Time generation (GSA White Paper - page 20) galileoTime = TimeNanos - (FullBiasNanos + BiasNanos); // Compute the time of signal reception for when GNSS_MEASUREMENT_STATE_TOW_KNOWN or GNSS_MEASUREMENT_STATE_TOW_DECODED are true tRxGalileoTOW = galileoTime % Constants.NUMBER_NANO_SECONDS_PER_WEEK; // Measurement time in full Galileo time without taking into account weekNumberNanos(the number of // nanoseconds that have occurred from the beginning of GPS time to the current // week number) weekNumber = System.Math.Floor((-1.0 * FullBiasNanos) / Constants.NUMBER_NANO_SECONDS_PER_WEEK); // Compute the signal reception for when GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is true tRxGalileoE1_2nd = galileoTime % Constants.NumberNanoSeconds100Milli; tTxGalileo = ReceivedSvTimeNanos + TimeOffsetNanos; // Valid only if GNSS_MEASUREMENT_STATE_TOW_KNOWN or GNSS_MEASUREMENT_STATE_TOW_DECODED are true pseudorangeTOW = (tRxGalileoTOW - tTxGalileo) * 1e-9 * Constants.SPEED_OF_LIGHT; // Valid only if GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK pseudorangeE1_2nd = ((galileoTime - tTxGalileo) % Constants.NumberNanoSeconds100Milli) * 1e-9 * Constants.SPEED_OF_LIGHT; /* * * According to https://developer.android.com/ and GSA White Paper (pg.20) * the GnssMeasurements States required for GALILEO valid pseudoranges are: * * STATE_TOW_KNOWN = 16384 (1 << 11) * STATE_TOW_DECODED = 8 (1 << 3) * STATE_GAL_E1C_2ND_CODE_LOCK = 2048 (1 << 11) * */ // Get the measurement state GnssState measState = measurement.State; // Bitwise AND to identify the states bool towKnown = false; if (Android.OS.Build.VERSION.SdkInt >= BuildVersionCodes.O) { towKnown = (measState & GnssState.TowKnown) != 0; } bool towDecoded = (measState & GnssState.TowDecoded) != 0; bool codeLockE1BC = (measState & GnssState.GalE1bcCodeLock) != 0; bool codeLockE1C = (measState & GnssState.GalE1c2ndCodeLock) != 0; // Variables for debugging double prTOW = pseudorangeTOW; double prE1_2nd = pseudorangeE1_2nd; double diffPR = prTOW - prE1_2nd; int svID = measurement.Svid; if (towDecoded || towKnown) { SatelliteParameters satelliteParameters = new SatelliteParameters( measurement.Svid, new Pseudorange(pseudorangeTOW, 0.0)); satelliteParameters.setUniqueSatId("E" + satelliteParameters.getSatId() + "_E1"); satelliteParameters.setSignalStrength(measurement.Cn0DbHz); satelliteParameters.setConstellationType(measurement.ConstellationType); if (measurement.HasCarrierFrequencyHz) { satelliteParameters.setCarrierFrequency(measurement.CarrierFrequencyHz); } observedSatellites.Add(satelliteParameters); Log.Debug(TAG, "updateConstellations(" + measurement.Svid + "): " + weekNumber + ", " + tRxGalileoTOW + ", " + pseudorangeTOW); Log.Debug(TAG, "updateConstellations: Passed with measurement state: " + measState); } else if (codeLockE1C) { SatelliteParameters satelliteParameters = new SatelliteParameters( measurement.Svid, new Pseudorange(pseudorangeE1_2nd, 0.0) ); satelliteParameters.setUniqueSatId("E" + satelliteParameters.getSatId() + "_E1"); satelliteParameters.setSignalStrength(measurement.Cn0DbHz); satelliteParameters.setConstellationType(measurement.ConstellationType); if (measurement.HasCarrierFrequencyHz) { satelliteParameters.setCarrierFrequency(measurement.CarrierFrequencyHz); } observedSatellites.Add(satelliteParameters); Log.Debug(TAG, "updateConstellations(" + measurement.Svid + "): " + weekNumber + ", " + tRxGalileoTOW + ", " + pseudorangeE1_2nd); Log.Debug(TAG, "updateConstellations: Passed with measurement state: " + measState); } else { SatelliteParameters satelliteParameters = new SatelliteParameters( measurement.Svid, null ); satelliteParameters.setUniqueSatId("E" + satelliteParameters.getSatId() + "_E1"); satelliteParameters.setSignalStrength(measurement.Cn0DbHz); satelliteParameters.setConstellationType(measurement.ConstellationType); if (measurement.HasCarrierFrequencyHz) { satelliteParameters.setCarrierFrequency(measurement.CarrierFrequencyHz); } unusedSatellites.Add(satelliteParameters); visibleButNotUsed++; } } } }
override public void updateMeasurements(GnssMeasurementsEvent evento) { lock (this) { visibleButNotUsed = 0; observedSatellites.Clear(); unusedSatellites.Clear(); GnssClock gnssClock = evento.Clock; long TimeNanos = gnssClock.TimeNanos; timeRefMsec = new Time(JavaSystem.CurrentTimeMillis()); double BiasNanos = gnssClock.BiasNanos; double gpsTime, pseudorange; // Use only the first instance of the FullBiasNanos (as done in gps-measurement-tools) if (!fullBiasNanosInitialized) { FullBiasNanos = gnssClock.FullBiasNanos; fullBiasNanosInitialized = true; } // Start computing the pseudoranges using the raw data from the phone's GNSS receiver foreach (GnssMeasurement measurement in evento.Measurements) { if (measurement.ConstellationType != constellationId) // si la senial no es de la gps, continue { continue; } if (measurement.HasCarrierFrequencyHz) { if (!approximateEqual(measurement.CarrierFrequencyHz, L1_FREQUENCY, FREQUENCY_MATCH_RANGE)) { continue; } } // excluding satellites which don't have the L5 component // if(measurement.getSvid() == 2 || measurement.getSvid() == 4 // || measurement.getSvid() == 5 || measurement.getSvid() == 7 // || measurement.getSvid() == 11 || measurement.getSvid() == 12 // || measurement.getSvid() == 13 || measurement.getSvid() == 14 // || measurement.getSvid() == 15 || measurement.getSvid() == 16 // || measurement.getSvid() == 17 || measurement.getSvid() == 18 // || measurement.getSvid() == 19 || measurement.getSvid() == 20 // || measurement.getSvid() == 21 || measurement.getSvid() == 22 // || measurement.getSvid() == 23 || measurement.getSvid() == 28 // || measurement.getSvid() == 29 || measurement.getSvid() == 31) // continue; long ReceivedSvTimeNanos = measurement.ReceivedSvTimeNanos; double TimeOffsetNanos = measurement.TimeOffsetNanos; // GPS Time generation (GSA White Paper - page 20) gpsTime = TimeNanos - (FullBiasNanos + BiasNanos); // TODO intersystem bias? // Measurement time in full GPS time without taking into account weekNumberNanos(the number of // nanoseconds that have occurred from the beginning of GPS time to the current // week number) tRxGPS = gpsTime + TimeOffsetNanos; weekNumberNanos = System.Math.Floor((-1.0 * FullBiasNanos) / Constants.NUMBER_NANO_SECONDS_PER_WEEK) * Constants.NUMBER_NANO_SECONDS_PER_WEEK; // GPS pseudorange computation pseudorange = (tRxGPS - weekNumberNanos - ReceivedSvTimeNanos) / 1.0E9 * Constants.SPEED_OF_LIGHT; // TODO Check that the measurement have a valid state such that valid pseudoranges are used in the PVT algorithm /* * * According to https://developer.android.com/ the GnssMeasurements States required * for GPS valid pseudoranges are: * * int STATE_CODE_LOCK = 1 (1 << 0) * int int STATE_TOW_DECODED = 8 (1 << 3) * */ GnssState measState = measurement.State; // Bitwise AND to identify the states bool codeLock = (measState & GnssState.CodeLock) != GnssState.Unknown; bool towDecoded = (measState & GnssState.TowDecoded) != 0; bool towKnown = false; if (Android.OS.Build.VERSION.SdkInt >= BuildVersionCodes.O) { towKnown = (measState & GnssState.TowKnown) != 0; } // bool towUncertainty = measurement.getReceivedSvTimeUncertaintyNanos() < MAXTOWUNCNS; if (codeLock && (towDecoded || towKnown) && pseudorange < 1e9) { // && towUncertainty SatelliteParameters satelliteParameters = new SatelliteParameters( measurement.Svid, new Pseudorange(pseudorange, 0.0)); satelliteParameters.setUniqueSatId("G" + satelliteParameters.getSatId() + "_L1"); satelliteParameters.setSignalStrength(measurement.Cn0DbHz); satelliteParameters.setConstellationType(measurement.ConstellationType); if (measurement.HasCarrierFrequencyHz) { satelliteParameters.setCarrierFrequency(measurement.CarrierFrequencyHz); } observedSatellites.Add(satelliteParameters); //Log.d(TAG, "updateConstellations(" + measurement.Svid + "): " + weekNumberNanos + ", " + tRxGPS + ", " + pseudorange); //Log.d(TAG, "updateConstellations: Passed with measurement state: " + measState); } else { SatelliteParameters satelliteParameters = new SatelliteParameters( measurement.Svid, null); satelliteParameters.setUniqueSatId("G" + satelliteParameters.getSatId() + "_L1"); satelliteParameters.setSignalStrength(measurement.Cn0DbHz); satelliteParameters.setConstellationType(measurement.ConstellationType); if (measurement.HasCarrierFrequencyHz) { satelliteParameters.setCarrierFrequency(measurement.CarrierFrequencyHz); } unusedSatellites.Add(satelliteParameters); visibleButNotUsed++; } } } }