Skip to content
This repository was archived by the owner on Apr 13, 2021. It is now read-only.

Commit 89c27d9

Browse files
committed
GPSTIME: gpsdifftime supports unknown week numbers via WN_UNKNOWN
1 parent a2efee3 commit 89c27d9

File tree

6 files changed

+76
-11
lines changed

6 files changed

+76
-11
lines changed

include/libswiftnav/gpstime.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,20 @@
2424

2525
/** Offset between GPS and UTC times in seconds.
2626
* Update when a new leap second is inserted and be careful about times in the
27-
* past when this offset was different. */
27+
* past when this offset was different.
28+
* TODO handle leap seconds properly!
29+
*/
2830
#define GPS_MINUS_UTC_SECS 17
2931

3032
/** Unix timestamp of the GPS epoch 1980-01-06 00:00:00 UTC */
3133
#define GPS_EPOCH 315964800
3234

35+
#define WN_UNKNOWN -1
36+
3337
/** Structure representing a GPS time. */
3438
typedef struct __attribute__((packed)) {
3539
double tow; /**< Seconds since the GPS start of week. */
36-
u16 wn; /**< GPS week number. */
40+
s16 wn; /**< GPS week number. */
3741
} gps_time_t;
3842

3943
gps_time_t normalize_gps_time(gps_time_t);

src/gpstime.c

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@
1111
*/
1212

1313
#include <math.h>
14-
1514
#include "gpstime.h"
1615

16+
#define WEEK_SECS (7*24*60*60)
17+
18+
/* TODO: does it make sense to be passing structs by value in all
19+
these functions? */
20+
1721
/** Normalize a `gps_time_t` GPS time struct.
1822
* Ensures that the time of week is greater than zero and less than one week by
1923
* wrapping and adjusting the week number accordingly.
@@ -25,12 +29,12 @@
2529
gps_time_t normalize_gps_time(gps_time_t t)
2630
{
2731
while(t.tow < 0) {
28-
t.tow += 3600*24*7;
32+
t.tow += WEEK_SECS;
2933
t.wn += 1;
3034
}
3135

32-
while(t.tow > 3600*24*7) {
33-
t.tow -= 3600*24*7;
36+
while(t.tow > WEEK_SECS) {
37+
t.tow -= WEEK_SECS;
3438
t.wn -= 1;
3539
}
3640

@@ -47,13 +51,16 @@ time_t gps2time(gps_time_t gps_t)
4751
{
4852
time_t t = GPS_EPOCH - GPS_MINUS_UTC_SECS;
4953

50-
t += 7*24*3600*gps_t.wn;
54+
t += WEEK_SECS*gps_t.wn;
5155
t += (s32)gps_t.tow;
5256

5357
return t;
5458
}
5559

5660
/** Time difference in seconds between two GPS times.
61+
* If the week number field of either time is unspecified, the result
62+
* will be as if the week numbers had been chosen for the times to be
63+
* as close as possible.
5764
* \param end Higher bound of the time interval whose length is calculated.
5865
* \param beginning Lower bound of the time interval whose length is
5966
* calculated. If this describes a time point later than end,
@@ -62,8 +69,17 @@ time_t gps2time(gps_time_t gps_t)
6269
*/
6370
double gpsdifftime(gps_time_t end, gps_time_t beginning)
6471
{
65-
return (end.wn - beginning.wn)*7*24*3600 + \
66-
end.tow - beginning.tow;
72+
double dt = end.tow - beginning.tow;
73+
if (end.wn == WN_UNKNOWN || beginning.wn == WN_UNKNOWN) {
74+
/* One or both of the week numbers is unspecified. Assume times
75+
are within +/- 0.5 weeks of each other. */
76+
if (dt > WEEK_SECS / 2)
77+
dt -= WEEK_SECS;
78+
if (dt < -WEEK_SECS / 2)
79+
dt += WEEK_SECS;
80+
} else {
81+
/* Week numbers were provided - use them. */
82+
dt += (end.wn - beginning.wn) * WEEK_SECS;
83+
}
84+
return dt;
6785
}
68-
69-

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ else (CMAKE_CROSSCOMPILING)
4141
check_filter_utils.c
4242
check_ephemeris.c
4343
check_set.c
44+
check_gpstime.c
4445
)
4546

4647
target_link_libraries(test_libswiftnav ${TEST_LIBS})

tests/check_gpstime.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include <check.h>
2+
#include <stdio.h>
3+
#include <math.h>
4+
#include "check_utils.h"
5+
6+
#include "gpstime.h"
7+
8+
START_TEST(test_gpsdifftime)
9+
{
10+
struct gpsdifftime_testcase {
11+
gps_time_t a, b;
12+
double dt;
13+
} testcases[] = {
14+
{.a = {567890.0, 1234}, .b = {567890.0, 1234}, .dt = 0},
15+
{.a = {567890.0, 1234}, .b = {0.0, 1234}, .dt = 567890},
16+
{.a = {567890.0, WN_UNKNOWN}, .b = {0.0, 1234}, .dt = -36910},
17+
{.a = {222222.0, 2222}, .b = {2222.0, WN_UNKNOWN}, .dt = 220000},
18+
{.a = {444444.0, WN_UNKNOWN}, .b = {2222.0, WN_UNKNOWN}, .dt = -162578},
19+
{.a = {604578.0, 1000}, .b = {222.222, 1001}, .dt = -444.222},
20+
{.a = {604578.0, 1001}, .b = {222.222, 1000}, .dt = 1209155.778},
21+
};
22+
const double tow_tol = 1e-10;
23+
for (size_t i = 0;
24+
i < sizeof(testcases) / sizeof(struct gpsdifftime_testcase); i++) {
25+
double dt = gpsdifftime(testcases[i].a, testcases[i].b);
26+
fail_unless(fabs(dt - testcases[i].dt) < tow_tol,
27+
"gpsdifftime test case %d failed, dt = %.12f", i, dt);
28+
}
29+
}
30+
END_TEST
31+
32+
Suite* gpstime_test_suite(void)
33+
{
34+
Suite *s = suite_create("GPS time handling");
35+
36+
TCase *tc_core = tcase_create("Core");
37+
tcase_add_test(tc_core, test_gpsdifftime);
38+
suite_add_tcase(s, tc_core);
39+
40+
return s;
41+
}
42+

tests/check_main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ int main(void)
2626
srunner_add_suite(sr, filter_utils_suite());
2727
srunner_add_suite(sr, ephemeris_suite());
2828
srunner_add_suite(sr, set_suite());
29+
srunner_add_suite(sr, gpstime_test_suite());
2930

3031
srunner_set_fork_status(sr, CK_NOFORK);
3132
srunner_run_all(sr, CK_NORMAL);

tests/check_suites.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ Suite* ambiguity_test_suite(void);
1717
Suite* filter_utils_suite(void);
1818
Suite* ephemeris_suite(void);
1919
Suite* set_suite(void);
20+
Suite* gpstime_test_suite(void);
2021

2122
#endif /* CHECK_SUITES_H */

0 commit comments

Comments
 (0)