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; 18 19 import android.annotation.FloatRange; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 26 /** 27 * A class that contains GNSS satellite position, velocity and time information at the 28 * same signal transmission time {@link GnssMeasurement#getReceivedSvTimeNanos()}. 29 * 30 * <p>The position and velocity must be in ECEF coordinates. 31 * 32 * <p>If {@link GnssMeasurement#getSatellitePvt()} is derived from Broadcast ephemeris, then the 33 * position is already w.r.t. the antenna phase center. However, if 34 * {@link GnssMeasurement#getSatellitePvt()} is derived from other modeled orbits, such as 35 * long-term orbits, or precise orbits, then the orbits may have been computed w.r.t. 36 * the satellite center of mass, and then GNSS vendors are expected to correct for the effect 37 * on different phase centers (can differ by meters) of different GNSS signals (e.g. L1, L5) 38 * on the reported satellite position. Accordingly, we might observe a different satellite 39 * position reported for L1 GnssMeasurement struct compared to L5 GnssMeasurement struct. 40 * 41 * <p>If {@link GnssMeasurement#getReceivedSvTimeNanos()} is not fully decoded, 42 * {@link GnssMeasurement#getSatellitePvt()} could still be reported and 43 * {@link GnssMeasurement#getReceivedSvTimeUncertaintyNanos()} would be used to provide confidence. 44 * @hide 45 */ 46 @SystemApi 47 public final class SatellitePvt implements Parcelable { 48 /** 49 * Bit mask for {@link #mFlags} indicating valid satellite position, velocity and clock info 50 * fields are stored in the SatellitePvt. 51 */ 52 private static final int HAS_POSITION_VELOCITY_CLOCK_INFO = 1 << 0; 53 54 /** 55 * Bit mask for {@link #mFlags} indicating a valid iono delay field is stored in the 56 * SatellitePvt. 57 */ 58 private static final int HAS_IONO = 1 << 1; 59 60 /** 61 * Bit mask for {@link #mFlags} indicating a valid tropo delay field is stored in the 62 * SatellitePvt. 63 */ 64 private static final int HAS_TROPO = 1 << 2; 65 66 /** 67 * A bitfield of flags indicating the validity of the fields in this SatellitePvt. 68 * The bit masks are defined in the constants with prefix HAS_* 69 * 70 * <p>Fields for which there is no corresponding flag must be filled in with a valid value. 71 * For convenience, these are marked as mandatory. 72 * 73 * <p>Others fields may have invalid information in them, if not marked as valid by the 74 * corresponding bit in flags. 75 */ 76 private final int mFlags; 77 78 @Nullable 79 private final PositionEcef mPositionEcef; 80 @Nullable 81 private final VelocityEcef mVelocityEcef; 82 @Nullable 83 private final ClockInfo mClockInfo; 84 private final double mIonoDelayMeters; 85 private final double mTropoDelayMeters; 86 87 /** 88 * Class containing estimates of the satellite position fields in ECEF coordinate frame. 89 * 90 * <p>The satellite position must be defined at the time of transmission of the signal 91 * receivedSvTimeNs. 92 */ 93 public static final class PositionEcef implements Parcelable { 94 private final double mXMeters; 95 private final double mYMeters; 96 private final double mZMeters; 97 private final double mUreMeters; 98 PositionEcef( double xMeters, double yMeters, double zMeters, double ureMeters)99 public PositionEcef( 100 double xMeters, 101 double yMeters, 102 double zMeters, 103 double ureMeters) { 104 mXMeters = xMeters; 105 mYMeters = yMeters; 106 mZMeters = zMeters; 107 mUreMeters = ureMeters; 108 } 109 110 public static final @NonNull Creator<PositionEcef> CREATOR = 111 new Creator<PositionEcef>() { 112 @Override 113 public PositionEcef createFromParcel(Parcel in) { 114 return new PositionEcef( 115 in.readDouble(), 116 in.readDouble(), 117 in.readDouble(), 118 in.readDouble() 119 ); 120 } 121 122 @Override 123 public PositionEcef[] newArray(int size) { 124 return new PositionEcef[size]; 125 } 126 }; 127 128 /** 129 * Returns the satellite position X in WGS84 ECEF (meters). 130 */ 131 @FloatRange() getXMeters()132 public double getXMeters() { 133 return mXMeters; 134 } 135 136 /** 137 * Returns the satellite position Y in WGS84 ECEF (meters). 138 */ 139 @FloatRange() getYMeters()140 public double getYMeters() { 141 return mYMeters; 142 } 143 144 /** 145 * Returns the satellite position Z in WGS84 ECEF (meters). 146 */ 147 @FloatRange() getZMeters()148 public double getZMeters() { 149 return mZMeters; 150 } 151 152 /** 153 * Returns the signal in Space User Range Error (URE) (meters). 154 */ 155 @FloatRange(from = 0.0f, fromInclusive = false) getUreMeters()156 public double getUreMeters() { 157 return mUreMeters; 158 } 159 160 @Override describeContents()161 public int describeContents() { 162 return 0; 163 } 164 165 @Override writeToParcel(@onNull Parcel dest, int flags)166 public void writeToParcel(@NonNull Parcel dest, int flags) { 167 dest.writeDouble(mXMeters); 168 dest.writeDouble(mYMeters); 169 dest.writeDouble(mZMeters); 170 dest.writeDouble(mUreMeters); 171 } 172 173 @Override toString()174 public String toString() { 175 return "PositionEcef{" 176 + "xMeters=" + mXMeters 177 + ", yMeters=" + mYMeters 178 + ", zMeters=" + mZMeters 179 + ", ureMeters=" + mUreMeters 180 + "}"; 181 } 182 } 183 184 /** 185 * Class containing estimates of the satellite velocity fields in the ECEF coordinate frame. 186 * 187 * <p>The satellite velocity must be defined at the time of transmission of the signal 188 * receivedSvTimeNs. 189 */ 190 public static final class VelocityEcef implements Parcelable { 191 private final double mXMetersPerSecond; 192 private final double mYMetersPerSecond; 193 private final double mZMetersPerSecond; 194 private final double mUreRateMetersPerSecond; 195 VelocityEcef( double xMetersPerSecond, double yMetersPerSecond, double zMetersPerSecond, double ureRateMetersPerSecond)196 public VelocityEcef( 197 double xMetersPerSecond, 198 double yMetersPerSecond, 199 double zMetersPerSecond, 200 double ureRateMetersPerSecond) { 201 mXMetersPerSecond = xMetersPerSecond; 202 mYMetersPerSecond = yMetersPerSecond; 203 mZMetersPerSecond = zMetersPerSecond; 204 mUreRateMetersPerSecond = ureRateMetersPerSecond; 205 } 206 207 public static final @NonNull Creator<VelocityEcef> CREATOR = 208 new Creator<VelocityEcef>() { 209 @Override 210 public VelocityEcef createFromParcel(Parcel in) { 211 return new VelocityEcef( 212 in.readDouble(), 213 in.readDouble(), 214 in.readDouble(), 215 in.readDouble() 216 ); 217 } 218 219 @Override 220 public VelocityEcef[] newArray(int size) { 221 return new VelocityEcef[size]; 222 } 223 }; 224 225 /** 226 * Returns the satellite velocity X in WGS84 ECEF (meters per second). 227 */ 228 @FloatRange() getXMetersPerSecond()229 public double getXMetersPerSecond() { 230 return mXMetersPerSecond; 231 } 232 233 /** 234 * Returns the satellite velocity Y in WGS84 ECEF (meters per second). 235 */ 236 @FloatRange() getYMetersPerSecond()237 public double getYMetersPerSecond() { 238 return mYMetersPerSecond; 239 } 240 241 /** 242 *Returns the satellite velocity Z in WGS84 ECEF (meters per second). 243 */ 244 @FloatRange() getZMetersPerSecond()245 public double getZMetersPerSecond() { 246 return mZMetersPerSecond; 247 } 248 249 /** 250 * Returns the signal in Space User Range Error Rate (URE Rate) (meters per second). 251 * 252 * <p>It covers satellite velocity error and Satellite clock drift 253 * projected to the pseudorange rate measurements. 254 */ 255 @FloatRange(from = 0.0f, fromInclusive = false) getUreRateMetersPerSecond()256 public double getUreRateMetersPerSecond() { 257 return mUreRateMetersPerSecond; 258 } 259 260 @Override describeContents()261 public int describeContents() { 262 return 0; 263 } 264 265 @Override writeToParcel(@onNull Parcel dest, int flags)266 public void writeToParcel(@NonNull Parcel dest, int flags) { 267 dest.writeDouble(mXMetersPerSecond); 268 dest.writeDouble(mYMetersPerSecond); 269 dest.writeDouble(mZMetersPerSecond); 270 dest.writeDouble(mUreRateMetersPerSecond); 271 } 272 273 @Override toString()274 public String toString() { 275 return "VelocityEcef{" 276 + "xMetersPerSecond=" + mXMetersPerSecond 277 + ", yMetersPerSecond=" + mYMetersPerSecond 278 + ", zMetersPerSecond=" + mZMetersPerSecond 279 + ", ureRateMetersPerSecond=" + mUreRateMetersPerSecond 280 + "}"; 281 } 282 } 283 284 /** 285 * Class containing estimates of the satellite clock info. 286 */ 287 public static final class ClockInfo implements Parcelable { 288 private final double mHardwareCodeBiasMeters; 289 private final double mTimeCorrectionMeters; 290 private final double mClockDriftMetersPerSecond; 291 ClockInfo( double hardwareCodeBiasMeters, double timeCorrectionMeters, double clockDriftMetersPerSecond)292 public ClockInfo( 293 double hardwareCodeBiasMeters, 294 double timeCorrectionMeters, 295 double clockDriftMetersPerSecond) { 296 mHardwareCodeBiasMeters = hardwareCodeBiasMeters; 297 mTimeCorrectionMeters = timeCorrectionMeters; 298 mClockDriftMetersPerSecond = clockDriftMetersPerSecond; 299 } 300 301 public static final @NonNull Creator<ClockInfo> CREATOR = 302 new Creator<ClockInfo>() { 303 @Override 304 public ClockInfo createFromParcel(Parcel in) { 305 return new ClockInfo( 306 in.readDouble(), 307 in.readDouble(), 308 in.readDouble() 309 ); 310 } 311 312 @Override 313 public ClockInfo[] newArray(int size) { 314 return new ClockInfo[size]; 315 } 316 }; 317 318 /** 319 * Returns the satellite hardware code bias of the reported code type w.r.t 320 * ionosphere-free measurement in meters. 321 * 322 * <p>When broadcast ephemeris is used, this is the offset caused 323 * by the satellite hardware delays at different frequencies; 324 * e.g. in IS-GPS-705D, this term is described in Section 325 * 20.3.3.3.1.2.1. 326 * 327 * <p>For GPS this term is ~10ns, and affects the satellite position 328 * computation by less than a millimeter. 329 */ 330 @FloatRange() getHardwareCodeBiasMeters()331 public double getHardwareCodeBiasMeters() { 332 return mHardwareCodeBiasMeters; 333 } 334 335 /** 336 * Returns the satellite time correction for ionospheric-free signal measurement 337 * (meters). The satellite clock correction for the given signal type 338 * = satTimeCorrectionMeters - satHardwareCodeBiasMeters. 339 * 340 * <p>When broadcast ephemeris is used, this is the offset modeled in the 341 * clock terms broadcast over the air by the satellites; 342 * e.g. in IS-GPS-200H, Section 20.3.3.3.3.1, this term is 343 * ∆tsv = af0 + af1(t - toc) + af2(t - toc)^2 + ∆tr. 344 * 345 * <p>If another source of ephemeris is used for SatellitePvt, then the 346 * equivalent value of satTimeCorrection must be provided. 347 * 348 * <p>For GPS this term is ~1ms, and affects the satellite position 349 * computation by ~1m. 350 */ 351 @FloatRange() getTimeCorrectionMeters()352 public double getTimeCorrectionMeters() { 353 return mTimeCorrectionMeters; 354 } 355 356 /** 357 * Returns the satellite clock drift (meters per second). 358 */ 359 @FloatRange() getClockDriftMetersPerSecond()360 public double getClockDriftMetersPerSecond() { 361 return mClockDriftMetersPerSecond; 362 } 363 364 @Override describeContents()365 public int describeContents() { 366 return 0; 367 } 368 369 @Override writeToParcel(@onNull Parcel dest, int flags)370 public void writeToParcel(@NonNull Parcel dest, int flags) { 371 dest.writeDouble(mHardwareCodeBiasMeters); 372 dest.writeDouble(mTimeCorrectionMeters); 373 dest.writeDouble(mClockDriftMetersPerSecond); 374 } 375 376 @Override toString()377 public String toString() { 378 return "ClockInfo{" 379 + "hardwareCodeBiasMeters=" + mHardwareCodeBiasMeters 380 + ", timeCorrectionMeters=" + mTimeCorrectionMeters 381 + ", clockDriftMetersPerSecond=" + mClockDriftMetersPerSecond 382 + "}"; 383 } 384 } 385 SatellitePvt( int flags, @Nullable PositionEcef positionEcef, @Nullable VelocityEcef velocityEcef, @Nullable ClockInfo clockInfo, double ionoDelayMeters, double tropoDelayMeters)386 private SatellitePvt( 387 int flags, 388 @Nullable PositionEcef positionEcef, 389 @Nullable VelocityEcef velocityEcef, 390 @Nullable ClockInfo clockInfo, 391 double ionoDelayMeters, 392 double tropoDelayMeters) { 393 mFlags = flags; 394 mPositionEcef = positionEcef; 395 mVelocityEcef = velocityEcef; 396 mClockInfo = clockInfo; 397 mIonoDelayMeters = ionoDelayMeters; 398 mTropoDelayMeters = tropoDelayMeters; 399 } 400 401 /** 402 * Returns a {@link PositionEcef} object that contains estimates of the satellite 403 * position fields in ECEF coordinate frame. 404 */ 405 @Nullable getPositionEcef()406 public PositionEcef getPositionEcef() { 407 return mPositionEcef; 408 } 409 410 /** 411 * Returns a {@link VelocityEcef} object that contains estimates of the satellite 412 * velocity fields in the ECEF coordinate frame. 413 */ 414 @Nullable getVelocityEcef()415 public VelocityEcef getVelocityEcef() { 416 return mVelocityEcef; 417 } 418 419 /** 420 * Returns a {@link ClockInfo} object that contains estimates of the satellite 421 * clock info. 422 */ 423 @Nullable getClockInfo()424 public ClockInfo getClockInfo() { 425 return mClockInfo; 426 } 427 428 /** 429 * Returns the ionospheric delay in meters. 430 */ 431 @FloatRange() getIonoDelayMeters()432 public double getIonoDelayMeters() { 433 return mIonoDelayMeters; 434 } 435 436 /** 437 * Returns the tropospheric delay in meters. 438 */ 439 @FloatRange() getTropoDelayMeters()440 public double getTropoDelayMeters() { 441 return mTropoDelayMeters; 442 } 443 444 /** Returns {@code true} if {@link #getPositionEcef()}, {@link #getVelocityEcef()}, 445 * and {@link #getClockInfo()} are valid. 446 */ hasPositionVelocityClockInfo()447 public boolean hasPositionVelocityClockInfo() { 448 return (mFlags & HAS_POSITION_VELOCITY_CLOCK_INFO) != 0; 449 } 450 451 /** Returns {@code true} if {@link #getIonoDelayMeters()} is valid. */ hasIono()452 public boolean hasIono() { 453 return (mFlags & HAS_IONO) != 0; 454 } 455 456 /** Returns {@code true} if {@link #getTropoDelayMeters()} is valid. */ hasTropo()457 public boolean hasTropo() { 458 return (mFlags & HAS_TROPO) != 0; 459 } 460 461 public static final @android.annotation.NonNull Creator<SatellitePvt> CREATOR = 462 new Creator<SatellitePvt>() { 463 @Override 464 @Nullable 465 public SatellitePvt createFromParcel(Parcel in) { 466 int flags = in.readInt(); 467 ClassLoader classLoader = getClass().getClassLoader(); 468 PositionEcef positionEcef = in.readParcelable(classLoader); 469 VelocityEcef velocityEcef = in.readParcelable(classLoader); 470 ClockInfo clockInfo = in.readParcelable(classLoader); 471 double ionoDelayMeters = in.readDouble(); 472 double tropoDelayMeters = in.readDouble(); 473 474 return new SatellitePvt( 475 flags, 476 positionEcef, 477 velocityEcef, 478 clockInfo, 479 ionoDelayMeters, 480 tropoDelayMeters); 481 } 482 483 @Override 484 public SatellitePvt[] newArray(int size) { 485 return new SatellitePvt[size]; 486 } 487 }; 488 489 @Override describeContents()490 public int describeContents() { 491 return 0; 492 } 493 494 @Override writeToParcel(@onNull Parcel parcel, int flags)495 public void writeToParcel(@NonNull Parcel parcel, int flags) { 496 parcel.writeInt(mFlags); 497 parcel.writeParcelable(mPositionEcef, flags); 498 parcel.writeParcelable(mVelocityEcef, flags); 499 parcel.writeParcelable(mClockInfo, flags); 500 parcel.writeDouble(mIonoDelayMeters); 501 parcel.writeDouble(mTropoDelayMeters); 502 } 503 504 @Override toString()505 public String toString() { 506 return "SatellitePvt{" 507 + "Flags=" + mFlags 508 + ", PositionEcef=" + mPositionEcef 509 + ", VelocityEcef=" + mVelocityEcef 510 + ", ClockInfo=" + mClockInfo 511 + ", IonoDelayMeters=" + mIonoDelayMeters 512 + ", TropoDelayMeters=" + mTropoDelayMeters 513 + "}"; 514 } 515 516 /** 517 * Builder class for SatellitePvt. 518 */ 519 public static final class Builder { 520 /** 521 * For documentation of below fields, see corresponding fields in {@link 522 * SatellitePvt}. 523 */ 524 private int mFlags; 525 @Nullable private PositionEcef mPositionEcef; 526 @Nullable private VelocityEcef mVelocityEcef; 527 @Nullable private ClockInfo mClockInfo; 528 private double mIonoDelayMeters; 529 private double mTropoDelayMeters; 530 531 /** 532 * Set position ECEF. 533 * 534 * @param positionEcef position ECEF object 535 * @return Builder builder object 536 */ 537 @NonNull setPositionEcef( @onNull PositionEcef positionEcef)538 public Builder setPositionEcef( 539 @NonNull PositionEcef positionEcef) { 540 mPositionEcef = positionEcef; 541 updateFlags(); 542 return this; 543 } 544 545 /** 546 * Set velocity ECEF. 547 * 548 * @param velocityEcef velocity ECEF object 549 * @return Builder builder object 550 */ 551 @NonNull setVelocityEcef( @onNull VelocityEcef velocityEcef)552 public Builder setVelocityEcef( 553 @NonNull VelocityEcef velocityEcef) { 554 mVelocityEcef = velocityEcef; 555 updateFlags(); 556 return this; 557 } 558 559 /** 560 * Set clock info. 561 * 562 * @param clockInfo clock info object 563 * @return Builder builder object 564 */ 565 @NonNull setClockInfo( @onNull ClockInfo clockInfo)566 public Builder setClockInfo( 567 @NonNull ClockInfo clockInfo) { 568 mClockInfo = clockInfo; 569 updateFlags(); 570 return this; 571 } 572 updateFlags()573 private void updateFlags() { 574 if (mPositionEcef != null && mVelocityEcef != null && mClockInfo != null) { 575 mFlags = (byte) (mFlags | HAS_POSITION_VELOCITY_CLOCK_INFO); 576 } 577 } 578 579 /** 580 * Set ionospheric delay in meters. 581 * 582 * @param ionoDelayMeters ionospheric delay (meters) 583 * @return Builder builder object 584 */ 585 @NonNull setIonoDelayMeters( @loatRangefrom = 0.0f, to = 100.0f) double ionoDelayMeters)586 public Builder setIonoDelayMeters( 587 @FloatRange(from = 0.0f, to = 100.0f) double ionoDelayMeters) { 588 mIonoDelayMeters = ionoDelayMeters; 589 mFlags = (byte) (mFlags | HAS_IONO); 590 return this; 591 } 592 593 /** 594 * Set tropospheric delay in meters. 595 * 596 * @param tropoDelayMeters tropospheric delay (meters) 597 * @return Builder builder object 598 */ 599 @NonNull setTropoDelayMeters( @loatRangefrom = 0.0f, to = 100.0f) double tropoDelayMeters)600 public Builder setTropoDelayMeters( 601 @FloatRange(from = 0.0f, to = 100.0f) double tropoDelayMeters) { 602 mTropoDelayMeters = tropoDelayMeters; 603 mFlags = (byte) (mFlags | HAS_TROPO); 604 return this; 605 } 606 607 /** 608 * Build SatellitePvt object. 609 * 610 * @return instance of SatellitePvt 611 */ 612 @NonNull build()613 public SatellitePvt build() { 614 return new SatellitePvt(mFlags, mPositionEcef, mVelocityEcef, mClockInfo, 615 mIonoDelayMeters, mTropoDelayMeters); 616 } 617 } 618 } 619