gps_pvt 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +2 -0
- data/exe/gps_pvt +4 -4
- data/ext/gps_pvt/Coordinate/Coordinate_wrap.cxx +5 -3
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +4229 -508
- data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +7 -5
- data/ext/ninja-scan-light/tool/navigation/GPS.h +4 -3
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +62 -15
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +6 -5
- data/ext/ninja-scan-light/tool/navigation/QZSS.h +62 -0
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +320 -22
- data/ext/ninja-scan-light/tool/navigation/SBAS.h +2330 -0
- data/ext/ninja-scan-light/tool/navigation/SBAS_Solver.h +329 -0
- data/ext/ninja-scan-light/tool/swig/GPS.i +197 -65
- data/lib/gps_pvt/receiver.rb +253 -132
- data/lib/gps_pvt/version.rb +1 -1
- metadata +5 -2
@@ -1,6 +1,6 @@
|
|
1
1
|
/* ----------------------------------------------------------------------------
|
2
2
|
* This file was automatically generated by SWIG (http://www.swig.org).
|
3
|
-
* Version 4.0.
|
3
|
+
* Version 4.0.2
|
4
4
|
*
|
5
5
|
* This file is not intended to be easily readable and contains a number of
|
6
6
|
* coding conventions designed to improve portability and efficiency. Do not make
|
@@ -1612,6 +1612,8 @@ SWIGRUNTIMEINLINE char *
|
|
1612
1612
|
SWIG_Ruby_MangleStr(VALUE obj)
|
1613
1613
|
{
|
1614
1614
|
VALUE stype = rb_iv_get(obj, "@__swigtype__");
|
1615
|
+
if (NIL_P(stype))
|
1616
|
+
return NULL;
|
1615
1617
|
return StringValuePtr(stype);
|
1616
1618
|
}
|
1617
1619
|
|
@@ -1876,7 +1878,7 @@ static VALUE mSylphideMath;
|
|
1876
1878
|
#define SWIG_RUBY_THREAD_END_BLOCK
|
1877
1879
|
|
1878
1880
|
|
1879
|
-
#define SWIGVERSION
|
1881
|
+
#define SWIGVERSION 0x040002
|
1880
1882
|
#define SWIG_VERSION SWIGVERSION
|
1881
1883
|
|
1882
1884
|
|
@@ -2259,7 +2261,7 @@ SWIG_ruby_failed(VALUE SWIGUNUSEDPARM(arg1), VALUE SWIGUNUSEDPARM(arg2))
|
|
2259
2261
|
}
|
2260
2262
|
|
2261
2263
|
|
2262
|
-
/*@SWIG:/usr/share/
|
2264
|
+
/*@SWIG:/usr/local/share/swig/4.0.2/ruby/rubyprimtypes.swg,19,%ruby_aux_method@*/
|
2263
2265
|
SWIGINTERN VALUE SWIG_AUX_NUM2DBL(VALUE arg)
|
2264
2266
|
{
|
2265
2267
|
VALUE *args = (VALUE *)arg;
|
@@ -3089,7 +3091,7 @@ SWIG_From_unsigned_SS_int (unsigned int value)
|
|
3089
3091
|
}
|
3090
3092
|
|
3091
3093
|
|
3092
|
-
/*@SWIG:/usr/share/
|
3094
|
+
/*@SWIG:/usr/local/share/swig/4.0.2/ruby/rubyprimtypes.swg,19,%ruby_aux_method@*/
|
3093
3095
|
SWIGINTERN VALUE SWIG_AUX_NUM2LONG(VALUE arg)
|
3094
3096
|
{
|
3095
3097
|
VALUE *args = (VALUE *)arg;
|
@@ -3155,7 +3157,7 @@ SWIG_AsVal_bool (VALUE obj, bool *val)
|
|
3155
3157
|
}
|
3156
3158
|
|
3157
3159
|
|
3158
|
-
/*@SWIG:/usr/share/
|
3160
|
+
/*@SWIG:/usr/local/share/swig/4.0.2/ruby/rubyprimtypes.swg,19,%ruby_aux_method@*/
|
3159
3161
|
SWIGINTERN VALUE SWIG_AUX_NUM2ULONG(VALUE arg)
|
3160
3162
|
{
|
3161
3163
|
VALUE *args = (VALUE *)arg;
|
@@ -405,11 +405,12 @@ struct GPS_Time {
|
|
405
405
|
}
|
406
406
|
|
407
407
|
// process remaining 4 years
|
408
|
-
int
|
408
|
+
int doy[] = {
|
409
409
|
leap_year ? 366 : 365,
|
410
410
|
365, 365, 365,
|
411
411
|
is_leap_year(year + 4) ? 366 : 365,
|
412
412
|
};
|
413
|
+
std::size_t doy_i(0);
|
413
414
|
for(; doy_i < sizeof(doy) / sizeof(doy[0]); ++doy_i){
|
414
415
|
if(days <= doy[doy_i]){break;}
|
415
416
|
days -= doy[doy_i];
|
@@ -2051,6 +2052,7 @@ if(std::abs(TARGET - eph.TARGET) > raw_t::sf[raw_t::SF_ ## TARGET]){break;}
|
|
2051
2052
|
* @param height_over_ellipsoid
|
2052
2053
|
* @see spherically single layer approach, for example,
|
2053
2054
|
* Eq.(3) of "Ionospheric Range Error Correction Models" by N. Jakowski
|
2055
|
+
* @see DO-229D A4.4.10.4 Eq.(A-42) is equivalent
|
2054
2056
|
*/
|
2055
2057
|
static float_t slant_factor(
|
2056
2058
|
const enu_t &relative_pos,
|
@@ -2089,8 +2091,7 @@ if(std::abs(TARGET - eph.TARGET) > raw_t::sf[raw_t::SF_ ## TARGET]){break;}
|
|
2089
2091
|
// Elevation and azimuth
|
2090
2092
|
float_t el(relative_pos.elevation()),
|
2091
2093
|
az(relative_pos.azimuth());
|
2092
|
-
float_t sc_el(rad2sc(el))
|
2093
|
-
sc_az(rad2sc(az));
|
2094
|
+
float_t sc_el(rad2sc(el));
|
2094
2095
|
|
2095
2096
|
// Pierce point (PP stands for the earth projection of the Pierce point)
|
2096
2097
|
// (the following equation is based on GPS ICD)
|
@@ -43,11 +43,13 @@
|
|
43
43
|
#include <exception>
|
44
44
|
|
45
45
|
#include <cmath>
|
46
|
+
#include <cstddef>
|
46
47
|
|
47
48
|
#include "param/bit_array.h"
|
48
49
|
|
49
50
|
#include "GPS.h"
|
50
51
|
#include "GPS_Solver_Base.h"
|
52
|
+
#include "SBAS.h"
|
51
53
|
#include "NTCM.h"
|
52
54
|
|
53
55
|
template <class FloatT>
|
@@ -57,6 +59,7 @@ struct GPS_Solver_GeneralOptions {
|
|
57
59
|
|
58
60
|
enum ionospheric_model_t {
|
59
61
|
IONOSPHERIC_KLOBUCHAR,
|
62
|
+
IONOSPHERIC_SBAS,
|
60
63
|
IONOSPHERIC_NTCM_GL,
|
61
64
|
IONOSPHERIC_NONE, // which allows no correction
|
62
65
|
IONOSPHERIC_MODELS,
|
@@ -66,7 +69,7 @@ struct GPS_Solver_GeneralOptions {
|
|
66
69
|
|
67
70
|
int count_ionospheric_models() const {
|
68
71
|
int res(0);
|
69
|
-
for(
|
72
|
+
for(std::size_t i(0); i < sizeof(ionospheric_models) / sizeof(ionospheric_models[0]); ++i){
|
70
73
|
if(ionospheric_models[i] != IONOSPHERIC_SKIP){res++;}
|
71
74
|
}
|
72
75
|
return res;
|
@@ -78,7 +81,7 @@ struct GPS_Solver_GeneralOptions {
|
|
78
81
|
: elevation_mask(0), // elevation mask default is 0 [deg]
|
79
82
|
residual_mask(30), // range residual mask is 30 [m]
|
80
83
|
f_10_7(-1) {
|
81
|
-
for(
|
84
|
+
for(std::size_t i(0); i < sizeof(ionospheric_models) / sizeof(ionospheric_models[0]); ++i){
|
82
85
|
ionospheric_models[i] = IONOSPHERIC_SKIP;
|
83
86
|
}
|
84
87
|
// default: broadcasted Klobuchar parameters are at least required for solution.
|
@@ -97,6 +100,22 @@ struct GPS_Solver_GeneralOptions {
|
|
97
100
|
}
|
98
101
|
ionospheric_models[index] = model;
|
99
102
|
|
103
|
+
return true;
|
104
|
+
}
|
105
|
+
bool remove_ionospheric_model(const ionospheric_model_t &model) {
|
106
|
+
// shift, then replace
|
107
|
+
int j(0);
|
108
|
+
for(int i(0); i < sizeof(ionospheric_models) / sizeof(ionospheric_models[0]); ++i){
|
109
|
+
if(ionospheric_models[i] == model){continue;}
|
110
|
+
ionospheric_models[j++] = ionospheric_models[i];
|
111
|
+
}
|
112
|
+
if(j == (sizeof(ionospheric_models) / sizeof(ionospheric_models[0]))){
|
113
|
+
return false;
|
114
|
+
}
|
115
|
+
do{
|
116
|
+
ionospheric_models[j++] = IONOSPHERIC_SKIP;
|
117
|
+
}while(j < sizeof(ionospheric_models) / sizeof(ionospheric_models[0]));
|
118
|
+
|
100
119
|
return true;
|
101
120
|
}
|
102
121
|
};
|
@@ -139,6 +158,8 @@ class GPS_SinglePositioning : public SolverBaseT {
|
|
139
158
|
inheritate_type(llh_t);
|
140
159
|
inheritate_type(enu_t);
|
141
160
|
|
161
|
+
typedef SBAS_SpaceNode<float_t> sbas_space_node_t;
|
162
|
+
|
142
163
|
inheritate_type(pos_t);
|
143
164
|
|
144
165
|
inheritate_type(prn_obs_t);
|
@@ -151,9 +172,10 @@ class GPS_SinglePositioning : public SolverBaseT {
|
|
151
172
|
inheritate_type(user_pvt_t);
|
152
173
|
#undef inheritate_type
|
153
174
|
|
175
|
+
const sbas_space_node_t *space_node_sbas; ///< optional
|
176
|
+
|
154
177
|
typedef typename GPS_Solver_Base<float_t>::options_t::template merge_t<
|
155
178
|
GPS_SinglePositioning_Options<float_t>, base_t> options_t;
|
156
|
-
|
157
179
|
protected:
|
158
180
|
const space_node_t &_space_node;
|
159
181
|
GPS_SinglePositioning_Options<float_t> _options;
|
@@ -172,22 +194,28 @@ class GPS_SinglePositioning : public SolverBaseT {
|
|
172
194
|
|
173
195
|
int available_models(0);
|
174
196
|
|
175
|
-
for(
|
197
|
+
for(std::size_t i(0);
|
198
|
+
i < sizeof(opt.ionospheric_models) / sizeof(opt.ionospheric_models[0]); ++i){
|
199
|
+
bool usable(false);
|
176
200
|
switch(opt.ionospheric_models[i]){
|
177
201
|
case options_t::IONOSPHERIC_KLOBUCHAR:
|
178
202
|
// check whether Klobuchar parameters alpha and beta have been already received
|
179
|
-
if(_space_node.is_valid_iono()){
|
180
|
-
|
181
|
-
|
203
|
+
if(_space_node.is_valid_iono()){usable = true;}
|
204
|
+
break;
|
205
|
+
case options_t::IONOSPHERIC_SBAS:
|
206
|
+
if(space_node_sbas){usable = true;}
|
207
|
+
break;
|
182
208
|
case options_t::IONOSPHERIC_NTCM_GL:
|
183
|
-
if(opt.f_10_7 >= 0){
|
209
|
+
if(opt.f_10_7 >= 0){usable = true;}
|
184
210
|
// check F10.7 has been already configured
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
211
|
+
break;
|
212
|
+
default: break;
|
213
|
+
}
|
214
|
+
if(usable){
|
215
|
+
available_models++;
|
216
|
+
}else{
|
217
|
+
opt.ionospheric_models[i] = options_t::IONOSPHERIC_SKIP;
|
189
218
|
}
|
190
|
-
available_models++;
|
191
219
|
}
|
192
220
|
|
193
221
|
return available_models;
|
@@ -209,7 +237,9 @@ class GPS_SinglePositioning : public SolverBaseT {
|
|
209
237
|
}
|
210
238
|
|
211
239
|
GPS_SinglePositioning(const space_node_t &sn)
|
212
|
-
: base_t(),
|
240
|
+
: base_t(),
|
241
|
+
_space_node(sn), space_node_sbas(NULL),
|
242
|
+
_options() {
|
213
243
|
filter_ionospheric_models(_options);
|
214
244
|
}
|
215
245
|
|
@@ -266,11 +296,28 @@ class GPS_SinglePositioning : public SolverBaseT {
|
|
266
296
|
if(error.unknown_flag & range_error_t::MASK_IONOSPHERIC){
|
267
297
|
// Ionospheric model selection, the fall back is no correction
|
268
298
|
bool iono_model_hit(false);
|
269
|
-
for(
|
299
|
+
for(std::size_t i(0);
|
300
|
+
i < sizeof(_options.ionospheric_models) / sizeof(_options.ionospheric_models[0]);
|
301
|
+
++i){
|
270
302
|
switch(_options.ionospheric_models[i]){
|
271
303
|
case options_t::IONOSPHERIC_KLOBUCHAR:
|
272
304
|
residual.residual += _space_node.iono_correction(relative_pos, usr_pos.llh, time_arrival);
|
273
305
|
break;
|
306
|
+
case options_t::IONOSPHERIC_SBAS: {
|
307
|
+
// placeholder of checking availability and performing correction
|
308
|
+
typedef typename SBAS_SpaceNode<float_t>::available_satellites_t sats_t;
|
309
|
+
sats_t sats(space_node_sbas->available_satellites(usr_pos.llh.longitude()));
|
310
|
+
|
311
|
+
typename SBAS_SpaceNode<float_t>::IonosphericGridPoints::PointProperty prop;
|
312
|
+
for(typename sats_t::const_iterator it(sats.begin()); it != sats.end(); ++it){
|
313
|
+
prop = it->second
|
314
|
+
->ionospheric_grid_points().iono_correction(relative_pos, usr_pos.llh);
|
315
|
+
break; // TODO The nearest satellite is only checked
|
316
|
+
}
|
317
|
+
if(!prop.is_available()){continue;}
|
318
|
+
residual.residual += prop.delay;
|
319
|
+
break;
|
320
|
+
}
|
274
321
|
case options_t::IONOSPHERIC_NTCM_GL: {
|
275
322
|
// TODO f_10_7 setup, optimization (mag_model etc.)
|
276
323
|
typename space_node_t::pierce_point_res_t pp(_space_node.pierce_point(relative_pos, usr_pos.llh));
|
@@ -202,9 +202,9 @@ struct GPS_Solver_Base {
|
|
202
202
|
virtual const float_t *rate(
|
203
203
|
const typename measurement_t::mapped_type &values, float_t &buf) const {
|
204
204
|
const float_t *res;
|
205
|
-
if(res = find_value(values, measurement_items_t::L1_RANGE_RATE, buf)){
|
205
|
+
if((res = find_value(values, measurement_items_t::L1_RANGE_RATE, buf))){
|
206
206
|
|
207
|
-
}else if(res = find_value(values, measurement_items_t::L1_DOPPLER, buf)){
|
207
|
+
}else if((res = find_value(values, measurement_items_t::L1_DOPPLER, buf))){
|
208
208
|
// Fall back to doppler
|
209
209
|
buf *= -space_node_t::L1_WaveLength();
|
210
210
|
}
|
@@ -214,9 +214,9 @@ struct GPS_Solver_Base {
|
|
214
214
|
virtual const float_t *rate_sigma(
|
215
215
|
const typename measurement_t::mapped_type &values, float_t &buf) const {
|
216
216
|
const float_t *res;
|
217
|
-
if(res = find_value(values, measurement_items_t::L1_RANGE_RATE_SIGMA, buf)){
|
217
|
+
if((res = find_value(values, measurement_items_t::L1_RANGE_RATE_SIGMA, buf))){
|
218
218
|
|
219
|
-
}else if(res = find_value(values, measurement_items_t::L1_DOPPLER_SIGMA, buf)){
|
219
|
+
}else if((res = find_value(values, measurement_items_t::L1_DOPPLER_SIGMA, buf))){
|
220
220
|
// Fall back to doppler
|
221
221
|
buf *= space_node_t::L1_WaveLength();
|
222
222
|
}
|
@@ -308,8 +308,9 @@ struct GPS_Solver_Base {
|
|
308
308
|
case ERROR_VELOCITY_INSUFFICIENT_SATELLITES:
|
309
309
|
case ERROR_VELOCITY_LS:
|
310
310
|
return true;
|
311
|
+
default:
|
312
|
+
return false;
|
311
313
|
}
|
312
|
-
return false;
|
313
314
|
}
|
314
315
|
bool velocity_solved() const {
|
315
316
|
return error_code == ERROR_NO;
|
@@ -0,0 +1,62 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2021, M.Naruoka (fenrir)
|
3
|
+
* All rights reserved.
|
4
|
+
*
|
5
|
+
* Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
* are permitted provided that the following conditions are met:
|
7
|
+
*
|
8
|
+
* - Redistributions of source code must retain the above copyright notice,
|
9
|
+
* this list of conditions and the following disclaimer.
|
10
|
+
* - Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
* this list of conditions and the following disclaimer in the documentation
|
12
|
+
* and/or other materials provided with the distribution.
|
13
|
+
* - Neither the name of the naruoka.org nor the names of its contributors
|
14
|
+
* may be used to endorse or promote products derived from this software
|
15
|
+
* without specific prior written permission.
|
16
|
+
*
|
17
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
19
|
+
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
|
21
|
+
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
22
|
+
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
23
|
+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
24
|
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
25
|
+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
26
|
+
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
27
|
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
28
|
+
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
*
|
30
|
+
*/
|
31
|
+
|
32
|
+
#ifndef __QZSS_H__
|
33
|
+
#define __QZSS_H__
|
34
|
+
|
35
|
+
/** @file
|
36
|
+
* @brief QZSS ICD definitions
|
37
|
+
*/
|
38
|
+
|
39
|
+
#include "GPS.h"
|
40
|
+
#include <limits>
|
41
|
+
|
42
|
+
template <class FloatT>
|
43
|
+
struct QZSS_LNAV_Ephemeris_Raw : public GPS_SpaceNode<FloatT>::Satellite::Ephemeris::raw_t {
|
44
|
+
typedef typename GPS_SpaceNode<FloatT>::Satellite::Ephemeris eph_t;
|
45
|
+
typedef typename eph_t::raw_t super_t;
|
46
|
+
|
47
|
+
operator eph_t() const {
|
48
|
+
eph_t res(super_t::operator eph_t());
|
49
|
+
res.fit_interval = super_t::fit_interval_flag
|
50
|
+
? (std::numeric_limits<FloatT>::max)()
|
51
|
+
: (2 * 60 * 60); // Fit interval (ICD:4.1.2.4 Subframe 2); should be zero
|
52
|
+
return res;
|
53
|
+
};
|
54
|
+
|
55
|
+
QZSS_LNAV_Ephemeris_Raw &operator=(const eph_t &eph){
|
56
|
+
super_t::operator=(eph);
|
57
|
+
super_t::fit_interval_flag = (eph.fit_interval > 2 * 60 * 60);
|
58
|
+
return *this;
|
59
|
+
}
|
60
|
+
};
|
61
|
+
|
62
|
+
#endif /* __QZSS_H__ */
|