gps_pvt 0.6.2 → 0.6.3
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.
- checksums.yaml +4 -4
- data/exe/to_ubx +213 -0
- data/ext/ninja-scan-light/tool/algorithm/interpolate.h +106 -0
- data/ext/ninja-scan-light/tool/navigation/SP3.h +20 -70
- data/gps_pvt.gemspec +3 -0
- data/lib/gps_pvt/receiver.rb +3 -3
- data/lib/gps_pvt/version.rb +5 -5
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9ab8f442240a2b92bfcb975ec6cb72000ec7d257bf7d5f41e0765905b9fa020
|
4
|
+
data.tar.gz: 52ed9e2141f4e0bc111da34be34b28414557fd02f003c3fbff84db571135ad1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63cc7efd29e6e576c15380bd43550b427015f57d99a545b3373ef829d496e87df799feed2b6499c2bf336619a81bb193ddd1c350990cc85ee7c52a7aadf0d264
|
7
|
+
data.tar.gz: 7911e374e8d1f33f283be0fd7a59262bd1bd2d0315d631456e37659b4729812c260f3f65495bb6de851e8ac7246f148d47129080717aeccc715cc1138e17e158
|
data/exe/to_ubx
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'gps_pvt'
|
4
|
+
require 'uri'
|
5
|
+
require 'gps_pvt/ubx'
|
6
|
+
|
7
|
+
# Convert file(s) to ubx format
|
8
|
+
# TODO currently only RINEX observation file is supported.
|
9
|
+
|
10
|
+
$stderr.puts <<__STRING__
|
11
|
+
Usage: #{__FILE__} GPS_file ... > as_you_like.ubx
|
12
|
+
As GPS_file, only rinex_obs(*.YYo) is currently supported.
|
13
|
+
(YY = last two digit of year)
|
14
|
+
File format is automatically determined based on its extention described in above parentheses.
|
15
|
+
If you want to specify its format manually, command options like --rinex_obs=file_name are available.
|
16
|
+
Supported RINEX versions are 2 and 3.
|
17
|
+
RXM-RAWX and RXM-SFRBX are included in output UBX if corresponding file(s) is given.
|
18
|
+
A file having additional ".gz" or ".Z" extension is recognized as a compressed file.
|
19
|
+
Major URL such as http(s)://... or ftp://... is acceptable as an input file name.
|
20
|
+
__STRING__
|
21
|
+
|
22
|
+
options = []
|
23
|
+
misc_options = {
|
24
|
+
:ubx_rawx => false
|
25
|
+
}
|
26
|
+
|
27
|
+
# check options and file format
|
28
|
+
files = ARGV.collect{|arg|
|
29
|
+
next [arg, nil] unless arg =~ /^--([^=]+)=?/
|
30
|
+
k, v = [$1.downcase.to_sym, $']
|
31
|
+
next [v, k] if [:rinex_nav, :rinex_obs].include?(k) # file type
|
32
|
+
options << [$1.to_sym, $']
|
33
|
+
nil
|
34
|
+
}.compact
|
35
|
+
|
36
|
+
# Check file existence and extension
|
37
|
+
files.collect!{|fname, ftype|
|
38
|
+
ftype ||= case fname
|
39
|
+
when /\.\d{2}[nhqg](?:\.gz)?$/; :rinex_nav
|
40
|
+
when /\.\d{2}o(?:\.gz)?$/; :rinex_obs
|
41
|
+
else
|
42
|
+
raise "Format cannot be guessed, use --(format, ex. rinex_obs)=#{fname}"
|
43
|
+
end
|
44
|
+
fname = proc{
|
45
|
+
next fname if File::exist?(fname)
|
46
|
+
if uri = URI::parse(fname) and !uri.instance_of?(URI::Generic) then
|
47
|
+
next uri
|
48
|
+
end
|
49
|
+
raise "File not found: #{fname}"
|
50
|
+
}.call
|
51
|
+
[fname, ftype]
|
52
|
+
}
|
53
|
+
|
54
|
+
options.reject!{|opt|
|
55
|
+
case opt[0]
|
56
|
+
when :ubx_rawx
|
57
|
+
misc_options[opt[0]] = opt[1]
|
58
|
+
true
|
59
|
+
else
|
60
|
+
false
|
61
|
+
end
|
62
|
+
}
|
63
|
+
|
64
|
+
rcv = GPS_PVT::Receiver::new(options)
|
65
|
+
|
66
|
+
obs = []
|
67
|
+
rcv.define_singleton_method(:run){|meas, t_meas, *args|
|
68
|
+
obs << [t_meas, meas]
|
69
|
+
}
|
70
|
+
|
71
|
+
# parse RINEX NAV
|
72
|
+
files.each{|fname, ftype|
|
73
|
+
case ftype
|
74
|
+
when :rinex_nav; rcv.parse_rinex_nav(fname)
|
75
|
+
end
|
76
|
+
}
|
77
|
+
|
78
|
+
# other files
|
79
|
+
files.each{|fname, ftype|
|
80
|
+
case ftype
|
81
|
+
when :rinex_obs; rcv.parse_rinex_obs(fname){}
|
82
|
+
end
|
83
|
+
}
|
84
|
+
|
85
|
+
obs.sort!{|a, b| a[0] <=> b[0]} # Sort by measurement time
|
86
|
+
|
87
|
+
glonass_freq_ch = proc{
|
88
|
+
freq0, delta = [:L1_frequency_base, :L1_frequency_gap].collect{|k|
|
89
|
+
GPS_PVT::GPS::SpaceNode_GLONASS.send(k)
|
90
|
+
}
|
91
|
+
proc{|freq| ((freq - freq0) / delta).to_i}
|
92
|
+
}.call
|
93
|
+
|
94
|
+
gen_raw = proc{|t_meas, meas| # Convert to RXM-RAW(0x10)
|
95
|
+
meas = meas.to_hash
|
96
|
+
ubx = [0xB5, 0x62, 0x02, 0x10, 0, 0]
|
97
|
+
ubx += [(t_meas.seconds * 1E3).to_i, t_meas.week].pack("Vv").unpack("C*")
|
98
|
+
ubx += [0] * 2
|
99
|
+
meas_ubx = meas.collect{|sat, items|
|
100
|
+
res = [0] * 24
|
101
|
+
setter = proc{|value, offset, len, str, pre_proc|
|
102
|
+
array = case value
|
103
|
+
when Array; value
|
104
|
+
when Symbol
|
105
|
+
[items[GPS_PVT::GPS::Measurement.const_get(value)]]
|
106
|
+
else
|
107
|
+
next nil
|
108
|
+
end
|
109
|
+
pre_proc.call(array) if pre_proc
|
110
|
+
next if array.empty?
|
111
|
+
array = array.pack(str).unpack("C*") if str
|
112
|
+
res[offset - 8, len] = array
|
113
|
+
}
|
114
|
+
svid = case sat
|
115
|
+
when 1..32, 120..158, 193..202 # GPS, SBAS, QZSS
|
116
|
+
sat
|
117
|
+
when (0x100 + 1)..(0x100 + 32) # GLONASS
|
118
|
+
sat - 0x100 + 64 # => 65..96
|
119
|
+
else
|
120
|
+
next nil # TODO Galileo, Beidou, ...
|
121
|
+
end
|
122
|
+
|
123
|
+
qi = 6
|
124
|
+
setter.call(:L1_CARRIER_PHASE,
|
125
|
+
8, 8, "E", proc{|v| next if v[0]; qi = 4; v.clear})
|
126
|
+
setter.call(:L1_PSEUDORANGE,
|
127
|
+
16, 8, "E", proc{|v| next if v[0]; qi = 0; v.clear})
|
128
|
+
setter.call(:L1_DOPPLER,
|
129
|
+
24, 4, "e", proc{|v| next if v[0]; qi = 0; v.clear})
|
130
|
+
setter.call([svid, qi], 28, 2)
|
131
|
+
setter.call(:L1_SIGNAL_STRENGTH_dBHz,
|
132
|
+
30, 1, nil, proc{|v| v.replace(v[0] ? [v[0].to_i] : [])})
|
133
|
+
setter.call(:L1_LOCK_SEC,
|
134
|
+
31, 1, nil, proc{|v| v.replace(v[0] ? [(v[0] < 0) ? 1 : 0] : [0])})
|
135
|
+
|
136
|
+
res
|
137
|
+
}.compact
|
138
|
+
ubx[6 + 6] = meas_ubx.size
|
139
|
+
ubx += meas_ubx.flatten(1)
|
140
|
+
ubx += [0, 0]
|
141
|
+
GPS_PVT::UBX::update(ubx).pack("C*")
|
142
|
+
}
|
143
|
+
|
144
|
+
gen_rawx = proc{|t_meas, meas| # Convert to RXM-RAWX(0x15)
|
145
|
+
meas = meas.to_hash
|
146
|
+
ubx = [0xB5, 0x62, 0x02, 0x15, 0, 0]
|
147
|
+
ubx += [t_meas.seconds, t_meas.week].pack("Ev").unpack("C*")
|
148
|
+
ubx += [0] * 6
|
149
|
+
meas_ubx = meas.collect{|sat, items|
|
150
|
+
res = [0] * 32
|
151
|
+
setter = proc{|value, offset, len, str, pre_proc|
|
152
|
+
array = case value
|
153
|
+
when Array; value
|
154
|
+
when Symbol
|
155
|
+
[items[GPS_PVT::GPS::Measurement.const_get(value)]]
|
156
|
+
else
|
157
|
+
next nil
|
158
|
+
end
|
159
|
+
pre_proc.call(array) if pre_proc
|
160
|
+
next if array.empty?
|
161
|
+
array = array.pack(str).unpack("C*") if str
|
162
|
+
res[offset - 16, len] = array
|
163
|
+
}
|
164
|
+
sys, svid = case sat
|
165
|
+
when 1..32 # GPS
|
166
|
+
[0, sat]
|
167
|
+
when 120..158 # SBAS
|
168
|
+
[1, sat]
|
169
|
+
when 193..202 # QZSS
|
170
|
+
[5, sat]
|
171
|
+
when (0x100 + 1)..(0x100 + 32) # GLONASS
|
172
|
+
setter.call(:L1_FREQUENCY,
|
173
|
+
39, 1, nil, proc{|v| v.replace(v[0] ? glonass_freq_ch.call(v[0]) : [7])})
|
174
|
+
[6, sat - 0x100]
|
175
|
+
else
|
176
|
+
next nil # TODO Galileo, Beidou, ...
|
177
|
+
end
|
178
|
+
setter.call([sys, svid], 36, 2)
|
179
|
+
|
180
|
+
trk_stat = 0
|
181
|
+
setter.call(:L1_PSEUDORANGE,
|
182
|
+
16, 8, "E", proc{|v| v[0] ? (trk_stat |= 0x1) : v.clear})
|
183
|
+
setter.call(:L1_PSEUDORANGE_SIGMA,
|
184
|
+
43, 1, nil, proc{|v|
|
185
|
+
b = (Math::log2(v[0] / 1E-2).to_i & 0xF) rescue 0x8
|
186
|
+
v.replace((trk_stat & 0x1 == 0x1) ? [b] : [])
|
187
|
+
})
|
188
|
+
setter.call(:L1_DOPPLER, 32, 4, "e")
|
189
|
+
setter.call(:L1_DOPPLER_SIGMA,
|
190
|
+
45, 1, nil, proc{|v| v.replace(v[0] ? [Math::log2(v[0] / 2E-3).to_i & 0xF] : [0x8])})
|
191
|
+
setter.call(:L1_CARRIER_PHASE,
|
192
|
+
24, 8, "E", proc{|v| v[0] ? (trk_stat |= 0x2) : v.clear})
|
193
|
+
setter.call(:L1_CARRIER_PHASE_SIGMA,
|
194
|
+
44, 1, nil, proc{|v|
|
195
|
+
b = ((v[0] / 0.004).to_i & 0xF) rescue 0x8
|
196
|
+
v.replace((trk_stat & 0x2 == 0x2) ? [b] : [])
|
197
|
+
})
|
198
|
+
setter.call(:L1_SIGNAL_STRENGTH_dBHz,
|
199
|
+
42, 1, nil, proc{|v| v.replace(v[0] ? [v[0].to_i] : [])})
|
200
|
+
setter.call(:L1_LOCK_SEC,
|
201
|
+
40, 2, "v", proc{|v| v.replace(v[0] ? [(v[0] / 1E-3).to_i] : [])})
|
202
|
+
setter.call([trk_stat], 46, 1)
|
203
|
+
|
204
|
+
res
|
205
|
+
}.compact
|
206
|
+
ubx[6 + 11] = meas_ubx.size
|
207
|
+
ubx += meas_ubx.flatten(1)
|
208
|
+
ubx += [0, 0]
|
209
|
+
GPS_PVT::UBX::update(ubx).pack("C*")
|
210
|
+
}
|
211
|
+
|
212
|
+
gen = misc_options[:ubx_rawx] ? gen_rawx : gen_raw
|
213
|
+
obs.each{|*item| print gen.call(*item)}
|
@@ -34,6 +34,9 @@
|
|
34
34
|
|
35
35
|
#include <cstddef>
|
36
36
|
#include <vector>
|
37
|
+
#include <map>
|
38
|
+
#include <algorithm>
|
39
|
+
#include <stdexcept>
|
37
40
|
|
38
41
|
/*
|
39
42
|
* perform Neville's interpolation (with derivative)
|
@@ -118,4 +121,107 @@ Ty interpolate_Neville(
|
|
118
121
|
return interpolate_Neville(x_given, y_given, x, y_buf, n)[0];
|
119
122
|
}
|
120
123
|
|
124
|
+
template <class Tx, class Ty, class Tx_delta = Tx>
|
125
|
+
struct InterpolatableSet {
|
126
|
+
struct condition_t {
|
127
|
+
std::size_t max_x_size; ///< maximum number of data used for interpolation
|
128
|
+
Tx_delta max_dx_range; ///< maximum acceptable absolute difference between x and x0
|
129
|
+
};
|
130
|
+
|
131
|
+
typedef typename std::vector<std::pair<Tx, Ty> > buffer_t;
|
132
|
+
buffer_t buf;
|
133
|
+
Tx x0, x_lower, x_upper;
|
134
|
+
std::vector<Tx_delta> dx;
|
135
|
+
bool ready;
|
136
|
+
|
137
|
+
InterpolatableSet() : x0(), dx(), ready(false) {}
|
138
|
+
|
139
|
+
/**
|
140
|
+
* update interpolation source
|
141
|
+
* @param force_update If true, update is forcibly performed irrespective of current state
|
142
|
+
* @param cnd condition for source data selection
|
143
|
+
*/
|
144
|
+
InterpolatableSet &update(
|
145
|
+
const Tx &x, const std::map<Tx, Ty> &xy_table,
|
146
|
+
const condition_t &cnd,
|
147
|
+
const bool &force_update = false){
|
148
|
+
|
149
|
+
do{
|
150
|
+
if(force_update){break;}
|
151
|
+
if(dx.size() <= 2){break;}
|
152
|
+
if(x < x_lower){break;}
|
153
|
+
if(x > x_upper){break;}
|
154
|
+
return *this;
|
155
|
+
}while(false);
|
156
|
+
|
157
|
+
// If the 1st and 2nd nearest items are changed, then recalculate interpolation targets.
|
158
|
+
struct {
|
159
|
+
const Tx &x_base;
|
160
|
+
bool operator()(
|
161
|
+
const typename std::map<Tx, Ty>::value_type &rhs,
|
162
|
+
const typename std::map<Tx, Ty>::value_type &lhs) const {
|
163
|
+
return std::abs(rhs.first - x_base) < std::abs(lhs.first - x_base);
|
164
|
+
}
|
165
|
+
} cmp = {(x0 = x)};
|
166
|
+
|
167
|
+
buf.resize(cnd.max_x_size);
|
168
|
+
dx.clear();
|
169
|
+
// extract x where x0-dx_range <= x <= x0+dx_range, then sort by ascending order of |x-x0|
|
170
|
+
for(typename buffer_t::const_iterator
|
171
|
+
it(buf.begin()),
|
172
|
+
it_end(std::partial_sort_copy(
|
173
|
+
xy_table.lower_bound(x - cnd.max_dx_range),
|
174
|
+
xy_table.upper_bound(x + cnd.max_dx_range),
|
175
|
+
buf.begin(), buf.end(), cmp));
|
176
|
+
it != it_end; ++it){
|
177
|
+
dx.push_back(it->first - x0);
|
178
|
+
}
|
179
|
+
if(dx.size() >= 2){ // calculate a necessary condition to update samples for new x
|
180
|
+
// According to Nth nearest points, x range in which the order of extracted samples
|
181
|
+
// is retained can be calculated.
|
182
|
+
bool ascending(buf[0].first <= buf[1].first);
|
183
|
+
Tx &xa(ascending ? x_lower : x_upper), &xb(ascending ? x_upper : x_lower);
|
184
|
+
xa = x0;
|
185
|
+
for(std::size_t i(2); i < buf.size(); ++i){
|
186
|
+
if(ascending ? (dx[1] <= dx[i]) : (dx[1] >= dx[i])){continue;}
|
187
|
+
xa = x0 + (dx[1] + dx[i]) / 2;
|
188
|
+
break;
|
189
|
+
}
|
190
|
+
xb = x0 + (dx[0] + dx[1]) / 2;
|
191
|
+
}
|
192
|
+
ready = (dx.size() >= cnd.max_x_size);
|
193
|
+
|
194
|
+
return *this;
|
195
|
+
}
|
196
|
+
|
197
|
+
template <class Ty2, class Ty2_Iterator>
|
198
|
+
Ty2 interpolate2(
|
199
|
+
const Tx &x, const Ty2_Iterator &y,
|
200
|
+
Ty2 *derivative = NULL) const {
|
201
|
+
int order(dx.size() - 1);
|
202
|
+
do{
|
203
|
+
if(order > 0){break;}
|
204
|
+
if((order == 0) && (!derivative)){return y[0];}
|
205
|
+
throw std::range_error("Insufficient records for interpolation");
|
206
|
+
}while(false);
|
207
|
+
std::vector<Ty2> y_buf(order), dy_buf(order);
|
208
|
+
interpolate_Neville(
|
209
|
+
dx, y, x - x0, y_buf, order,
|
210
|
+
&dy_buf, derivative ? 1 : 0);
|
211
|
+
if(derivative){*derivative = dy_buf[0];}
|
212
|
+
return y_buf[0];
|
213
|
+
}
|
214
|
+
|
215
|
+
Ty interpolate(const Tx &x, Ty *derivative = NULL) const {
|
216
|
+
struct second_iterator : public buffer_t::const_iterator {
|
217
|
+
second_iterator(const typename buffer_t::const_iterator &it)
|
218
|
+
: buffer_t::const_iterator(it) {}
|
219
|
+
const Ty &operator[](const int &n) const {
|
220
|
+
return buffer_t::const_iterator::operator[](n).second;
|
221
|
+
}
|
222
|
+
} y_it(buf.begin());
|
223
|
+
return interpolate2(x, y_it, derivative);
|
224
|
+
}
|
225
|
+
};
|
226
|
+
|
121
227
|
#endif /* __INTERPOLATE_H__ */
|
@@ -41,7 +41,6 @@
|
|
41
41
|
#include <cstring>
|
42
42
|
#include <map>
|
43
43
|
#include <set>
|
44
|
-
#include <algorithm>
|
45
44
|
#include <stdexcept>
|
46
45
|
|
47
46
|
#include "util/text_helper.h"
|
@@ -61,22 +60,15 @@ struct SP3_Product {
|
|
61
60
|
typedef std::map<GPS_Time<FloatT>, prop_t> history_t;
|
62
61
|
history_t pos_history;
|
63
62
|
history_t vel_history;
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
} interpolate_cnd_default;
|
63
|
+
|
64
|
+
typedef InterpolatableSet<GPS_Time<FloatT>, prop_t, FloatT> interpolator_t;
|
65
|
+
typedef typename interpolator_t::condition_t interpolate_cnd_t;
|
66
|
+
static const interpolate_cnd_t interpolate_cnd_default;
|
69
67
|
|
70
68
|
mutable struct {
|
71
|
-
struct target_t {
|
72
|
-
|
73
|
-
typedef typename std::vector<std::pair<GPS_Time<FloatT>, prop_t> > buf_t;
|
74
|
-
buf_t buf;
|
75
|
-
GPS_Time<FloatT> t0;
|
76
|
-
std::vector<FloatT> dt;
|
77
|
-
bool updated_full_cnd;
|
69
|
+
struct target_t : public interpolator_t {
|
78
70
|
|
79
|
-
target_t() :
|
71
|
+
target_t() : interpolator_t() {}
|
80
72
|
|
81
73
|
/**
|
82
74
|
* update interpolation source
|
@@ -88,58 +80,13 @@ struct SP3_Product {
|
|
88
80
|
const bool &force_update = false,
|
89
81
|
const interpolate_cnd_t &cnd = interpolate_cnd_default){
|
90
82
|
|
91
|
-
|
92
|
-
|
93
|
-
&& ((std::abs(t_diff) <= 10)
|
94
|
-
|| ((dt.size() >= 2)
|
95
|
-
&& (std::abs(t_diff + dt[0]) <= std::abs(t_diff + dt[1])))) ){
|
96
|
-
return *this;
|
97
|
-
}
|
98
|
-
|
99
|
-
// If the 1st and 2nd nearest epochs are changed, then recalculate interpolation targets.
|
100
|
-
struct {
|
101
|
-
const GPS_Time<FloatT> &t_base;
|
102
|
-
bool operator()(
|
103
|
-
const typename history_t::value_type &rhs,
|
104
|
-
const typename history_t::value_type &lhs) const {
|
105
|
-
return std::abs(rhs.first - t_base) < std::abs(lhs.first - t_base);
|
106
|
-
}
|
107
|
-
} cmp = {(t0 = t)};
|
108
|
-
|
109
|
-
buf.resize(cnd.max_epochs);
|
110
|
-
dt.clear();
|
111
|
-
// extract t where t0-dt <= t <= t0+dt, then sort by ascending order of |t-t0|
|
112
|
-
for(typename buf_t::const_iterator
|
113
|
-
it(buf.begin()),
|
114
|
-
it_end(std::partial_sort_copy(
|
115
|
-
history.lower_bound(t - cnd.max_delta_t),
|
116
|
-
history.upper_bound(t + cnd.max_delta_t),
|
117
|
-
buf.begin(), buf.end(), cmp));
|
118
|
-
it != it_end; ++it){
|
119
|
-
dt.push_back(it->first - t0);
|
120
|
-
}
|
121
|
-
updated_full_cnd = (dt.size() >= cnd.max_epochs);
|
122
|
-
|
83
|
+
if((!force_update) && (std::abs(t - interpolator_t::x0) <= 10)){return *this;}
|
84
|
+
interpolator_t::update(t, history, cnd, force_update);
|
123
85
|
return *this;
|
124
86
|
}
|
125
87
|
|
126
|
-
|
127
|
-
|
128
|
-
const GPS_Time<FloatT> &t, const Ty_Array &y,
|
129
|
-
Ty *derivative = NULL) const {
|
130
|
-
int order(dt.size() - 1);
|
131
|
-
do{
|
132
|
-
if(order > 0){break;}
|
133
|
-
if((order == 0) && (!derivative)){return y[0];}
|
134
|
-
throw std::range_error("Insufficient records for interpolation");
|
135
|
-
}while(false);
|
136
|
-
std::vector<Ty> y_buf(order), dy_buf(order);
|
137
|
-
interpolate_Neville(
|
138
|
-
dt, y, t - t0, y_buf, order,
|
139
|
-
&dy_buf, derivative ? 1 : 0);
|
140
|
-
if(derivative){*derivative = dy_buf[0];}
|
141
|
-
return y_buf[0];
|
142
|
-
}
|
88
|
+
typedef typename interpolator_t::buffer_t buf_t;
|
89
|
+
|
143
90
|
Vector3<FloatT> interpolate_xyz(
|
144
91
|
const GPS_Time<FloatT> &t,
|
145
92
|
Vector3<FloatT> *derivative = NULL) const {
|
@@ -149,8 +96,8 @@ struct SP3_Product {
|
|
149
96
|
const Vector3<FloatT> &operator[](const int &n) const {
|
150
97
|
return buf_t::const_iterator::operator[](n).second.xyz;
|
151
98
|
}
|
152
|
-
} xyz(buf.begin());
|
153
|
-
return
|
99
|
+
} xyz(interpolator_t::buf.begin());
|
100
|
+
return interpolator_t::interpolate2(t, xyz, derivative);
|
154
101
|
}
|
155
102
|
FloatT interpolate_clk(
|
156
103
|
const GPS_Time<FloatT> &t,
|
@@ -161,8 +108,8 @@ struct SP3_Product {
|
|
161
108
|
const FloatT &operator[](const int &n) const {
|
162
109
|
return buf_t::const_iterator::operator[](n).second.clk;
|
163
110
|
}
|
164
|
-
} clk(buf.begin());
|
165
|
-
return
|
111
|
+
} clk(interpolator_t::buf.begin());
|
112
|
+
return interpolator_t::interpolate2(t, clk, derivative);
|
166
113
|
}
|
167
114
|
} pos_clk, vel_rate;
|
168
115
|
} subset;
|
@@ -175,7 +122,7 @@ struct SP3_Product {
|
|
175
122
|
bool precheck(const GPS_Time<FloatT> &t) const {
|
176
123
|
// Only position/clock is checked, because velocity/rate can be calculated based on pos/clk.
|
177
124
|
subset.pos_clk.update(t, pos_history);
|
178
|
-
return subset.pos_clk.
|
125
|
+
return subset.pos_clk.ready;
|
179
126
|
}
|
180
127
|
|
181
128
|
typename GPS_SpaceNode<FloatT>::SatelliteProperties::constellation_t
|
@@ -381,8 +328,11 @@ static typename GPS_Solver_Base<FloatT>::satellite_t select_ ## sys( \
|
|
381
328
|
template <class FloatT>
|
382
329
|
const typename SP3_Product<FloatT>::per_satellite_t::interpolate_cnd_t
|
383
330
|
SP3_Product<FloatT>::per_satellite_t::interpolate_cnd_default = {
|
384
|
-
9, //
|
385
|
-
|
331
|
+
9, // maximum number of epochs used for interpolation
|
332
|
+
/* maximum acceptable absolute time difference between t and epoch,
|
333
|
+
* default is 2 hr = 15 min interval records; (2 hr * 2 / (9 - 1) = 15 min)
|
334
|
+
*/
|
335
|
+
60 * 60 * 2,
|
386
336
|
};
|
387
337
|
|
388
338
|
template <class FloatT>
|
data/gps_pvt.gemspec
CHANGED
@@ -53,6 +53,9 @@ Gem::Specification.new do |spec|
|
|
53
53
|
}.flatten
|
54
54
|
}.call
|
55
55
|
|
56
|
+
spec.rdoc_options << '--exclude=ext/ninja-scan-light'
|
57
|
+
spec.extra_rdoc_files = []
|
58
|
+
|
56
59
|
# Uncomment to register a new dependency of your gem
|
57
60
|
# spec.add_dependency "example-gem", "~> 1.0"
|
58
61
|
spec.add_development_dependency "rake"
|
data/lib/gps_pvt/receiver.rb
CHANGED
@@ -410,7 +410,7 @@ class Receiver
|
|
410
410
|
@solver.sbas_space_node.ionospheric_grid_points(prn)].each{|str|
|
411
411
|
$stderr.puts str
|
412
412
|
} if @debug[:SBAS_IGP]
|
413
|
-
end
|
413
|
+
end if t_meas
|
414
414
|
when :GLONASS
|
415
415
|
next unless eph = eph_glonass_list[prn]
|
416
416
|
leap_sec = @solver.gps_space_node.is_valid_utc ?
|
@@ -508,10 +508,10 @@ class Receiver
|
|
508
508
|
{
|
509
509
|
:L1_PSEUDORANGE => [16, 8, "E", proc{|v| (trk_stat & 0x1 == 0x1) ? v : nil}],
|
510
510
|
:L1_PSEUDORANGE_SIGMA => [43, 1, nil, proc{|v|
|
511
|
-
(trk_stat & 0x1 == 0x1) ? (1E-2 * (v[0] & 0xF)) : nil
|
511
|
+
(trk_stat & 0x1 == 0x1) ? (1E-2 * (1 << (v[0] & 0xF))) : nil
|
512
512
|
}],
|
513
513
|
:L1_DOPPLER => [32, 4, "e"],
|
514
|
-
:L1_DOPPLER_SIGMA => [45, 1, nil, proc{|v| 2E-3 * (v[0] & 0xF)}],
|
514
|
+
:L1_DOPPLER_SIGMA => [45, 1, nil, proc{|v| 2E-3 * (1 << (v[0] & 0xF))}],
|
515
515
|
:L1_CARRIER_PHASE => [24, 8, "E", proc{|v| (trk_stat & 0x2 == 0x2) ? v : nil}],
|
516
516
|
:L1_CARRIER_PHASE_SIGMA => [44, 1, nil, proc{|v|
|
517
517
|
(trk_stat & 0x2 == 0x2) ? (0.004 * (v[0] & 0xF)) : nil
|
data/lib/gps_pvt/version.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module GPS_PVT
|
4
|
-
VERSION = "0.6.
|
5
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GPS_PVT
|
4
|
+
VERSION = "0.6.3"
|
5
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gps_pvt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- fenrir(M.Naruoka)
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-08-
|
11
|
+
date: 2022-08-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -44,6 +44,7 @@ email:
|
|
44
44
|
- fenrir.naru@gmail.com
|
45
45
|
executables:
|
46
46
|
- gps_pvt
|
47
|
+
- to_ubx
|
47
48
|
extensions:
|
48
49
|
- ext/gps_pvt/extconf.rb
|
49
50
|
extra_rdoc_files: []
|
@@ -57,6 +58,7 @@ files:
|
|
57
58
|
- bin/console
|
58
59
|
- bin/setup
|
59
60
|
- exe/gps_pvt
|
61
|
+
- exe/to_ubx
|
60
62
|
- ext/gps_pvt/Coordinate/Coordinate_wrap.cxx
|
61
63
|
- ext/gps_pvt/GPS/GPS_wrap.cxx
|
62
64
|
- ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx
|
@@ -109,7 +111,8 @@ metadata:
|
|
109
111
|
homepage_uri: https://github.com/fenrir-naru/gps_pvt
|
110
112
|
source_code_uri: https://github.com/fenrir-naru/gps_pvt
|
111
113
|
post_install_message:
|
112
|
-
rdoc_options:
|
114
|
+
rdoc_options:
|
115
|
+
- "--exclude=ext/ninja-scan-light"
|
113
116
|
require_paths:
|
114
117
|
- lib
|
115
118
|
required_ruby_version: !ruby/object:Gem::Requirement
|