1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.location.cts.common; 18 19 import static org.junit.Assert.assertNotNull; 20 21 import android.content.Context; 22 import android.content.pm.PackageManager; 23 import android.location.CorrelationVector; 24 import android.location.GnssClock; 25 import android.location.GnssMeasurement; 26 import android.location.GnssMeasurementsEvent; 27 import android.location.GnssNavigationMessage; 28 import android.location.GnssStatus; 29 import android.location.LocationManager; 30 import android.location.SatellitePvt; 31 import android.util.Log; 32 33 import com.google.common.collect.Range; 34 35 import java.util.ArrayList; 36 import java.util.Arrays; 37 import java.util.Collection; 38 import java.util.HashMap; 39 import java.util.HashSet; 40 import java.util.List; 41 import java.util.Map; 42 import java.util.Set; 43 import java.util.concurrent.TimeUnit; 44 45 /** 46 * Helper class for GnssMeasurement Tests. 47 */ 48 public final class TestMeasurementUtil { 49 50 private static final String TAG = "TestMeasurementUtil"; 51 52 private static final long NSEC_IN_SEC = 1000_000_000L; 53 // Generally carrier phase quality prr's have uncertainties around 0.001-0.05 m/s, vs. 54 // doppler energy quality prr's closer to 0.25-10 m/s. Threshold is chosen between those 55 // typical ranges. 56 private static final float THRESHOLD_FOR_CARRIER_PRR_UNC_METERS_PER_SEC = 0.15F; 57 58 // For gpsTimeInNs >= 1.14 * 10^18 (year 2016+) 59 private static final long GPS_TIME_YEAR_2016_IN_NSEC = 1_140_000_000L * NSEC_IN_SEC; 60 61 // Error message for GnssMeasurements Registration. 62 public static final String REGISTRATION_ERROR_MESSAGE = "Registration of GnssMeasurements" + 63 " listener has failed, this indicates a platform bug. Please report the issue with" + 64 " a full bugreport."; 65 66 private static final Range<Double> GPS_L5_QZSS_J5_FREQ_RANGE_HZ = 67 Range.closed(1.164e9, 1.189e9); 68 private static final Range<Double> GAL_E1_FREQ_RANGE_HZ = 69 Range.closed(1.559e9, 1.591e9); 70 private static final Range<Double> GAL_E5_FREQ_RANGE_HZ = 71 Range.closed(1.164e9, 1.218e9); 72 73 private enum GnssBand { 74 GNSS_L1, 75 GNSS_L2, 76 GNSS_L5, 77 GNSS_E6 78 } 79 80 // The valid Gnss navigation message type as listed in 81 // android/hardware/libhardware/include/hardware/gps.h 82 public static final Set<Integer> GNSS_NAVIGATION_MESSAGE_TYPE = 83 new HashSet<Integer>(Arrays.asList( 84 GnssNavigationMessage.TYPE_UNKNOWN, 85 GnssNavigationMessage.TYPE_GPS_L1CA, 86 GnssNavigationMessage.TYPE_GPS_L2CNAV, 87 GnssNavigationMessage.TYPE_GPS_L5CNAV, 88 GnssNavigationMessage.TYPE_GPS_CNAV2, 89 GnssNavigationMessage.TYPE_SBS, 90 GnssNavigationMessage.TYPE_GLO_L1CA, 91 GnssNavigationMessage.TYPE_QZS_L1CA, 92 GnssNavigationMessage.TYPE_BDS_D1, 93 GnssNavigationMessage.TYPE_BDS_D2, 94 GnssNavigationMessage.TYPE_BDS_CNAV1, 95 GnssNavigationMessage.TYPE_BDS_CNAV2, 96 GnssNavigationMessage.TYPE_GAL_I, 97 GnssNavigationMessage.TYPE_GAL_F, 98 GnssNavigationMessage.TYPE_IRN_L5CA 99 )); 100 101 /** 102 * Check if test can be run on the current device. 103 * 104 * @param testLocationManager TestLocationManager 105 * @return true if Build.VERSION >= {@code androidSdkVersionCode} and Location GPS present on 106 * device. 107 */ canTestRunOnCurrentDevice(TestLocationManager testLocationManager, String testTag)108 public static boolean canTestRunOnCurrentDevice(TestLocationManager testLocationManager, 109 String testTag) { 110 // If device does not have a GPS, skip the test. 111 if (!TestUtils.deviceHasGpsFeature(testLocationManager.getContext())) { 112 Log.i(TAG, "Skip the test since GPS is not supported on the device."); 113 return false; 114 } 115 116 boolean gpsProviderEnabled = testLocationManager.getLocationManager() 117 .isProviderEnabled(LocationManager.GPS_PROVIDER); 118 SoftAssert.failOrWarning(true, " GPS location disabled on the device. " 119 + "Enable location in settings to continue test.", gpsProviderEnabled); 120 return gpsProviderEnabled; 121 } 122 123 /** 124 * Check if current device is an Android Automotive OS device. 125 */ isAutomotiveDevice(Context context)126 public static boolean isAutomotiveDevice(Context context) { 127 return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); 128 } 129 130 /** 131 * Check if pseudorange rate uncertainty in Gnss Measurement is in the expected range. 132 * See field description in {@code gps.h}. 133 * 134 * @param measurement GnssMeasurement 135 * @return true if this measurement has prr uncertainty in a range indicative of carrier phase 136 */ gnssMeasurementHasCarrierPhasePrr(GnssMeasurement measurement)137 public static boolean gnssMeasurementHasCarrierPhasePrr(GnssMeasurement measurement) { 138 return (measurement.getPseudorangeRateUncertaintyMetersPerSecond() < 139 THRESHOLD_FOR_CARRIER_PRR_UNC_METERS_PER_SEC); 140 } 141 142 /** 143 * Assert all mandatory fields in Gnss Clock are in expected range. 144 * See mandatory fields in {@code gps.h}. 145 * 146 * @param clock GnssClock 147 * @param softAssert custom SoftAssert 148 * @param timeInNs event time in ns 149 */ assertGnssClockFields(GnssClock clock, SoftAssert softAssert, long timeInNs)150 public static void assertGnssClockFields(GnssClock clock, 151 SoftAssert softAssert, 152 long timeInNs) { 153 softAssert.assertTrue("time_ns: clock value", 154 timeInNs, 155 "X >= 0", 156 String.valueOf(timeInNs), 157 timeInNs >= 0L); 158 159 // If full bias is valid and accurate within one sec. verify its sign & magnitude 160 if (clock.hasFullBiasNanos() && 161 ((!clock.hasBiasUncertaintyNanos()) || 162 (clock.getBiasUncertaintyNanos() < NSEC_IN_SEC))) { 163 long gpsTimeInNs = timeInNs - clock.getFullBiasNanos(); 164 softAssert.assertTrue("TimeNanos - FullBiasNanos = GpsTimeNanos: clock value", 165 gpsTimeInNs, 166 "gpsTimeInNs >= 1.14 * 10^18 (year 2016+)", 167 String.valueOf(gpsTimeInNs), 168 gpsTimeInNs >= GPS_TIME_YEAR_2016_IN_NSEC); 169 } 170 } 171 172 /** 173 * Asserts the same FullBiasNanos of multiple GnssMeasurementEvents at the same time epoch. 174 * 175 * <p>FullBiasNanos denotes the receiver clock bias calculated by the GNSS chipset. If multiple 176 * GnssMeasurementEvents are tagged with the same time epoch, their FullBiasNanos should be the 177 * same. 178 * 179 * @param softAssert custom SoftAssert 180 * @param events GnssMeasurementEvents. Each event includes one GnssClock with a 181 * fullBiasNanos. 182 */ assertGnssClockHasConsistentFullBiasNanos(SoftAssert softAssert, List<GnssMeasurementsEvent> events)183 public static void assertGnssClockHasConsistentFullBiasNanos(SoftAssert softAssert, 184 List<GnssMeasurementsEvent> events) { 185 Map<Long, List<Long>> timeToFullBiasList = new HashMap<>(); 186 for (GnssMeasurementsEvent event : events) { 187 long timeNanos = event.getClock().getTimeNanos(); 188 long fullBiasNanos = event.getClock().getFullBiasNanos(); 189 190 timeToFullBiasList.putIfAbsent(timeNanos, new ArrayList<>()); 191 List<Long> fullBiasNanosList = timeToFullBiasList.get(timeNanos); 192 fullBiasNanosList.add(fullBiasNanos); 193 } 194 195 for (Map.Entry<Long, List<Long>> entry : timeToFullBiasList.entrySet()) { 196 long timeNanos = entry.getKey(); 197 List<Long> fullBiasNanosList = entry.getValue(); 198 if (fullBiasNanosList.size() < 2) { 199 continue; 200 } 201 long fullBiasNanos = fullBiasNanosList.get(0); 202 for (int i = 1; i < fullBiasNanosList.size(); i++) { 203 softAssert.assertTrue("FullBiasNanos are the same at the same timeNanos", 204 timeNanos, 205 "fullBiasNanosList.get(i) - fullBiasNanosList.get(0) == 0", 206 String.valueOf(fullBiasNanosList.get(i) - fullBiasNanos), 207 fullBiasNanosList.get(i) - fullBiasNanos == 0); 208 } 209 } 210 } 211 212 /** 213 * Assert all mandatory fields in Gnss Measurement are in expected range. 214 * See mandatory fields in {@code gps.h}. 215 * 216 * @param testLocationManager TestLocationManager 217 * @param measurement GnssMeasurement 218 * @param softAssert custom SoftAssert 219 * @param timeInNs event time in ns 220 */ assertAllGnssMeasurementMandatoryFields( TestLocationManager testLocationManager, GnssMeasurement measurement, SoftAssert softAssert, long timeInNs)221 public static void assertAllGnssMeasurementMandatoryFields( 222 TestLocationManager testLocationManager, GnssMeasurement measurement, 223 SoftAssert softAssert, long timeInNs) { 224 225 verifySvid(measurement, softAssert, timeInNs); 226 verifyReceivedSatelliteVehicleTimeInNs(measurement, softAssert, timeInNs); 227 verifyAccumulatedDeltaRanges(measurement, softAssert, timeInNs); 228 229 int state = measurement.getState(); 230 softAssert.assertTrue("state: Satellite code sync state", 231 timeInNs, 232 "X >= 0", 233 String.valueOf(state), 234 state >= 0); 235 236 // Check received_gps_tow_uncertainty_ns 237 softAssert.assertTrueAsWarning("received_gps_tow_uncertainty_ns:" + 238 " Uncertainty of received GPS Time-of-Week in ns", 239 timeInNs, 240 "X > 0", 241 String.valueOf(measurement.getReceivedSvTimeUncertaintyNanos()), 242 measurement.getReceivedSvTimeUncertaintyNanos() > 0L); 243 244 long timeOffsetInSec = TimeUnit.NANOSECONDS.toSeconds( 245 (long) measurement.getTimeOffsetNanos()); 246 softAssert.assertTrue("time_offset_ns: Time offset", 247 timeInNs, 248 "-100 seconds < X < +10 seconds", 249 String.valueOf(measurement.getTimeOffsetNanos()), 250 (-100 < timeOffsetInSec) && (timeOffsetInSec < 10)); 251 252 softAssert.assertTrue("c_n0_dbhz: Carrier-to-noise density", 253 timeInNs, 254 "0.0 >= X <=63", 255 String.valueOf(measurement.getCn0DbHz()), 256 measurement.getCn0DbHz() >= 0.0 && 257 measurement.getCn0DbHz() <= 63.0); 258 259 softAssert.assertTrue("pseudorange_rate_uncertainty_mps: " + 260 "Pseudorange Rate Uncertainty in m/s", 261 timeInNs, 262 "X > 0.0", 263 String.valueOf( 264 measurement.getPseudorangeRateUncertaintyMetersPerSecond()), 265 measurement.getPseudorangeRateUncertaintyMetersPerSecond() > 0.0); 266 267 verifyGnssCarrierFrequency(softAssert, testLocationManager, 268 measurement.hasCarrierFrequencyHz(), 269 measurement.hasCarrierFrequencyHz() ? measurement.getCarrierFrequencyHz() : 0F); 270 271 // Check carrier_phase. 272 if (measurement.hasCarrierPhase()) { 273 softAssert.assertTrue("carrier_phase: Carrier phase", 274 timeInNs, 275 "0.0 >= X <= 1.0", 276 String.valueOf(measurement.getCarrierPhase()), 277 measurement.getCarrierPhase() >= 0.0 && measurement.getCarrierPhase() <= 1.0); 278 } 279 280 // Check carrier_phase_uncertainty.. 281 if (measurement.hasCarrierPhaseUncertainty()) { 282 softAssert.assertTrue("carrier_phase_uncertainty: 1-Sigma uncertainty of the " + 283 "carrier-phase", 284 timeInNs, 285 "X > 0.0", 286 String.valueOf(measurement.getCarrierPhaseUncertainty()), 287 measurement.getCarrierPhaseUncertainty() > 0.0); 288 } 289 290 // Check GNSS Measurement's multipath_indicator. 291 softAssert.assertTrue("multipath_indicator: GNSS Measurement's multipath indicator", 292 timeInNs, 293 "0 >= X <= 2", 294 String.valueOf(measurement.getMultipathIndicator()), 295 measurement.getMultipathIndicator() >= 0 296 && measurement.getMultipathIndicator() <= 2); 297 298 299 // Check Signal-to-Noise ratio (SNR). 300 if (measurement.hasSnrInDb()) { 301 softAssert.assertTrue("snr: Signal-to-Noise ratio (SNR) in dB", 302 timeInNs, 303 "0.0 >= X <= 63", 304 String.valueOf(measurement.getSnrInDb()), 305 measurement.getSnrInDb() >= 0.0 && measurement.getSnrInDb() <= 63); 306 } 307 308 if (measurement.hasAutomaticGainControlLevelDb()) { 309 softAssert.assertTrue("Automatic Gain Control level in dB", 310 timeInNs, 311 "-100 >= X <= 100", 312 String.valueOf(measurement.getAutomaticGainControlLevelDb()), 313 measurement.getAutomaticGainControlLevelDb() >= -100 314 && measurement.getAutomaticGainControlLevelDb() <= 100); 315 } 316 } 317 318 /** 319 * Assert all SystemApi fields in Gnss Measurement are in expected range. 320 * 321 * @param measurement GnssMeasurement 322 * @param softAssert custom SoftAssert 323 * @param timeInNs event time in ns 324 */ assertAllGnssMeasurementSystemFields(GnssMeasurement measurement, SoftAssert softAssert, long timeInNs)325 public static void assertAllGnssMeasurementSystemFields(GnssMeasurement measurement, 326 SoftAssert softAssert, long timeInNs) { 327 328 if (measurement.hasCorrelationVectors()) { 329 verifyCorrelationVectors(measurement, softAssert, timeInNs); 330 } 331 332 if (measurement.hasSatellitePvt()) { 333 verifySatellitePvt(measurement, softAssert, timeInNs); 334 } 335 } 336 337 /** 338 * Verify correlation vectors are in expected range. 339 * 340 * @param measurement GnssMeasurement 341 * @param softAssert custom SoftAssert 342 * @param timeInNs event time in ns 343 */ verifyCorrelationVectors(GnssMeasurement measurement, SoftAssert softAssert, long timeInNs)344 private static void verifyCorrelationVectors(GnssMeasurement measurement, 345 SoftAssert softAssert, long timeInNs) { 346 Collection<CorrelationVector> correlationVectors = 347 measurement.getCorrelationVectors(); 348 assertNotNull("CorrelationVectors cannot be null.", correlationVectors); 349 softAssert.assertTrue("CorrelationVectors count", 350 timeInNs, 351 "X > 0", 352 String.valueOf(correlationVectors.size()), 353 correlationVectors.size() > 0); 354 for (CorrelationVector correlationVector : correlationVectors) { 355 assertNotNull("CorrelationVector cannot be null.", correlationVector); 356 int[] magnitude = correlationVector.getMagnitude(); 357 softAssert.assertTrue("frequency_offset_mps : " 358 + "Frequency offset from reported pseudorange rate " 359 + "for this CorrelationVector", 360 timeInNs, 361 "X >= 0.0", 362 String.valueOf(correlationVector.getFrequencyOffsetMetersPerSecond()), 363 correlationVector.getFrequencyOffsetMetersPerSecond() >= 0.0); 364 softAssert.assertTrue("sampling_width_m : " 365 + "The space between correlation samples in meters", 366 timeInNs, 367 "X > 0.0", 368 String.valueOf(correlationVector.getSamplingWidthMeters()), 369 correlationVector.getSamplingWidthMeters() > 0.0); 370 softAssert.assertTrue("Magnitude count", 371 timeInNs, 372 "X > 0", 373 String.valueOf(magnitude.length), 374 magnitude.length > 0); 375 for (int value : magnitude) { 376 softAssert.assertTrue("magnitude : Data representing normalized " 377 + "correlation magnitude values", 378 timeInNs, 379 "-32768 <= X < 32767", 380 String.valueOf(value), 381 value >= -32768 && value < 32767); 382 } 383 } 384 } 385 386 /** 387 * Verify accumulated delta ranges are in expected range. 388 * 389 * @param measurement GnssMeasurement 390 * @param softAssert custom SoftAssert 391 * @param timeInNs event time in ns 392 */ verifyAccumulatedDeltaRanges(GnssMeasurement measurement, SoftAssert softAssert, long timeInNs)393 private static void verifyAccumulatedDeltaRanges(GnssMeasurement measurement, 394 SoftAssert softAssert, long timeInNs) { 395 396 int accumulatedDeltaRangeState = measurement.getAccumulatedDeltaRangeState(); 397 softAssert.assertTrue("accumulated_delta_range_state: " + 398 "Accumulated delta range state", 399 timeInNs, 400 "X & ~ADR_STATE_ALL == 0", 401 String.valueOf(accumulatedDeltaRangeState), 402 (accumulatedDeltaRangeState & ~GnssMeasurement.ADR_STATE_ALL) == 0); 403 softAssert.assertTrue("accumulated_delta_range_state: " + 404 "Accumulated delta range state", 405 timeInNs, 406 "ADR_STATE_HALF_CYCLE_REPORTED, or !ADR_STATE_HALF_CYCLE_RESOLVED", 407 String.valueOf(accumulatedDeltaRangeState), 408 ((accumulatedDeltaRangeState & 409 GnssMeasurement.ADR_STATE_HALF_CYCLE_REPORTED) != 0) || 410 (accumulatedDeltaRangeState & 411 GnssMeasurement.ADR_STATE_HALF_CYCLE_RESOLVED) == 0); 412 if ((accumulatedDeltaRangeState & GnssMeasurement.ADR_STATE_VALID) != 0) { 413 double accumulatedDeltaRangeInMeters = 414 measurement.getAccumulatedDeltaRangeMeters(); 415 softAssert.assertTrue("accumulated_delta_range_m: " + 416 "Accumulated delta range in meter", 417 timeInNs, 418 "X != 0.0", 419 String.valueOf(accumulatedDeltaRangeInMeters), 420 accumulatedDeltaRangeInMeters != 0.0); 421 double accumulatedDeltaRangeUncertainty = 422 measurement.getAccumulatedDeltaRangeUncertaintyMeters(); 423 softAssert.assertTrue("accumulated_delta_range_uncertainty_m: " + 424 "Accumulated delta range uncertainty in meter", 425 timeInNs, 426 "X > 0.0", 427 String.valueOf(accumulatedDeltaRangeUncertainty), 428 accumulatedDeltaRangeUncertainty > 0.0); 429 } 430 } 431 432 /** 433 * Verify svid's are in expected range. 434 * 435 * @param measurement GnssMeasurement 436 * @param softAssert custom SoftAssert 437 * @param timeInNs event time in ns 438 */ verifySvid(GnssMeasurement measurement, SoftAssert softAssert, long timeInNs)439 private static void verifySvid(GnssMeasurement measurement, SoftAssert softAssert, 440 long timeInNs) { 441 442 int constellationType = measurement.getConstellationType(); 443 int svid = measurement.getSvid(); 444 validateSvidSub(softAssert, timeInNs, constellationType, svid); 445 } 446 validateSvidSub(SoftAssert softAssert, Long timeInNs, int constellationType, int svid)447 public static void validateSvidSub(SoftAssert softAssert, Long timeInNs, 448 int constellationType, int svid) { 449 450 String svidValue = String.valueOf(svid); 451 452 switch (constellationType) { 453 case GnssStatus.CONSTELLATION_GPS: 454 softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " + 455 "= CONSTELLATION_GPS", 456 timeInNs, 457 "[1, 32]", 458 svidValue, 459 svid > 0 && svid <= 32); 460 break; 461 case GnssStatus.CONSTELLATION_SBAS: 462 softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " + 463 "= CONSTELLATION_SBAS", 464 timeInNs, 465 "120 <= X <= 192", 466 svidValue, 467 svid >= 120 && svid <= 192); 468 break; 469 case GnssStatus.CONSTELLATION_GLONASS: 470 softAssert.assertTrue("svid: Slot ID, or if unknown, Frequency + 100 (93-106). " + 471 "Constellation type = CONSTELLATION_GLONASS", 472 timeInNs, 473 "1 <= svid <= 24 || 93 <= svid <= 106", 474 svidValue, 475 (svid >= 1 && svid <= 24) || (svid >= 93 && svid <= 106)); 476 break; 477 case GnssStatus.CONSTELLATION_QZSS: 478 softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " + 479 "= CONSTELLATION_QZSS", 480 timeInNs, 481 "193 <= X <= 200", 482 svidValue, 483 svid >= 193 && svid <= 200); 484 break; 485 case GnssStatus.CONSTELLATION_BEIDOU: 486 softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " + 487 "= CONSTELLATION_BEIDOU", 488 timeInNs, 489 "1 <= X <= 63", 490 svidValue, 491 svid >= 1 && svid <= 63); 492 break; 493 case GnssStatus.CONSTELLATION_GALILEO: 494 softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " + 495 "= CONSTELLATION_GALILEO", 496 timeInNs, 497 "1 <= X <= 36", 498 String.valueOf(svid), 499 svid >= 1 && svid <= 36); 500 break; 501 case GnssStatus.CONSTELLATION_IRNSS: 502 softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " + 503 "= CONSTELLATION_IRNSS", 504 timeInNs, 505 "1 <= X <= 14", 506 String.valueOf(svid), 507 svid >= 1 && svid <= 14); 508 break; 509 default: 510 // Explicit fail if did not receive valid constellation type. 511 softAssert.assertTrue("svid: Space Vehicle ID. Did not receive any valid " + 512 "constellation type.", 513 timeInNs, 514 "Valid constellation type.", 515 svidValue, 516 false); 517 break; 518 } 519 } 520 521 /** 522 * Verify sv times are in expected range. 523 * 524 * @param measurement GnssMeasurement 525 * @param softAssert custom SoftAssert 526 * @param timeInNs event time in ns 527 * */ verifyReceivedSatelliteVehicleTimeInNs(GnssMeasurement measurement, SoftAssert softAssert, long timeInNs)528 private static void verifyReceivedSatelliteVehicleTimeInNs(GnssMeasurement measurement, 529 SoftAssert softAssert, long timeInNs) { 530 531 int constellationType = measurement.getConstellationType(); 532 int state = measurement.getState(); 533 long received_sv_time_ns = measurement.getReceivedSvTimeNanos(); 534 double sv_time_ms = TimeUnit.NANOSECONDS.toMillis(received_sv_time_ns); 535 double sv_time_sec = TimeUnit.NANOSECONDS.toSeconds(received_sv_time_ns); 536 double sv_time_days = TimeUnit.NANOSECONDS.toDays(received_sv_time_ns); 537 538 // Check ranges for received_sv_time_ns for given Gps State 539 if (state == 0) { 540 softAssert.assertTrue("received_sv_time_ns:" + 541 " Received SV Time-of-Week in ns." + 542 " GNSS_MEASUREMENT_STATE_UNKNOWN.", 543 timeInNs, 544 "X == 0", 545 String.valueOf(received_sv_time_ns), 546 sv_time_ms == 0); 547 } 548 549 switch (constellationType) { 550 case GnssStatus.CONSTELLATION_GPS: 551 verifyGpsQzssSvTimes(measurement, softAssert, timeInNs, state, "CONSTELLATION_GPS"); 552 break; 553 case GnssStatus.CONSTELLATION_QZSS: 554 verifyGpsQzssSvTimes(measurement, softAssert, timeInNs, state, 555 "CONSTELLATION_QZSS"); 556 break; 557 case GnssStatus.CONSTELLATION_SBAS: 558 if ((state & GnssMeasurement.STATE_SBAS_SYNC) 559 == GnssMeasurement.STATE_SBAS_SYNC) { 560 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 561 "GNSS_MEASUREMENT_STATE_SBAS_SYNC", 562 "GnssStatus.CONSTELLATION_SBAS"), 563 timeInNs, 564 "0s >= X <= 1s", 565 String.valueOf(sv_time_sec), 566 sv_time_sec >= 0 && sv_time_sec <= 1); 567 } else if ((state & GnssMeasurement.STATE_SYMBOL_SYNC) 568 == GnssMeasurement.STATE_SYMBOL_SYNC) { 569 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 570 "GNSS_MEASUREMENT_STATE_SYMBOL_SYNC", 571 "GnssStatus.CONSTELLATION_SBAS"), 572 timeInNs, 573 "0ms >= X <= 2ms", 574 String.valueOf(sv_time_ms), 575 sv_time_ms >= 0 && sv_time_ms <= 2); 576 } else if ((state & GnssMeasurement.STATE_CODE_LOCK) 577 == GnssMeasurement.STATE_CODE_LOCK) { 578 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 579 "GNSS_MEASUREMENT_STATE_CODE_LOCK", 580 "GnssStatus.CONSTELLATION_SBAS"), 581 timeInNs, 582 "0ms >= X <= 1ms", 583 String.valueOf(sv_time_ms), 584 sv_time_ms >= 0 && sv_time_ms <= 1); 585 } 586 break; 587 case GnssStatus.CONSTELLATION_GLONASS: 588 if ((state & GnssMeasurement.STATE_GLO_TOD_DECODED) 589 == GnssMeasurement.STATE_GLO_TOD_DECODED) { 590 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 591 "GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED", 592 "GnssStatus.CONSTELLATION_GLONASS"), 593 timeInNs, 594 "0 day >= X <= 1 day", 595 String.valueOf(sv_time_days), 596 sv_time_days >= 0 && sv_time_days <= 1); 597 } else if ((state & GnssMeasurement.STATE_GLO_TOD_KNOWN) 598 == GnssMeasurement.STATE_GLO_TOD_KNOWN) { 599 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 600 "GNSS_MEASUREMENT_STATE_GLO_TOD_KNOWN", 601 "GnssStatus.CONSTELLATION_GLONASS"), 602 timeInNs, 603 "0 day >= X <= 1 day", 604 String.valueOf(sv_time_days), 605 sv_time_days >= 0 && sv_time_days <= 1); 606 } else if ((state & GnssMeasurement.STATE_GLO_STRING_SYNC) 607 == GnssMeasurement.STATE_GLO_STRING_SYNC) { 608 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 609 "GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC", 610 "GnssStatus.CONSTELLATION_GLONASS"), 611 timeInNs, 612 "0s >= X <= 2s", 613 String.valueOf(sv_time_sec), 614 sv_time_sec >= 0 && sv_time_sec <= 2); 615 } else if ((state & GnssMeasurement.STATE_BIT_SYNC) 616 == GnssMeasurement.STATE_BIT_SYNC) { 617 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 618 "GNSS_MEASUREMENT_STATE_BIT_SYNC", 619 "GnssStatus.CONSTELLATION_GLONASS"), 620 timeInNs, 621 "0ms >= X <= 20ms", 622 String.valueOf(sv_time_ms), 623 sv_time_ms >= 0 && sv_time_ms <= 20); 624 } else if ((state & GnssMeasurement.STATE_SYMBOL_SYNC) 625 == GnssMeasurement.STATE_SYMBOL_SYNC) { 626 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 627 "GNSS_MEASUREMENT_STATE_SYMBOL_SYNC", 628 "GnssStatus.CONSTELLATION_GLONASS"), 629 timeInNs, 630 "0ms >= X <= 10ms", 631 String.valueOf(sv_time_ms), 632 sv_time_ms >= 0 && sv_time_ms <= 10); 633 } else if ((state & GnssMeasurement.STATE_CODE_LOCK) 634 == GnssMeasurement.STATE_CODE_LOCK) { 635 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 636 "GNSS_MEASUREMENT_STATE_CODE_LOCK", 637 "GnssStatus.CONSTELLATION_GLONASS"), 638 timeInNs, 639 "0ms >= X <= 1ms", 640 String.valueOf(sv_time_ms), 641 sv_time_ms >= 0 && sv_time_ms <= 1); 642 } 643 break; 644 case GnssStatus.CONSTELLATION_GALILEO: 645 if ((state & GnssMeasurement.STATE_TOW_DECODED) 646 == GnssMeasurement.STATE_TOW_DECODED) { 647 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 648 "GNSS_MEASUREMENT_STATE_TOW_DECODED", 649 "GnssStatus.CONSTELLATION_GALILEO"), 650 timeInNs, 651 "0 >= X <= 7 days", 652 String.valueOf(sv_time_days), 653 sv_time_days >= 0 && sv_time_days <= 7); 654 } else if ((state & GnssMeasurement.STATE_TOW_KNOWN) 655 == GnssMeasurement.STATE_TOW_KNOWN) { 656 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 657 "GNSS_MEASUREMENT_STATE_TOW_DECODED", 658 "GnssStatus.CONSTELLATION_GALILEO"), 659 timeInNs, 660 "0 >= X <= 7 days", 661 String.valueOf(sv_time_days), 662 sv_time_days >= 0 && sv_time_days <= 7); 663 } else if ((state & GnssMeasurement.STATE_GAL_E1B_PAGE_SYNC) 664 == GnssMeasurement.STATE_GAL_E1B_PAGE_SYNC) { 665 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 666 "GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC", 667 "GnssStatus.CONSTELLATION_GALILEO"), 668 timeInNs, 669 "0s >= X <= 2s", 670 String.valueOf(sv_time_sec), 671 sv_time_sec >= 0 && sv_time_sec <= 2); 672 } else if ((state & GnssMeasurement.STATE_GAL_E1C_2ND_CODE_LOCK) 673 == GnssMeasurement.STATE_GAL_E1C_2ND_CODE_LOCK) { 674 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 675 "GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK", 676 "GnssStatus.CONSTELLATION_GALILEO"), 677 timeInNs, 678 "0ms >= X <= 100ms", 679 String.valueOf(sv_time_ms), 680 sv_time_ms >= 0 && sv_time_ms <= 100); 681 } else if ((state & GnssMeasurement.STATE_GAL_E1BC_CODE_LOCK) 682 == GnssMeasurement.STATE_GAL_E1BC_CODE_LOCK) { 683 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 684 "GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK", 685 "GnssStatus.CONSTELLATION_GALILEO"), 686 timeInNs, 687 "0ms >= X <= 4ms", 688 String.valueOf(sv_time_ms), 689 sv_time_ms >= 0 && sv_time_ms <= 4); 690 } 691 break; 692 case GnssStatus.CONSTELLATION_BEIDOU: 693 if ((state & GnssMeasurement.STATE_TOW_DECODED) 694 == GnssMeasurement.STATE_TOW_DECODED) { 695 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 696 "GNSS_MEASUREMENT_STATE_TOW_DECODED", 697 "GnssStatus.CONSTELLATION_BEIDOU"), 698 timeInNs, 699 "0 >= X <= 7 days", 700 String.valueOf(sv_time_days), 701 sv_time_days >= 0 && sv_time_days <= 7); 702 } else if ((state & GnssMeasurement.STATE_TOW_KNOWN) 703 == GnssMeasurement.STATE_TOW_KNOWN) { 704 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 705 "GNSS_MEASUREMENT_STATE_TOW_KNOWN", 706 "GnssStatus.CONSTELLATION_BEIDOU"), 707 timeInNs, 708 "0 >= X <= 7 days", 709 String.valueOf(sv_time_days), 710 sv_time_days >= 0 && sv_time_days <= 7); 711 } else if ((state & GnssMeasurement.STATE_SUBFRAME_SYNC) 712 == GnssMeasurement.STATE_SUBFRAME_SYNC) { 713 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 714 "GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC", 715 "GnssStatus.CONSTELLATION_BEIDOU"), 716 timeInNs, 717 "0s >= X <= 6s", 718 String.valueOf(sv_time_sec), 719 sv_time_sec >= 0 && sv_time_sec <= 6); 720 } else if ((state & GnssMeasurement.STATE_BDS_D2_SUBFRAME_SYNC) 721 == GnssMeasurement.STATE_BDS_D2_SUBFRAME_SYNC) { 722 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 723 "GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC", 724 "GnssStatus.CONSTELLATION_BEIDOU"), 725 timeInNs, 726 "0ms >= X <= 600ms (0.6sec)", 727 String.valueOf(sv_time_ms), 728 sv_time_ms >= 0 && sv_time_ms <= 600); 729 } else if ((state & GnssMeasurement.STATE_BIT_SYNC) 730 == GnssMeasurement.STATE_BIT_SYNC) { 731 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 732 "GNSS_MEASUREMENT_STATE_BIT_SYNC", 733 "GnssStatus.CONSTELLATION_BEIDOU"), 734 timeInNs, 735 "0ms >= X <= 20ms", 736 String.valueOf(sv_time_ms), 737 sv_time_ms >= 0 && sv_time_ms <= 20); 738 } else if ((state & GnssMeasurement.STATE_BDS_D2_BIT_SYNC) 739 == GnssMeasurement.STATE_BDS_D2_BIT_SYNC) { 740 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 741 "GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC", 742 "GnssStatus.CONSTELLATION_BEIDOU"), 743 timeInNs, 744 "0ms >= X <= 2ms", 745 String.valueOf(sv_time_ms), 746 sv_time_ms >= 0 && sv_time_ms <= 2); 747 } else if ((state & GnssMeasurement.STATE_CODE_LOCK) 748 == GnssMeasurement.STATE_CODE_LOCK) { 749 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 750 "GNSS_MEASUREMENT_STATE_CODE_LOCK", 751 "GnssStatus.CONSTELLATION_BEIDOU"), 752 timeInNs, 753 "0ms >= X <= 1ms", 754 String.valueOf(sv_time_ms), 755 sv_time_ms >= 0 && sv_time_ms <= 1); 756 } 757 break; 758 } 759 } 760 getReceivedSvTimeNsLogMessage(String state, String constellationType)761 private static String getReceivedSvTimeNsLogMessage(String state, String constellationType) { 762 return "received_sv_time_ns: Received SV Time-of-Week in ns. Constellation type = " 763 + constellationType + ". State = " + state; 764 } 765 766 /** 767 * Verify sv times are in expected range for given constellation type. 768 * This is common check for CONSTELLATION_GPS & CONSTELLATION_QZSS. 769 * 770 * @param measurement GnssMeasurement 771 * @param softAssert custom SoftAssert 772 * @param timeInNs event time in ns 773 * @param state GnssMeasurement State 774 * @param constellationType Gnss Constellation type 775 */ verifyGpsQzssSvTimes(GnssMeasurement measurement, SoftAssert softAssert, long timeInNs, int state, String constellationType)776 private static void verifyGpsQzssSvTimes(GnssMeasurement measurement, 777 SoftAssert softAssert, long timeInNs, int state, String constellationType) { 778 779 long received_sv_time_ns = measurement.getReceivedSvTimeNanos(); 780 double sv_time_ms = TimeUnit.NANOSECONDS.toMillis(received_sv_time_ns); 781 double sv_time_sec = TimeUnit.NANOSECONDS.toSeconds(received_sv_time_ns); 782 double sv_time_days = TimeUnit.NANOSECONDS.toDays(received_sv_time_ns); 783 784 if ((state & GnssMeasurement.STATE_TOW_DECODED) 785 == GnssMeasurement.STATE_TOW_DECODED) { 786 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 787 "GNSS_MEASUREMENT_STATE_TOW_DECODED", 788 constellationType), 789 timeInNs, 790 "0 >= X <= 7 days", 791 String.valueOf(sv_time_days), 792 sv_time_days >= 0 && sv_time_days <= 7); 793 } else if ((state & GnssMeasurement.STATE_TOW_KNOWN) 794 == GnssMeasurement.STATE_TOW_KNOWN) { 795 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 796 "GNSS_MEASUREMENT_STATE_TOW_KNOWN", 797 constellationType), 798 timeInNs, 799 "0 >= X <= 7 days", 800 String.valueOf(sv_time_days), 801 sv_time_days >= 0 && sv_time_days <= 7); 802 } else if ((state & GnssMeasurement.STATE_SUBFRAME_SYNC) 803 == GnssMeasurement.STATE_SUBFRAME_SYNC) { 804 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 805 "GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC", 806 constellationType), 807 timeInNs, 808 "0s >= X <= 6s", 809 String.valueOf(sv_time_sec), 810 sv_time_sec >= 0 && sv_time_sec <= 6); 811 } else if ((state & GnssMeasurement.STATE_BIT_SYNC) 812 == GnssMeasurement.STATE_BIT_SYNC) { 813 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 814 "GNSS_MEASUREMENT_STATE_BIT_SYNC", 815 constellationType), 816 timeInNs, 817 "0ms >= X <= 20ms", 818 String.valueOf(sv_time_ms), 819 sv_time_ms >= 0 && sv_time_ms <= 20); 820 821 } else if ((state & GnssMeasurement.STATE_2ND_CODE_LOCK) 822 == GnssMeasurement.STATE_2ND_CODE_LOCK) { 823 int maxReceivedSvTimeMs = -1; 824 if (isGpsL5OrQzssJ5I(measurement)) { 825 maxReceivedSvTimeMs = 10; 826 } else if (isGpsL5OrQzssJ5Q(measurement)) { 827 maxReceivedSvTimeMs = 20; 828 } else if (isGalileoE1C(measurement)) { 829 maxReceivedSvTimeMs = 100; 830 } else if (isGalileoE5AQ(measurement)) { 831 maxReceivedSvTimeMs = 100; 832 } else { 833 softAssert.assertTrue( 834 "Signal type does not have secondary code but has have " 835 + "STATE_2ND_CODE_LOCK state set. constellation=" 836 + measurement.getConstellationType() 837 + ", carrierFrequencyHz=" + measurement.getCarrierFrequencyHz() 838 + ", codeType=" + measurement.getCodeType() 839 , false); 840 } 841 842 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 843 "GNSS_MEASUREMENT_STATE_2ND_CODE_LOCK", 844 constellationType), 845 timeInNs, 846 "0ms >= X <= " + maxReceivedSvTimeMs + "ms", 847 String.valueOf(sv_time_ms), 848 sv_time_ms >= 0 && sv_time_ms <= maxReceivedSvTimeMs); 849 } else if ((state & GnssMeasurement.STATE_CODE_LOCK) 850 == GnssMeasurement.STATE_CODE_LOCK) { 851 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 852 "GNSS_MEASUREMENT_STATE_CODE_LOCK", 853 constellationType), 854 timeInNs, 855 "0ms >= X <= 1ms", 856 String.valueOf(sv_time_ms), 857 sv_time_ms >= 0 && sv_time_ms <= 1); 858 } 859 } 860 861 862 /** 863 * Get a unique string for the SV including the constellation and the default L1 band. 864 * 865 * @param constellationType Gnss Constellation type 866 * @param svId Gnss Sv Identifier 867 */ getUniqueSvStringId(int constellationType, int svId)868 public static String getUniqueSvStringId(int constellationType, int svId) { 869 return getUniqueSvStringId(constellationType, svId, GnssBand.GNSS_L1); 870 } 871 872 /** 873 * Get a unique string for the SV including the constellation and the band. 874 * 875 * @param constellationType Gnss Constellation type 876 * @param svId Gnss Sv Identifier 877 * @param carrierFrequencyHz Carrier Frequency for Sv in Hz 878 */ getUniqueSvStringId(int constellationType, int svId, float carrierFrequencyHz)879 public static String getUniqueSvStringId(int constellationType, int svId, 880 float carrierFrequencyHz) { 881 return getUniqueSvStringId(constellationType, svId, 882 frequencyToGnssBand(carrierFrequencyHz)); 883 } 884 getUniqueSvStringId(int constellationType, int svId, GnssBand gnssBand)885 private static String getUniqueSvStringId(int constellationType, int svId, GnssBand gnssBand) { 886 return gnssBand.toString() + "." + constellationType + "." + svId; 887 } 888 889 /** 890 * Assert all mandatory fields in Gnss Navigation Message are in expected range. 891 * See mandatory fields in {@code gps.h}. 892 * 893 * @param testLocationManager TestLocationManager 894 * @param events GnssNavigationMessageEvents 895 */ verifyGnssNavMessageMandatoryField(TestLocationManager testLocationManager, List<GnssNavigationMessage> events)896 public static void verifyGnssNavMessageMandatoryField(TestLocationManager testLocationManager, 897 List<GnssNavigationMessage> events) { 898 // Verify mandatory GnssNavigationMessage field values. 899 SoftAssert softAssert = new SoftAssert(TAG); 900 for (GnssNavigationMessage message : events) { 901 int type = message.getType(); 902 softAssert.assertTrue("Gnss Navigation Message Type:expected [" + 903 getGnssNavMessageTypes() + "] actual = " + type, 904 GNSS_NAVIGATION_MESSAGE_TYPE.contains(type)); 905 906 int messageType = message.getType(); 907 softAssert.assertTrue("Message ID cannot be 0", message.getMessageId() != 0); 908 if (messageType == GnssNavigationMessage.TYPE_GAL_I) { 909 softAssert.assertTrue("Sub Message ID can not be negative.", 910 message.getSubmessageId() >= 0); 911 } else { 912 softAssert.assertTrue("Sub Message ID has to be greater than 0.", 913 message.getSubmessageId() > 0); 914 } 915 916 // if message type == TYPE_L1CA, verify PRN & Data Size. 917 if (messageType == GnssNavigationMessage.TYPE_GPS_L1CA) { 918 int svid = message.getSvid(); 919 softAssert.assertTrue("Space Vehicle ID : expected = [1, 32], actual = " + 920 svid, 921 svid >= 1 && svid <= 32); 922 int dataSize = message.getData().length; 923 softAssert.assertTrue("Data size: expected = 40, actual = " + dataSize, 924 dataSize == 40); 925 } else { 926 Log.i(TAG, "GnssNavigationMessage (type = " + messageType 927 + ") skipped for verification."); 928 } 929 } 930 softAssert.assertAll(); 931 } 932 933 /** 934 * Asserts presence of CarrierFrequency and the values are in expected range. 935 * As per CDD 7.3.3 / C-3-3 Year 2107+ should have Carrier Frequency present 936 * As of 2018, per http://www.navipedia.net/index.php/GNSS_signal, all known GNSS bands 937 * lie within 2 frequency ranges [1100-1300] & [1500-1700]. 938 * 939 * @param softAssert custom SoftAssert 940 * @param testLocationManager TestLocationManager 941 * @param hasCarrierFrequency Whether carrierFrequency is present 942 * @param carrierFrequencyHz Value of carrier frequency in Hz if hasCarrierFrequency is true. 943 * It is ignored when hasCarrierFrequency is false. 944 */ verifyGnssCarrierFrequency(SoftAssert softAssert, TestLocationManager testLocationManager, boolean hasCarrierFrequency, float carrierFrequencyHz)945 public static void verifyGnssCarrierFrequency(SoftAssert softAssert, 946 TestLocationManager testLocationManager, 947 boolean hasCarrierFrequency, float carrierFrequencyHz) { 948 949 if (hasCarrierFrequency) { 950 float frequencyMhz = carrierFrequencyHz/1e6F; 951 softAssert.assertTrue("carrier_frequency_mhz: Carrier frequency in Mhz", 952 "1100 < X < 1300 || 1500 < X < 1700", 953 String.valueOf(frequencyMhz), 954 (frequencyMhz > 1100.0 && frequencyMhz < 1300.0) || 955 (frequencyMhz > 1500.0 && frequencyMhz < 1700.0)); 956 } 957 } 958 getGnssNavMessageTypes()959 private static String getGnssNavMessageTypes() { 960 StringBuilder typesStr = new StringBuilder(); 961 for (int type : GNSS_NAVIGATION_MESSAGE_TYPE) { 962 typesStr.append(String.format("0x%04X", type)); 963 typesStr.append(", "); 964 } 965 966 return typesStr.length() > 2 ? typesStr.substring(0, typesStr.length() - 2) : ""; 967 } 968 969 /** 970 * The band information is as of 2018, per http://www.navipedia.net/index.php/GNSS_signal 971 * Bands are combined for simplicity as the constellation is also tracked. 972 * 973 * @param frequencyHz Frequency in Hz 974 * @return GnssBand where the frequency lies. 975 */ frequencyToGnssBand(float frequencyHz)976 private static GnssBand frequencyToGnssBand(float frequencyHz) { 977 float frequencyMhz = frequencyHz/1e6F; 978 if (frequencyMhz >= 1151 && frequencyMhz <= 1214) { 979 return GnssBand.GNSS_L5; 980 } 981 if (frequencyMhz > 1214 && frequencyMhz <= 1255) { 982 return GnssBand.GNSS_L2; 983 } 984 if (frequencyMhz > 1255 && frequencyMhz <= 1300) { 985 return GnssBand.GNSS_E6; 986 } 987 return GnssBand.GNSS_L1; // default to L1 band 988 } 989 990 /** 991 * Assert most of the fields in Satellite PVT are in expected range. 992 * 993 * @param measurement GnssMeasurement 994 * @param softAssert custom SoftAssert 995 * @param timeInNs event time in ns 996 */ verifySatellitePvt(GnssMeasurement measurement, SoftAssert softAssert, long timeInNs)997 private static void verifySatellitePvt(GnssMeasurement measurement, 998 SoftAssert softAssert, long timeInNs) { 999 SatellitePvt satellitePvt = measurement.getSatellitePvt(); 1000 assertNotNull("SatellitePvt cannot be null when HAS_SATELLITE_PVT is true.", satellitePvt); 1001 1002 if (satellitePvt.hasPositionVelocityClockInfo()){ 1003 assertNotNull("PositionEcef cannot be null when " 1004 + "HAS_POSITION_VELOCITY_CLOCK_INFO is true.", satellitePvt.getPositionEcef()); 1005 assertNotNull("VelocityEcef cannot be null when " 1006 + "HAS_POSITION_VELOCITY_CLOCK_INFO is true.", satellitePvt.getVelocityEcef()); 1007 assertNotNull("ClockInfo cannot be null when " 1008 + "HAS_POSITION_VELOCITY_CLOCK_INFO is true.", satellitePvt.getClockInfo()); 1009 softAssert.assertTrue("x_meters : " 1010 + "Satellite position X in WGS84 ECEF (meters)", 1011 timeInNs, 1012 "-43000000 <= X <= 43000000", 1013 String.valueOf(satellitePvt.getPositionEcef().getXMeters()), 1014 satellitePvt.getPositionEcef().getXMeters() >= -43000000 && 1015 satellitePvt.getPositionEcef().getXMeters() <= 43000000); 1016 softAssert.assertTrue("y_meters : " 1017 + "Satellite position Y in WGS84 ECEF (meters)", 1018 timeInNs, 1019 "-43000000 <= X <= 43000000", 1020 String.valueOf(satellitePvt.getPositionEcef().getYMeters()), 1021 satellitePvt.getPositionEcef().getYMeters() >= -43000000 && 1022 satellitePvt.getPositionEcef().getYMeters() <= 43000000); 1023 softAssert.assertTrue("z_meters : " 1024 + "Satellite position Z in WGS84 ECEF (meters)", 1025 timeInNs, 1026 "-43000000 <= X <= 43000000", 1027 String.valueOf(satellitePvt.getPositionEcef().getZMeters()), 1028 satellitePvt.getPositionEcef().getZMeters() >= -43000000 && 1029 satellitePvt.getPositionEcef().getZMeters() <= 43000000); 1030 softAssert.assertTrue("ure_meters : " 1031 + "The Signal in Space User Range Error (URE) (meters)", 1032 timeInNs, 1033 "X > 0", 1034 String.valueOf(satellitePvt.getPositionEcef().getUreMeters()), 1035 satellitePvt.getPositionEcef().getUreMeters() > 0); 1036 softAssert.assertTrue("x_mps : " 1037 + "Satellite velocity X in WGS84 ECEF (meters per second)", 1038 timeInNs, 1039 "-4000 <= X <= 4000", 1040 String.valueOf(satellitePvt.getVelocityEcef().getXMetersPerSecond()), 1041 satellitePvt.getVelocityEcef().getXMetersPerSecond() >= -4000 && 1042 satellitePvt.getVelocityEcef().getXMetersPerSecond() <= 4000); 1043 softAssert.assertTrue("y_mps : " 1044 + "Satellite velocity Y in WGS84 ECEF (meters per second)", 1045 timeInNs, 1046 "-4000 <= X <= 4000", 1047 String.valueOf(satellitePvt.getVelocityEcef().getYMetersPerSecond()), 1048 satellitePvt.getVelocityEcef().getYMetersPerSecond() >= -4000 && 1049 satellitePvt.getVelocityEcef().getYMetersPerSecond() <= 4000); 1050 softAssert.assertTrue("z_mps : " 1051 + "Satellite velocity Z in WGS84 ECEF (meters per second)", 1052 timeInNs, 1053 "-4000 <= X <= 4000", 1054 String.valueOf(satellitePvt.getVelocityEcef().getZMetersPerSecond()), 1055 satellitePvt.getVelocityEcef().getZMetersPerSecond() >= -4000 && 1056 satellitePvt.getVelocityEcef().getZMetersPerSecond() <= 4000); 1057 softAssert.assertTrue("ure_rate_mps : " 1058 + "The Signal in Space User Range Error Rate (URE Rate) (meters per second)", 1059 timeInNs, 1060 "X > 0", 1061 String.valueOf(satellitePvt.getVelocityEcef().getUreRateMetersPerSecond()), 1062 satellitePvt.getVelocityEcef().getUreRateMetersPerSecond() > 0); 1063 softAssert.assertTrue("hardware_code_bias_meters : " 1064 + "The satellite hardware code bias of the reported code type " 1065 + "w.r.t ionosphere-free measurement in meters.", 1066 timeInNs, 1067 "-17.869 < X < 17.729", 1068 String.valueOf(satellitePvt.getClockInfo().getHardwareCodeBiasMeters()), 1069 satellitePvt.getClockInfo().getHardwareCodeBiasMeters() > -17.869 && 1070 satellitePvt.getClockInfo().getHardwareCodeBiasMeters() < 17.729); 1071 softAssert.assertTrue("time_correction_meters : " 1072 + "The satellite time correction for ionospheric-free signal measurement " 1073 + "(meters)", 1074 timeInNs, 1075 "-3e6 < X < 3e6", 1076 String.valueOf(satellitePvt.getClockInfo().getTimeCorrectionMeters()), 1077 satellitePvt.getClockInfo().getTimeCorrectionMeters() > -3e6 && 1078 satellitePvt.getClockInfo().getTimeCorrectionMeters() < 3e6); 1079 softAssert.assertTrue("clock_drift_mps : " 1080 + "The satellite clock drift (meters per second)", 1081 timeInNs, 1082 "-1.117 < X < 1.117", 1083 String.valueOf(satellitePvt.getClockInfo().getClockDriftMetersPerSecond()), 1084 satellitePvt.getClockInfo().getClockDriftMetersPerSecond() > -1.117 && 1085 satellitePvt.getClockInfo().getClockDriftMetersPerSecond() < 1.117); 1086 } 1087 1088 if (satellitePvt.hasIono()){ 1089 softAssert.assertTrue("iono_delay_meters : " 1090 + "The ionospheric delay in meters", 1091 timeInNs, 1092 "0 < X < 100", 1093 String.valueOf(satellitePvt.getIonoDelayMeters()), 1094 satellitePvt.getIonoDelayMeters() > 0 && 1095 satellitePvt.getIonoDelayMeters() < 100); 1096 } 1097 1098 if (satellitePvt.hasTropo()){ 1099 softAssert.assertTrue("tropo_delay_meters : " 1100 + "The tropospheric delay in meters", 1101 timeInNs, 1102 "0 < X < 100", 1103 String.valueOf(satellitePvt.getTropoDelayMeters()), 1104 satellitePvt.getTropoDelayMeters() > 0 && 1105 satellitePvt.getTropoDelayMeters() < 100); 1106 } 1107 } 1108 isGpsL5OrQzssJ5I(GnssMeasurement measurement)1109 private static boolean isGpsL5OrQzssJ5I(GnssMeasurement measurement) { 1110 return (measurement.getConstellationType() == GnssStatus.CONSTELLATION_GPS || 1111 measurement.getConstellationType() == GnssStatus.CONSTELLATION_QZSS) 1112 && GPS_L5_QZSS_J5_FREQ_RANGE_HZ.contains( 1113 (double) measurement.getCarrierFrequencyHz()) 1114 && measurement.hasCodeType() 1115 && "I".equals(measurement.getCodeType()); 1116 } 1117 isGpsL5OrQzssJ5Q(GnssMeasurement measurement)1118 private static boolean isGpsL5OrQzssJ5Q(GnssMeasurement measurement) { 1119 return (measurement.getConstellationType() == GnssStatus.CONSTELLATION_GPS || 1120 measurement.getConstellationType() == GnssStatus.CONSTELLATION_QZSS) 1121 && GPS_L5_QZSS_J5_FREQ_RANGE_HZ.contains( 1122 (double) measurement.getCarrierFrequencyHz()) 1123 && measurement.hasCodeType() 1124 && "Q".equals(measurement.getCodeType()); 1125 } 1126 isGalileoE1C(GnssMeasurement measurement)1127 private static boolean isGalileoE1C(GnssMeasurement measurement) { 1128 return measurement.getConstellationType() == GnssStatus.CONSTELLATION_GALILEO 1129 && GAL_E1_FREQ_RANGE_HZ.contains((double) measurement.getCarrierFrequencyHz()) 1130 && measurement.hasCodeType() 1131 && "C".equals(measurement.getCodeType()); 1132 } 1133 isGalileoE5AQ(GnssMeasurement measurement)1134 private static boolean isGalileoE5AQ(GnssMeasurement measurement) { 1135 return measurement.getConstellationType() == GnssStatus.CONSTELLATION_GALILEO 1136 && GAL_E5_FREQ_RANGE_HZ.contains((double) measurement.getCarrierFrequencyHz()) 1137 && measurement.hasCodeType() 1138 && "Q".equals(measurement.getCodeType()); 1139 } 1140 } 1141