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

Commit 1b14cfb

Browse files
committed
Updated Cython bindings for libswiftnav.
(Also known as the "A bird in the hand is worth two in the bush" commit). A massive monolithic commit (sorry!) containing: - Updated coverage on bindings - Removes c-specific Cython declaration files and other detritus - Very mild unit test coverage on ported structs and functions Some notes: - Documentation is still lacking, but perhaps we can just point people at the corresponding C documentation or something. - Some of the changes here are trying to minimize boiler plate, such as struct initialization for CPython wrapper objects. Many of the Cython objects are missing boilerplate setters and getters, but hopefully that can be handled some more nicer way. - Calling conventions are a bit inconsistent in the bindings and the underlying C library. See, I & Q quadratures vs complex p in the tracking loop stuff: track.c. /cc @mfine @fnoble @benjamin0 @kovach @JoshuaGross @henryhallam @jacobmcnamee @gsmcmullin @akleeman
1 parent 250dfc6 commit 1b14cfb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+4275
-2555
lines changed

.travis.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,16 @@ before_install:
99
- sudo add-apt-repository --yes ppa:kalakris/cmake
1010
- travis_retry sudo apt-get update -qq
1111
- sudo apt-get install cmake check
12+
- export LD_LIBRARY_PATH=/usr/local/lib
1213

1314
script:
15+
# Test libswiftnav
1416
- mkdir build
1517
- cd build/
1618
- cmake ../
1719
- make
20+
- sudo make install
21+
# Test libswiftnav-python
22+
- cd ../python
23+
- sudo pip install tox
24+
- tox

python/README.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,15 @@ To install libswiftnav-python (from the root of the source tree)::
3939
$ python setup.py build
4040
$ (sudo) python setup.py install
4141

42+
4243
Building Documentation
4344
----------------------
4445

46+
Much of this library provides bindings for functions in
47+
libswiftnav. Please see the accompanying comments and implementation
48+
of the C source for additional details that might be missing in this
49+
package.
50+
4551
Building the documentation requires the libswiftnav-python source code
4652
and some additional packages:
4753

python/setup.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
version = get_git_version(),
66
description = 'Python bindings to the libswiftnav library.',
77
license = 'LGPLv3',
8-
url = 'http://www.swift-nav.com',
8+
url = 'http://www.swiftnav.com',
99
author = 'Swift Navigation Inc.',
10-
author_email = 'info@swift-nav.com',
11-
maintainer = 'Fergus Noble',
12-
maintainer_email = 'fergus@swift-nav.com',
10+
author_email = 'dev@swiftnav.com',
11+
maintainer = 'Swift Navigation',
12+
maintainer_email = 'dev@swiftnav.com',
1313
packages = ['swiftnav'],
1414
)
1515

@@ -27,26 +27,37 @@ def make_extension(ext_name):
2727
ext_path = ext_name.replace('.', os.path.sep) + '.pyx'
2828
return Extension(
2929
ext_name, [ext_path],
30-
include_dirs = [np.get_include(), '.'],
30+
include_dirs = [np.get_include(), '.', '../include/libswiftnav/'],
3131
extra_compile_args = ['-O0', '-g'],
3232
extra_link_args = ['-g'],
3333
libraries = ['m', 'swiftnav'],
3434
)
3535
ext_names = [
36+
'swiftnav.edc',
37+
'swiftnav.signal',
3638
'swiftnav.coord_system',
39+
'swiftnav.constants',
3740
'swiftnav.nav_msg',
3841
'swiftnav.pvt',
3942
'swiftnav.correlate',
4043
'swiftnav.track',
4144
'swiftnav.almanac',
42-
'swiftnav.lam',
45+
'swiftnav.lambda_',
4346
'swiftnav.ephemeris',
4447
'swiftnav.linear_algebra',
4548
'swiftnav.amb_kf',
4649
'swiftnav.gpstime',
4750
'swiftnav.observation',
4851
'swiftnav.dgnss_management',
49-
'swiftnav.ambiguity_test'
52+
'swiftnav.ambiguity_test',
53+
'swiftnav.baseline',
54+
'swiftnav.bits',
55+
'swiftnav.filter_utils',
56+
'swiftnav.memory_pool',
57+
'swiftnav.prns',
58+
'swiftnav.sats_management',
59+
'swiftnav.tropo',
60+
'swiftnav.set',
5061
]
5162
extensions = [make_extension(name) for name in ext_names]
5263
setup_args['ext_modules'] = extensions

python/swiftnav/almanac.pxd

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2014 Swift Navigation Inc.
1+
# Copyright (C) 2015 Swift Navigation Inc.
22
#
33
# This source is subject to the license found in the file 'LICENSE' which must
44
# be be distributed together with this source. All other rights reserved.
@@ -7,7 +7,44 @@
77
# EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
88
# WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
99

