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.
- checksums.yaml +4 -4
- data/README.md +33 -6
- data/Rakefile +0 -0
- data/exe/gps_pvt +28 -19
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +596 -467
- data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +277 -14
- data/ext/ninja-scan-light/tool/navigation/GPS.h +8 -43
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +61 -147
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +83 -22
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +15 -5
- data/ext/ninja-scan-light/tool/navigation/SBAS.h +2 -2
- data/ext/ninja-scan-light/tool/navigation/SBAS_Solver.h +55 -78
- data/ext/ninja-scan-light/tool/param/bit_array.h +4 -3
- data/ext/ninja-scan-light/tool/swig/GPS.i +342 -103
- data/ext/ninja-scan-light/tool/swig/SylphideMath.i +53 -6
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +42 -6
- data/ext/ninja-scan-light/tool/swig/spec/SylphideMath_spec.rb +38 -4
- data/gps_pvt.gemspec +63 -0
- data/lib/gps_pvt/receiver.rb +86 -41
- data/lib/gps_pvt/version.rb +1 -1
- metadata +7 -6
@@ -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
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
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
|
-
|
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
|
-
|
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
|
156
|
-
: base_t(),
|
157
|
-
|
158
|
-
|
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
|
-
?
|
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
|
-
|
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(
|
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[
|
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;
|