diff --git a/core/lib/TimeHandling/TimeCorrection.cpp b/core/lib/TimeHandling/TimeCorrection.cpp new file mode 100644 index 000000000..78e728083 --- /dev/null +++ b/core/lib/TimeHandling/TimeCorrection.cpp @@ -0,0 +1,74 @@ +//============================================================================ +// +// This file is part of GPSTk, the GPS Toolkit. +// +// The GPSTk is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 3.0 of the License, or +// any later version. +// +// The GPSTk is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with GPSTk; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA +// +// Copyright 2018, The University of Texas at Austin +// +//============================================================================ + +//============================================================================ +// +//This software developed by Applied Research Laboratories at the University of +//Texas at Austin, under contract to an agency or agencies within the U.S. +//Department of Defense. The U.S. Government retains all rights to use, +//duplicate, distribute, disclose, or release this software. +// +//Pursuant to DoD Directive 523024 +// +// DISTRIBUTION STATEMENT A: This software has been approved for public +// release, distribution is unlimited. +// +//============================================================================= + +#include "TimeCorrection.hpp" +#include "SystemTime.hpp" +#include "GPSWeekSecond.hpp" + +namespace gpstk +{ + + long timeAdjustWeekRollover(long toCorrectWeek, long& refWeek) + { + // gotta use signed ints so that the weeks can actually go + // negative when doing subtraction and comparison. + long rv = toCorrectWeek; + if (refWeek == 0) + { + // One might be inclined to try to cache the refWeek value + // from the clock internally, but that would mean that + // applications would be unable to process data from + // different epochs. An unusual situation, to be sure, + // but I'd rather not make assumptions about everyone's + // use cases. + GPSWeekSecond ref = SystemTime().convertToCommonTime(); + refWeek = ref.week; + } + // GPS_WEEK_PER_EPOCH >> 1 is the same as /2, i.e. half-epoch. + // The while loops allow us to correct data that's more than + // one "epoch" out. + while (refWeek - rv > (GPS_WEEK_PER_EPOCH>>1)) + { + rv += GPS_WEEK_PER_EPOCH; + } + while (refWeek - rv < -(GPS_WEEK_PER_EPOCH>>1)) + { + rv -= GPS_WEEK_PER_EPOCH; + } + return rv; + } + +} // namespace gpstk diff --git a/core/lib/TimeHandling/TimeCorrection.hpp b/core/lib/TimeHandling/TimeCorrection.hpp new file mode 100644 index 000000000..1217e5887 --- /dev/null +++ b/core/lib/TimeHandling/TimeCorrection.hpp @@ -0,0 +1,70 @@ +//============================================================================ +// +// This file is part of GPSTk, the GPS Toolkit. +// +// The GPSTk is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 3.0 of the License, or +// any later version. +// +// The GPSTk is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with GPSTk; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA +// +// Copyright 2018, The University of Texas at Austin +// +//============================================================================ + +//============================================================================ +// +//This software developed by Applied Research Laboratories at the University of +//Texas at Austin, under contract to an agency or agencies within the U.S. +//Department of Defense. The U.S. Government retains all rights to use, +//duplicate, distribute, disclose, or release this software. +// +//Pursuant to DoD Directive 523024 +// +// DISTRIBUTION STATEMENT A: This software has been approved for public +// release, distribution is unlimited. +// +//============================================================================= + +#ifndef GPSTK_TIMECORRECTION_HPP +#define GPSTK_TIMECORRECTION_HPP + +namespace gpstk +{ + /// @ingroup TimeHandling + //@{ + + /** Implement a correction for errors in week-rollover, + * i.e. when the GPS 10-bit week changes from 1023 to 0. + * @param[in] toCorrectWeek The suspect week from data that + * might be off by 1024 weeks. + * @param[in,out] refWeek The known full week that will be used + * as a reference. If this value is zero (the default), the + * local system clock will be consulted to obtain a reference + * week. It is recommended for the best performance that the + * calling application retain this reference week for + * subsequent calls to this function as each time the function + * is called with a reference week of zero, system calls are + * performed to obtain the system clock, and conversions are + * performed to turn that time into GPS week-second time. The + * week according to the system clock should be valid for at + * least a single week epoch, i.e. 1024 weeks (~19 years), so + * unless you're planning on leaving your software running for + * more than 19 years straight, it should be valid. + * @return The value of toCorrectWeek having been adjusted by as + * many epochs as necessary to bring it to within half a GPS + * week epoch (i.e. 512 weeks) of the reference time. + */ + long timeAdjustWeekRollover(long toCorrectWeek, long& refWeek); + //@} +} + +#endif // GPSTK_TIMECORRECTION_HPP diff --git a/core/tests/TimeHandling/CMakeLists.txt b/core/tests/TimeHandling/CMakeLists.txt index d5bb74f02..afe7c418f 100644 --- a/core/tests/TimeHandling/CMakeLists.txt +++ b/core/tests/TimeHandling/CMakeLists.txt @@ -84,3 +84,8 @@ add_executable(GPSZcount_T GPSZcount_T.cpp) target_link_libraries(GPSZcount_T gpstk) add_test(TimeHandling_GPSZcount GPSZcount_T) set_property(TEST TimeHandling_GPSZcount PROPERTY LABELS TimeHandling TimeStorage) + +add_executable(TimeCorrection_T TimeCorrection_T.cpp) +target_link_libraries(TimeCorrection_T gpstk) +add_test(TimeHandling_TimeCorrection TimeCorrection_T) +set_property(TEST TimeHandling_TimeCorrection PROPERTY LABELS TimeHandling TimeStorage) diff --git a/core/tests/TimeHandling/TimeCorrection_T.cpp b/core/tests/TimeHandling/TimeCorrection_T.cpp new file mode 100644 index 000000000..214691a70 --- /dev/null +++ b/core/tests/TimeHandling/TimeCorrection_T.cpp @@ -0,0 +1,120 @@ +//============================================================================ +// +// This file is part of GPSTk, the GPS Toolkit. +// +// The GPSTk is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 3.0 of the License, or +// any later version. +// +// The GPSTk is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with GPSTk; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA +// +// Copyright 2018, The University of Texas at Austin +// +//============================================================================ + +//============================================================================ +// +//This software developed by Applied Research Laboratories at the University of +//Texas at Austin, under contract to an agency or agencies within the U.S. +//Department of Defense. The U.S. Government retains all rights to use, +//duplicate, distribute, disclose, or release this software. +// +//Pursuant to DoD Directive 523024 +// +// DISTRIBUTION STATEMENT A: This software has been approved for public +// release, distribution is unlimited. +// +//============================================================================= + +#include "TimeCorrection.hpp" +#include "GPSWeekZcount.hpp" +#include "SystemTime.hpp" +#include "TestUtil.hpp" + +using namespace std; +using namespace gpstk; + +class TimeCorrection_T +{ +public: + unsigned testEpochRollover(); +}; + + +unsigned TimeCorrection_T :: testEpochRollover() +{ + TUDEF("TestCorrection", "timeAdjustWeekRollover"); + long refWeek = 123; + // week year week year + // 123 = 1982 635 = 1992 + // 1147 = 2001 1659 = 2011 + // 2171 = 2021 2683 = 2031 + // 3195 = 2041 + // test same week with 10-bit weeks + TUASSERTE(long, 123, timeAdjustWeekRollover(123, refWeek)); + TUASSERTE(long, 123, refWeek); + refWeek = 128; + // test slightly different week with 10-bit weeks + TUASSERTE(long, 123, timeAdjustWeekRollover(123, refWeek)); + TUASSERTE(long, 128, refWeek); + // test 10-bit week edge cases + refWeek = 123 + 512; + TUASSERTE(long, 123, timeAdjustWeekRollover(123, refWeek)); + TUASSERTE(long, 123 + 512, refWeek); + refWeek++; + TUASSERTE(long, 1147, timeAdjustWeekRollover(123, refWeek)); + TUASSERTE(long, 123 + 513, refWeek); + // test 10-bit to-correct and full ref week + refWeek = 2014; + TUASSERTE(long, 2014, timeAdjustWeekRollover(990, refWeek)); + TUASSERTE(long, 2014, refWeek); + // test 10-bit to-correct and full ref week, two epochs off + refWeek = 3038; + TUASSERTE(long, 3038, timeAdjustWeekRollover(990, refWeek)); + TUASSERTE(long, 3038, refWeek); + // test full to-correct week and full ref week, one epoch off + refWeek = 3038; + TUASSERTE(long, 3038, timeAdjustWeekRollover(2014, refWeek)); + TUASSERTE(long, 3038, refWeek); + // test future data + refWeek = 2014; + TUASSERTE(long, 2015, timeAdjustWeekRollover(2015, refWeek)); + TUASSERTE(long, 2014, refWeek); + // test future data edge cases + refWeek = 2014; + TUASSERTE(long, refWeek + 512, timeAdjustWeekRollover(refWeek + 512, refWeek)); + TUASSERTE(long, 2014, refWeek); + TUASSERTE(long, refWeek - 511, timeAdjustWeekRollover(refWeek + 513, refWeek)); + TUASSERTE(long, 2014, refWeek); + // test real-time path + refWeek = 0; + GPSWeekZcount cwz = SystemTime().convertToCommonTime(); + long expected = 1659; + // This code should be able to function as expected at least through 2031. + if (cwz.week > 2683) + expected = 3195; + else if (cwz.week > 1659) + expected = 2171; + TUASSERTE(long, expected, timeAdjustWeekRollover(123, refWeek)); + // refWeek should have been set to the system clock's time's week + TUASSERTE(long, cwz.week, refWeek); + TURETURN(); +} + + +int main() +{ + TimeCorrection_T testClass; + unsigned errorTotal = 0; + errorTotal += testClass.testEpochRollover(); + cout << "Total Errors for " << __FILE__ <<": "<< errorTotal << endl; + return errorTotal; +}