10-
cimport almanac_c
10+
from common cimport *
11+
from signal cimport *
12+
13+
cdef extern from "libswiftnav/almanac.h":
14+
ctypedef struct almanac_gps_t:
15+
double ecc
16+
double toa
17+
double inc
18+
double rora
19+
double a
20+
double raaw
21+
double argp
22+
double ma
23+
double af0
24+
double af1
25+
u16 week
26+
27+
ctypedef struct almanac_sbas_t:
28+
u8 data_id
29+
u16 x
30+
u16 y
31+
u16 z
32+
u8 x_rate
33+
u8 y_rate
34+
u8 z_rate
35+
u16 t0
36+
37+
ctypedef struct almanac_t:
38+
gnss_signal_t sid
39+
u8 healthy
40+
u8 valid
41+
# HACK: Actually an anonymous union in libswiftnat!
42+
almanac_gps_t gps
43+
almanac_sbas_t sbas
44+
45+
void calc_sat_state_almanac(almanac_t* alm, double t, s16 week, double pos[3], double vel[3])
46+
void calc_sat_az_el_almanac(almanac_t* alm, double t, s16 week, double ref[3], double* az, double* el)
47+
double calc_sat_doppler_almanac(almanac_t* alm, double t, s16 week, double ref[3])
1148

1249
cdef class Almanac:
13-
cdef almanac_c.almanac_t almanac
50+
cdef almanac_t _thisptr

python/swiftnav/almanac.pyx

Lines changed: 40 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -9,64 +9,39 @@
99

1010
# cython: embedsignature=True
1111

12-
import numpy as np
12+
"""Almanac
13+
14+
Functions and calculations related to the GPS almanac.
15+
16+
Note: All positions are referenced to the WGS84 coordinate system.
17+
"""
18+
19+
from common cimport *
20+
from fmt_utils import fmt_repr
21+
from libc.string cimport memset
1322
cimport numpy as np
14-
cimport almanac_c
23+
import numpy as np
1524

1625
cdef class Almanac:
17-
"""
18-
Wraps the :libswiftnav:`almanac_t` structure and associated functions for
19-
performing calculations with almanacs.
20-
21-
Parameters
22-
----------
23-
ecc : float
24-
Eccentricity in radians.
25-
toa : float
26-
Time of Applicability in seconds since Sunday.
27-
inc : float
28-
Inclination in radians.
29-
rora : float
30-
Rate of Right Ascension in radians/sec.
31-
a : float
32-
Semi-major axis in meters.
33-
raaw : float
34-
Right Ascension at Week in radians.
35-
argp : float
36-
Argument of Perigee in radians.
37-
ma : float
38-
Mean Anomaly at Time of Applicability in radians.
39-
af0 : float
40-
0-order clock correction in seconds.
41-
af1 : float
42-
1-order clock correction in seconds/second.
43-
week : int
44-
GPS week number, modulo 1024.
45-
prn : int
46-
PRN number of the satellite.
47-
healthy : bool
48-
Satellite health status.
49-
50-
"""
51-
#cdef almanac_c.almanac_t almanac
52-
53-
def __init__(self, ecc, toa, inc, rora, a, raaw,
54-
argp, ma, af0, af1, week, prn, healthy):
55-
self.ecc = ecc
56-
self.toa = toa
57-
self.inc = inc
58-
self.rora = rora
59-
self.a = a
60-
self.raaw = raaw
61-
self.argp = argp
62-
self.ma = ma
63-
self.af0 = af0
64-
self.af1 = af1
65-
self.week = week
66-
self.prn = prn
67-
self.healthy = healthy
68-
69-
def calc_state(self, t, week=None):
26+
27+
def __init__(self, **kwargs):
28+
memset(&self._thisptr, 0, sizeof(almanac_t))
29+
if kwargs:
30+
self._thisptr = kwargs
31+
32+
def __getattr__(self, k):
33+
return self._thisptr.get(k)
34+
35+
def __repr__(self):
36+
return fmt_repr(self)
37+
38+
def to_dict(self):
39+
return self._thisptr
40+
41+
def from_dict(self, d):
42+
self._thisptr = d
43+
44+
def calc_state(self, t, week=-1):
7045
"""
7146
Wraps the function :libswiftnav:`calc_sat_state_almanac`.
7247
@@ -85,16 +60,9 @@ cdef class Almanac:
8560
coordinate system.
8661
8762
"""
88-
cdef np.ndarray[np.double_t, ndim=1, mode="c"] pos = \
89-
np.empty(3, dtype=np.double)
90-
cdef np.ndarray[np.double_t, ndim=1, mode="c"] vel = \
91-
np.empty(3, dtype=np.double)
92-
93-
if week is None:
94-
week = -1
95-
96-
almanac_c.calc_sat_state_almanac(&self.almanac, t, week, &pos[0], &vel[0])
97-
63+
cdef np.ndarray[np.double_t, ndim=1, mode="c"] pos = np.empty(3, dtype=np.double)
64+
cdef np.ndarray[np.double_t, ndim=1, mode="c"] vel = np.empty(3, dtype=np.double)
65+
calc_sat_state_almanac(&self._thisptr, t, week, &pos[0], &vel[0])
9866
return (pos, vel)
9967

