gps_pvt 0.6.3 → 0.7.1

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.
@@ -0,0 +1,458 @@
1
+ /*
2
+ * Copyright (c) 2022, 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
+ /** @file
33
+ * @brief Loader of RINEX Clock extension, support versions are 3 including 3.04
34
+ */
35
+
36
+ #ifndef __RINEX_CLOCK__
37
+ #define __RINEX_CLOCK__
38
+
39
+ #include <cstring>
40
+ #include <cctype>
41
+ #include <string>
42
+
43
+ #include "RINEX.h"
44
+ #include "GPS.h"
45
+ #include "algorithm/interpolate.h"
46
+ #include "GPS_Solver_Base.h"
47
+
48
+ template <class FloatT>
49
+ struct RINEX_CLK {
50
+ struct record_t {
51
+ char type[2], name[9];
52
+ std::tm epoch;
53
+ int epoch_year4, epoch_mon12;
54
+ FloatT epoch_sec;
55
+ int items_followed;
56
+ bool valid[6];
57
+ union {
58
+ FloatT array[6];
59
+ struct {
60
+ FloatT bias, bias_sigma, rate, rate_sigma, acc, acc_sigma;
61
+ } v;
62
+ } values;
63
+
64
+ GPS_Time<FloatT> get_epoch() const {
65
+ return GPS_Time<FloatT>(epoch) + (epoch_sec - epoch.tm_sec);
66
+ }
67
+ record_t &set_epoch(const GPS_Time<FloatT> &t){
68
+ epoch = t.c_tm();
69
+ epoch_year4 = epoch.tm_year + 1900;
70
+ epoch_mon12 = epoch.tm_mon + 1;
71
+ epoch_sec = std::fmod(t.seconds, 60);
72
+ return *this;
73
+ }
74
+
75
+ std::string get_name() const {
76
+ std::string res;
77
+ for(std::size_t i(0); i < sizeof(name); ++i){
78
+ if(!std::isgraph(name[i])){break;}
79
+ res.push_back(name[i]);
80
+ }
81
+ return res;
82
+ }
83
+ record_t &set_name(const std::string &str){
84
+ std::memset(name, ' ', sizeof(name));
85
+ str.copy(name, str.size() > sizeof(name) ? sizeof(name) : str.size());
86
+ return *this;
87
+ }
88
+ };
89
+
90
+ struct per_node_t {
91
+ std::map<GPS_Time<FloatT>, FloatT> bias;
92
+ typedef InterpolatableSet<GPS_Time<FloatT>, FloatT, FloatT> interpolator_t;
93
+ static const typename interpolator_t::condition_t interpolator_cnd_default;
94
+ mutable struct {
95
+ interpolator_t bias;
96
+ } subset;
97
+ bool precheck(const GPS_Time<FloatT> &t) const {
98
+ subset.bias.update(t, bias, interpolator_cnd_default);
99
+ return subset.bias.ready;
100
+ }
101
+ FloatT clock_error(const GPS_Time<FloatT> &t) const {
102
+ return subset.bias.update(t, bias, interpolator_cnd_default).interpolate(t);
103
+ }
104
+ FloatT clock_error_dot(const GPS_Time<FloatT> &t) const {
105
+ FloatT res;
106
+ subset.bias.update(t, bias, interpolator_cnd_default).interpolate(t, &res);
107
+ return res;
108
+ }
109
+ };
110
+ struct satellites_t {
111
+ typedef std::map<int, per_node_t> buf_t; // prn => per_node_t
112
+ buf_t buf;
113
+
114
+ enum system_t {
115
+ SYSTEM_GPS,
116
+ SYSTEM_SBAS,
117
+ SYSTEM_QZSS,
118
+ SYSTEM_GLONASS,
119
+ SYSTEM_GALILEO,
120
+ SYSTEM_BEIDOU,
121
+ SYSTEM_IRNSS,
122
+ NUM_OF_SYSTEMS,
123
+ };
124
+
125
+ static const int offset_list[NUM_OF_SYSTEMS];
126
+
127
+ protected:
128
+
129
+ typedef typename GPS_Solver_Base<FloatT>::satellite_t sat_t;
130
+
131
+ mutable struct per_system_t {
132
+ struct {
133
+ const satellites_t *sats;
134
+ } clk_rate;
135
+ struct {
136
+ const void *impl;
137
+ sat_t (*impl_select)(const void *, const int &, const GPS_Time<FloatT> &);
138
+ } pos_vel;
139
+ system_t sys;
140
+ } per_system[NUM_OF_SYSTEMS];
141
+
142
+ static sat_t select(
143
+ const void *ptr, const int &prn, const GPS_Time<FloatT> &receiver_time){
144
+ const per_system_t *ptr_sys(reinterpret_cast<const per_system_t *>(ptr));
145
+
146
+ // retrieve position/velocity supplier
147
+ sat_t res(
148
+ ptr_sys->pos_vel.impl_select(ptr_sys->pos_vel.impl, prn, receiver_time));
149
+
150
+ int sat_id((prn & 0xFF) + offset_list[ptr_sys->sys]);
151
+
152
+ // check clock_error/clock_error_dot availability
153
+ typename buf_t::const_iterator it(ptr_sys->clk_rate.sats->buf.find(sat_id));
154
+ if((it == ptr_sys->clk_rate.sats->buf.end()) || !it->second.precheck(receiver_time)){
155
+ // unavailable case
156
+ static const sat_t &unavailable(sat_t::unavailable());
157
+ res.impl_t = unavailable.impl_t;
158
+ res.impl_clock_error = unavailable.impl_clock_error;
159
+ res.impl_clock_error_dot = unavailable.impl_clock_error_dot;
160
+ return res;
161
+ }
162
+
163
+ struct impl_t {
164
+ static inline const per_node_t &sat(const void *ptr) {
165
+ return *reinterpret_cast<const per_node_t *>(ptr);
166
+ }
167
+ static typename GPS_Solver_Base<FloatT>::float_t clock_error(
168
+ const void *ptr, const GPS_Time<FloatT> &t_tx) {
169
+ return sat(ptr).clock_error(t_tx);
170
+ }
171
+ static typename GPS_Solver_Base<FloatT>::float_t clock_error_dot(
172
+ const void *ptr, const GPS_Time<FloatT> &t_tx) {
173
+ return sat(ptr).clock_error_dot(t_tx);
174
+ }
175
+ };
176
+ res.impl_t = &(it->second);
177
+ res.impl_clock_error = impl_t::clock_error;
178
+ res.impl_clock_error_dot = impl_t::clock_error_dot;
179
+ return res;
180
+ }
181
+
182
+ public:
183
+
184
+ template <class SelectorT>
185
+ bool push(SelectorT &slct, const system_t &sys = SYSTEM_GPS) const {
186
+ if(sys >= NUM_OF_SYSTEMS){return false;}
187
+ per_system[sys].clk_rate.sats = this;
188
+ per_system[sys].sys = sys;
189
+ if(slct.impl_select != select){
190
+ per_system[sys].pos_vel.impl = slct.impl;
191
+ per_system[sys].pos_vel.impl_select = slct.impl_select;
192
+ }
193
+ slct.impl_select = select;
194
+ slct.impl = &per_system[sys];
195
+ return true;
196
+ }
197
+
198
+ struct count_t {
199
+ int gps, sbas, qzss, glonass, galileo, beidou, irnss, unknown;
200
+ };
201
+ count_t count() const {
202
+ count_t res = {0};
203
+ for(typename buf_t::const_iterator it(buf.begin()), it_end(buf.end());
204
+ it != it_end; ++it){
205
+ switch((char)(it->first >> 8)){
206
+ case '\0': {
207
+ int id(it->first & 0xFF);
208
+ if(id < 100){++res.gps;}
209
+ else if(id < 192){++res.sbas;}
210
+ else{++res.qzss;}
211
+ break;
212
+ }
213
+ case 'R': ++res.glonass; break;
214
+ case 'E': ++res.galileo; break;
215
+ case 'C': ++res.beidou; break;
216
+ case 'I': ++res.irnss; break;
217
+ default: ++res.unknown; break;
218
+ }
219
+ }
220
+ return res;
221
+ }
222
+ };
223
+ typedef std::map<std::string, per_node_t> collection_t; // satellites + receivers, name => per_node_t
224
+ };
225
+
226
+ template <class FloatT>
227
+ const typename RINEX_CLK<FloatT>::per_node_t::interpolator_t::condition_t
228
+ RINEX_CLK<FloatT>::per_node_t::interpolator_cnd_default = {
229
+ 5, // max_x_size
230
+ 60 * 60 * 2, // subset.cnd.max_dx_range
231
+ };
232
+
233
+ template <class FloatT>
234
+ const int RINEX_CLK<FloatT>::satellites_t::offset_list[NUM_OF_SYSTEMS] = {
235
+ 0, 0, 0, // GPS, SBAS, QZSS
236
+ (int)'R' << 8, // GLONASS
237
+ (int)'E' << 8, // GALILEO
238
+ (int)'C' << 8, // BEIDOU
239
+ (int)'I' << 8, // IRNSS,
240
+ };
241
+
242
+ template <class FloatT = double>
243
+ class RINEX_CLK_Reader : public RINEX_Reader<> {
244
+ protected:
245
+ typedef RINEX_Reader<> super_t;
246
+ public:
247
+ typedef typename RINEX_CLK<FloatT>::record_t record_t;
248
+ static const typename super_t::convert_item_t head_v3[7];
249
+ static const typename super_t::convert_item_t head_v304[7];
250
+
251
+ protected:
252
+ record_t record;
253
+
254
+ void read_header(){
255
+ if(super_t::src.fail()){return;}
256
+
257
+ char buf[256];
258
+ int label_offset(60);
259
+
260
+ // Read header
261
+ for(int line(0); !super_t::src.eof(); ++line){
262
+ super_t::src.getline(buf, sizeof(buf));
263
+
264
+ std::string content(buf);
265
+
266
+ if(line == 0){ // Check version and type extraction
267
+ switch(content.find("RINEX VERSION / TYPE")){
268
+ case 60:
269
+ super_t::version_type.parse(content);
270
+ break;
271
+ case 65: {
272
+ double temp(0);
273
+ super_t::conv_t<double>::f(content, 0, 4, &temp, 2);
274
+ super_t::version_type.version = (int)(temp * 100);
275
+ if(super_t::version_type.version != 304){return;}
276
+ if(content[21] != 'C'){return;}
277
+ super_t::version_type.file_type
278
+ = super_t::version_type_t::FTYPE_CLOCK;
279
+ super_t::version_type.sat_system
280
+ = super_t::version_type_t::char2sys_v3(content[42]);
281
+ label_offset = 65;
282
+ break;
283
+ }
284
+ default: // includes std::string::npos:
285
+ return;
286
+ }
287
+ }
288
+
289
+ std::string label(content, label_offset, 20);
290
+ {
291
+ int real_length(label.find_last_not_of(' ') + 1);
292
+ if(real_length < (int)label.length()){
293
+ label = label.substr(0, real_length);
294
+ }
295
+ }
296
+
297
+ if(label.find("END OF HEADER") == 0){break;}
298
+
299
+ _header[label].push_back(content.substr(0, label_offset));
300
+ }
301
+ }
302
+
303
+ public:
304
+ void seek_next() {
305
+ super_t::_has_next = false;
306
+
307
+ char buf[1024];
308
+ std::string str;
309
+ bool v304(super_t::version_type.version == 304);
310
+ while(true){
311
+ if(super_t::src.getline(buf, sizeof(buf)).fail()){return;}
312
+ str.assign(buf);
313
+ if(str.size() < (v304 ? 45 : 37)){continue;}
314
+ str.copy(record.type, 2);
315
+ if((std::memcmp(record.type, "AR", 2) == 0)
316
+ || (std::memcmp(record.type, "AS", 2) == 0)
317
+ || (std::memcmp(record.type, "CR", 2) == 0)
318
+ || (std::memcmp(record.type, "DR", 2) == 0)
319
+ || (std::memcmp(record.type, "MS", 2) == 0)){
320
+ break;
321
+ }
322
+ }
323
+ std::memset(record.name, ' ', sizeof(record.name));
324
+ str.copy(record.name, v304 ? 9 : 4, 3);
325
+ v304 ? super_t::convert(head_v304, str, &record) : super_t::convert(head_v3, str, &record);
326
+ record.epoch.tm_year = record.epoch_year4 - 1900; // greater than 1980
327
+ record.epoch.tm_mon = record.epoch_mon12 - 1; // month [0, 11]
328
+ record.epoch.tm_sec = (int)record.epoch_sec;
329
+
330
+ for(int i(0), j(2), k(v304 ? 45 : 40); i < 6; ++i, ++j, k += (v304 ? 21 : 20)){
331
+ record.valid[i] = false;
332
+ if(i >= record.items_followed){continue;}
333
+ if(j % 4 == 0){
334
+ j = 0; k = 3;
335
+ if(super_t::src.getline(buf, sizeof(buf)).fail()){break;}
336
+ str.assign(buf);
337
+ }
338
+ if(!super_t::template conv_t<FloatT>::e_dot_head(
339
+ str, k, 19, &record.values.array[i], 12)){break;}
340
+ record.valid[i] = true;
341
+ }
342
+
343
+ super_t::_has_next = true;
344
+ }
345
+
346
+ RINEX_CLK_Reader(std::istream &in)
347
+ : super_t(in, static_cast<void(super_t::*)()>(
348
+ &RINEX_CLK_Reader::read_header)) {
349
+ seek_next();
350
+ }
351
+ ~RINEX_CLK_Reader(){}
352
+
353
+ void next() {
354
+ seek_next();
355
+ }
356
+
357
+ protected:
358
+ static int read_all(
359
+ std::istream &in,
360
+ void *buf, bool (*callback)(void *, const record_t &)){
361
+ RINEX_CLK_Reader reader(in);
362
+ if(reader.version_type.file_type != version_type_t::FTYPE_CLOCK){
363
+ return -1;
364
+ }
365
+ int res(0);
366
+ for(; reader.has_next(); reader.next()){
367
+ if(!reader.record.valid[0]){continue;}
368
+ if(!callback(buf, reader.record)){continue;}
369
+ ++res;
370
+ }
371
+ return res;
372
+ }
373
+
374
+ public:
375
+ static int read_all(
376
+ std::istream &in,
377
+ typename RINEX_CLK<FloatT>::satellites_t &dst){
378
+ struct func_t {
379
+ static bool add(void *ptr, const record_t &record){
380
+ typename RINEX_CLK<FloatT>::satellites_t &dst(
381
+ *reinterpret_cast<typename RINEX_CLK<FloatT>::satellites_t *>(ptr));
382
+ if((record.type[0] != 'A') || (record.type[1] != 'S')){return false;}
383
+ int offset(0);
384
+ char sys(record.name[0]);
385
+ switch(sys){
386
+ case 'G': break; // GPS
387
+ case 'R': offset = (int)'R' << 8; break; // GLONASS
388
+ case 'E': offset = (int)'E' << 8; break; // Galileo
389
+ case 'C': offset = (int)'C' << 8; break; // BeiDou
390
+ case 'J': offset = 192; break; // QZSS
391
+ case 'S': offset = 100; break; // SBAS
392
+ case 'I': offset = (int)'I' << 8; break; // IRNSS
393
+ default: return false;
394
+ }
395
+ if(record.name[1] < '0' || record.name[1] > '9'
396
+ || record.name[2] < '0' || record.name[2] > '9'){return false;}
397
+ int idx((record.name[1] - '0') * 10 + (record.name[2] - '0') + offset);
398
+ dst.buf[idx].bias[record.get_epoch()] = record.values.v.bias;
399
+ return true;
400
+ }
401
+ };
402
+ return read_all(in, &dst, func_t::add);
403
+ }
404
+
405
+ static int read_all(
406
+ std::istream &in,
407
+ typename RINEX_CLK<FloatT>::collection_t &dst){
408
+ struct func_t {
409
+ static bool add(void *ptr, const record_t &record){
410
+ typename RINEX_CLK<FloatT>::collection_t &dst(
411
+ *reinterpret_cast<typename RINEX_CLK<FloatT>::collection_t *>(ptr));
412
+ dst[record.get_name()].bias[record.get_epoch()] = record.values.v.bias;
413
+ return true;
414
+ }
415
+ };
416
+ return read_all(in, &dst, func_t::add);
417
+ }
418
+ };
419
+
420
+ #define GEN_D(offset, length, container_type, container_member, value_type) \
421
+ {super_t::template conv_t<value_type>::d, offset, length, \
422
+ offsetof(container_type, container_member)}
423
+ #define GEN_I(offset, length, container_type, container_member, value_type) \
424
+ {super_t::template conv_t<value_type>::d, offset, length, \
425
+ offsetof(container_type, container_member), 1}
426
+ #define GEN_F2(offset, length, precision, container_type, container_member, value_type) \
427
+ {super_t::template conv_t<value_type>::f_dot_head, offset, length, \
428
+ offsetof(container_type, container_member), precision}
429
+ #define GEN_F(offset, length, precision, container_type, container_member) \
430
+ GEN_F2(offset, length, precision, container_type, container_member, FloatT)
431
+
432
+ template <class FloatT>
433
+ const typename RINEX_CLK_Reader<FloatT>::convert_item_t RINEX_CLK_Reader<FloatT>::head_v3[] = {
434
+ GEN_I( 8, 4, record_t, epoch_year4, int),
435
+ GEN_I(13, 2, record_t, epoch_mon12, int),
436
+ GEN_I(16, 2, record_t, epoch.tm_mday, int),
437
+ GEN_I(19, 2, record_t, epoch.tm_hour, int),
438
+ GEN_I(22, 2, record_t, epoch.tm_min, int),
439
+ GEN_F(24, 10, 6, record_t, epoch_sec),
440
+ GEN_D(34, 3, record_t, items_followed, int),
441
+ };
442
+
443
+ template <class FloatT>
444
+ const typename RINEX_CLK_Reader<FloatT>::convert_item_t RINEX_CLK_Reader<FloatT>::head_v304[] = {
445
+ GEN_I(13, 4, record_t, epoch_year4, int),
446
+ GEN_I(18, 2, record_t, epoch_mon12, int),
447
+ GEN_I(21, 2, record_t, epoch.tm_mday, int),
448
+ GEN_I(24, 2, record_t, epoch.tm_hour, int),
449
+ GEN_I(27, 2, record_t, epoch.tm_min, int),
450
+ GEN_F(29, 9, 6, record_t, epoch_sec),
451
+ GEN_D(40, 2, record_t, items_followed, int),
452
+ };
453
+
454
+ #undef GEN_D
455
+ #undef GEN_I
456
+ #undef GEN_F
457
+
458
+ #endif /* __RINEX_CLOCK__ */
@@ -1387,16 +1387,16 @@ sf[SF_ ## TARGET] * msg_t::TARGET(buf)
1387
1387
 
1388
1388
  // the first line
1389
1389
  out << " ";
1390
- for(int j(0); j < sizeof(igp.properties[0]) / sizeof(igp.properties[0][0]); ++j){
1390
+ for(std::size_t j(0); j < sizeof(igp.properties[0]) / sizeof(igp.properties[0][0]); ++j){
1391
1391
  int lng(position_index_t::idx2lng(j));
1392
1392
  out << (lng == 0 ? '0' : (lng % 90 == 0 ? '|' : (lng % 30 == 0 ? '+' : ' ')));
1393
1393
  }
1394
1394
  out << std::endl;
1395
1395
 
1396
- for(int i(0); i < sizeof(igp.properties) / sizeof(igp.properties[0]); ++i){
1396
+ for(std::size_t i(0); i < sizeof(igp.properties) / sizeof(igp.properties[0]); ++i){
1397
1397
  out.width(4);
1398
1398
  out << position_index_t::idx2lat(i) << ' ';
1399
- for(int j(0); j < sizeof(igp.properties[0]) / sizeof(igp.properties[0][0]); ++j){
1399
+ for(std::size_t j(0); j < sizeof(igp.properties[0]) / sizeof(igp.properties[0][0]); ++j){
1400
1400
  if(!igp.properties[i][j].is_available()){
1401
1401
  out << ' ';
1402
1402
  }else{
@@ -128,7 +128,7 @@ class SBAS_SinglePositioning : public SolverBaseT {
128
128
  }
129
129
  };
130
130
  satellite_t res = {
131
- &(it_sat->second),
131
+ &(it_sat->second), &(it_sat->second),
132
132
  impl_t::position, impl_t::velocity,
133
133
  impl_t::clock_error, impl_t::clock_error_dot};
134
134
  return res;
@@ -185,7 +185,7 @@ struct SP3_Product {
185
185
  }
186
186
  };
187
187
  typename GPS_Solver_Base<FloatT>::satellite_t res = {
188
- this,
188
+ this, this,
189
189
  impl_t::position, impl_t::velocity,
190
190
  impl_t::clock_error, impl_t::clock_error_dot
191
191
  };
@@ -248,29 +248,33 @@ struct SP3_Product {
248
248
  }
249
249
 
250
250
  enum system_t {
251
- SYSTEM_GPS = (int)'\0' << 8,
252
- SYSTEM_SBAS = SYSTEM_GPS,
253
- SYSTEM_QZSS = SYSTEM_GPS,
254
- SYSTEM_GLONASS = (int)'R' << 8,
255
- SYSTEM_LEO = (int)'L' << 8,
256
- SYSTEM_GALILEO = (int)'E' << 8,
257
- SYSTEM_BEIDOU = (int)'C' << 8,
258
- SYSTEM_IRNSS = (int)'I' << 8,
251
+ SYSTEM_GPS,
252
+ SYSTEM_SBAS,
253
+ SYSTEM_QZSS,
254
+ SYSTEM_GLONASS,
255
+ SYSTEM_LEO,
256
+ SYSTEM_GALILEO,
257
+ SYSTEM_BEIDOU,
258
+ SYSTEM_IRNSS,
259
+ NUM_OF_SYSTEMS,
259
260
  };
260
261
 
261
- #define gen_func(sys) \
262
- static typename GPS_Solver_Base<FloatT>::satellite_t select_ ## sys( \
263
- const void *ptr, const int &prn, const GPS_Time<FloatT> &receiver_time){ \
264
- return reinterpret_cast<const SP3_Product<FloatT> *>(ptr) \
265
- ->select(prn + SYSTEM_ ## sys, receiver_time); \
266
- }
267
- gen_func(GPS);
268
- gen_func(GLONASS);
269
- gen_func(LEO);
270
- gen_func(GALILEO);
271
- gen_func(BEIDOU);
272
- gen_func(IRNSS);
273
- #undef gen_fun
262
+ static const int offset_list[NUM_OF_SYSTEMS];
263
+
264
+ protected:
265
+
266
+ mutable struct per_system_t {
267
+ const SP3_Product<FloatT> *product;
268
+ system_t sys;
269
+ } per_system[NUM_OF_SYSTEMS];
270
+
271
+ static typename GPS_Solver_Base<FloatT>::satellite_t select(
272
+ const void *ptr, const int &prn, const GPS_Time<FloatT> &receiver_time){
273
+ const per_system_t *ptr_impl(reinterpret_cast<const per_system_t *>(ptr));
274
+ return ptr_impl->product->select((prn & 0xFF) + offset_list[ptr_impl->sys], receiver_time);
275
+ }
276
+
277
+ public:
274
278
 
275
279
  /**
276
280
  * push SP3 product to satellite selector
@@ -281,19 +285,11 @@ static typename GPS_Solver_Base<FloatT>::satellite_t select_ ## sys( \
281
285
  */
282
286
  template <class SelectorT>
283
287
  bool push(SelectorT &slct, const system_t &sys = SYSTEM_GPS) const {
284
- switch(sys){
285
- case SYSTEM_GPS: // SBAS and QZSS are identically treated as GPS.
286
- //case SYSTEM_SBAS:
287
- //case SYSTEM_QZSS:
288
- slct.impl_select = select_GPS; break;
289
- case SYSTEM_GLONASS: slct.impl_select = select_GLONASS; break;
290
- case SYSTEM_LEO: slct.impl_select = select_LEO; break;
291
- case SYSTEM_GALILEO: slct.impl_select = select_GALILEO; break;
292
- case SYSTEM_BEIDOU: slct.impl_select = select_BEIDOU; break;
293
- case SYSTEM_IRNSS: slct.impl_select = select_IRNSS; break;
294
- default: return false;
295
- }
296
- slct.impl = this;
288
+ if(sys >= NUM_OF_SYSTEMS){return false;}
289
+ per_system[sys].product = this;
290
+ per_system[sys].sys = sys;
291
+ slct.impl_select = select;
292
+ slct.impl = &per_system[sys];
297
293
  return true;
298
294
  }
299
295
 
@@ -305,19 +301,19 @@ static typename GPS_Solver_Base<FloatT>::satellite_t select_ ## sys( \
305
301
  for(typename satellites_t::const_iterator
306
302
  it(satellites.begin()), it_end(satellites.end());
307
303
  it != it_end; ++it){
308
- switch(it->first & 0xFF00){
309
- case SYSTEM_GPS: {
304
+ switch((char)(it->first >> 8)){
305
+ case '\0': {
310
306
  int id(it->first & 0xFF);
311
307
  if(id < 100){++res.gps;}
312
308
  else if(id < 192){++res.sbas;}
313
309
  else{++res.qzss;}
314
310
  break;
315
311
  }
316
- case SYSTEM_GLONASS: ++res.glonass; break;
317
- case SYSTEM_LEO: ++res.leo; break;
318
- case SYSTEM_GALILEO: ++res.galileo; break;
319
- case SYSTEM_BEIDOU: ++res.beidou; break;
320
- case SYSTEM_IRNSS: ++res.irnss; break;
312
+ case 'R': ++res.glonass; break;
313
+ case 'L': ++res.leo; break;
314
+ case 'E': ++res.galileo; break;
315
+ case 'C': ++res.beidou; break;
316
+ case 'I': ++res.irnss; break;
321
317
  default: ++res.unknown; break;
322
318
  }
323
319
  }
@@ -335,6 +331,17 @@ const typename SP3_Product<FloatT>::per_satellite_t::interpolate_cnd_t
335
331
  60 * 60 * 2,
336
332
  };
337
333
 
334
+ template <class FloatT>
335
+ const int SP3_Product<FloatT>::offset_list[NUM_OF_SYSTEMS] = {
336
+ 0, 0, 0, // GPS, SBAS, QZSS
337
+ ((int)'R' << 8), // GLONASS
338
+ ((int)'L' << 8), // LEO
339
+ ((int)'E' << 8), // GALILEO
340
+ ((int)'C' << 8), // BEIDOU
341
+ ((int)'I' << 8), // IRNSS
342
+ };
343
+
344
+
338
345
  template <class FloatT>
339
346
  class SP3_Reader {
340
347
  protected:
@@ -125,9 +125,9 @@ struct BitArray {
125
125
  return (unsigned int)res;
126
126
  }
127
127
  }
128
- std::vector<int> indices_one() const {
128
+ std::vector<int> indices_one(const int &offset = 0) const {
129
129
  std::vector<int> res;
130
- int idx(0);
130
+ int idx(offset);
131
131
  static const const_div_t<bits_per_addr> qr(MAX_SIZE);
132
132
  int rem(qr.rem), i(0);
133
133
  for(; i < qr.quot; ++i, idx += bits_per_addr){
@@ -130,7 +130,7 @@ class QuaternionData : public QuaternionDataProperty<FloatT> {
130
130
  * @param q �R�s�[��
131
131
  */
132
132
  QuaternionData(const self_t &q){
133
- if(storage = q.storage){(storage->ref)++;}
133
+ if((storage = q.storage)){(storage->ref)++;}
134
134
  }
135
135
 
136
136
  /**
@@ -143,7 +143,7 @@ class QuaternionData : public QuaternionDataProperty<FloatT> {
143
143
  self_t &operator=(const self_t &q){
144
144
  if(this == &q){return *this;}
145
145
  if(storage && ((--(storage->ref)) <= 0)){delete storage;}
146
- if(storage = q.storage){(storage->ref)++;}
146
+ if((storage = q.storage)){(storage->ref)++;}
147
147
  return *this;
148
148
  }
149
149
 
@@ -133,7 +133,7 @@ class Vector3Data : public Vector3DataProperty<FloatT> {
133
133
  * @param v �R�s�[��
134
134
  */
135
135
  Vector3Data(const self_t &v){
136
- if(storage = v.storage){(storage->ref)++;}
136
+ if((storage = v.storage)){(storage->ref)++;}
137
137
  }
138
138
 
139
139
  /**
@@ -146,7 +146,7 @@ class Vector3Data : public Vector3DataProperty<FloatT> {
146
146
  self_t &operator=(const self_t &v){
147
147
  if(this == &v){return *this;}
148
148
  if(storage && ((--(storage->ref)) <= 0)){delete storage;}
149
- if(storage = v.storage){(storage->ref)++;}
149
+ if((storage = v.storage)){(storage->ref)++;}
150
150
  return *this;
151
151
  }
152
152