Permalink
Browse files

Merge pull request #366 from denniszollo/almanac

Add proper handling of signal component health for
  • Loading branch information...
2 parents da4bfcb + 3d3d765 commit a5c13baf4d112cf06802bbd7e828c8a5ba7cf090 @denniszollo denniszollo committed on GitHub Nov 11, 2016
@@ -69,7 +69,7 @@ typedef struct {
float ura; /**< User range accuracy [m] */
u32 fit_interval; /**< Curve fit interval [s] */
u8 valid; /**< Almanac is valid. */
- u8 healthy; /**< Satellite health status. */
+ u8 health_bits; /**< Satellite health status. */
union {
almanac_kepler_t kepler; /**< Parameters specific to GPS. */
almanac_xyz_t xyz; /**< Parameters specific to SBAS. */
@@ -18,6 +18,10 @@
#include <libswiftnav/time.h>
#include <libswiftnav/common.h>
+#define INVALID_GPS_URA_INDEX -1
+#define INVALID_GPS_URA_VALUE -1.0f
+#define MAX_ALLOWED_GPS_URA_IDX 15
+
/** \addtogroup ephemeris
* \{ */
@@ -84,7 +88,7 @@ typedef struct {
float ura; /**< User range accuracy [m] */
u32 fit_interval; /**< Curve fit interval [s] */
u8 valid; /**< Ephemeris is valid. */
- u8 healthy; /**< Satellite health status. */
+ u8 health_bits; /**< Satellite health status. */
union {
ephemeris_kepler_t kepler; /**< Parameters specific to GPS. */
ephemeris_xyz_t xyz; /**< Parameters specific to SBAS. */
@@ -105,9 +109,11 @@ s8 calc_sat_doppler(const ephemeris_t *e, const gps_time_t *t,
u8 ephemeris_valid(const ephemeris_t *e, const gps_time_t *t);
u8 ephemeris_params_valid(const u8 valid, const u32 fit_interval,
const gps_time_t* toe, const gps_time_t *t);
-u8 satellite_healthy(const ephemeris_t *e);
+u8 signal_healthy(const ephemeris_t *e, code_t code);
void decode_ephemeris(u32 frame_words[4][8], ephemeris_t *e);
bool ephemeris_equal(const ephemeris_t *a, const ephemeris_t *b);
+float decode_ura_index(const u8 index);
+
#endif /* LIBSWIFTNAV_EPHEMERIS_H */
@@ -27,7 +27,7 @@ cdef extern from "libswiftnav/almanac.h":
float ura
u32 fit_interval
u8 valid
- u8 healthy
+ u8 health_bits
# HACK: Actually an anonymous union in libswiftnat!
almanac_kepler_t kepler
almanac_xyz_t xyz
@@ -33,7 +33,7 @@ cdef class Almanac:
self._thisptr.ura = kwargs.pop('ura')
self._thisptr.fit_interval = kwargs.pop('fit_interval')
self._thisptr.valid = kwargs.pop('valid')
- self._thisptr.healthy = kwargs.pop('healthy')
+ self._thisptr.health_bits = kwargs.pop('health_bits')
if 'kepler' in kwargs:
self._thisptr.kepler = kwargs.pop('kepler')
elif 'xyz' in kwargs:
@@ -10,6 +10,7 @@
from common cimport *
from time cimport gps_time_t
from signal cimport gnss_signal_t
+from signal cimport code
cdef extern from "libswiftnav/ephemeris.h":
@@ -42,7 +43,7 @@ cdef extern from "libswiftnav/ephemeris.h":
float ura
u32 fit_interval
u8 valid
- u8 healthy
+ u8 health_bits
# HACK: Actually an anonymous union in libswiftnat!
ephemeris_kepler_t kepler
ephemeris_xyz_t xyz
@@ -56,7 +57,7 @@ cdef extern from "libswiftnav/ephemeris.h":
s8 calc_sat_doppler(const ephemeris_t *e, const gps_time_t *t,
double ref[3], double *doppler)
u8 ephemeris_valid(const ephemeris_t *e, const gps_time_t *t)
- u8 satellite_healthy(const ephemeris_t *e)
+ u8 signal_healthy(const ephemeris_t *e, code code)
void decode_ephemeris(u32 frame_words[3][8], ephemeris_t *e)
u8 ephemeris_equal(const ephemeris_t *a, const ephemeris_t *b)
u8 ephemeris_params_valid(const u8 valid, const u32 fit_interval,
@@ -39,8 +39,8 @@ cdef class Ephemeris:
self._thisptr.fit_interval = kwargs.pop('fit_interval')
if 'valid' in kwargs:
self._thisptr.valid = kwargs.pop('valid')
- if 'healthy' in kwargs:
- self._thisptr.healthy = kwargs.pop('healthy')
+ if 'health_bits' in kwargs:
+ self._thisptr.health_bits = kwargs.pop('health_bits')
if 'kepler' in kwargs:
self._thisptr.kepler = kwargs.pop('kepler')
elif 'xyz' in kwargs:
@@ -139,7 +139,7 @@ cdef class Ephemeris:
return ephemeris_params_valid(valid, fit_interval, &toe._thisptr, &t._thisptr)
def is_healthy(self):
- return satellite_healthy(&self._thisptr)
+ return signal_healthy(&self._thisptr, self._thisptr.sid.code)
def __rich_cmp__(self, eph2, op):
if op != Py_EQ:
@@ -17,10 +17,10 @@ def test_init():
alm = {
'sid': {'code': 0, 'sat': 1},
'toa': {'tow': 2, 'wn': 11,},
- 'ura': 12,
+ 'ura': 10.0,
'fit_interval': 13,
'valid': 1,
- 'healthy': 1,
+ 'health_bits': 0,
'kepler': {
'sqrta': 8,
'af0': 9,
@@ -45,7 +45,7 @@ def test_almanac_functions():
'ura': 900.0,
'fit_interval': 144 * 60 * 60,
'valid': 1,
- 'healthy': 1,
+ 'health_bits': 0,
'kepler': {
'sqrta': np.sqrt(26559810.38052176),
'ecc': 0.004033565521,
@@ -16,12 +16,12 @@
tol = 1e-10
def test_sat_state():
- eph = e.Ephemeris(**{'sid': {'sat': 17, 'code': 0,},
+ eph = e.Ephemeris(**{'sid': {'sat': 17, 'code': 1,},
'toe': {'wn': 1867, 'tow': 518400.0,},
- 'ura': 2.0,
+ 'ura': 10.0,
'fit_interval': 4 * 60 * 60,
'valid': 1,
- 'healthy': 1,
+ 'health_bits': 0,
'kepler': {
'toc': {'tow': 518400.0, 'wn': 1867,},
'crs': 25.125,
@@ -70,10 +70,10 @@ def test_sat_state():
assert repr(eph)
eph = e.Ephemeris(**{'sid': {'sat': 17, 'code': 0},
'toe': { 'wn': 1867, 'tow': 518400.0,},
- 'ura': 2.0,
+ 'ura': 4000.0,
'fit_interval': 4 * 60 * 60,
'valid': 1,
- 'healthy': 0,
+ 'health_bits': 0x3F,
'kepler': {'crs': 25.125,
'inc_dot': 3.78944355982045e-10,
'tgd': -1.1175870895385742e-08,
@@ -101,10 +101,103 @@ def test_sat_state():
assert not eph.is_healthy()
eph = e.Ephemeris(**{'sid': {'sat': 17, 'code': 0},
'toe': { 'wn': 1867, 'tow': 518400.0,},
- 'ura': 2.0,
+ 'ura': 1000000.0,
+ 'fit_interval': 4 * 60 * 60,
+ 'valid': 1,
+ 'health_bits': 0,
+ 'kepler': {'crs': 25.125,
+ 'inc_dot': 3.78944355982045e-10,
+ 'tgd': -1.1175870895385742e-08,
+ 'crc': 106.65625,
+ 'ecc': 0.016364791779778898,
+ 'omegadot': -8.013190924423338e-09,
+ 'inc': 0.9253317285121154,
+ 'cuc': 1.255422830581665e-06,
+ 'omega0': 2.7384009602031045,
+ 'cus': 1.280754804611206e-05,
+ 'm0': -2.057975194561658,
+ 'toc': {'tow': 518400.0, 'wn': 1867,},
+ 'dn': 5.035924052164783e-09,
+ 'cic': 2.7194619178771973e-07,
+ 'sqrta': 5153.647108078003,
+ 'cis': 9.313225746154785e-09,
+ 'iode': 50,
+ 'iodc': 21845,
+ 'crc': 49614,
+ 'w': -1.9329047030450934,
+ 'af0': 0.0004458986222743988,
+ 'af1': 3.637978807091713e-12,
+ 'af2': 0.0}})
+ assert eph.is_valid(t.GpsTime(**{ 'wn': 1867, 'tow': 518400.0,}))
+ assert not eph.is_healthy()
+ eph = e.Ephemeris(**{'sid': {'sat': 11, 'code': 1},
+ 'toe': { 'wn': 1867, 'tow': 518400.0,},
+ 'ura': 10.0,
+ 'fit_interval': 4 * 60 * 60,
+ 'valid': 1,
+ 'health_bits': 0x3A,
+ 'kepler': {'crs': 25.125,
+ 'inc_dot': 3.78944355982045e-10,
+ 'tgd': -1.1175870895385742e-08,
+ 'crc': 106.65625,
+ 'ecc': 0.016364791779778898,
+ 'omegadot': -8.013190924423338e-09,
+ 'inc': 0.9253317285121154,
+ 'cuc': 1.255422830581665e-06,
+ 'omega0': 2.7384009602031045,
+ 'cus': 1.280754804611206e-05,
+ 'm0': -2.057975194561658,
+ 'toc': {'tow': 518400.0, 'wn': 1867,},
+ 'dn': 5.035924052164783e-09,
+ 'cic': 2.7194619178771973e-07,
+ 'sqrta': 5153.647108078003,
+ 'cis': 9.313225746154785e-09,
+ 'iode': 50,
+ 'iodc': 21845,
+ 'crc': 49614,
+ 'w': -1.9329047030450934,
+ 'af0': 0.0004458986222743988,
+ 'af1': 3.637978807091713e-12,
+ 'af2': 0.0}})
+ assert eph.is_valid(t.GpsTime(**{ 'wn': 1867, 'tow': 518400.0,}))
+ assert not eph.is_healthy()
+ eph = e.Ephemeris(**{'sid': {'sat': 13, 'code': 1},
+ 'toe': { 'wn': 1867, 'tow': 518400.0,},
+ 'ura': 100.0,
+ 'fit_interval': 4 * 60 * 60,
+ 'valid': 1,
+ 'health_bits': 0,
+ 'kepler': {'crs': 25.125,
+ 'inc_dot': 3.78944355982045e-10,
+ 'tgd': -1.1175870895385742e-08,
+ 'crc': 106.65625,
+ 'ecc': 0.016364791779778898,
+ 'omegadot': -8.013190924423338e-09,
+ 'inc': 0.9253317285121154,
+ 'cuc': 1.255422830581665e-06,
+ 'omega0': 2.7384009602031045,
+ 'cus': 1.280754804611206e-05,
+ 'm0': -2.057975194561658,
+ 'toc': {'tow': 518400.0, 'wn': 1867,},
+ 'dn': 5.035924052164783e-09,
+ 'cic': 2.7194619178771973e-07,
+ 'sqrta': 5153.647108078003,
+ 'cis': 9.313225746154785e-09,
+ 'iode': 50,
+ 'iodc': 21845,
+ 'crc': 49614,
+ 'w': -1.9329047030450934,
+ 'af0': 0.0004458986222743988,
+ 'af1': 3.637978807091713e-12,
+ 'af2': 0.0}})
+ assert eph.is_valid(t.GpsTime(**{ 'wn': 1867, 'tow': 518400.0,}))
+ assert eph.is_healthy()
+ eph = e.Ephemeris(**{'sid': {'sat': 17, 'code': 0},
+ 'toe': { 'wn': 1867, 'tow': 518400.0,},
+ 'ura': 3333.3,
'fit_interval': 4 * 60 * 60,
'valid': 0,
- 'healthy': 0,
+ 'health_bits': 0,
'kepler': {'crs': 25.125,
'inc_dot': 3.78944355982045e-10,
'tgd': -1.1175870895385742e-08,
@@ -132,10 +225,10 @@ def test_sat_state():
assert eph.is_healthy()
eph = e.Ephemeris(**{'sid': {'sat': 17, 'code': 0},
'toe': { 'wn': 1867, 'tow': 518400.0,},
- 'ura': 2.0,
+ 'ura': 5.0,
'fit_interval': 6 * 60 * 60,
'valid': 1,
- 'healthy': 1,
+ 'health_bits': 0,
'kepler': {'crs': 25.125,
'inc_dot': 3.78944355982045e-10,
'tgd': -1.1175870895385742e-08,
@@ -197,10 +290,10 @@ def test_parameters():
def test_glo_sat_state():
eph1 = e.Ephemeris(**{'sid': {'sat': 3, 'code': 3,},
'toe': {'wn': 1892, 'tow': 303900.0,}, #from GPS
- 'ura': 2.0,
+ 'ura': 1.0,
'fit_interval': 4 * 60 * 60,
'valid': 1,
- 'healthy': 1,
+ 'health_bits': 0,
'glo': { #data at 2016-04-13T12:25:00
'gamma' : 9.09494701772928238e-13,
'tau' : -6.72144815325737000e-05,
@@ -210,10 +303,10 @@ def test_glo_sat_state():
}})
eph2 = e.Ephemeris(**{'sid': {'sat': 3, 'code': 3,},
'toe': {'wn': 1892, 'tow': 305700.0,}, #from GPS
- 'ura': 2.0,
+ 'ura': 1.0,
'fit_interval': 4 * 60 * 60,
'valid': 1,
- 'healthy': 1,
+ 'health_bits': 0,
'glo': { #data at 2016-04-13T12:55:00
'gamma' : 9.09494701772928238e-13,
'tau' : -6.72172755002975464e-05,
@@ -241,10 +334,10 @@ def test_glo_sat_state():
# set reference ephemeris at 2007-15-11T06.15.00
eph = e.Ephemeris(**{'sid': {'sat': 3, 'code': 3,},
'toe': {'wn': 1453, 'tow': 368100.0,}, #from GPS
- 'ura': 2.0,
+ 'ura': 1.0,
'fit_interval': 4 * 60 * 60,
'valid': 1,
- 'healthy': 1,
+ 'health_bits': 0,
'glo': { #input data from GLO ICD, pg. 55
'gamma' : 0, #not necessary for the test
'tau' : 0, #not necessary for the test
View
@@ -51,7 +51,7 @@ static s8 calc_sat_state_xyz_almanac(const almanac_t *a, const gps_time_t *t,
e.ura = a->ura;
e.fit_interval = a->fit_interval;
e.valid = a->valid;
- e.healthy = a->healthy;
+ e.health_bits = a->health_bits;
memcpy(e.xyz.pos, a->xyz.pos, sizeof(e.xyz.pos));
memcpy(e.xyz.vel, a->xyz.vel, sizeof(e.xyz.vel));
memcpy(e.xyz.acc, a->xyz.acc, sizeof(e.xyz.acc));
@@ -87,7 +87,7 @@ static s8 calc_sat_state_kepler_almanac(const almanac_t *a, const gps_time_t *t,
e.ura = a->ura;
e.fit_interval = a->fit_interval;
e.valid = a->valid;
- e.healthy = a->healthy;
+ e.health_bits = a->health_bits;
e.kepler.m0 = a->kepler.m0;
e.kepler.ecc = a->kepler.ecc;
e.kepler.sqrta = a->kepler.sqrta;
@@ -255,7 +255,12 @@ u8 almanac_valid(const almanac_t *a, const gps_time_t *t)
*/
u8 satellite_healthy_almanac(const almanac_t *a)
{
- return a->healthy;
+ /* TODO
+ * Proper implementation:
+ * http://www.gps.gov/technical/icwg/IS-GPS-200H.pdf
+ * 20.3.3.5.1.2 Almanac Data.
+ */
+ return (0 == a->health_bits) ? 1 : 0;
}
static bool almanac_xyz_equal(const almanac_xyz_t *a,
@@ -292,7 +297,7 @@ bool almanac_equal(const almanac_t *a, const almanac_t *b)
(a->ura != b->ura) ||
(a->fit_interval != b->fit_interval) ||
(a->valid != b->valid) ||
- (a->healthy != b->healthy) ||
+ (a->health_bits != b->health_bits) ||
(a->toa.wn != b->toa.wn) ||
(a->toa.tow != b->toa.tow))
return false;
Oops, something went wrong.

0 comments on commit a5c13ba

Please sign in to comment.