10068
def calc_az_el(self, t, ref, week=None):
@@ -117,23 +85,13 @@ cdef class Almanac:
11785
The tuple (azimuth, elevation) in radians.
11886
11987
"""
120-
if len(ref) != 3:
121-
raise ValueError("ECEF coordinates must have dimension 3.")
122-
123-
cdef np.ndarray[np.double_t, ndim=1, mode="c"] ref_ = \
124-
np.array(ref, dtype=np.double)
125-
88+
assert len(ref) != 3, "ECEF coordinates must have dimension 3."
89+
cdef np.ndarray[np.double_t, ndim=1, mode="c"] ref_ = np.array(ref, dtype=np.double)
12690
cdef double az, el
127-
128-
if week is None:
129-
week = -1
130-
131-
almanac_c.calc_sat_az_el_almanac(&self.almanac, t, week,
132-
&ref_[0], &az, &el)
133-
91+
calc_sat_az_el_almanac(&self._thisptr, t, week, &ref_[0], &az, &el)
13492
return (az, el)
13593

136-
def calc_doppler(self, t, ref, week=None):
94+
def calc_doppler(self, t, ref, week=-1):
13795
"""
13896
Wraps the function :libswiftnav:`calc_sat_doppler_almanac`.
13997
@@ -153,99 +111,6 @@ cdef class Almanac:
153111
The Doppler shift in Hz.
154112
155113
"""
156-
if len(ref) != 3:
157-
raise ValueError("ECEF coordinates must have dimension 3.")
158-
159-
cdef np.ndarray[np.double_t, ndim=1, mode="c"] ref_ = \
160-
np.array(ref, dtype=np.double)
161-
162-
cdef double az, el
163-
164-
if week is None:
165-
week = -1
166-
167-
return almanac_c.calc_sat_doppler_almanac(&self.almanac, t, week,
168-
&ref_[0])
169-
170-
def __repr__(self):
171-
return "<Almanac PRN %02d, Week %d, ToA %.1f>" % \
172-
(self.prn, self.week, self.toa)
173-
174-
property ecc:
175-
def __get__(self):
176-
return self.almanac.ecc
177-
def __set__(self, ecc):
178-
self.almanac.ecc = ecc
179-
180-
property toa:
181-
def __get__(self):
182-
return self.almanac.toa
183-
def __set__(self, toa):
184-
self.almanac.toa = toa
185-
186-
property inc:
187-
def __get__(self):
188-
return self.almanac.inc
189-
def __set__(self, inc):
190-
self.almanac.inc = inc
191-
192-
property rora:
193-
def __get__(self):
194-
return self.almanac.rora
195-
def __set__(self, rora):
196-
self.almanac.rora = rora
197-
198-
property a:
199-
def __get__(self):
200-
return self.almanac.a
201-
def __set__(self, a):
202-
self.almanac.a = a
203-
204-
property raaw:
205-
def __get__(self):
206-
return self.almanac.raaw
207-
def __set__(self, raaw):
208-
self.almanac.raaw = raaw
209-
210-
property argp:
211-
def __get__(self):
212-
return self.almanac.argp
213-
def __set__(self, argp):
214-
self.almanac.argp = argp
215-
216-
property ma:
217-
def __get__(self):
218-
return self.almanac.ma
219-
def __set__(self, ma):
220-
self.almanac.ma = ma
221-
222-
property af0:
223-
def __get__(self):
224-
return self.almanac.af0
225-
def __set__(self, af0):
226-
self.almanac.af0 = af0
227-
228-
property af1:
229-
def __get__(self):
230-
return self.almanac.af1
231-
def __set__(self, af1):
232-
self.almanac.af1 = af1
233-
234-
property week:
235-
def __get__(self):
236-
return self.almanac.week
237-
def __set__(self, week):
238-
self.almanac.week = week
239-
240-
property prn:
241-
def __get__(self):
242-
return self.almanac.prn
243-
def __set__(self, prn):
244-
self.almanac.prn = prn
245-
246-
property healthy:
247-
def __get__(self):
248-
return (self.almanac.healthy > 0)
249-
def __set__(self, healthy):
250-
self.almanac.healthy = 1 if healthy else 0
251-
114+
assert len(ref) != 3, "ECEF coordinates must have dimension 3."
115+
cdef np.ndarray[np.double_t, ndim=1, mode="c"] ref_ = np.array(ref, dtype=np.double)
116+
return calc_sat_doppler_almanac(&self._thisptr, t, week, &ref_[0])

0 commit comments

Comments
 (0)