gps_pvt 0.1.4 → 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.
@@ -1,6 +1,6 @@
1
1
  /* ----------------------------------------------------------------------------
2
2
  * This file was automatically generated by SWIG (http://www.swig.org).
3
- * Version 4.0.1
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 0x040001
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/swig4.0/ruby/rubyprimtypes.swg,19,%ruby_aux_method@*/
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/swig4.0/ruby/rubyprimtypes.swg,19,%ruby_aux_method@*/
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/swig4.0/ruby/rubyprimtypes.swg,19,%ruby_aux_method@*/
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;
@@ -243,7 +243,7 @@ struct GPS_Time {
243
243
  GPS_Time &canonicalize(){
244
244
  int quot(std::floor(seconds / seconds_week));
245
245
  week += quot;
246
- seconds -= (seconds_week * quot);
246
+ seconds -= (quot * (int)seconds_week);
247
247
  return *this;
248
248
  }
249
249
  GPS_Time(const std::tm &t, const float_t &leap_seconds = 0) {
@@ -405,11 +405,12 @@ struct GPS_Time {
405
405
  }
406
406
 
407
407
  // process remaining 4 years
408
- int doy_i(0), doy[] = {
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(int i(0); i < sizeof(ionospheric_models) / sizeof(ionospheric_models[0]); ++i){
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(int i(0); i < sizeof(ionospheric_models) / sizeof(ionospheric_models[0]); ++i){
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(int i(0); i < sizeof(opt.ionospheric_models) / sizeof(opt.ionospheric_models[0]); ++i){
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()){break;}
180
- opt.ionospheric_models[i] = options_t::IONOSPHERIC_SKIP;
181
- continue;
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){break;}
209
+ if(opt.f_10_7 >= 0){usable = true;}
184
210
  // check F10.7 has been already configured
185
- opt.ionospheric_models[i] = options_t::IONOSPHERIC_SKIP;
186
- continue;
187
- case options_t::IONOSPHERIC_SKIP:
188
- continue;
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(), _space_node(sn), _options() {
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(int i(0); i < sizeof(_options.ionospheric_models) / sizeof(_options.ionospheric_models[0]); ++i){
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__ */