gps_pvt 0.6.4 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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:
@@ -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