/* * Copyright (C) 2014 The Android Open Source Project * * Licensed 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 android.location; import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_AUTOMATIC_GAIN_CONTROL; import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_CARRIER_CYCLES; import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_CARRIER_FREQUENCY; import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_CARRIER_PHASE; import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_CARRIER_PHASE_UNCERTAINTY; import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_FULL_ISB; import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_FULL_ISB_UNCERTAINTY; import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_SATELLITE_ISB; import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_SATELLITE_ISB_UNCERTAINTY; import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_SNR; import android.annotation.FloatRange; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * A class representing a GNSS satellite measurement, containing raw and computed information. */ public final class GnssMeasurement implements Parcelable { private int mFlags; private int mSvid; private int mConstellationType; private double mTimeOffsetNanos; private int mState; private long mReceivedSvTimeNanos; private long mReceivedSvTimeUncertaintyNanos; private double mCn0DbHz; private double mBasebandCn0DbHz; private double mPseudorangeRateMetersPerSecond; private double mPseudorangeRateUncertaintyMetersPerSecond; private int mAccumulatedDeltaRangeState; private double mAccumulatedDeltaRangeMeters; private double mAccumulatedDeltaRangeUncertaintyMeters; private float mCarrierFrequencyHz; private long mCarrierCycles; private double mCarrierPhase; private double mCarrierPhaseUncertainty; private int mMultipathIndicator; private double mSnrInDb; private double mAutomaticGainControlLevelInDb; @NonNull private String mCodeType; private double mFullInterSignalBiasNanos; private double mFullInterSignalBiasUncertaintyNanos; private double mSatelliteInterSignalBiasNanos; private double mSatelliteInterSignalBiasUncertaintyNanos; // The following enumerations must be in sync with the values declared in GNSS HAL. private static final int HAS_NO_FLAGS = 0; private static final int HAS_CODE_TYPE = (1 << 14); private static final int HAS_BASEBAND_CN0 = (1 << 15); /** * The status of the multipath indicator. * @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef({MULTIPATH_INDICATOR_UNKNOWN, MULTIPATH_INDICATOR_DETECTED, MULTIPATH_INDICATOR_NOT_DETECTED}) public @interface MultipathIndicator {} /** * The indicator is not available or the presence or absence of multipath is unknown. */ public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; /** * The measurement shows signs of multi-path. */ public static final int MULTIPATH_INDICATOR_DETECTED = 1; /** * The measurement shows no signs of multi-path. */ public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; /** * GNSS measurement tracking loop state * @hide */ @IntDef(flag = true, prefix = { "STATE_" }, value = { STATE_CODE_LOCK, STATE_BIT_SYNC, STATE_SUBFRAME_SYNC, STATE_TOW_DECODED, STATE_MSEC_AMBIGUOUS, STATE_SYMBOL_SYNC, STATE_GLO_STRING_SYNC, STATE_GLO_TOD_DECODED, STATE_BDS_D2_BIT_SYNC, STATE_BDS_D2_SUBFRAME_SYNC, STATE_GAL_E1BC_CODE_LOCK, STATE_GAL_E1C_2ND_CODE_LOCK, STATE_GAL_E1B_PAGE_SYNC, STATE_SBAS_SYNC, STATE_TOW_KNOWN, STATE_GLO_TOD_KNOWN, STATE_2ND_CODE_LOCK }) @Retention(RetentionPolicy.SOURCE) public @interface State {} /** This GNSS measurement's tracking state is invalid or unknown. */ public static final int STATE_UNKNOWN = 0; /** This GNSS measurement's tracking state has code lock. */ public static final int STATE_CODE_LOCK = (1<<0); /** This GNSS measurement's tracking state has bit sync. */ public static final int STATE_BIT_SYNC = (1<<1); /** This GNSS measurement's tracking state has sub-frame sync. */ public static final int STATE_SUBFRAME_SYNC = (1<<2); /** This GNSS measurement's tracking state has time-of-week decoded. */ public static final int STATE_TOW_DECODED = (1<<3); /** This GNSS measurement's tracking state contains millisecond ambiguity. */ public static final int STATE_MSEC_AMBIGUOUS = (1<<4); /** This GNSS measurement's tracking state has symbol sync. */ public static final int STATE_SYMBOL_SYNC = (1<<5); /** This Glonass measurement's tracking state has string sync. */ public static final int STATE_GLO_STRING_SYNC = (1<<6); /** This Glonass measurement's tracking state has time-of-day decoded. */ public static final int STATE_GLO_TOD_DECODED = (1<<7); /** This Beidou measurement's tracking state has D2 bit sync. */ public static final int STATE_BDS_D2_BIT_SYNC = (1<<8); /** This Beidou measurement's tracking state has D2 sub-frame sync. */ public static final int STATE_BDS_D2_SUBFRAME_SYNC = (1<<9); /** This Galileo measurement's tracking state has E1B/C code lock. */ public static final int STATE_GAL_E1BC_CODE_LOCK = (1<<10); /** This Galileo measurement's tracking state has E1C secondary code lock. */ public static final int STATE_GAL_E1C_2ND_CODE_LOCK = (1<<11); /** This Galileo measurement's tracking state has E1B page sync. */ public static final int STATE_GAL_E1B_PAGE_SYNC = (1<<12); /** This SBAS measurement's tracking state has whole second level sync. */ public static final int STATE_SBAS_SYNC = (1<<13); /** * This GNSS measurement's tracking state has time-of-week known, possibly not decoded * over the air but has been determined from other sources. If TOW decoded is set then TOW Known * will also be set. */ public static final int STATE_TOW_KNOWN = (1<<14); /** * This Glonass measurement's tracking state has time-of-day known, possibly not decoded * over the air but has been determined from other sources. If TOD decoded is set then TOD Known * will also be set. */ public static final int STATE_GLO_TOD_KNOWN = (1<<15); /** This GNSS measurement's tracking state has secondary code lock. */ public static final int STATE_2ND_CODE_LOCK = (1 << 16); /** * All the GNSS receiver state flags, for bit masking purposes (not a sensible state for any * individual measurement.) */ private static final int STATE_ALL = 0x3fff; // 2 bits + 4 bits + 4 bits + 4 bits = 14 bits /** * GNSS measurement accumulated delta range state * @hide */ @IntDef(flag = true, prefix = { "ADR_STATE_" }, value = { ADR_STATE_VALID, ADR_STATE_RESET, ADR_STATE_CYCLE_SLIP, ADR_STATE_HALF_CYCLE_RESOLVED, ADR_STATE_HALF_CYCLE_REPORTED }) @Retention(RetentionPolicy.SOURCE) public @interface AdrState {} /** * The state of the value {@link #getAccumulatedDeltaRangeMeters()} is invalid or unknown. */ public static final int ADR_STATE_UNKNOWN = 0; /** * The state of the {@link #getAccumulatedDeltaRangeMeters()} is valid. */ public static final int ADR_STATE_VALID = (1<<0); /** * The state of the {@link #getAccumulatedDeltaRangeMeters()} has detected a reset. */ public static final int ADR_STATE_RESET = (1<<1); /** * The state of the {@link #getAccumulatedDeltaRangeMeters()} has a cycle slip detected. */ public static final int ADR_STATE_CYCLE_SLIP = (1<<2); /** * Reports whether the value {@link #getAccumulatedDeltaRangeMeters()} has resolved the half * cycle ambiguity. * *
When this bit is set, the {@link #getAccumulatedDeltaRangeMeters()} corresponds to the * carrier phase measurement plus an accumulated integer number of carrier full cycles. * *
When this bit is unset, the {@link #getAccumulatedDeltaRangeMeters()} corresponds to the * carrier phase measurement plus an accumulated integer number of carrier half cycles. */ public static final int ADR_STATE_HALF_CYCLE_RESOLVED = (1<<3); /** * Reports whether the flag {@link #ADR_STATE_HALF_CYCLE_RESOLVED} has been reported by the * GNSS hardware. * *
When this bit is set, the value of {@link #getAccumulatedDeltaRangeUncertaintyMeters()} * can be low (centimeter level) whether or not the half cycle ambiguity is resolved. * *
When this bit is unset, the value of {@link #getAccumulatedDeltaRangeUncertaintyMeters()} * is larger, to cover the potential error due to half cycle ambiguity being unresolved. */ public static final int ADR_STATE_HALF_CYCLE_REPORTED = (1<<4); /** * All the 'Accumulated Delta Range' flags. * @hide */ @TestApi public static final int ADR_STATE_ALL = ADR_STATE_VALID | ADR_STATE_RESET | ADR_STATE_CYCLE_SLIP | ADR_STATE_HALF_CYCLE_RESOLVED | ADR_STATE_HALF_CYCLE_REPORTED; // End enumerations in sync with gps.h /** * @hide */ @TestApi public GnssMeasurement() { initialize(); } /** * Sets all contents to the values stored in the provided object. * @hide */ @TestApi public void set(GnssMeasurement measurement) { mFlags = measurement.mFlags; mSvid = measurement.mSvid; mConstellationType = measurement.mConstellationType; mTimeOffsetNanos = measurement.mTimeOffsetNanos; mState = measurement.mState; mReceivedSvTimeNanos = measurement.mReceivedSvTimeNanos; mReceivedSvTimeUncertaintyNanos = measurement.mReceivedSvTimeUncertaintyNanos; mCn0DbHz = measurement.mCn0DbHz; mBasebandCn0DbHz = measurement.mBasebandCn0DbHz; mPseudorangeRateMetersPerSecond = measurement.mPseudorangeRateMetersPerSecond; mPseudorangeRateUncertaintyMetersPerSecond = measurement.mPseudorangeRateUncertaintyMetersPerSecond; mAccumulatedDeltaRangeState = measurement.mAccumulatedDeltaRangeState; mAccumulatedDeltaRangeMeters = measurement.mAccumulatedDeltaRangeMeters; mAccumulatedDeltaRangeUncertaintyMeters = measurement.mAccumulatedDeltaRangeUncertaintyMeters; mCarrierFrequencyHz = measurement.mCarrierFrequencyHz; mCarrierCycles = measurement.mCarrierCycles; mCarrierPhase = measurement.mCarrierPhase; mCarrierPhaseUncertainty = measurement.mCarrierPhaseUncertainty; mMultipathIndicator = measurement.mMultipathIndicator; mSnrInDb = measurement.mSnrInDb; mAutomaticGainControlLevelInDb = measurement.mAutomaticGainControlLevelInDb; mCodeType = measurement.mCodeType; mFullInterSignalBiasNanos = measurement.mFullInterSignalBiasNanos; mFullInterSignalBiasUncertaintyNanos = measurement.mFullInterSignalBiasUncertaintyNanos; mSatelliteInterSignalBiasNanos = measurement.mSatelliteInterSignalBiasNanos; mSatelliteInterSignalBiasUncertaintyNanos = measurement.mSatelliteInterSignalBiasUncertaintyNanos; } /** * Resets all the contents to its original state. * @hide */ @TestApi public void reset() { initialize(); } /** * Gets the satellite ID. * *
Interpretation depends on {@link #getConstellationType()}. * See {@link GnssStatus#getSvid(int)}. */ public int getSvid() { return mSvid; } /** * Sets the Satellite ID. * @hide */ @TestApi public void setSvid(int value) { mSvid = value; } /** * Gets the constellation type. * *
The return value is one of those constants with {@code CONSTELLATION_} prefix in * {@link GnssStatus}. */ @GnssStatus.ConstellationType public int getConstellationType() { return mConstellationType; } /** * Sets the constellation type. * @hide */ @TestApi public void setConstellationType(@GnssStatus.ConstellationType int value) { mConstellationType = value; } /** * Gets the time offset at which the measurement was taken in nanoseconds. * *
The reference receiver's time from which this is offset is specified by * {@link GnssClock#getTimeNanos()}. * *
The sign of this value is given by the following equation: *
* measurement time = TimeNanos + TimeOffsetNanos
*
* The value provides an individual time-stamp for the measurement, and allows sub-nanosecond * accuracy. */ public double getTimeOffsetNanos() { return mTimeOffsetNanos; } /** * Sets the time offset at which the measurement was taken in nanoseconds. * @hide */ @TestApi public void setTimeOffsetNanos(double value) { mTimeOffsetNanos = value; } /** * Gets per-satellite sync state. * *
It represents the current sync state for the associated satellite. * *
This value helps interpret {@link #getReceivedSvTimeNanos()}. */ @State public int getState() { return mState; } /** * Sets the sync state. * @hide */ @TestApi public void setState(@State int value) { mState = value; } /** * Gets a string representation of the 'sync state'. * *
For internal and logging use only. */ private String getStateString() { if (mState == STATE_UNKNOWN) { return "Unknown"; } StringBuilder builder = new StringBuilder(); if ((mState & STATE_CODE_LOCK) != 0) { builder.append("CodeLock|"); } if ((mState & STATE_BIT_SYNC) != 0) { builder.append("BitSync|"); } if ((mState & STATE_SUBFRAME_SYNC) != 0) { builder.append("SubframeSync|"); } if ((mState & STATE_TOW_DECODED) != 0) { builder.append("TowDecoded|"); } if ((mState & STATE_TOW_KNOWN) != 0) { builder.append("TowKnown|"); } if ((mState & STATE_MSEC_AMBIGUOUS) != 0) { builder.append("MsecAmbiguous|"); } if ((mState & STATE_SYMBOL_SYNC) != 0) { builder.append("SymbolSync|"); } if ((mState & STATE_GLO_STRING_SYNC) != 0) { builder.append("GloStringSync|"); } if ((mState & STATE_GLO_TOD_DECODED) != 0) { builder.append("GloTodDecoded|"); } if ((mState & STATE_GLO_TOD_KNOWN) != 0) { builder.append("GloTodKnown|"); } if ((mState & STATE_BDS_D2_BIT_SYNC) != 0) { builder.append("BdsD2BitSync|"); } if ((mState & STATE_BDS_D2_SUBFRAME_SYNC) != 0) { builder.append("BdsD2SubframeSync|"); } if ((mState & STATE_GAL_E1BC_CODE_LOCK) != 0) { builder.append("GalE1bcCodeLock|"); } if ((mState & STATE_GAL_E1C_2ND_CODE_LOCK) != 0) { builder.append("E1c2ndCodeLock|"); } if ((mState & STATE_GAL_E1B_PAGE_SYNC) != 0) { builder.append("GalE1bPageSync|"); } if ((mState & STATE_SBAS_SYNC) != 0) { builder.append("SbasSync|"); } if ((mState & STATE_2ND_CODE_LOCK) != 0) { builder.append("2ndCodeLock|"); } int remainingStates = mState & ~STATE_ALL; if (remainingStates > 0) { builder.append("Other("); builder.append(Integer.toBinaryString(remainingStates)); builder.append(")|"); } builder.setLength(builder.length() - 1); return builder.toString(); } /** * Gets the received GNSS satellite time, at the measurement time, in nanoseconds. * *
The received satellite time is relative to the beginning of the system week for all * constellations except for Glonass where it is relative to the beginning of the Glonass * system day. * *
The table below indicates the valid range of the received GNSS satellite time. These * ranges depend on the constellation and code being tracked and the state of the tracking * algorithms given by the {@link #getState} method. The minimum value of this field is zero. * The maximum value of this field is determined by looking across all of the state flags * that are set, for the given constellation and code type, and finding the the maximum value * in this table. * *
For example, for GPS L1 C/A, if STATE_TOW_KNOWN is set, this field can be any value from 0 * to 1 week (in nanoseconds), and for GAL E1B code, if only STATE_GAL_E1BC_CODE_LOCK is set, * then this field can be any value from 0 to 4 milliseconds (in nanoseconds.) * *
| * | GPS/QZSS | *GLNS | *BDS | *GAL | *SBAS | *|||||
| State Flag | *L1 C/A | *L5I | *L5Q | *L1OF | *B1I (D1) | *B1I (D2) | *E1B | *E1C | *E5AQ | *L1 C/A | *
| * STATE_UNKNOWN * | *0 | *0 | *0 | *0 | *0 | *0 | *0 | *0 | *0 | *0 | *
| * STATE_CODE_LOCK * | *1 ms | *1 ms | *1 ms | *1 ms | *1 ms | *1 ms | *- | *- | *1 ms | *1 ms | *
| * STATE_SYMBOL_SYNC * | *20 ms (optional) | *10 ms | *1 ms (optional) | *10 ms | *20 ms (optional) | *2 ms | *4 ms (optional) | *4 ms (optional) | *1 ms (optional) | *2 ms | *
| * STATE_BIT_SYNC * | *20 ms | *20 ms | *1 ms (optional) | *20 ms | *20 ms | *- | *8 ms | *- | *1 ms (optional) | *4 ms | *
| * STATE_SUBFRAME_SYNC * | *6s | *6s | *- | *2 s | *6 s | *- | *- | *- | *100 ms | *- | *
| * STATE_TOW_DECODED * | *1 week | *- | *1 day | *1 week | *1 week | *- | *1 week | *|||
| * STATE_TOW_KNOWN * | *1 week | *1 day | *1 week | *1 week | *1 week | *|||||
| * STATE_GLO_STRING_SYNC * | *- | *- | *- | *2 s | *- | *- | *- | *- | *- | *- | *
| * STATE_GLO_TOD_DECODED * | *- | *- | *- | *1 day | *- | *- | *- | *- | *- | *- | *
| * STATE_GLO_TOD_KNOWN * | *- | *- | *- | *1 day | *- | *- | *- | *- | *- | *- | *
| * STATE_BDS_D2_BIT_SYNC * | *- | *- | *- | *- | *- | *2 ms | *- | *- | *- | *- | *
| * STATE_BDS_D2_SUBFRAME_SYNC * | *- | *- | *- | *- | *- | *600 ms | *- | *- | *- | *- | *
| * STATE_GAL_E1BC_CODE_LOCK * | *- | *- | *- | *- | *- | *- | *4 ms | *4 ms | *- | *- | *
| * STATE_GAL_E1C_2ND_CODE_LOCK * | *- | *- | *- | *- | *- | *- | *- | *100 ms | *- | *- | *
| * STATE_2ND_CODE_LOCK * | *- | *10 ms (optional) | *20 ms | *- | *- | *- | *- | *100 ms (optional) | *100 ms | *- | *
| * STATE_GAL_E1B_PAGE_SYNC * | *- | *- | *- | *- | *- | *- | *2 s | *- | *- | *- | *
| * STATE_SBAS_SYNC * | *- | *- | *- | *- | *- | *- | *- | *- | *- | *1 s | *
Note: TOW Known refers to the case where TOW is possibly not decoded over the air but has * been determined from other sources. If TOW decoded is set then TOW Known must also be set. * *
Note well: if there is any ambiguity in integer millisecond, STATE_MSEC_AMBIGUOUS must be * set accordingly, in the 'state' field. This value must be populated, unless the 'state' == * STATE_UNKNOWN. * *
Note on optional flags: *
Typical range: 10-50 dB-Hz. The range of possible C/N0 values is 0-63 dB-Hz to handle * some edge cases. * *
The value contains the measured C/N0 for the signal at the antenna input. */ @FloatRange(from = 0, to = 63) public double getCn0DbHz() { return mCn0DbHz; } /** * Sets the carrier-to-noise density in dB-Hz. * @hide */ @TestApi public void setCn0DbHz(double value) { mCn0DbHz = value; } /** * Returns {@code true} if {@link #getBasebandCn0DbHz()} is available, {@code false} otherwise. */ public boolean hasBasebandCn0DbHz() { return isFlagSet(HAS_BASEBAND_CN0); } /** * Gets the baseband carrier-to-noise density in dB-Hz. * *
Typical range: 10-50 dB-Hz. The range of possible baseband C/N0 values is 0-63 dB-Hz to * handle some edge cases. * *
The value contains the measured C/N0 for the signal at the baseband. This is typically * a few dB weaker than the value estimated for C/N0 at the antenna port, which is reported * in {@link #getCn0DbHz()}. */ @FloatRange(from = 0, to = 63) public double getBasebandCn0DbHz() { return mBasebandCn0DbHz; } /** * Sets the baseband carrier-to-noise density in dB-Hz. * * @hide */ @TestApi public void setBasebandCn0DbHz(double value) { setFlag(HAS_BASEBAND_CN0); mBasebandCn0DbHz = value; } /** * Resets the baseband carrier-to-noise density in dB-Hz. * * @hide */ @TestApi public void resetBasebandCn0DbHz() { resetFlag(HAS_BASEBAND_CN0); } /** * Gets the Pseudorange rate at the timestamp in m/s. * *
The error estimate for this value is * {@link #getPseudorangeRateUncertaintyMetersPerSecond()}. * *
The value is uncorrected, i.e. corrections for receiver and satellite clock frequency * errors are not included. * *
A positive 'uncorrected' value indicates that the SV is moving away from the receiver. The * sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler shift' * is given by the equation: * *
* pseudorange rate = -k * doppler shift (where k is a constant)
*/
public double getPseudorangeRateMetersPerSecond() {
return mPseudorangeRateMetersPerSecond;
}
/**
* Sets the pseudorange rate at the timestamp in m/s.
* @hide
*/
@TestApi
public void setPseudorangeRateMetersPerSecond(double value) {
mPseudorangeRateMetersPerSecond = value;
}
/**
* Gets the pseudorange's rate uncertainty (1-Sigma) in m/s.
*
* The uncertainty is represented as an absolute (single sided) value. */ public double getPseudorangeRateUncertaintyMetersPerSecond() { return mPseudorangeRateUncertaintyMetersPerSecond; } /** * Sets the pseudorange's rate uncertainty (1-Sigma) in m/s. * @hide */ @TestApi public void setPseudorangeRateUncertaintyMetersPerSecond(double value) { mPseudorangeRateUncertaintyMetersPerSecond = value; } /** * Gets 'Accumulated Delta Range' state. * *
It indicates whether {@link #getAccumulatedDeltaRangeMeters()} is reset or there is a * cycle slip (indicating 'loss of lock'). */ @AdrState public int getAccumulatedDeltaRangeState() { return mAccumulatedDeltaRangeState; } /** * Sets the 'Accumulated Delta Range' state. * @hide */ @TestApi public void setAccumulatedDeltaRangeState(@AdrState int value) { mAccumulatedDeltaRangeState = value; } /** * Gets a string representation of the 'Accumulated Delta Range state'. * *
For internal and logging use only. */ private String getAccumulatedDeltaRangeStateString() { if (mAccumulatedDeltaRangeState == ADR_STATE_UNKNOWN) { return "Unknown"; } StringBuilder builder = new StringBuilder(); if ((mAccumulatedDeltaRangeState & ADR_STATE_VALID) == ADR_STATE_VALID) { builder.append("Valid|"); } if ((mAccumulatedDeltaRangeState & ADR_STATE_RESET) == ADR_STATE_RESET) { builder.append("Reset|"); } if ((mAccumulatedDeltaRangeState & ADR_STATE_CYCLE_SLIP) == ADR_STATE_CYCLE_SLIP) { builder.append("CycleSlip|"); } if ((mAccumulatedDeltaRangeState & ADR_STATE_HALF_CYCLE_RESOLVED) == ADR_STATE_HALF_CYCLE_RESOLVED) { builder.append("HalfCycleResolved|"); } if ((mAccumulatedDeltaRangeState & ADR_STATE_HALF_CYCLE_REPORTED) == ADR_STATE_HALF_CYCLE_REPORTED) { builder.append("HalfCycleReported|"); } int remainingStates = mAccumulatedDeltaRangeState & ~ADR_STATE_ALL; if (remainingStates > 0) { builder.append("Other("); builder.append(Integer.toBinaryString(remainingStates)); builder.append(")|"); } builder.deleteCharAt(builder.length() - 1); return builder.toString(); } /** * Gets the accumulated delta range since the last channel reset, in meters. * *
The error estimate for this value is {@link #getAccumulatedDeltaRangeUncertaintyMeters()}. * *
The availability of the value is represented by {@link #getAccumulatedDeltaRangeState()}. * *
A positive value indicates that the SV is moving away from the receiver. * The sign of {@link #getAccumulatedDeltaRangeMeters()} and its relation to the sign of * {@link #getCarrierPhase()} is given by the equation: * *
* accumulated delta range = -k * carrier phase (where k is a constant)
*
* Similar to the concept of an RTCM "Phaserange", when the accumulated delta range is * initially chosen, and whenever it is reset, it will retain the integer nature * of the relative carrier phase offset between satellites observed by this receiver, such that * the double difference of this value between receivers and satellites may be used, together * with integer ambiguity resolution, to determine highly precise relative location between * receivers. * *
This includes ensuring that all half-cycle ambiguities are resolved before this value is * reported as {@link #ADR_STATE_VALID}. * *
The alignment of the phase measurement will not be adjusted by the receiver so the * in-phase and quadrature phase components will have a quarter cycle offset as they do when * transmitted from the satellites. If the measurement is from a combination of the in-phase * and quadrature phase components, then the alignment of the phase measurement will be aligned * to the in-phase component. */ public double getAccumulatedDeltaRangeMeters() { return mAccumulatedDeltaRangeMeters; } /** * Sets the accumulated delta range in meters. * @hide */ @TestApi public void setAccumulatedDeltaRangeMeters(double value) { mAccumulatedDeltaRangeMeters = value; } /** * Gets the accumulated delta range's uncertainty (1-Sigma) in meters. * *
The uncertainty is represented as an absolute (single sided) value. * *
The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}. */ public double getAccumulatedDeltaRangeUncertaintyMeters() { return mAccumulatedDeltaRangeUncertaintyMeters; } /** * Sets the accumulated delta range's uncertainty (1-sigma) in meters. * *
The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}. * * @hide */ @TestApi public void setAccumulatedDeltaRangeUncertaintyMeters(double value) { mAccumulatedDeltaRangeUncertaintyMeters = value; } /** * Returns {@code true} if {@link #getCarrierFrequencyHz()} is available, {@code false} * otherwise. */ public boolean hasCarrierFrequencyHz() { return isFlagSet(HAS_CARRIER_FREQUENCY); } /** * Gets the carrier frequency of the tracked signal. * *
For example it can be the GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz, * L5 = 1176.45 MHz, varying GLO channels, etc. If the field is not set, it is the primary * common use central frequency, e.g. L1 = 1575.45 MHz for GPS. * *
For an L1, L5 receiver tracking a satellite on L1 and L5 at the same time, two raw * measurement objects will be reported for this same satellite, in one of the measurement * objects, all the values related to L1 will be filled, and in the other all of the values * related to L5 will be filled. * *
The value is only available if {@link #hasCarrierFrequencyHz()} is {@code true}. * * @return the carrier frequency of the signal tracked in Hz. */ public float getCarrierFrequencyHz() { return mCarrierFrequencyHz; } /** * Sets the Carrier frequency in Hz. * @hide */ @TestApi public void setCarrierFrequencyHz(float carrierFrequencyHz) { setFlag(HAS_CARRIER_FREQUENCY); mCarrierFrequencyHz = carrierFrequencyHz; } /** * Resets the Carrier frequency in Hz. * @hide */ @TestApi public void resetCarrierFrequencyHz() { resetFlag(HAS_CARRIER_FREQUENCY); mCarrierFrequencyHz = Float.NaN; } /** * Returns {@code true} if {@link #getCarrierCycles()} is available, {@code false} otherwise. * * @deprecated use {@link #getAccumulatedDeltaRangeState()} instead. */ @Deprecated public boolean hasCarrierCycles() { return isFlagSet(HAS_CARRIER_CYCLES); } /** * The number of full carrier cycles between the satellite and the receiver. * *
The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}. * *
The value is only available if {@link #hasCarrierCycles()} is {@code true}. * * @deprecated use {@link #getAccumulatedDeltaRangeMeters()} instead. */ @Deprecated public long getCarrierCycles() { return mCarrierCycles; } /** * Sets the number of full carrier cycles between the satellite and the receiver. * * @deprecated use {@link #setAccumulatedDeltaRangeMeters(double)} * and {@link #setAccumulatedDeltaRangeState(int)} instead. * * @hide */ @TestApi @Deprecated public void setCarrierCycles(long value) { setFlag(HAS_CARRIER_CYCLES); mCarrierCycles = value; } /** * Resets the number of full carrier cycles between the satellite and the receiver. * * @deprecated use {@link #setAccumulatedDeltaRangeMeters(double)} * and {@link #setAccumulatedDeltaRangeState(int)} instead. * @hide */ @TestApi @Deprecated public void resetCarrierCycles() { resetFlag(HAS_CARRIER_CYCLES); mCarrierCycles = Long.MIN_VALUE; } /** * Returns {@code true} if {@link #getCarrierPhase()} is available, {@code false} otherwise. * * @deprecated use {@link #getAccumulatedDeltaRangeState()} instead. */ @Deprecated public boolean hasCarrierPhase() { return isFlagSet(HAS_CARRIER_PHASE); } /** * Gets the RF phase detected by the receiver. * *
Range: [0.0, 1.0]. * *
This is the fractional part of the complete carrier phase measurement. * *
The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}. * *
The error estimate for this value is {@link #getCarrierPhaseUncertainty()}. * *
The value is only available if {@link #hasCarrierPhase()} is {@code true}. * * @deprecated use {@link #getAccumulatedDeltaRangeMeters()} instead. */ @Deprecated public double getCarrierPhase() { return mCarrierPhase; } /** * Sets the RF phase detected by the receiver. * * @deprecated use {@link #setAccumulatedDeltaRangeMeters(double)} * and {@link #setAccumulatedDeltaRangeState(int)} instead. * * @hide */ @TestApi @Deprecated public void setCarrierPhase(double value) { setFlag(HAS_CARRIER_PHASE); mCarrierPhase = value; } /** * Resets the RF phase detected by the receiver. * * @deprecated use {@link #setAccumulatedDeltaRangeMeters(double)} * and {@link #setAccumulatedDeltaRangeState(int)} instead. * * @hide */ @TestApi @Deprecated public void resetCarrierPhase() { resetFlag(HAS_CARRIER_PHASE); } /** * Returns {@code true} if {@link #getCarrierPhaseUncertainty()} is available, {@code false} * otherwise. * * @deprecated use {@link #getAccumulatedDeltaRangeState()} instead. */ @Deprecated public boolean hasCarrierPhaseUncertainty() { return isFlagSet(HAS_CARRIER_PHASE_UNCERTAINTY); } /** * Gets the carrier-phase's uncertainty (1-Sigma). * *
The uncertainty is represented as an absolute (single sided) value. * *
The value is only available if {@link #hasCarrierPhaseUncertainty()} is {@code true}. * * @deprecated use {@link #getAccumulatedDeltaRangeUncertaintyMeters()} instead. */ @Deprecated public double getCarrierPhaseUncertainty() { return mCarrierPhaseUncertainty; } /** * Sets the Carrier-phase's uncertainty (1-Sigma) in cycles. * * @deprecated use {@link #setAccumulatedDeltaRangeUncertaintyMeters(double)} * and {@link #setAccumulatedDeltaRangeState(int)} instead. * * @hide */ @TestApi @Deprecated public void setCarrierPhaseUncertainty(double value) { setFlag(HAS_CARRIER_PHASE_UNCERTAINTY); mCarrierPhaseUncertainty = value; } /** * Resets the Carrier-phase's uncertainty (1-Sigma) in cycles. * * @deprecated use {@link #setAccumulatedDeltaRangeUncertaintyMeters(double)} * and {@link #setAccumulatedDeltaRangeState(int)} instead. * * @hide */ @TestApi @Deprecated public void resetCarrierPhaseUncertainty() { resetFlag(HAS_CARRIER_PHASE_UNCERTAINTY); } /** * Gets a value indicating the 'multipath' state of the event. */ @MultipathIndicator public int getMultipathIndicator() { return mMultipathIndicator; } /** * Sets the 'multi-path' indicator. * @hide */ @TestApi public void setMultipathIndicator(@MultipathIndicator int value) { mMultipathIndicator = value; } /** * Gets a string representation of the 'multi-path indicator'. * *
For internal and logging use only.
*/
private String getMultipathIndicatorString() {
switch (mMultipathIndicator) {
case MULTIPATH_INDICATOR_UNKNOWN:
return "Unknown";
case MULTIPATH_INDICATOR_DETECTED:
return "Detected";
case MULTIPATH_INDICATOR_NOT_DETECTED:
return "NotDetected";
default:
return " The value is only available if {@link #hasSnrInDb()} is {@code true}.
*/
public double getSnrInDb() {
return mSnrInDb;
}
/**
* Sets the Signal-to-noise ratio (SNR) in dB.
* @hide
*/
@TestApi
public void setSnrInDb(double snrInDb) {
setFlag(HAS_SNR);
mSnrInDb = snrInDb;
}
/**
* Resets the Signal-to-noise ratio (SNR) in dB.
* @hide
*/
@TestApi
public void resetSnrInDb() {
resetFlag(HAS_SNR);
}
/**
* Returns {@code true} if {@link #getAutomaticGainControlLevelDb()} is available,
* {@code false} otherwise.
*/
public boolean hasAutomaticGainControlLevelDb() {
return isFlagSet(HAS_AUTOMATIC_GAIN_CONTROL);
}
/**
* Gets the Automatic Gain Control level in dB.
*
* AGC acts as a variable gain amplifier adjusting the power of the incoming signal. The AGC
* level may be used to indicate potential interference. When AGC is at a nominal level, this
* value must be set as 0. Higher gain (and/or lower input power) shall be output as a positive
* number. Hence in cases of strong jamming, in the band of this signal, this value will go more
* negative.
*
* Note: Different hardware designs (e.g. antenna, pre-amplification, or other RF HW
* components) may also affect the typical output of of this value on any given hardware design
* in an open sky test - the important aspect of this output is that changes in this value are
* indicative of changes on input signal power in the frequency band for this measurement.
*
* The value is only available if {@link #hasAutomaticGainControlLevelDb()} is {@code true}
*/
public double getAutomaticGainControlLevelDb() {
return mAutomaticGainControlLevelInDb;
}
/**
* Sets the Automatic Gain Control level in dB.
* @hide
*/
@TestApi
public void setAutomaticGainControlLevelInDb(double agcLevelDb) {
setFlag(HAS_AUTOMATIC_GAIN_CONTROL);
mAutomaticGainControlLevelInDb = agcLevelDb;
}
/**
* Resets the Automatic Gain Control level.
* @hide
*/
@TestApi
public void resetAutomaticGainControlLevel() {
resetFlag(HAS_AUTOMATIC_GAIN_CONTROL);
}
/**
* Returns {@code true} if {@link #getCodeType()} is available,
* {@code false} otherwise.
*/
public boolean hasCodeType() {
return isFlagSet(HAS_CODE_TYPE);
}
/**
* Gets the GNSS measurement's code type.
*
* Similar to the Attribute field described in RINEX 3.03, e.g., in Tables 4-10, and Table
* A2 at the RINEX 3.03 Update 1 Document.
*
* Returns "A" for GALILEO E1A, GALILEO E6A, IRNSS L5A, IRNSS SA.
*
* Returns "B" for GALILEO E1B, GALILEO E6B, IRNSS L5B, IRNSS SB.
*
* Returns "C" for GPS L1 C/A, GPS L2 C/A, GLONASS G1 C/A, GLONASS G2 C/A, GALILEO E1C,
* GALILEO E6C, SBAS L1 C/A, QZSS L1 C/A, IRNSS L5C.
*
* Returns "D" for BDS B1C D.
*
* Returns "I" for GPS L5 I, GLONASS G3 I, GALILEO E5a I, GALILEO E5b I, GALILEO E5a+b I,
* SBAS L5 I, QZSS L5 I, BDS B1 I, BDS B2 I, BDS B3 I.
*
* Returns "L" for GPS L1C (P), GPS L2C (L), QZSS L1C (P), QZSS L2C (L), LEX(6) L.
*
* Returns "M" for GPS L1M, GPS L2M.
*
* Returns "N" for GPS L1 codeless, GPS L2 codeless.
*
* Returns "P" for GPS L1P, GPS L2P, GLONASS G1P, GLONASS G2P, BDS B1C P.
*
* Returns "Q" for GPS L5 Q, GLONASS G3 Q, GALILEO E5a Q, GALILEO E5b Q, GALILEO E5a+b Q,
* SBAS L5 Q, QZSS L5 Q, BDS B1 Q, BDS B2 Q, BDS B3 Q.
*
* Returns "S" for GPS L1C (D), GPS L2C (M), QZSS L1C (D), QZSS L2C (M), LEX(6) S.
*
* Returns "W" for GPS L1 Z-tracking, GPS L2 Z-tracking.
*
* Returns "X" for GPS L1C (D+P), GPS L2C (M+L), GPS L5 (I+Q), GLONASS G3 (I+Q), GALILEO
* E1 (B+C), GALILEO E5a (I+Q), GALILEO E5b (I+Q), GALILEO E5a+b(I+Q), GALILEO E6 (B+C), SBAS
* L5 (I+Q), QZSS L1C (D+P), QZSS L2C (M+L), QZSS L5 (I+Q), LEX(6) (S+L), BDS B1 (I+Q), BDS
* B1C (D+P), BDS B2 (I+Q), BDS B3 (I+Q), IRNSS L5 (B+C).
*
* Returns "Y" for GPS L1Y, GPS L2Y.
*
* Returns "Z" for GALILEO E1 (A+B+C), GALILEO E6 (A+B+C), QZSS L1-SAIF.
*
* Returns "UNKNOWN" if the GNSS Measurement's code type is unknown.
*
* This is used to specify the observation descriptor defined in GNSS Observation Data File
* Header Section Description in the RINEX standard (Version 3.XX), in cases where the code type
* does not align with the above listed values. For example, if a code type "G" is added, this
* string shall be set to "G".
*/
@NonNull
public String getCodeType() {
return mCodeType;
}
/**
* Sets the GNSS measurement's code type.
*
* @hide
*/
@TestApi
public void setCodeType(@NonNull String codeType) {
setFlag(HAS_CODE_TYPE);
mCodeType = codeType;
}
/**
* Resets the GNSS measurement's code type.
*
* @hide
*/
@TestApi
public void resetCodeType() {
resetFlag(HAS_CODE_TYPE);
mCodeType = "UNKNOWN";
}
/**
* Returns {@code true} if {@link #getFullInterSignalBiasNanos()} is available,
* {@code false} otherwise.
*/
public boolean hasFullInterSignalBiasNanos() {
return isFlagSet(HAS_FULL_ISB);
}
/**
* Gets the GNSS measurement's inter-signal bias in nanoseconds with sub-nanosecond accuracy.
*
* This value is the sum of the estimated receiver-side and the space-segment-side
* inter-system bias, inter-frequency bias and inter-code bias, including:
*
* If a component of the above is already compensated in the provided
* {@link GnssMeasurement#getReceivedSvTimeNanos()}, then it must not be included in the
* reported full ISB.
*
* The value does not include the inter-frequency Ionospheric bias.
*
* The value is only available if {@link #hasFullInterSignalBiasNanos()} is {@code true}.
*/
public double getFullInterSignalBiasNanos() {
return mFullInterSignalBiasNanos;
}
/**
* Sets the GNSS measurement's inter-signal bias in nanoseconds.
*
* @hide
*/
@TestApi
public void setFullInterSignalBiasNanos(double fullInterSignalBiasNanos) {
setFlag(HAS_FULL_ISB);
mFullInterSignalBiasNanos = fullInterSignalBiasNanos;
}
/**
* Resets the GNSS measurement's inter-signal bias in nanoseconds.
*
* @hide
*/
@TestApi
public void resetFullInterSignalBiasNanos() {
resetFlag(HAS_FULL_ISB);
}
/**
* Returns {@code true} if {@link #getFullInterSignalBiasUncertaintyNanos()} is available,
* {@code false} otherwise.
*/
public boolean hasFullInterSignalBiasUncertaintyNanos() {
return isFlagSet(HAS_FULL_ISB_UNCERTAINTY);
}
/**
* Gets the GNSS measurement's inter-signal bias uncertainty (1 sigma) in
* nanoseconds with sub-nanosecond accuracy.
*
* The value is only available if {@link #hasFullInterSignalBiasUncertaintyNanos()} is
* {@code true}.
*/
@FloatRange(from = 0.0)
public double getFullInterSignalBiasUncertaintyNanos() {
return mFullInterSignalBiasUncertaintyNanos;
}
/**
* Sets the GNSS measurement's inter-signal bias uncertainty (1 sigma) in nanoseconds.
*
* @hide
*/
@TestApi
public void setFullInterSignalBiasUncertaintyNanos(@FloatRange(from = 0.0)
double fullInterSignalBiasUncertaintyNanos) {
setFlag(HAS_FULL_ISB_UNCERTAINTY);
mFullInterSignalBiasUncertaintyNanos = fullInterSignalBiasUncertaintyNanos;
}
/**
* Resets the GNSS measurement's inter-signal bias uncertainty (1 sigma) in
* nanoseconds.
*
* @hide
*/
@TestApi
public void resetFullInterSignalBiasUncertaintyNanos() {
resetFlag(HAS_FULL_ISB_UNCERTAINTY);
}
/**
* Returns {@code true} if {@link #getSatelliteInterSignalBiasNanos()} is available,
* {@code false} otherwise.
*/
public boolean hasSatelliteInterSignalBiasNanos() {
return isFlagSet(HAS_SATELLITE_ISB);
}
/**
* Gets the GNSS measurement's satellite inter-signal bias in nanoseconds with sub-nanosecond
* accuracy.
*
* This value is the space-segment-side inter-system bias, inter-frequency bias and
* inter-code bias, including:
*
* The value is only available if {@link #hasSatelliteInterSignalBiasNanos()} is {@code
* true}.
*/
public double getSatelliteInterSignalBiasNanos() {
return mSatelliteInterSignalBiasNanos;
}
/**
* Sets the GNSS measurement's satellite inter-signal bias in nanoseconds.
*
* @hide
*/
@TestApi
public void setSatelliteInterSignalBiasNanos(double satelliteInterSignalBiasNanos) {
setFlag(HAS_SATELLITE_ISB);
mSatelliteInterSignalBiasNanos = satelliteInterSignalBiasNanos;
}
/**
* Resets the GNSS measurement's satellite inter-signal bias in nanoseconds.
*
* @hide
*/
@TestApi
public void resetSatelliteInterSignalBiasNanos() {
resetFlag(HAS_SATELLITE_ISB);
}
/**
* Returns {@code true} if {@link #getSatelliteInterSignalBiasUncertaintyNanos()} is available,
* {@code false} otherwise.
*/
public boolean hasSatelliteInterSignalBiasUncertaintyNanos() {
return isFlagSet(HAS_SATELLITE_ISB_UNCERTAINTY);
}
/**
* Gets the GNSS measurement's satellite inter-signal bias uncertainty (1 sigma) in
* nanoseconds with sub-nanosecond accuracy.
*
* The value is only available if {@link #hasSatelliteInterSignalBiasUncertaintyNanos()} is
* {@code true}.
*/
@FloatRange(from = 0.0)
public double getSatelliteInterSignalBiasUncertaintyNanos() {
return mSatelliteInterSignalBiasUncertaintyNanos;
}
/**
* Sets the GNSS measurement's satellite inter-signal bias uncertainty (1 sigma) in nanoseconds.
*
* @hide
*/
@TestApi
public void setSatelliteInterSignalBiasUncertaintyNanos(@FloatRange(from = 0.0)
double satelliteInterSignalBiasUncertaintyNanos) {
setFlag(HAS_SATELLITE_ISB_UNCERTAINTY);
mSatelliteInterSignalBiasUncertaintyNanos = satelliteInterSignalBiasUncertaintyNanos;
}
/**
* Resets the GNSS measurement's satellite inter-signal bias uncertainty (1 sigma) in
* nanoseconds.
*
* @hide
*/
@TestApi
public void resetSatelliteInterSignalBiasUncertaintyNanos() {
resetFlag(HAS_SATELLITE_ISB_UNCERTAINTY);
}
public static final @NonNull Creator
*
*
*
*
*
*