1 //============================================================================== 2 // 3 // This file is part of GPSTk, the GPS Toolkit. 4 // 5 // The GPSTk is free software; you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published 7 // by the Free Software Foundation; either version 3.0 of the License, or 8 // any later version. 9 // 10 // The GPSTk is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with GPSTk; if not, write to the Free Software Foundation, 17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 18 // 19 // This software was developed by Applied Research Laboratories at the 20 // University of Texas at Austin. 21 // Copyright 2004-2020, The Board of Regents of The University of Texas System 22 // 23 //============================================================================== 24 25 //============================================================================== 26 // 27 // This software was developed by Applied Research Laboratories at the 28 // University of Texas at Austin, under contract to an agency or agencies 29 // within the U.S. Department of Defense. The U.S. Government retains all 30 // rights to use, duplicate, distribute, disclose, or release this software. 31 // 32 // Pursuant to DoD Directive 523024 33 // 34 // DISTRIBUTION STATEMENT A: This software has been approved for public 35 // release, distribution is unlimited. 36 // 37 //============================================================================== 38 39 /** @file SP3EphemerisStore.hpp 40 * Store a tabular list of position and clock bias (perhaps also 41 * velocity and clock drift) data from SP3 file(s) for several 42 * satellites; access the tables to compute values at any timetag, 43 * within the limits of the data, from this table via interpolation. 44 * An option allows assigning the clock store to RINEX clock files, 45 * with separate timestep and interpolation algorithm. */ 46 47 #ifndef GPSTK_SP3_EPHEMERIS_STORE_INCLUDE 48 #define GPSTK_SP3_EPHEMERIS_STORE_INCLUDE 49 50 #include <map> 51 #include <vector> 52 #include <algorithm> 53 #include <iostream> 54 55 #include "Exception.hpp" 56 #include "SatID.hpp" 57 #include "CommonTime.hpp" 58 #include "XvtStore.hpp" 59 60 #include "FileStore.hpp" 61 #include "ClockSatStore.hpp" 62 #include "PositionSatStore.hpp" 63 64 #include "SP3Header.hpp" 65 #include "Rinex3ClockHeader.hpp" 66 67 namespace gpstk 68 { 69 /// @ingroup GNSSEph 70 //@{ 71 72 /** Store position and clock bias (and perhaps velocity and 73 * drift) data from SP3 files, using (separate) stores based on 74 * TabularSatStore. An option allows the clock store to be taken 75 * from RINEX clock files instead. Keep a FileStore for the SP3 76 * input files, and for the RINEX clock files, if they are 77 * used. Inherit XvtStore for the interface it defines. */ 78 class SP3EphemerisStore : public XvtStore<SatID> 79 { 80 81 // member data 82 private: 83 /** Time system for this store. Must set, and keep 84 * consistent, in loadFile. Returned in getTimeSystem() 85 * (virtual in XvtStore). 86 * @note usually GPS, but CANNOT assume so. */ 87 TimeSystem storeTimeSystem; 88 89 /// PositionSatStore for SP3 ephemeris data 90 PositionSatStore posStore; 91 92 /// ClockSatStore for SP3 OR RINEX clock data 93 ClockSatStore clkStore; 94 95 /// FileStore for the SP3 input files 96 FileStore<SP3Header> SP3Files; 97 98 /// FileStore for the (optional) RINEX clock input files 99 FileStore<Rinex3ClockHeader> clkFiles; 100 101 /** flag indicating whether the clock store contains data 102 * from SP3 (true, the default) or Rinex clock (false) 103 * files */ 104 bool useSP3clock; 105 106 /** Flag to reject all data when there are bad positions, 107 * default true. */ 108 bool rejectBadPosFlag; 109 110 /** Flag to reject all data when there are bad clocks, 111 * default true. 112 * @note this flag has no effect if the clock store comes 113 * from RINEX clock files. */ 114 bool rejectBadClockFlag; 115 116 /** Flag to reject predicted position data, using 117 * orbitPredFlag in SP3Data. */ 118 bool rejectPredPosFlag; 119 120 /** Flag to reject predicted clock data, using clockPredFlag 121 * in SP3Data. 122 * @note this flag has no effect if the clock store comes 123 * from RINEX clock files. */ 124 bool rejectPredClockFlag; 125 126 // member functions 127 128 /** Private utility routine used by the loadFile and 129 * loadSP3File routines. Store position (velocity) and clock 130 * data from SP3 files in clock and position stores. Also 131 * update the FileStore with the filename and SP3 header. 132 * Check time systems consistentcy, and if possible set store 133 * time system. 134 * @throw Exception 135 */ 136 void loadSP3Store(const std::string& filename, bool fillClockStore); 137 138 public: 139 140 /// Default constructor SP3EphemerisStore()141 SP3EphemerisStore() throw() : storeTimeSystem(TimeSystem::Any), 142 useSP3clock(true), 143 rejectBadPosFlag(true), 144 rejectBadClockFlag(true), 145 rejectPredPosFlag(false), 146 rejectPredClockFlag(false) 147 { } 148 149 /// Destructor ~SP3EphemerisStore()150 virtual ~SP3EphemerisStore() 151 { } 152 153 // XvtStore interface: 154 /** Returns the position, velocity, and clock offset of the 155 * indicated object in ECEF coordinates (meters) at the 156 * indicated time. 157 * @param[in] sat the satellite of interest 158 * @param[in] ttag the time to look up 159 * @return the Xvt of the object at the indicated time 160 * @throw InvalidRequest If the request can not be completed for any 161 * reason, this is thrown. The text may have additional 162 * information as to why the request failed. */ 163 virtual Xvt getXvt(const SatID& sat, const CommonTime& ttag) const; 164 165 /** Compute the position, velocity and clock offset of the 166 * indicated object in ECEF coordinates (meters) at the 167 * indicated time. 168 * This method functions similarly to getXvt() except that it 169 * does not throw an exception for any reason. Instead, the 170 * caller is expected to check the value of the "health" 171 * field of the returned Xvt and decide what to do with the 172 * data. 173 * @note This function ignores the onlyHealthy flag as health 174 * information is not available in the SP3 format. 175 * @note The health flag in the returned Xvt can have one of 176 * two values, "Unavailable", in which case the Xvt could 177 * not be determined from the data in the store, or 178 * "Unused" in which case the Xvt could be determined. 179 * "Unused" because the SP3 format does not include health 180 * status information. 181 * @param[in] id the object's identifier 182 * @param[in] t the time to look up 183 * @return the Xvt of the object at the indicated time */ 184 virtual Xvt computeXvt(const SatID& id, const CommonTime& t) const 185 throw(); 186 187 /** Get the satellite health at a specific time. 188 * @param[in] id the object's identifier 189 * @param[in] t the time to look up 190 * @return "Unused" at all times as the SP3 format does not 191 * provide health status. */ 192 virtual Xvt::HealthStatus getSVHealth(const SatID& id, 193 const CommonTime& t) const throw(); 194 195 /** Dump information about the store to an ostream. 196 * @param[in] os ostream to receive the output; defaults to std::cout 197 * @param[in] detail integer level of detail to provide; 198 * allowed values are 199 * 0: number of satellites, time step and time limits 200 * 1: above plus flags, gap and interval values, and 201 * number of data/sat 202 * 2: above plus all the data tables */ dump(std::ostream & os=std::cout,short detail=0) const203 virtual void dump(std::ostream& os = std::cout, short detail = 0) 204 const throw() 205 { 206 // may have to re-write this... 207 os << "Dump SP3EphemerisStore:" << std::endl; 208 // 'reject' flags 209 os << (rejectBadPosFlag ? " Reject":" Do not reject") 210 << " bad positions." << std::endl; 211 os << (rejectBadClockFlag ? " Reject":" Do not reject") 212 << " bad clocks." << std::endl; 213 os << (rejectPredPosFlag ? " Reject":" Do not reject") 214 << " predicted positions." << std::endl; 215 os << (rejectPredClockFlag ? " Reject":" Do not reject") 216 << " predicted clocks." << std::endl; 217 218 SP3Files.dump(os, detail); 219 posStore.dump(os, detail); 220 if(!useSP3clock) clkFiles.dump(os, detail); 221 clkStore.dump(os, detail); 222 223 os << "End dump SP3EphemerisStore." << std::endl; 224 } 225 226 /** Edit the dataset, removing data outside the indicated 227 * time interval 228 * @param[in] tmin defines the beginning of the time interval 229 * @param[in] tmax defines the end of the time interval */ edit(const CommonTime & tmin,const CommonTime & tmax=CommonTime::END_OF_TIME)230 virtual void edit(const CommonTime& tmin, 231 const CommonTime& tmax = CommonTime::END_OF_TIME) throw() 232 { 233 posStore.edit(tmin, tmax); 234 clkStore.edit(tmin, tmax); 235 } 236 237 /// Clear the dataset, meaning remove all data clear(void)238 virtual void clear(void) throw() 239 { clearPosition(); clearClock(); } 240 241 /// Return time system (@note usually GPS, but CANNOT assume so) getTimeSystem(void) const242 virtual TimeSystem getTimeSystem(void) const throw() 243 { return storeTimeSystem; } 244 245 /** Determine the earliest time for which this object can 246 * successfully determine the Xvt for any object. 247 * @return the earliest time in the table 248 * @throw InvalidRequest if the object has no data. */ 249 virtual CommonTime getInitialTime() const; 250 251 /** Determine the latest time for which this object can 252 * successfully determine the Xvt for any object. 253 * @return the latest time in the table 254 * @throw InvalidRequest if the object has no data. */ 255 virtual CommonTime getFinalTime() const; 256 257 /// Return true if IndexType=SatID is present in the data tables isPresent(const SatID & sat) const258 virtual bool isPresent(const SatID& sat) const throw() 259 { return (posStore.isPresent(sat) && clkStore.isPresent(sat)); } 260 261 /// Return true if velocity is present in the data tables hasVelocity() const262 virtual bool hasVelocity() const throw() 263 { return posStore.hasVelocity(); } 264 265 // end of XvtStore interface 266 267 /** Dump information about the position store to an ostream. 268 * @param[in] os ostream to receive the output; defaults to std::cout 269 * @param[in] detail integer level of detail to provide; 270 * allowed values are 271 * 0: number of satellites, time step and time limits 272 * 1: above plus flags, gap and interval values, and 273 * number of data/sat 274 * 2: above plus all the data tables */ dumpPosition(std::ostream & os=std::cout,short detail=0) const275 void dumpPosition(std::ostream& os = std::cout, short detail = 0) 276 const throw() 277 { 278 SP3Files.dump(os, detail); 279 posStore.dump(os, detail); 280 } 281 282 /** Dump information about the clock store to an ostream. 283 * @param[in] os ostream to receive the output; defaults to std::cout 284 * @param[in] detail integer level of detail to provide; 285 * allowed values are 286 * 0: number of satellites, time step and time limits 287 * 1: above plus flags, gap and interval values, and 288 * number of data/sat 289 * 2: above plus all the data tables */ dumpClock(std::ostream & os=std::cout,short detail=0) const290 void dumpClock(std::ostream& os = std::cout, short detail = 0) 291 const throw() 292 { 293 if(useSP3clock) 294 SP3Files.dump(os, detail); 295 else 296 clkFiles.dump(os, detail); 297 clkStore.dump(os, detail); 298 } 299 300 /** Return the position for the given satellite at the given time. 301 * @param[in] sat the SatID of the satellite of interest 302 * @param[in] ttag the time (CommonTime) of interest 303 * @return Triple containing the position ECEF XYZ meters 304 * @throw InvalidRequest if result cannot be computed, for 305 * example because: 306 * a) the time t does not lie within the time limits of the 307 * data table 308 * b) checkDataGap is true and there is a data gap 309 * c) checkInterval is true and the interval is larger than 310 * maxInterval */ 311 Triple getPosition(const SatID sat, const CommonTime ttag) 312 const; 313 314 /** Return the velocity for the given satellite at the given time 315 * @param[in] sat the SatID of the satellite of interest 316 * @param[in] ttag the time (CommonTime) of interest 317 * @return Triple containing the velocity ECEF XYZ meters/second 318 * @throw InvalidRequest if result cannot be computed, for 319 * example because 320 * a) the time t does not lie within the time limits of the 321 * data table 322 * b) checkDataGap is true and there is a data gap 323 * c) checkInterval is true and the interval is larger than 324 * maxInterval */ 325 Triple getVelocity(const SatID sat, const CommonTime ttag) 326 const; 327 328 /** Return the acceleration for the given satellite at the given time 329 * @param[in] sat the SatID of the satellite of interest 330 * @param[in] ttag the time (CommonTime) of interest 331 * @return Triple containing the acceleration ECEF XYZ 332 * meters/second/second 333 * @throw InvalidRequest if result cannot be computed, for 334 * example because 335 * a) the time t does not lie within the time limits of the 336 * data table 337 * b) checkDataGap is true and there is a data gap 338 * c) checkInterval is true and the interval is larger than 339 * maxInterval */ getAcceleration(const SatID sat,const CommonTime ttag) const340 Triple getAcceleration(const SatID sat, const CommonTime ttag) 341 const 342 { return posStore.getAcceleration(sat,ttag); } 343 344 345 /** Clear the position dataset only, meaning remove all data 346 * from the tables. */ clearPosition(void)347 virtual void clearPosition(void) throw() 348 { posStore.clear(); } 349 350 /** Clear the clock dataset only, meaning remove all data 351 * from the tables. */ clearClock(void)352 virtual void clearClock(void) throw() 353 { clkStore.clear(); } 354 355 356 /** Choose to load the clock data tables from RINEX clock 357 * files. This will clear the clock store; loadFile() or 358 * loadRinexClockFile() should be called after this, to load 359 * data into the clock store from RINEX clock files. This 360 * routine has no effect if the clock store is already set to 361 * RINEX clock. 362 * @note will be called by loadRinexClockFile() if clock 363 * store is set to SP3. */ useRinexClockData(void)364 void useRinexClockData(void) throw() 365 { 366 if(!useSP3clock) return; 367 useSP3clock = false; 368 clearClock(); 369 } 370 371 /** Choose to load the clock data tables from SP3 files (this 372 * is the default). This will clear the clock store; if the 373 * position store has already been loaded it should also be 374 * cleared. The routines loadFile() or loadSP3File() should be 375 * called after this, to load data into the clock store from 376 * SP3 files. 377 * @note this will also load position data into the position 378 * store. This routine has no effect if the clock store is 379 * already set to SP3. */ useSP3ClockData(void)380 void useSP3ClockData(void) throw() 381 { 382 if(useSP3clock) return; 383 useSP3clock = true; 384 clearClock(); 385 } 386 387 /** Get the earliest time of data in the position store. 388 * @return CommonTime the first time 389 * @throw InvalidRequest if there is no data */ getPositionInitialTime(void) const390 CommonTime getPositionInitialTime(void) const 391 { return posStore.getInitialTime(); } 392 393 /** Get the latest time of data in the position store. 394 * @return CommonTime the latest time 395 * @throw InvalidRequest if there is no data */ getPositionFinalTime(void) const396 CommonTime getPositionFinalTime(void) const 397 { return posStore.getFinalTime(); } 398 399 /** Get the earliest time of data in the clock store. 400 * @return CommonTime the first time 401 * @throw InvalidRequest if there is no data */ getClockInitialTime(void) const402 CommonTime getClockInitialTime(void) const 403 { return clkStore.getInitialTime(); } 404 405 /** Get the latest time of data in the clock store. 406 * @return CommonTime the latest time 407 * @throw InvalidRequest if there is no data */ getClockFinalTime(void) const408 CommonTime getClockFinalTime(void) const 409 { return clkStore.getFinalTime(); } 410 411 /** Get the earliest time of data in the position store for 412 * the given satellite. 413 * @return CommonTime the first time 414 * @throw InvalidRequest if there is no data */ getPositionInitialTime(const SatID & sat) const415 CommonTime getPositionInitialTime(const SatID& sat) const 416 { return posStore.getInitialTime(sat); } 417 418 /** Get the latest time of data in the position store for the 419 * given satellite. 420 * @return CommonTime the latest time 421 * @throw InvalidRequest if there is no data */ getPositionFinalTime(const SatID & sat) const422 CommonTime getPositionFinalTime(const SatID& sat) const 423 { return posStore.getFinalTime(sat); } 424 425 /** Get the earliest time of data in the clock store for the 426 * given satellite. 427 * @return CommonTime the first time 428 * @throw InvalidRequest if there is no data */ getClockInitialTime(const SatID & sat) const429 CommonTime getClockInitialTime(const SatID& sat) const 430 { return clkStore.getInitialTime(sat); } 431 432 /** Get the latest time of data in the clock store for the 433 * given satellite. 434 * @return CommonTime the latest time 435 * @throw InvalidRequest if there is no data */ getClockFinalTime(const SatID & sat) const436 CommonTime getClockFinalTime(const SatID& sat) const 437 { return clkStore.getFinalTime(sat); } 438 439 /** Get the earliest time of both clock and position data in 440 * the store for the given satellite. 441 * @return CommonTime the first time 442 * @throw InvalidRequest if there is no data */ 443 CommonTime getInitialTime(const SatID& sat) const; 444 445 /** Get the latest time of both clock and position data in 446 * the store for the given satellite. 447 * @return the latest time 448 * @throw InvalidRequest if there is no data */ 449 CommonTime getFinalTime(const SatID& sat) const; 450 451 452 /** Get the nominal time step in seconds for the position 453 * data and the given sat */ getPositionTimeStep(const SatID & sat) const454 double getPositionTimeStep(const SatID& sat) const throw() 455 { return posStore.nomTimeStep(sat); } 456 457 /** Get the nominal time step in seconds for the clock data 458 * and the given sat */ getClockTimeStep(const SatID & sat) const459 double getClockTimeStep(const SatID& sat) const throw() 460 { return clkStore.nomTimeStep(sat); } 461 462 463 /// Get current interpolation order for the position table getPositionInterpOrder(void) const464 unsigned int getPositionInterpOrder(void) const throw() 465 { return posStore.getInterpolationOrder(); } 466 467 /** Set the interpolation order for the position table; it is 468 * forced to be even. */ setPositionInterpOrder(unsigned int order)469 void setPositionInterpOrder(unsigned int order) throw() 470 { posStore.setInterpolationOrder(order); } 471 472 /** Get current interpolation order for the clock data 473 * (meaningless if the interpolation type is linear). */ getClockInterpOrder(void)474 unsigned int getClockInterpOrder(void) throw() 475 { return clkStore.getInterpolationOrder(); } 476 477 /** Set the interpolation order for the clock table; it is 478 * forced to be even. This is ignored if the clock 479 * interpolation type is linear. */ setClockInterpOrder(unsigned int order)480 void setClockInterpOrder(unsigned int order) throw() 481 { clkStore.setInterpolationOrder(order); } 482 483 /** Set the type of clock interpolation to Lagrange (the 484 * default); set the order of the interpolation with 485 * setClockInterpolationOrder(order); */ setClockLagrangeInterp(void)486 void setClockLagrangeInterp(void) throw() 487 { clkStore.setLagrangeInterp(); } 488 489 /** Set the type of clock interpolation to linear 490 * (interpolation order is ignored). */ setClockLinearInterp(void)491 void setClockLinearInterp(void) throw() 492 { clkStore.setLinearInterp(); } 493 494 495 /** Get a list (std::vector) of SatIDs present in both clock 496 * and position stores */ getSatList(void) const497 std::vector<SatID> getSatList(void) const throw() 498 { 499 std::vector<SatID> posList(posStore.getSatList()); 500 std::vector<SatID> clkList(clkStore.getSatList()); 501 std::vector<SatID> retList; 502 for(size_t i=0; i<posList.size(); i++) 503 if(std::find(clkList.begin(),clkList.end(),posList[i]) != clkList.end()) 504 retList.push_back(posList[i]); 505 return retList; 506 } 507 508 // Get a set of the SatIDs present in both clock and position stores getIndexSet(void) const509 std::set<SatID> getIndexSet(void) const 510 { 511 std::set<SatID> retSet; 512 try 513 { 514 std::vector<SatID> posList(posStore.getSatList()); 515 std::vector<SatID> clkList(clkStore.getSatList()); 516 for(size_t i=0; i<posList.size(); i++) 517 if(std::find(clkList.begin(),clkList.end(),posList[i]) != clkList.end()) 518 retSet.insert(posList[i]); 519 } 520 catch(gpstk::Exception) 521 { 522 // do nothing 523 } 524 return retSet; 525 } 526 527 /// Get a list (std::vector) of SatIDs present in the position store getPositionSatList(void) const528 std::vector<SatID> getPositionSatList(void) const throw() 529 { return posStore.getSatList(); } 530 531 /// Get a list (std::vector) of SatIDs present in the clock store getClockSatList(void) const532 std::vector<SatID> getClockSatList(void) const throw() 533 { return clkStore.getSatList(); } 534 535 536 /// Get the total number of (position) data records in the store ndata(void) const537 inline int ndata(void) const throw() 538 { return posStore.ndata(); } 539 540 /// Get the number of (position) data records for the given sat ndata(const SatID & sat) const541 inline int ndata(const SatID& sat) const throw() 542 { return posStore.ndata(sat); } 543 544 /** Get the number of (position) data records for the given 545 * satellite system */ ndata(const SatelliteSystem & sys) const546 inline int ndata(const SatelliteSystem& sys) const throw() 547 { return posStore.ndata(sys); } 548 549 /// Get the total number of position data records in the store ndataPosition(void) const550 inline int ndataPosition(void) const throw() 551 { return posStore.ndata(); } 552 553 /// Get the number of position data records for the given sat ndataPosition(const SatID & sat) const554 inline int ndataPosition(const SatID& sat) const throw() 555 { return posStore.ndata(sat); } 556 557 /** Get the number of position data records for the given 558 * satellite system */ ndataPosition(const SatelliteSystem & sys) const559 inline int ndataPosition(const SatelliteSystem& sys) const throw() 560 { return posStore.ndata(sys); } 561 562 /// Get the total number of clock data records in the store ndataClock(void) const563 inline int ndataClock(void) const throw() 564 { return clkStore.ndata(); } 565 566 /// Get the number of clock data records for the given sat ndataClock(const SatID & sat) const567 inline int ndataClock(const SatID& sat) const throw() 568 { return clkStore.ndata(sat); } 569 570 /** Get the number of clock data records for the given 571 * satellite system */ ndataClock(const SatelliteSystem & sys) const572 inline int ndataClock(const SatelliteSystem& sys) const throw() 573 { return clkStore.ndata(sys); } 574 575 /// same as ndataPosition() size(void) const576 inline int size(void) const throw() { return ndataPosition(); } 577 578 579 /** Load an SP3 ephemeris file; if the clock store uses RINEX 580 * clock files, this routine will also accept that file type 581 * and load the data into the clock store. This routine will 582 * may set the velocity, acceleration, bias or drift 'have' 583 * flags. 584 * @param filename name of file (SP3 or RINEX clock format) to load 585 * @throw Exception if time step is inconsistent with previous value 586 */ 587 void loadFile(const std::string& filename); 588 589 /** Load an SP3 ephemeris file; may set the velocity and 590 * acceleration flags. If the clock store uses RINEX clock 591 * data, this will ignore the clock data. 592 * @param filename name of file (SP3 format) to load 593 * @throw Exception if time step is inconsistent with previous value 594 */ 595 void loadSP3File(const std::string& filename); 596 597 /** Load a RINEX clock file; may set the 'have' bias and 598 * drift flags. If clock store is set to use SP3 data, this 599 * will call useRinexClockData() 600 * @param filename name of file (RINEX clock format) to load 601 * @throw Exception if time step is inconsistent with previous value 602 */ 603 void loadRinexClockFile(const std::string& filename); 604 605 606 /** Add a complete PositionRecord to the store; this is the 607 * preferred method of adding data to the tables. 608 * @note If these addXXX() routines are used more than once 609 * for the same record (sat,ttag), be aware that since ttag 610 * is used as they key in a std::map, the value used must be 611 * EXACTLY the same in all calls; (numerical noise could 612 * cause the std::map to consider two "equal" ttags as 613 * different). 614 * @throw InvalidRequest 615 */ addPositionRecord(const SatID & sat,const CommonTime & ttag,const PositionRecord & data)616 void addPositionRecord(const SatID& sat, const CommonTime& ttag, 617 const PositionRecord& data) 618 { 619 try { posStore.addPositionRecord(sat,ttag,data); } 620 catch(InvalidRequest& ir) { GPSTK_RETHROW(ir); } 621 } 622 623 /** Add position data to the store 624 * @throw InvalidRequest 625 */ addPositionData(const SatID & sat,const CommonTime & ttag,const Triple & Pos,const Triple & sig)626 void addPositionData(const SatID& sat, const CommonTime& ttag, 627 const Triple& Pos, const Triple& sig) 628 { 629 try { posStore.addPositionData(sat,ttag,Pos,sig); } 630 catch(InvalidRequest& ir) { GPSTK_RETHROW(ir); } 631 } 632 633 /** Add velocity data to the store 634 * @throw InvalidRequest 635 */ addVelocityData(const SatID & sat,const CommonTime & ttag,const Triple & Vel,const Triple & sig)636 void addVelocityData(const SatID& sat, const CommonTime& ttag, 637 const Triple& Vel, const Triple& sig) 638 { 639 try { posStore.addVelocityData(sat,ttag,Vel,sig); } 640 catch(InvalidRequest& ir) { GPSTK_RETHROW(ir); } 641 } 642 643 /** Add a complete ClockRecord to the store; this is the 644 * preferred method of adding data to the tables. 645 * @note If these addXXX() routines are used more than once 646 * for the same record (sat,ttag), be aware that since ttag 647 * is used as they key in a std::map, the value used must be 648 * EXACTLY the same in all calls; (numerical noise could 649 * cause the std::map to consider two "equal" ttags as 650 * different). 651 * @throw InvalidRequest 652 */ addClockRecord(const SatID & sat,const CommonTime & ttag,const ClockRecord & rec)653 void addClockRecord(const SatID& sat, const CommonTime& ttag, 654 const ClockRecord& rec) 655 { 656 try { clkStore.addClockRecord(sat,ttag,rec); } 657 catch(InvalidRequest& ir) { GPSTK_RETHROW(ir); } 658 } 659 660 /** Add clock bias data (only) to the store 661 * @throw InvalidRequest 662 */ addClockBias(const SatID & sat,const CommonTime & ttag,const double & bias,const double & sig=0.0)663 void addClockBias(const SatID& sat, const CommonTime& ttag, 664 const double& bias, const double& sig=0.0) 665 { 666 try { clkStore.addClockBias(sat,ttag,bias,sig); } 667 catch(InvalidRequest& ir) { GPSTK_RETHROW(ir); } 668 } 669 670 /** Add clock drift data (only) to the store 671 * @throw InvalidRequest 672 */ addClockDrift(const SatID & sat,const CommonTime & ttag,const double & drift,const double & sig=0.0)673 void addClockDrift(const SatID& sat, const CommonTime& ttag, 674 const double& drift, const double& sig=0.0) 675 { 676 try { clkStore.addClockDrift(sat,ttag,drift,sig); } 677 catch(InvalidRequest& ir) { GPSTK_RETHROW(ir); } 678 } 679 680 /** Add clock acceleration data (only) to the store 681 * @throw InvalidRequest 682 */ addClockAcceleration(const SatID & sat,const CommonTime & ttag,const double & accel,const double & sig=0.0)683 void addClockAcceleration(const SatID& sat, const CommonTime& ttag, 684 const double& accel, const double& sig=0.0) 685 { 686 try { clkStore.addClockAcceleration(sat,ttag,accel,sig); } 687 catch(InvalidRequest& ir) { GPSTK_RETHROW(ir); } 688 } 689 690 691 /// Get number of files (all types) in FileStore. nfiles(void)692 int nfiles(void) throw() 693 { return (SP3Files.size() + (useSP3clock ? 0 : clkFiles.size())); } 694 695 /// Get number of SP3 files in FileStore. nSP3files(void)696 int nSP3files(void) throw() 697 { return SP3Files.size(); } 698 699 /// Get number of clock files in FileStore. nClockfiles(void)700 int nClockfiles(void) throw() 701 { return (useSP3clock ? SP3Files.size() : clkFiles.size()); } 702 703 704 /// Return true if there is drift data in the tables hasClockDrift() const705 virtual bool hasClockDrift() const throw() 706 { return clkStore.hasClockDrift(); } 707 708 709 /** Set the flag; if true then all values are rejected when a 710 * bad position value is found, while adding data to the 711 * store. */ rejectBadPositions(const bool flag)712 void rejectBadPositions(const bool flag) 713 { rejectBadPosFlag = flag; } 714 715 /** Set the flag; if true then all values are rejected when bad clock 716 * values are found, while adding data to the store. */ rejectBadClocks(const bool flag)717 void rejectBadClocks(const bool flag) 718 { rejectBadClockFlag = flag; } 719 720 /** Set the flag; if true then predicted position values are 721 * rejected when adding data to the store. */ rejectPredPositions(const bool flag)722 void rejectPredPositions(const bool flag) 723 { rejectPredPosFlag = flag; } 724 725 /** Set the flag; if true then predicted clock values are 726 * rejected when adding data to the store. */ rejectPredClocks(const bool flag)727 void rejectPredClocks(const bool flag) 728 { rejectPredClockFlag = flag; } 729 730 731 /// Is gap checking for position on? isPosDataGapCheck(void)732 bool isPosDataGapCheck(void) throw() 733 { return posStore.isDataGapCheck(); } 734 735 /// Is gap checking for clock on? isClkDataGapCheck(void)736 bool isClkDataGapCheck(void) throw() 737 { return clkStore.isDataGapCheck(); } 738 739 /// Disable checking of data gaps in both position and clock. disableDataGapCheck(void)740 void disableDataGapCheck(void) throw() 741 { posStore.disableDataGapCheck(); clkStore.disableDataGapCheck(); } 742 743 /// Disable checking of data gaps in position store disablePosDataGapCheck(void)744 void disablePosDataGapCheck(void) throw() 745 { posStore.disableDataGapCheck(); } 746 747 /// Disable checking of data gaps in clock store disableClockDataGapCheck(void)748 void disableClockDataGapCheck(void) throw() 749 { clkStore.disableDataGapCheck(); } 750 751 /// Get current gap interval in the position store. getPosGapInterval(void)752 double getPosGapInterval(void) throw() 753 { return posStore.getGapInterval(); } 754 755 /// Get current gap interval in the clock store. getClockGapInterval(void)756 double getClockGapInterval(void) throw() 757 { return clkStore.getGapInterval(); } 758 759 /** Set gap interval and turn on gap checking in the position 760 * store. There is no default. */ setPosGapInterval(double interval)761 void setPosGapInterval(double interval) throw() 762 { posStore.setGapInterval(interval); } 763 764 /** Set gap interval and turn on gap checking in the clock 765 * store. There is no default. */ setClockGapInterval(double interval)766 void setClockGapInterval(double interval) throw() 767 { clkStore.setGapInterval(interval); } 768 769 770 /// Is interval checking for position on? isPosIntervalCheck(void)771 bool isPosIntervalCheck(void) throw() 772 { return posStore.isIntervalCheck(); } 773 774 /// Is interval checking for clock on? isClkIntervalCheck(void)775 bool isClkIntervalCheck(void) throw() 776 { return clkStore.isIntervalCheck(); } 777 778 /// Disable checking of maximum interval in both position and clock. disableIntervalCheck(void)779 void disableIntervalCheck(void) throw() 780 { posStore.disableIntervalCheck(); clkStore.disableIntervalCheck(); } 781 782 /// Disable checking of maximum interval in position store disablePosIntervalCheck(void)783 void disablePosIntervalCheck(void) throw() 784 { posStore.disableIntervalCheck(); } 785 786 /// Disable checking of maximum interval in clock store disableClockIntervalCheck(void)787 void disableClockIntervalCheck(void) throw() 788 { clkStore.disableIntervalCheck(); } 789 790 /// Get current maximum interval in the position store getPosMaxInterval(void)791 double getPosMaxInterval(void) throw() 792 { return posStore.getMaxInterval(); } 793 794 /// Get current maximum interval in the clock store getClockMaxInterval(void)795 double getClockMaxInterval(void) throw() 796 { return clkStore.getMaxInterval(); } 797 798 /** Set maximum interval and turn on interval checking in the 799 * position store There is no default. */ setPosMaxInterval(double interval)800 void setPosMaxInterval(double interval) throw() 801 { posStore.setMaxInterval(interval); } 802 803 /** Set maximum interval and turn on interval checking in the 804 * clock store There is no default. */ setClockMaxInterval(double interval)805 void setClockMaxInterval(double interval) throw() 806 { clkStore.setMaxInterval(interval); } 807 808 809 /// @deprecated velocityIsPresent() const810 virtual bool velocityIsPresent() const throw() 811 { return posStore.hasVelocity(); } 812 813 /// @deprecated clockIsPresent() const814 virtual bool clockIsPresent() const throw() 815 { return true; } 816 817 /** @deprecated 818 * Get current (position) interpolation order */ getInterpolationOrder(void)819 unsigned int getInterpolationOrder(void) throw() 820 { return getPositionInterpOrder(); } 821 822 /** @deprecated 823 * Set the (position) interpolation order for the position table; 824 * it is forced to be even. */ setInterpolationOrder(unsigned int order)825 void setInterpolationOrder(unsigned int order) throw() 826 { setPositionInterpOrder(order); } 827 828 }; // end class SP3EphemerisStore 829 830 //@} 831 832 } // End of namespace gpstk 833 834 #endif // GPSTK_SP3_EPHEMERIS_STORE_INCLUDE 835