gps_pvt 0.6.2 → 0.7.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 +1 -0
- data/Rakefile +1 -0
- data/exe/gps_pvt +3 -1
- data/exe/to_ubx +214 -0
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +787 -205
- data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +2 -3
- data/ext/ninja-scan-light/tool/algorithm/interpolate.h +106 -0
- data/ext/ninja-scan-light/tool/navigation/ANTEX.h +1 -1
- data/ext/ninja-scan-light/tool/navigation/GLONASS_Solver.h +1 -1
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +1 -1
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +7 -7
- data/ext/ninja-scan-light/tool/navigation/MagneticField.h +4 -3
- data/ext/ninja-scan-light/tool/navigation/NTCM.h +1 -1
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +29 -14
- data/ext/ninja-scan-light/tool/navigation/RINEX_Clock.h +458 -0
- data/ext/ninja-scan-light/tool/navigation/SBAS.h +3 -3
- data/ext/ninja-scan-light/tool/navigation/SBAS_Solver.h +1 -1
- data/ext/ninja-scan-light/tool/navigation/SP3.h +69 -112
- data/ext/ninja-scan-light/tool/param/quaternion.h +2 -2
- data/ext/ninja-scan-light/tool/param/vector3.h +2 -2
- data/ext/ninja-scan-light/tool/swig/GPS.i +95 -51
- data/ext/ninja-scan-light/tool/swig/SylphideMath.i +1 -2
- data/gps_pvt.gemspec +3 -0
- data/lib/gps_pvt/receiver.rb +19 -3
- data/lib/gps_pvt/version.rb +5 -5
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d2ab5f33d6ba6233e7a52b05ac2f89306e181240bb2510d6ffe697467278178
|
4
|
+
data.tar.gz: d592b929d56554cb3a1e82e734d90366e32ac083eeacfc8535457a5518952075
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 826e7a745be07aad5c86b075e5285d0e31212b6fe83cce8c7af67b500645a698e2c60bd67e6f0ecc6ccd114db2754286941c9e90a72deab7b3219132028cf242
|
7
|
+
data.tar.gz: f11f9c72d8bd30f72e77969eb694ce5a5b7d25db5b251e275b2840511d1836275ba5d7adf1829cbeef691f423c7ddf3a5defbb8919f8bd93bc6cd532649bbd4b
|
data/README.md
CHANGED
@@ -41,6 +41,7 @@ The format of file is automatically determined with its extension, such as .ubx
|
|
41
41
|
| --ubx=file_or_URI | [U-blox](https://www.u-blox.com/) dedicated format |
|
42
42
|
| --sp3=file_or_URI | [Standard Product 3 Orbit Format](https://files.igs.org/pub/data/format/sp3c.txt) (supported gps_pvt version >= 0.6.0) |
|
43
43
|
| --antex=file_or_URI | [Antenna Exchange Format](https://igs.org/wg/antenna#files) (supported gps_pvt version >= 0.6.0) |
|
44
|
+
| --rinex_clk=file_or_URI | [RINEX clock](https://files.igs.org/pub/data/format/rinex_clock304.txt) file (supported gps_pvt version >= 0.7.0) |
|
44
45
|
|
45
46
|
Since version 0.2.0, SBAS and QZSS are supported in addition to GPS. Since version 0.4.0, GLONASS is also available. QZSS ranging is activated in default, however, SBAS is just utilized for ionospheric correction. GLONASS is also turned off by default. If you want to activate SBAS or GLONASS ranging, "--with=(system or PRN)" options are used with gps_pvt executable like
|
46
47
|
|
data/Rakefile
CHANGED
data/exe/gps_pvt
CHANGED
@@ -24,7 +24,7 @@ misc_options = {}
|
|
24
24
|
files = ARGV.collect{|arg|
|
25
25
|
next [arg, nil] unless arg =~ /^--([^=]+)=?/
|
26
26
|
k, v = [$1.downcase.to_sym, $']
|
27
|
-
next [v, k] if [:rinex_nav, :rinex_obs, :ubx, :sp3, :antex].include?(k) # file type
|
27
|
+
next [v, k] if [:rinex_nav, :rinex_obs, :ubx, :sp3, :antex, :rinex_clk].include?(k) # file type
|
28
28
|
options << [$1.to_sym, $']
|
29
29
|
nil
|
30
30
|
}.compact
|
@@ -74,6 +74,7 @@ files.collect!{|fname, ftype|
|
|
74
74
|
when /\.ubx$/; :ubx
|
75
75
|
when /\.sp3(?:\.Z)?$/; :sp3
|
76
76
|
when /\.atx(?:\.Z)?$/; :antex
|
77
|
+
when /\.clk$/; :rinex_clk
|
77
78
|
else
|
78
79
|
raise "Format cannot be guessed, use --(format, ex. rinex_nav)=#{fname}"
|
79
80
|
end
|
@@ -145,6 +146,7 @@ files.each{|fname, ftype|
|
|
145
146
|
when :rinex_nav; rcv.parse_rinex_nav(fname)
|
146
147
|
when :sp3; rcv.attach_sp3(fname)
|
147
148
|
when :antex; rcv.attach_antex(fname)
|
149
|
+
when :rinex_clk; rcv.attach_rinex_clk(fname)
|
148
150
|
end
|
149
151
|
}
|
150
152
|
|
data/exe/to_ubx
ADDED
@@ -0,0 +1,214 @@
|
|
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
|
+
STDOUT.binmode
|
214
|
+
obs.each{|*item| print gen.call(*item)}
|