gps_pvt 0.6.2 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|