gps_pvt 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -49,11 +49,7 @@ struct SBAS_SinglePositioning_Options : public GPS_Solver_GeneralOptions<FloatT>
49
49
 
50
50
  typename GPS_Solver_Base<FloatT>::options_t::template exclude_prn_t<120, 158> exclude_prn; // SBAS PRN ranges from 120 to 158
51
51
  SBAS_SinglePositioning_Options()
52
- : super_t() {
53
- // default: SBAS IGP, then broadcasted Klobuchar.
54
- super_t::ionospheric_models[0] = super_t::IONOSPHERIC_SBAS;
55
- super_t::ionospheric_models[1] = super_t::IONOSPHERIC_KLOBUCHAR;
56
-
52
+ : super_t(), exclude_prn() {
57
53
  exclude_prn.set(true); // SBAS ranging is default off.
58
54
  }
59
55
  };
@@ -86,6 +82,8 @@ class SBAS_SinglePositioning : public SolverBaseT {
86
82
 
87
83
  typedef typename base_t::measurement_t measurement_t;
88
84
  typedef typename base_t::range_error_t range_error_t;
85
+ typedef typename base_t::range_corrector_t range_corrector_t;
86
+ typedef typename base_t::range_correction_t range_correction_t;
89
87
 
90
88
  inheritate_type(relative_property_t);
91
89
  #undef inheritate_type
@@ -93,8 +91,6 @@ class SBAS_SinglePositioning : public SolverBaseT {
93
91
  typedef typename GPS_Solver_Base<float_t>::options_t::template merge_t<
94
92
  SBAS_SinglePositioning_Options<float_t>, base_t> options_t;
95
93
 
96
- typedef GPS_SpaceNode<float_t> gps_space_node_t;
97
- const gps_space_node_t *space_node_gps; ///< optional
98
94
  protected:
99
95
  const space_node_t &_space_node;
100
96
  SBAS_SinglePositioning_Options<float_t> _options;
@@ -102,40 +98,47 @@ class SBAS_SinglePositioning : public SolverBaseT {
102
98
  public:
103
99
  const space_node_t &space_node() const {return _space_node;}
104
100
 
105
- /**
106
- * Check availability of ionospheric models
107
- * If a model is completely unavailable, it will be replaced to IONOSPHERIC_SKIP.
108
- * It implies that when a model has conditional applicability (such as SBAS), it will be retained.
109
- *
110
- * @return (int) number of (possibly) available models
111
- */
112
- int filter_ionospheric_models(SBAS_SinglePositioning_Options<float_t> &opt) const {
113
- int available_models(0);
114
- for(std::size_t i(0); i < sizeof(opt.ionospheric_models) / sizeof(opt.ionospheric_models[0]); ++i){
115
- bool usable(false);
116
- switch(opt.ionospheric_models[i]){
117
- case options_t::IONOSPHERIC_KLOBUCHAR:
118
- // check whether Klobuchar parameters alpha and beta have been already received
119
- if(space_node_gps && space_node_gps->is_valid_iono()){usable = true;}
120
- break;
121
- case options_t::IONOSPHERIC_SBAS:
122
- usable = true;
123
- break;
124
- case options_t::IONOSPHERIC_NTCM_GL:
125
- if(opt.f_10_7 >= 0){usable = true;}
126
- // check F10.7 has been already configured
127
- break;
128
- default:
129
- break;
130
- }
131
- if(usable){
132
- available_models++;
133
- }else{
134
- opt.ionospheric_models[i] = options_t::IONOSPHERIC_SKIP;
101
+ struct ionospheric_sbas_t : public range_corrector_t {
102
+ const space_node_t &space_node;
103
+ ionospheric_sbas_t(const space_node_t &sn) : range_corrector_t(), space_node(sn) {}
104
+ bool is_available(const gps_time_t &t) const {
105
+ return true;
106
+ }
107
+ float_t *calculate(
108
+ const gps_time_t &t, const pos_t &usr_pos, const enu_t &sat_rel_pos,
109
+ float_t &buf) const {
110
+
111
+ // placeholder of checking availability and performing correction
112
+ typedef typename space_node_t::available_satellites_t sats_t;
113
+ sats_t sats(space_node.available_satellites(usr_pos.llh.longitude()));
114
+
115
+ typename space_node_t::IonosphericGridPoints::PointProperty prop;
116
+ for(typename sats_t::const_iterator it(sats.begin()); it != sats.end(); ++it){
117
+ prop = it->second
118
+ ->ionospheric_grid_points().iono_correction(sat_rel_pos, usr_pos.llh);
119
+ if(prop.is_available()){
120
+ return &(buf = prop.delay);
121
+ }
122
+ break; // TODO The nearest satellite is only checked
135
123
  }
124
+ return NULL;
136
125
  }
137
- return available_models;
138
- }
126
+ } ionospheric_sbas;
127
+
128
+ struct tropospheric_sbas_t : public range_corrector_t {
129
+ tropospheric_sbas_t() : range_corrector_t() {}
130
+ bool is_available(const gps_time_t &t) const {
131
+ return true;
132
+ }
133
+ float_t *calculate(
134
+ const gps_time_t &t, const pos_t &usr_pos, const enu_t &sat_rel_pos,
135
+ float_t &buf) const {
136
+ return &(buf = space_node_t::tropo_correction(
137
+ t.year(), sat_rel_pos, usr_pos.llh));
138
+ }
139
+ } tropospheric_sbas;
140
+
141
+ range_correction_t ionospheric_correction, tropospheric_correction;
139
142
 
140
143
  options_t available_options() const {
141
144
  return options_t(base_t::available_options(), _options);
@@ -143,19 +146,24 @@ class SBAS_SinglePositioning : public SolverBaseT {
143
146
 
144
147
  options_t available_options(const options_t &opt_wish) const {
145
148
  SBAS_SinglePositioning_Options<float_t> opt(opt_wish);
146
- filter_ionospheric_models(opt);
147
149
  return options_t(base_t::available_options(opt_wish), opt);
148
150
  }
149
151
 
150
152
  options_t update_options(const options_t &opt_wish){
151
- filter_ionospheric_models(_options = opt_wish);
153
+ _options = opt_wish;
152
154
  return options_t(base_t::update_options(opt_wish), _options);
153
155
  }
154
156
 
155
- SBAS_SinglePositioning(const space_node_t &sn, const options_t &opt_wish = options_t())
156
- : base_t(),
157
- _space_node(sn), space_node_gps(NULL),
158
- _options(available_options(opt_wish)) {}
157
+ SBAS_SinglePositioning(const space_node_t &sn)
158
+ : base_t(), _space_node(sn), _options(available_options(options_t())),
159
+ ionospheric_sbas(sn), tropospheric_sbas() {
160
+
161
+ // default ionospheric correction: Broadcasted IGP.
162
+ ionospheric_correction.push_front(&ionospheric_sbas);
163
+
164
+ // default troposheric correction: SBAS
165
+ tropospheric_correction.push_front(&tropospheric_sbas);
166
+ }
159
167
 
160
168
  ~SBAS_SinglePositioning(){}
161
169
 
@@ -245,43 +253,12 @@ class SBAS_SinglePositioning : public SolverBaseT {
245
253
 
246
254
  // Tropospheric (2.1.4.10.3, A.4.2.4)
247
255
  res.range_residual += (range_error.unknown_flag & range_error_t::MASK_TROPOSPHERIC)
248
- ? _space_node.tropo_correction(time_arrival.year(), relative_pos, usr_pos.llh)
256
+ ? tropospheric_correction(time_arrival, usr_pos, relative_pos)
249
257
  : range_error.value[range_error_t::TROPOSPHERIC];
250
258
 
251
259
  // Ionospheric (2.1.4.10.2, A.4.4.10.4)
252
260
  if(range_error.unknown_flag & range_error_t::MASK_IONOSPHERIC){
253
- // Ionospheric model selection, the fall back is no correction
254
- bool iono_model_hit(false);
255
- for(std::size_t i(0); i < sizeof(_options.ionospheric_models) / sizeof(_options.ionospheric_models[0]); ++i){
256
- switch(_options.ionospheric_models[i]){
257
- case options_t::IONOSPHERIC_KLOBUCHAR: // 20.3.3.5.2.5
258
- res.range_residual += space_node_gps->iono_correction(relative_pos, usr_pos.llh, time_arrival);
259
- break;
260
- case options_t::IONOSPHERIC_SBAS: { // 2.1.4.10.2, A.4.4.10.4
261
- typename space_node_t::IonosphericGridPoints::PointProperty prop(
262
- sat->ionospheric_grid_points().iono_correction(relative_pos, usr_pos.llh));
263
- if(!prop.is_available()){continue;}
264
- res.range_residual += prop.delay;
265
- break;
266
- }
267
- case options_t::IONOSPHERIC_NTCM_GL: {
268
- // TODO f_10_7 setup, optimization (mag_model etc.)
269
- typename gps_space_node_t::pierce_point_res_t pp(gps_space_node_t::pierce_point(relative_pos, usr_pos.llh));
270
- res.range_residual -= gps_space_node_t::tec2delay(
271
- gps_space_node_t::slant_factor(relative_pos)
272
- * NTCM_GL_Generic<float_t>::tec_vert(
273
- pp.latitude, pp.longitude,
274
- time_arrival.year(), _options.f_10_7));
275
- break;
276
- }
277
- case options_t::IONOSPHERIC_NONE:
278
- break;
279
- default:
280
- continue;
281
- }
282
- iono_model_hit = true;
283
- break;
284
- }
261
+ res.range_residual += ionospheric_correction(time_arrival, usr_pos, relative_pos);
285
262
  }else{
286
263
  res.range_residual += range_error.value[range_error_t::IONOSPHERIC];
287
264
  }
@@ -60,6 +60,7 @@ struct const_div_t<denom, denom, log2, 0> {
60
60
  template <int MAX_SIZE, class ContainerT = unsigned char>
61
61
  struct BitArray {
62
62
  static const int bits_per_addr = (int)sizeof(ContainerT) * CHAR_BIT;
63
+ static const int max_size = MAX_SIZE;
63
64
  ContainerT buf[(MAX_SIZE + bits_per_addr - 1) / bits_per_addr];
64
65
  void set(const bool &new_bit = false) {
65
66
  std::memset(buf, (new_bit ? (~0) : 0), sizeof(buf));
@@ -128,14 +129,14 @@ struct BitArray {
128
129
  std::vector<int> res;
129
130
  int idx(0);
130
131
  static const const_div_t<bits_per_addr> qr(MAX_SIZE);
131
- int rem(qr.rem);
132
- for(int i(0); i < qr.quot; ++i, idx += bits_per_addr){
132
+ int rem(qr.rem), i(0);
133
+ for(; i < qr.quot; ++i, idx += bits_per_addr){
133
134
  int idx2(idx);
134
135
  for(ContainerT temp(buf[i]); temp > 0; temp >>= 1, ++idx2){
135
136
  if(temp & 0x1){res.push_back(idx2);}
136
137
  }
137
138
  }
138
- for(ContainerT temp(buf[qr.quot + 1]); (temp > 0) && (rem > 0); --rem, ++idx, temp >>= 1){
139
+ for(ContainerT temp(buf[i]); (temp > 0) && (rem > 0); --rem, ++idx, temp >>= 1){
139
140
  if(temp & 0x1){res.push_back(idx);}
140
141
  }
141
142
  return res;