gps_pvt 0.5.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -7
- data/Rakefile +42 -23
- data/exe/gps_pvt +13 -6
- data/ext/gps_pvt/Coordinate/Coordinate_wrap.cxx +44 -0
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +9015 -7695
- data/ext/ninja-scan-light/tool/algorithm/interpolate.h +121 -0
- data/ext/ninja-scan-light/tool/navigation/ANTEX.h +747 -0
- data/ext/ninja-scan-light/tool/navigation/GLONASS.h +37 -35
- data/ext/ninja-scan-light/tool/navigation/GLONASS_Solver.h +16 -13
- data/ext/ninja-scan-light/tool/navigation/GPS.h +121 -29
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +19 -12
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +39 -11
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +40 -171
- data/ext/ninja-scan-light/tool/navigation/SBAS.h +21 -13
- data/ext/ninja-scan-light/tool/navigation/SBAS_Solver.h +19 -16
- data/ext/ninja-scan-light/tool/navigation/SP3.h +1189 -0
- data/ext/ninja-scan-light/tool/navigation/coordinate.h +81 -1
- data/ext/ninja-scan-light/tool/swig/GPS.i +153 -40
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +503 -0
- data/ext/ninja-scan-light/tool/util/text_helper.h +248 -0
- data/lib/gps_pvt/receiver.rb +24 -0
- data/lib/gps_pvt/util.rb +25 -7
- data/lib/gps_pvt/version.rb +1 -1
- metadata +6 -2
@@ -51,6 +51,7 @@
|
|
51
51
|
#endif
|
52
52
|
|
53
53
|
#include "param/vector3.h"
|
54
|
+
#include "param/quaternion.h"
|
54
55
|
#include "param/matrix.h"
|
55
56
|
|
56
57
|
#include "WGS84.h"
|
@@ -130,6 +131,73 @@ class System_3D {
|
|
130
131
|
in >> self[2];
|
131
132
|
return in;
|
132
133
|
}
|
134
|
+
|
135
|
+
|
136
|
+
///< Coordinate rotation
|
137
|
+
struct Rotation {
|
138
|
+
Quaternion<FloatT> q;
|
139
|
+
Rotation() : q(1, 0, 0, 0) {}
|
140
|
+
Rotation &then(const Quaternion<FloatT> &q_) {
|
141
|
+
q *= q_;
|
142
|
+
return *this;
|
143
|
+
}
|
144
|
+
Rotation &then(const Rotation &rot) {
|
145
|
+
return then(rot.q);
|
146
|
+
}
|
147
|
+
Rotation &then_x(const FloatT &rad) {
|
148
|
+
return then(Quaternion<FloatT>(
|
149
|
+
std::cos(rad / 2), std::sin(rad / 2), 0, 0));
|
150
|
+
}
|
151
|
+
Rotation &then_y(const FloatT &rad) {
|
152
|
+
return then(Quaternion<FloatT>(
|
153
|
+
std::cos(rad / 2), 0, std::sin(rad / 2), 0));
|
154
|
+
}
|
155
|
+
Rotation &then_z(const FloatT &rad) {
|
156
|
+
return then(Quaternion<FloatT>(
|
157
|
+
std::cos(rad / 2), 0, 0, std::sin(rad / 2)));
|
158
|
+
}
|
159
|
+
operator Matrix<FloatT>() const {
|
160
|
+
return q.getDCM();
|
161
|
+
}
|
162
|
+
/**
|
163
|
+
* Perform coordinate rotation
|
164
|
+
* For example; application of clockwise 90 degree coordinate rotation along to z axis
|
165
|
+
* to vector(1,0,0) yields to vector(0,-1,0).
|
166
|
+
* This is not identical to vector rotation along with some axis,
|
167
|
+
* which corresponds to vector(0,1,0) of example, i.e.,
|
168
|
+
* z-axis 90 degree rotation of vector(1,0,0).
|
169
|
+
*
|
170
|
+
* @param vec target vector to which rotation is applied.
|
171
|
+
*/
|
172
|
+
void apply(FloatT (&vec)[3]) const {
|
173
|
+
#if 0
|
174
|
+
// as definition: (~q * vec * q).vector();
|
175
|
+
Vector3<FloatT> v(((q.conj() *= Vector3<FloatT>(vec.v)) *= q).vector());
|
176
|
+
vec[0] = v[0];
|
177
|
+
vec[1] = v[1];
|
178
|
+
vec[2] = v[2];
|
179
|
+
#else // optimized version
|
180
|
+
FloatT q0(q[0]), qv[3] = {q[1], q[2], q[3]};
|
181
|
+
FloatT q0_(qv[0] * vec[0] + qv[1] * vec[1] + qv[2] * vec[2]), // -q~.vec (i*) vec
|
182
|
+
qv_[3] = { // q~[0] * vec + q~.vec (e*) vec
|
183
|
+
q0 * vec[0] - qv[1] * vec[2] + qv[2] * vec[1], // polarity checked; q~.vec = -qv
|
184
|
+
q0 * vec[1] - qv[2] * vec[0] + qv[0] * vec[2],
|
185
|
+
q0 * vec[2] - qv[0] * vec[1] + qv[1] * vec[0]};
|
186
|
+
vec[0] = q0_ * qv[0] + q0 * qv_[0] + qv_[1] * qv[2] - qv_[2] * qv[1];
|
187
|
+
vec[1] = q0_ * qv[1] + q0 * qv_[1] + qv_[2] * qv[0] - qv_[0] * qv[2];
|
188
|
+
vec[2] = q0_ * qv[2] + q0 * qv_[2] + qv_[0] * qv[1] - qv_[1] * qv[0];
|
189
|
+
#endif
|
190
|
+
}
|
191
|
+
|
192
|
+
/**
|
193
|
+
* Perform coordinate rotation by invoking apply(vec.v)
|
194
|
+
*
|
195
|
+
* @see apply(FloatT (&vec)[3])
|
196
|
+
*/
|
197
|
+
void apply(System_3D &vec) const {
|
198
|
+
apply(vec.v);
|
199
|
+
}
|
200
|
+
};
|
133
201
|
};
|
134
202
|
|
135
203
|
template <class FloatT, class Earth> class System_XYZ;
|
@@ -186,7 +254,6 @@ class System_XYZ : public System_3D<FloatT> {
|
|
186
254
|
}
|
187
255
|
|
188
256
|
FloatT dist() const {
|
189
|
-
|
190
257
|
return FloatT(std::sqrt(
|
191
258
|
pow2(x()) + pow2(y()) + pow2(z())));
|
192
259
|
}
|
@@ -220,6 +287,19 @@ class System_XYZ : public System_3D<FloatT> {
|
|
220
287
|
std::atan2(y(), x()),
|
221
288
|
(p / std::cos(_lat) - n));
|
222
289
|
}
|
290
|
+
|
291
|
+
/**
|
292
|
+
* Get coordinates in a delayed (i.e., rotated) ECEF frame.
|
293
|
+
*
|
294
|
+
* @param (delay_sec) delayed seconds (both positive (delayed) and negative (hasten) values
|
295
|
+
* are acceptable)
|
296
|
+
* @return (self_t) coordinates
|
297
|
+
*/
|
298
|
+
self_t after(const FloatT &delay_sec) const {
|
299
|
+
FloatT rad(delay_sec * -Earth::Omega_Earth_IAU); // Earth rotation is negative direction (y->x)
|
300
|
+
FloatT crad(std::cos(rad)), srad(std::sin(rad));
|
301
|
+
return self_t(x() * crad - y() * srad, x() * srad + y() * crad, z());
|
302
|
+
}
|
223
303
|
};
|
224
304
|
|
225
305
|
template <class FloatT, class Earth>
|
@@ -22,6 +22,8 @@
|
|
22
22
|
#include "navigation/QZSS.h"
|
23
23
|
#include "navigation/GLONASS.h"
|
24
24
|
#include "navigation/RINEX.h"
|
25
|
+
#include "navigation/SP3.h"
|
26
|
+
#include "navigation/ANTEX.h"
|
25
27
|
|
26
28
|
#include "navigation/GPS_Solver_Base.h"
|
27
29
|
#include "navigation/GPS_Solver.h"
|
@@ -300,6 +302,10 @@ struct GPS_Ephemeris : public GPS_SpaceNode<FloatT>::SatelliteProperties::Epheme
|
|
300
302
|
GPS_Ephemeris(const typename GPS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris &eph)
|
301
303
|
: GPS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris(eph),
|
302
304
|
iode_subframe3(eph.iode) {}
|
305
|
+
struct constellation_res_t {
|
306
|
+
System_XYZ<FloatT, WGS84> position, velocity;
|
307
|
+
FloatT clock_error, clock_error_dot;
|
308
|
+
};
|
303
309
|
};
|
304
310
|
%}
|
305
311
|
%extend GPS_Ephemeris {
|
@@ -387,20 +393,21 @@ struct GPS_Ephemeris : public GPS_SpaceNode<FloatT>::SatelliteProperties::Epheme
|
|
387
393
|
break;
|
388
394
|
}
|
389
395
|
}
|
390
|
-
%typemap(
|
391
|
-
$1
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
const
|
400
|
-
typename GPS_SpaceNode<FloatT>::SatelliteProperties::constellation_t
|
401
|
-
self->constellation(
|
402
|
-
|
403
|
-
|
396
|
+
%typemap(out) constellation_res_t {
|
397
|
+
%append_output(SWIG_NewPointerObj((new System_XYZ<FloatT, WGS84>($1.position)),
|
398
|
+
$descriptor(System_XYZ<FloatT, WGS84> *), SWIG_POINTER_OWN));
|
399
|
+
%append_output(SWIG_NewPointerObj((new System_XYZ<FloatT, WGS84>($1.velocity)),
|
400
|
+
$descriptor(System_XYZ<FloatT, WGS84> *), SWIG_POINTER_OWN));
|
401
|
+
%append_output(swig::from($1.clock_error));
|
402
|
+
%append_output(swig::from($1.clock_error_dot));
|
403
|
+
}
|
404
|
+
typename GPS_Ephemeris<FloatT>::constellation_res_t constellation(
|
405
|
+
const GPS_Time<FloatT> &t_tx, const FloatT &dt_transit = 0) const {
|
406
|
+
typename GPS_SpaceNode<FloatT>::SatelliteProperties::constellation_t pv(
|
407
|
+
self->constellation(t_tx, dt_transit, true));
|
408
|
+
typename GPS_Ephemeris<FloatT>::constellation_res_t res = {
|
409
|
+
pv.position, pv.velocity, self->clock_error(t_tx), self->clock_error_dot(t_tx)};
|
410
|
+
return res;
|
404
411
|
}
|
405
412
|
#if defined(SWIGRUBY)
|
406
413
|
%rename("consistent?") is_consistent;
|
@@ -459,15 +466,14 @@ struct SBAS_Ephemeris : public SBAS_SpaceNode<FloatT>::SatelliteProperties::Ephe
|
|
459
466
|
MAKE_ACCESSOR(ddx, FloatT); MAKE_ACCESSOR(ddy, FloatT); MAKE_ACCESSOR(ddz, FloatT);
|
460
467
|
MAKE_ACCESSOR(a_Gf0, FloatT);
|
461
468
|
MAKE_ACCESSOR(a_Gf1, FloatT);
|
462
|
-
|
463
|
-
|
464
|
-
System_XYZ<FloatT, WGS84> &position, System_XYZ<FloatT, WGS84> &velocity,
|
465
|
-
const GPS_Time<FloatT> &t, const FloatT &pseudo_range = 0,
|
469
|
+
typename GPS_Ephemeris<FloatT>::constellation_res_t constellation(
|
470
|
+
const GPS_Time<FloatT> &t_tx, const FloatT &dt_transit = 0,
|
466
471
|
const bool &with_velocity = true) const {
|
467
|
-
typename SBAS_SpaceNode<FloatT>::SatelliteProperties::constellation_t
|
468
|
-
self->constellation(
|
469
|
-
|
470
|
-
|
472
|
+
typename SBAS_SpaceNode<FloatT>::SatelliteProperties::constellation_t pv(
|
473
|
+
self->constellation(t_tx, dt_transit, with_velocity));
|
474
|
+
typename GPS_Ephemeris<FloatT>::constellation_res_t res = {
|
475
|
+
pv.position, pv.velocity, self->clock_error(t_tx), self->clock_error_dot(t_tx)};
|
476
|
+
return res;
|
471
477
|
}
|
472
478
|
}
|
473
479
|
|
@@ -610,23 +616,13 @@ struct GLONASS_Ephemeris
|
|
610
616
|
self->has_string = has_string;
|
611
617
|
return updated;
|
612
618
|
}
|
613
|
-
FloatT
|
614
|
-
const GPS_Time<FloatT> &
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
%typemap(argout) System_XYZ<FloatT, WGS84> & {
|
621
|
-
%append_output(SWIG_NewPointerObj((new $*1_ltype(*$1)), $1_descriptor, SWIG_POINTER_OWN));
|
622
|
-
}
|
623
|
-
void constellation(
|
624
|
-
System_XYZ<FloatT, WGS84> &position, System_XYZ<FloatT, WGS84> &velocity,
|
625
|
-
const GPS_Time<FloatT> &t, const FloatT &pseudo_range = 0) const {
|
626
|
-
typename GPS_SpaceNode<FloatT>::SatelliteProperties::constellation_t res(
|
627
|
-
self->constellation(t, pseudo_range));
|
628
|
-
position = res.position;
|
629
|
-
velocity = res.velocity;
|
619
|
+
typename GPS_Ephemeris<FloatT>::constellation_res_t constellation(
|
620
|
+
const GPS_Time<FloatT> &t_tx, const FloatT &dt_transit = 0) const {
|
621
|
+
typename GPS_SpaceNode<FloatT>::SatelliteProperties::constellation_t pv(
|
622
|
+
self->constellation(t_tx, dt_transit));
|
623
|
+
typename GPS_Ephemeris<FloatT>::constellation_res_t res = {
|
624
|
+
pv.position, pv.velocity, self->clock_error(t_tx), self->clock_error_dot()};
|
625
|
+
return res;
|
630
626
|
}
|
631
627
|
#if defined(SWIGRUBY)
|
632
628
|
%rename("consistent?") is_consistent;
|
@@ -1378,7 +1374,28 @@ struct GPS_Solver
|
|
1378
1374
|
GPS_SpaceNode<FloatT> space_node;
|
1379
1375
|
GPS_SolverOptions<FloatT> options;
|
1380
1376
|
GPS_SinglePositioning<FloatT> solver;
|
1381
|
-
|
1377
|
+
struct ephemeris_proxy_t {
|
1378
|
+
struct item_t {
|
1379
|
+
const void *impl;
|
1380
|
+
typename base_t::satellite_t (*impl_select)(
|
1381
|
+
const void *,
|
1382
|
+
const typename base_t::prn_t &, const typename base_t::gps_time_t &);
|
1383
|
+
} gps, qzss;
|
1384
|
+
static typename base_t::satellite_t forward(
|
1385
|
+
const void *ptr,
|
1386
|
+
const typename base_t::prn_t &prn, const typename base_t::gps_time_t &t){
|
1387
|
+
const ephemeris_proxy_t *proxy(static_cast<const ephemeris_proxy_t *>(ptr));
|
1388
|
+
const item_t &target(((prn >= 193) && (prn <= 202)) ? proxy->qzss : proxy->gps);
|
1389
|
+
return target.impl_select(target.impl, prn, t);
|
1390
|
+
}
|
1391
|
+
ephemeris_proxy_t(GPS_SinglePositioning<FloatT> &solver){
|
1392
|
+
gps.impl = qzss.impl = solver.satellites.impl;
|
1393
|
+
gps.impl_select = qzss.impl_select = solver.satellites.impl_select;
|
1394
|
+
solver.satellites.impl = this;
|
1395
|
+
solver.satellites.impl_select = forward;
|
1396
|
+
}
|
1397
|
+
} ephemeris_proxy;
|
1398
|
+
gps_t() : space_node(), options(), solver(space_node), ephemeris_proxy(solver) {}
|
1382
1399
|
} gps;
|
1383
1400
|
struct sbas_t {
|
1384
1401
|
SBAS_SpaceNode<FloatT> space_node;
|
@@ -1636,6 +1653,101 @@ template <class FloatT>
|
|
1636
1653
|
struct RINEX_Observation {};
|
1637
1654
|
}
|
1638
1655
|
|
1656
|
+
%extend SP3 {
|
1657
|
+
%typemap(in,numinputs=0) int count[ANY] (int temp[$1_dim0]) "$1 = temp;"
|
1658
|
+
%typemap(argout) int count[ANY] {
|
1659
|
+
for(int i(0); i < $1_dim0; ++i){
|
1660
|
+
%append_output(SWIG_From(int)($1[i]));
|
1661
|
+
}
|
1662
|
+
}
|
1663
|
+
void satellites(int count[SP3::SYS_SYSTEMS]) const {
|
1664
|
+
typename SP3_Product<FloatT>::satellite_count_t x(self->satellite_count());
|
1665
|
+
count[SP3<FloatT>::SYS_GPS] = x.gps;
|
1666
|
+
count[SP3<FloatT>::SYS_SBAS] = x.sbas;
|
1667
|
+
count[SP3<FloatT>::SYS_QZSS] = x.qzss;
|
1668
|
+
count[SP3<FloatT>::SYS_GLONASS] = x.glonass;
|
1669
|
+
count[SP3<FloatT>::SYS_GALILEO] = x.galileo;
|
1670
|
+
count[SP3<FloatT>::SYS_BEIDOU] = x.beidou;
|
1671
|
+
}
|
1672
|
+
|
1673
|
+
}
|
1674
|
+
%inline {
|
1675
|
+
template <class FloatT>
|
1676
|
+
struct SP3 : public SP3_Product<FloatT> {
|
1677
|
+
int read(const char *fname) {
|
1678
|
+
std::fstream fin(fname, std::ios::in | std::ios::binary);
|
1679
|
+
return SP3_Reader<FloatT>::read_all(fin, *this);
|
1680
|
+
}
|
1681
|
+
enum system_t {
|
1682
|
+
SYS_GPS,
|
1683
|
+
SYS_SBAS,
|
1684
|
+
SYS_QZSS,
|
1685
|
+
SYS_GLONASS,
|
1686
|
+
SYS_GALILEO,
|
1687
|
+
SYS_BEIDOU,
|
1688
|
+
SYS_SYSTEMS,
|
1689
|
+
};
|
1690
|
+
bool push(GPS_Solver<FloatT> &solver, const system_t &sys) const {
|
1691
|
+
switch(sys){
|
1692
|
+
case SYS_GPS:
|
1693
|
+
return SP3_Product<FloatT>::push(
|
1694
|
+
solver.gps.ephemeris_proxy.gps, SP3_Product<FloatT>::SYSTEM_GPS);
|
1695
|
+
case SYS_SBAS:
|
1696
|
+
return SP3_Product<FloatT>::push(
|
1697
|
+
solver.sbas.solver.satellites, SP3_Product<FloatT>::SYSTEM_SBAS);
|
1698
|
+
case SYS_QZSS:
|
1699
|
+
return SP3_Product<FloatT>::push(
|
1700
|
+
solver.gps.ephemeris_proxy.qzss, SP3_Product<FloatT>::SYSTEM_QZSS);
|
1701
|
+
case SYS_GLONASS:
|
1702
|
+
return SP3_Product<FloatT>::push(
|
1703
|
+
solver.glonass.solver.satellites, SP3_Product<FloatT>::SYSTEM_GLONASS);
|
1704
|
+
case SYS_GALILEO:
|
1705
|
+
case SYS_BEIDOU:
|
1706
|
+
default:
|
1707
|
+
break;
|
1708
|
+
}
|
1709
|
+
return false;
|
1710
|
+
}
|
1711
|
+
bool push(GPS_Solver<FloatT> &solver) const {
|
1712
|
+
system_t target[] = {
|
1713
|
+
SYS_GPS,
|
1714
|
+
SYS_SBAS,
|
1715
|
+
SYS_QZSS,
|
1716
|
+
SYS_GLONASS,
|
1717
|
+
//SYS_GALILEO,
|
1718
|
+
//SYS_BEIDOU,
|
1719
|
+
};
|
1720
|
+
for(std::size_t i(0); i < sizeof(target) / sizeof(target[0]); ++i){
|
1721
|
+
if(!push(solver, target[i])){return false;}
|
1722
|
+
}
|
1723
|
+
return true;
|
1724
|
+
}
|
1725
|
+
System_XYZ<FloatT, WGS84> position(
|
1726
|
+
const int &sat_id, const GPS_Time<FloatT> &t) const {
|
1727
|
+
return SP3_Product<FloatT>::select(sat_id, t).position(t);
|
1728
|
+
}
|
1729
|
+
System_XYZ<FloatT, WGS84> velocity(
|
1730
|
+
const int &sat_id, const GPS_Time<FloatT> &t) const {
|
1731
|
+
return SP3_Product<FloatT>::select(sat_id, t).velocity(t);
|
1732
|
+
}
|
1733
|
+
FloatT clock_error(
|
1734
|
+
const int &sat_id, const GPS_Time<FloatT> &t) const {
|
1735
|
+
return SP3_Product<FloatT>::select(sat_id, t).clock_error(t);
|
1736
|
+
}
|
1737
|
+
FloatT clock_error_dot(
|
1738
|
+
const int &sat_id, const GPS_Time<FloatT> &t) const {
|
1739
|
+
return SP3_Product<FloatT>::select(sat_id, t).clock_error_dot(t);
|
1740
|
+
}
|
1741
|
+
int apply_antex(const char *fname) {
|
1742
|
+
ANTEX_Product<FloatT> antex;
|
1743
|
+
std::fstream fin(fname, std::ios::in | std::ios::binary);
|
1744
|
+
int read_items(ANTEX_Reader<FloatT>::read_all(fin, antex));
|
1745
|
+
if(read_items < 0){return read_items;}
|
1746
|
+
return antex.move_to_antenna_position(*this);
|
1747
|
+
}
|
1748
|
+
};
|
1749
|
+
}
|
1750
|
+
|
1639
1751
|
#undef MAKE_ACCESSOR
|
1640
1752
|
#undef MAKE_VECTOR2ARRAY
|
1641
1753
|
#undef MAKE_ARRAY_INPUT
|
@@ -1663,6 +1775,7 @@ struct RINEX_Observation {};
|
|
1663
1775
|
%template(SolverOptions_GLONASS) GLONASS_SolverOptions<type>;
|
1664
1776
|
|
1665
1777
|
%template(RINEX_Observation) RINEX_Observation<type>;
|
1778
|
+
%template(SP3) SP3<type>;
|
1666
1779
|
%enddef
|
1667
1780
|
|
1668
1781
|
CONCRETIZE(double);
|