gps_pvt 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +10 -0
- data/README.md +86 -0
- data/Rakefile +86 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/ext/gps_pvt/Coordinate/Coordinate_wrap.cxx +6613 -0
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +16019 -0
- data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +21050 -0
- data/ext/gps_pvt/extconf.rb +70 -0
- data/ext/ninja-scan-light/tool/navigation/EGM.h +2971 -0
- data/ext/ninja-scan-light/tool/navigation/GPS.h +2432 -0
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +479 -0
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +1081 -0
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_MultiFrequency.h +199 -0
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_RAIM.h +210 -0
- data/ext/ninja-scan-light/tool/navigation/MagneticField.h +928 -0
- data/ext/ninja-scan-light/tool/navigation/NTCM.h +211 -0
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +1781 -0
- data/ext/ninja-scan-light/tool/navigation/WGS84.h +186 -0
- data/ext/ninja-scan-light/tool/navigation/coordinate.h +406 -0
- data/ext/ninja-scan-light/tool/param/bit_array.h +145 -0
- data/ext/ninja-scan-light/tool/param/complex.h +558 -0
- data/ext/ninja-scan-light/tool/param/matrix.h +4049 -0
- data/ext/ninja-scan-light/tool/param/matrix_fixed.h +665 -0
- data/ext/ninja-scan-light/tool/param/matrix_special.h +562 -0
- data/ext/ninja-scan-light/tool/param/quaternion.h +765 -0
- data/ext/ninja-scan-light/tool/param/vector3.h +651 -0
- data/ext/ninja-scan-light/tool/swig/Coordinate.i +177 -0
- data/ext/ninja-scan-light/tool/swig/GPS.i +1102 -0
- data/ext/ninja-scan-light/tool/swig/SylphideMath.i +1234 -0
- data/ext/ninja-scan-light/tool/swig/extconf.rb +5 -0
- data/ext/ninja-scan-light/tool/swig/makefile +53 -0
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +417 -0
- data/ext/ninja-scan-light/tool/swig/spec/SylphideMath_spec.rb +489 -0
- data/gps_pvt.gemspec +57 -0
- data/lib/gps_pvt/receiver.rb +375 -0
- data/lib/gps_pvt/ubx.rb +148 -0
- data/lib/gps_pvt/version.rb +5 -0
- data/lib/gps_pvt.rb +9 -0
- data/sig/gps_pvt.rbs +4 -0
- metadata +117 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
SWIG = swig
|
2
|
+
SWIGFLAGS = -c++ -ruby $(shell if [ -n "$$MSYSTEM" ]; then echo -D__MINGW__; fi)
|
3
|
+
INCLUDES = -I../
|
4
|
+
BUILD_DIR = build_SWIG
|
5
|
+
|
6
|
+
RUBY = ruby
|
7
|
+
RUBY_CONF = extconf.rb
|
8
|
+
|
9
|
+
SRCS = $(shell ls *.i)
|
10
|
+
|
11
|
+
PACKAGES = $(SRCS:.i=.so)
|
12
|
+
|
13
|
+
all : $(BUILD_DIR) depend $(PACKAGES)
|
14
|
+
|
15
|
+
depend : INCLUDES+=-I$(shell echo $${MSYSTEM_PREFIX:-/usr})/include/
|
16
|
+
|
17
|
+
# �w�b�_�[�t�@�C���̈ˑ��W
|
18
|
+
depend : $(SRCS)
|
19
|
+
if [ -f $(BUILD_DIR)/depend.inc ]; then rm -f $(BUILD_DIR)/depend.inc; fi
|
20
|
+
for i in $^; do\
|
21
|
+
$(SWIG) $(SWIGFLAGS) $(INCLUDES) -MM -MP $$i | sed -e 's/[^\.]*\.cxx/$$\(BUILD_DIR\)\/&/g' >> $(BUILD_DIR)/depend.inc;\
|
22
|
+
done
|
23
|
+
|
24
|
+
-include $(BUILD_DIR)/depend.inc
|
25
|
+
|
26
|
+
$(PACKAGES) : $(patsubst %,$(BUILD_DIR)/%,$(PACKAGES))
|
27
|
+
|
28
|
+
$(BUILD_DIR)/BoostDistributions_wrap.cxx : INCLUDES+=-I$(shell echo $${MSYSTEM_PREFIX:-/usr})/include/
|
29
|
+
|
30
|
+
$(BUILD_DIR)/%_wrap.cxx : %.i
|
31
|
+
$(SWIG) $(SWIGFLAGS) $(INCLUDES) -o $@ $<
|
32
|
+
|
33
|
+
$(BUILD_DIR)/%.so : PACKAGE = $(shell echo $@ | sed -e 's/^$(BUILD_DIR)\/\([^\.]*\)\.so/\1/g')
|
34
|
+
$(BUILD_DIR)/%.so : $(BUILD_DIR)/%_wrap.cxx $(RUBY_CONF)
|
35
|
+
echo "building $(PACKAGE) ..."
|
36
|
+
if ! [ -d $(BUILD_DIR)/$(PACKAGE) ]; then mkdir $(BUILD_DIR)/$(PACKAGE); fi
|
37
|
+
cp $(RUBY_CONF) $(BUILD_DIR)/$(PACKAGE)/
|
38
|
+
cp $(BUILD_DIR)/$(PACKAGE)_wrap.cxx $(BUILD_DIR)/$(PACKAGE)/
|
39
|
+
cd $(BUILD_DIR)/$(PACKAGE); \
|
40
|
+
echo 'create_makefile("$(PACKAGE)")' >> $(RUBY_CONF); \
|
41
|
+
$(RUBY) $(RUBY_CONF); \
|
42
|
+
make; \
|
43
|
+
cp *.so ../
|
44
|
+
|
45
|
+
$(BUILD_DIR) :
|
46
|
+
mkdir $@
|
47
|
+
|
48
|
+
clean :
|
49
|
+
rm -rf $(BUILD_DIR)/*
|
50
|
+
|
51
|
+
run : all
|
52
|
+
|
53
|
+
.PHONY : clean all depend
|
@@ -0,0 +1,417 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
$: << File::join(File::dirname(__FILE__), '..', 'build_SWIG')
|
6
|
+
require 'GPS.so'
|
7
|
+
|
8
|
+
describe 'GPS solver' do
|
9
|
+
let(:input){{
|
10
|
+
:rinex_nav => Tempfile::open{|f|
|
11
|
+
if true then
|
12
|
+
f.write(<<-__RINEX_NAV_TEXT__)
|
13
|
+
2.10 N: GPS NAV DATA RINEX VERSION / TYPE
|
14
|
+
teqc 2013Mar15 BKG Frankfurt 20150617 00:16:14UTCPGM / RUN BY / DATE
|
15
|
+
Linux 2.4.21-27.ELsmp|Opteron|gcc -static|Linux x86_64|=+ COMMENT
|
16
|
+
2.10 N: GPS NAV DATA COMMENT
|
17
|
+
teqc 2008Feb15 20150617 00:10:22UTCCOMMENT
|
18
|
+
Linux 2.4.20-8|Pentium IV|gcc -static|Linux|486/DX+ COMMENT
|
19
|
+
1.3970D-08 2.2352D-08 -1.1921D-07 -1.1921D-07 ION ALPHA
|
20
|
+
1.1059D+05 1.6384D+05 -6.5536D+04 -5.2429D+05 ION BETA
|
21
|
+
3.725290298462D-09 1.509903313490D-14 319488 1849 DELTA-UTC: A0,A1,T,W
|
22
|
+
16 LEAP SECONDS
|
23
|
+
Concatenated RINEX files (28/) COMMENT
|
24
|
+
Original file name: brdc1670.15n COMMENT
|
25
|
+
END OF HEADER
|
26
|
+
31 15 6 16 0 0 0.0 3.128303214908D-04-1.136868377216D-12 0.000000000000D+00
|
27
|
+
7.800000000000D+01 1.292812500000D+02 4.074098273975D-09 1.410690806649D+00
|
28
|
+
6.768852472305D-06 8.027532137930D-03 4.271045327187D-06 5.153535821915D+03
|
29
|
+
1.728000000000D+05 9.872019290924D-08 8.650894583569D-01 8.940696716309D-08
|
30
|
+
9.750288799237D-01 3.013750000000D+02-5.268559212524D-01-8.036049019412D-09
|
31
|
+
3.664438352852D-10 1.000000000000D+00 1.849000000000D+03 0.000000000000D+00
|
32
|
+
2.000000000000D+00 0.000000000000D+00-1.350417733192D-08 7.800000000000D+01
|
33
|
+
1.663560000000D+05 4.000000000000D+00
|
34
|
+
24 15 6 16 0 0 0.0-4.998780786991D-05-5.684341886081D-13 0.000000000000D+00
|
35
|
+
9.000000000000D+01 1.401250000000D+02 4.642336229081D-09 2.380519254182D+00
|
36
|
+
7.258728146553D-06 3.228595596738D-03 3.971159458160D-06 5.153673912048D+03
|
37
|
+
1.728000000000D+05-2.980232238770D-08 8.160388274984D-01-1.490116119385D-08
|
38
|
+
9.533772739559D-01 2.969375000000D+02 3.612098431884D-01-8.379634759709D-09
|
39
|
+
4.025167664390D-10 1.000000000000D+00 1.849000000000D+03 0.000000000000D+00
|
40
|
+
2.900000000000D+00 0.000000000000D+00 2.328306436539D-09 9.000000000000D+01
|
41
|
+
1.656600000000D+05 4.000000000000D+00
|
42
|
+
12 15 6 16 0 0 0.0 3.018006682396D-04 3.183231456205D-12 0.000000000000D+00
|
43
|
+
9.000000000000D+01-8.984375000000D+01 4.146244136282D-09 1.019955493515D+00
|
44
|
+
-4.906207323074D-06 5.596161005087D-03 2.166256308556D-06 5.153664655685D+03
|
45
|
+
1.728000000000D+05-3.352761268616D-08 1.926955253672D+00 9.685754776001D-08
|
46
|
+
9.895896897770D-01 3.531562500000D+02 6.166481681571D-01-8.222842514396D-09
|
47
|
+
-2.525105180766D-10 1.000000000000D+00 1.849000000000D+03 0.000000000000D+00
|
48
|
+
2.000000000000D+00 0.000000000000D+00-1.210719347000D-08 9.000000000000D+01
|
49
|
+
1.708800000000D+05 4.000000000000D+00
|
50
|
+
25 15 6 16 0 0 0.0-2.291053533554D-06-4.206412995700D-12 0.000000000000D+00
|
51
|
+
4.300000000000D+01-8.231250000000D+01 4.456614188797D-09 3.514302168106D-01
|
52
|
+
-4.393979907036D-06 4.659408819862D-03 1.480802893639D-06 5.153666315079D+03
|
53
|
+
1.728000000000D+05 0.000000000000D+00 1.880081553172D+00 1.080334186554D-07
|
54
|
+
9.780612252959D-01 3.641250000000D+02 7.406192694225D-01-8.389992700586D-09
|
55
|
+
-1.742929689463D-10 1.000000000000D+00 1.849000000000D+03 0.000000000000D+00
|
56
|
+
2.000000000000D+00 0.000000000000D+00 5.587935447693D-09 4.300000000000D+01
|
57
|
+
1.728000000000D+05
|
58
|
+
18 15 6 15 23 59 44.0 4.096841439605D-04 2.955857780762D-12 0.000000000000D+00
|
59
|
+
0.000000000000D+00-2.200000000000D+01 5.964177003340D-09-4.658085121885D-01
|
60
|
+
-1.063570380211D-06 1.631921075750D-02 5.243346095085D-06 5.153597631454D+03
|
61
|
+
1.727840000000D+05-9.499490261078D-08-1.282443549024D+00 1.769512891769D-07
|
62
|
+
9.246030417022D-01 2.601875000000D+02-1.955724914307D+00-8.981445541829D-09
|
63
|
+
-4.760912596834D-10 1.000000000000D+00 1.849000000000D+03 0.000000000000D+00
|
64
|
+
2.000000000000D+00 0.000000000000D+00-1.117587089539D-08 0.000000000000D+00
|
65
|
+
1.696560000000D+05 4.000000000000D+00
|
66
|
+
29 15 6 16 0 0 0.0 6.168931722641D-04 2.273736754432D-12 0.000000000000D+00
|
67
|
+
7.300000000000D+01-1.041875000000D+02 4.061597753278D-09 5.907941646969D-01
|
68
|
+
-5.280598998070D-06 1.195417135023D-03 1.201778650284D-05 5.153755130768D+03
|
69
|
+
1.728000000000D+05 9.313225746155D-09 2.981267878597D+00-1.303851604462D-08
|
70
|
+
9.739471617229D-01 1.573125000000D+02-5.419126340021D-01-7.659961925303D-09
|
71
|
+
2.107230631757D-10 1.000000000000D+00 1.849000000000D+03 0.000000000000D+00
|
72
|
+
2.000000000000D+00 0.000000000000D+00-9.778887033463D-09 7.300000000000D+01
|
73
|
+
1.656180000000D+05 4.000000000000D+00
|
74
|
+
__RINEX_NAV_TEXT__
|
75
|
+
else # equivalent
|
76
|
+
open(File::join(File::dirname(__FILE__), "..", "..", "test_log", "brdc1670.15n"), 'r'){|io|
|
77
|
+
while (str = io.readline)
|
78
|
+
f.puts("%-80s"%[str.chomp])
|
79
|
+
break if str =~ /END OF HEADER/
|
80
|
+
end
|
81
|
+
while !io.eof?
|
82
|
+
entry = 8.times.collect{io.readline}
|
83
|
+
next unless entry[0] =~ /^([ \d]\d) /
|
84
|
+
prn = $1.to_i
|
85
|
+
next unless entry[6] =~ /(\d\.\d{12})D([+-]\d{2})\s*$/
|
86
|
+
iode = ($1.to_f * (10 ** $2.to_i)).to_i
|
87
|
+
next unless [[12, 90], [18, 0], [24, 90], [25, 43], [29, 73], [31, 78]] \
|
88
|
+
.include?([prn, iode])
|
89
|
+
entry.each{|str|
|
90
|
+
f.print("%-80s\n"%[str.chomp])
|
91
|
+
}
|
92
|
+
end
|
93
|
+
}
|
94
|
+
end
|
95
|
+
f.path
|
96
|
+
},
|
97
|
+
:measurement => proc{
|
98
|
+
l1p = GPS::Measurement::L1_PSEUDORANGE
|
99
|
+
l1d = GPS::Measurement::L1_RANGE_RATE
|
100
|
+
{
|
101
|
+
12 => {l1p => 23707858.8131, l1d => -466.953123206},
|
102
|
+
18 => {l1p => 25319310.9754, l1d => -453.797772239},
|
103
|
+
24 => {l1p => 25683081.3903, l1d => -579.768048832},
|
104
|
+
25 => {l1p => 21551698.5927, l1d => -847.86674626},
|
105
|
+
29 => {l1p => 23637198.3968, l1d => -1560.30646593},
|
106
|
+
31 => {l1p => 23707474.1231, l1d => -1423.67588761},
|
107
|
+
}
|
108
|
+
}.call,
|
109
|
+
:rinex_obs => Tempfile::open{|f|
|
110
|
+
if true then
|
111
|
+
f.write(<<-__RINEX_OBS_TEXT__)
|
112
|
+
2.11 OBSERVATION DATA M (MIXED) RINEX VERSION / TYPE
|
113
|
+
BINEX2RINEX 1.00 GSI, JAPAN 20150617 18:30:58UTCPGM / RUN BY / DATE
|
114
|
+
0228 MARKER NAME
|
115
|
+
GSI, JAPAN GEOSPATIAL INFORMATION AUTHORITY OF JAPAOBSERVER / AGENCY
|
116
|
+
00000 TRIMBLE NETR9 4.93,26/NOV/2014 REC # / TYPE / VERS
|
117
|
+
TRM59800.80 GSI ANT # / TYPE
|
118
|
+
-3952590.4754 3360273.8926 3697987.2632 APPROX POSITION XYZ
|
119
|
+
0.0000 0.0000 0.0000 ANTENNA: DELTA H/E/N
|
120
|
+
1 1 WAVELENGTH FACT L1/2
|
121
|
+
6 L1 C1 L2 P2 S1 S2 # / TYPES OF OBSERV
|
122
|
+
2015 6 16 0 0 0.0000000 GPS TIME OF FIRST OBS
|
123
|
+
30.000 INTERVAL
|
124
|
+
16 LEAP SECONDS
|
125
|
+
smtt on - smooth time tag (ms jumps in phase and range) COMMENT
|
126
|
+
END OF HEADER
|
127
|
+
15 6 16 0 0 0.0000000 0 13R04R14G22G18G25G14R03G12R13G29R23R24 0.000000000
|
128
|
+
G26
|
129
|
+
107962537.996 8 20161244.813 83970896.187 7 20161248.340 53.100
|
130
|
+
45.700
|
131
|
+
108292688.703 7 20315410.305 84227597.491 6 20315417.836 44.900
|
132
|
+
38.600
|
133
|
+
120164532.762 7 22866559.250 93634735.08845 22866565.0164 44.800
|
134
|
+
31.9004
|
135
|
+
127657315.100 5 24292417.195 99473356.27642 24292426.4844 33.000
|
136
|
+
16.9004
|
137
|
+
107108718.011 8 20382088.883 83461307.35447 20382098.2114 52.700
|
138
|
+
44.8004
|
139
|
+
106665594.451 8 20297781.844 83116060.16147 20297788.3284 48.500
|
140
|
+
43.6004
|
141
|
+
112247722.253 8 20968815.328 87303792.973 7 20968819.930 48.200
|
142
|
+
43.900
|
143
|
+
119180856.024 7 22679363.352 92868240.86845 22679370.8554 46.000
|
144
|
+
34.4004
|
145
|
+
113219403.456 7 21202362.125 88059583.077 7 21202366.582 43.300
|
146
|
+
42.600
|
147
|
+
116573807.952 8 22183256.359 90836814.38846 22183263.8554 48.000
|
148
|
+
37.2004
|
149
|
+
118068213.681 8 22071607.477 91830908.595 5 22071616.434 48.300
|
150
|
+
34.300
|
151
|
+
122821571.168 6 22968227.047 95527813.562 5 22968231.008 41.000
|
152
|
+
33.400
|
153
|
+
126887720.863 7 24145939.008 98873654.81144 24145951.6954 42.000
|
154
|
+
24.8004
|
155
|
+
15 6 16 0 0 30.0000000 0 13R04R14G22G18G25G14R03G12R13G29R23R24 0.000000000
|
156
|
+
G26
|
157
|
+
107953906.562 8 20159632.578 83964182.831 7 20159636.547 52.900
|
158
|
+
45.500
|
159
|
+
108275524.990 7 20312191.531 84214247.928 6 20312198.477 46.000
|
160
|
+
37.900
|
161
|
+
120243117.022 7 22881512.617 93695969.52045 22881519.3444 43.200
|
162
|
+
30.0004
|
163
|
+
127752623.271 5 24310554.234 99547622.25842 24310562.6254 34.300
|
164
|
+
14.8004
|
165
|
+
107148475.172 8 20389654.469 83492286.95147 20389663.6914 53.000
|
166
|
+
44.7004
|
167
|
+
106649633.973 8 20294744.781 83103623.41147 20294751.4144 49.800
|
168
|
+
44.5004
|
169
|
+
112354437.822 8 20988750.797 87386793.909 7 20988756.371 48.000
|
170
|
+
44.200
|
171
|
+
119276901.051 7 22697639.727 92943081.07945 22697647.7704 47.500
|
172
|
+
34.6004
|
173
|
+
113277695.919 7 21213278.297 88104921.616 7 21213283.438 43.800
|
174
|
+
42.700
|
175
|
+
116499708.794 8 22169155.719 90779074.87246 22169163.7704 48.500
|
176
|
+
37.6004
|
177
|
+
118027431.830 8 22063984.773 91799189.430 5 22063991.707 49.300
|
178
|
+
35.100
|
179
|
+
122710898.974 6 22947531.234 95441735.252 5 22947536.609 40.900
|
180
|
+
33.600
|
181
|
+
126789541.785 6 24127256.484 98797151.68444 24127268.9224 41.900
|
182
|
+
25.3004
|
183
|
+
15 6 16 0 1 0.0000000 0 13R04R14G22G18G25G14R03G12R13G29R23R24 0.000000000
|
184
|
+
G26
|
185
|
+
107946098.362 8 20158174.969 83958109.762 7 20158178.289 53.200
|
186
|
+
44.900
|
187
|
+
108258590.494 7 20309014.148 84201076.653 6 20309021.145 46.000
|
188
|
+
38.700
|
189
|
+
120321906.821 7 22896506.344 93757364.10145 22896512.2934 44.600
|
190
|
+
30.2004
|
191
|
+
127847866.993 6 24328677.648 99621838.11742 24328687.3954 37.300
|
192
|
+
16.9004
|
193
|
+
107188670.264 8 20397303.531 83523607.79247 20397312.3054 53.700
|
194
|
+
44.3004
|
195
|
+
106634143.554 8 20291797.133 83091552.94947 20291803.6724 49.900
|
196
|
+
44.0004
|
197
|
+
112461605.174 7 21008771.203 87470146.236 7 21008775.176 47.500
|
198
|
+
43.900
|
199
|
+
119373111.958 8 22715948.289 93018050.54445 22715955.9534 48.100
|
200
|
+
34.1004
|
201
|
+
113336078.148 7 21224212.609 88150329.998 7 21224216.957 43.000
|
202
|
+
42.500
|
203
|
+
116425964.067 7 22155122.617 90721611.48746 22155131.1914 46.200
|
204
|
+
37.6004
|
205
|
+
117987330.119 7 22056486.641 91767999.260 5 22056494.809 46.900
|
206
|
+
34.500
|
207
|
+
122600398.977 6 22926865.672 95355790.881 5 22926871.977 39.700
|
208
|
+
32.500
|
209
|
+
126691542.694 6 24108607.188 98720788.84544 24108620.5234 41.700
|
210
|
+
24.8004
|
211
|
+
__RINEX_OBS_TEXT__
|
212
|
+
else # equivalent
|
213
|
+
# GEONET Setagaya from https://terras.gsi.go.jp/data_service.php#11/35.663712/139.630394
|
214
|
+
open(File::join(File::dirname(__FILE__), "..", "..", "test_log", "02281670.15o"), 'r'){|io|
|
215
|
+
99.times{|i|
|
216
|
+
break unless str = io.readline
|
217
|
+
f.write(str)
|
218
|
+
}
|
219
|
+
}
|
220
|
+
end
|
221
|
+
f.path
|
222
|
+
},
|
223
|
+
}}
|
224
|
+
let(:solver){GPS::Solver::new}
|
225
|
+
|
226
|
+
describe 'demo' do
|
227
|
+
it 'calculates position without any error' do
|
228
|
+
sn = solver.gps_space_node
|
229
|
+
puts "RINEX NAV read: %d items."%[sn.read(input[:rinex_nav])]
|
230
|
+
meas = GPS::Measurement::new
|
231
|
+
input[:measurement].each{|prn, items|
|
232
|
+
items.each{|k, v|
|
233
|
+
meas.add(prn, k, v)
|
234
|
+
}
|
235
|
+
}
|
236
|
+
expect(meas.to_hash).to eq(proc{|array|
|
237
|
+
res = {}
|
238
|
+
array.each{|prn, k, v|
|
239
|
+
(res[prn][k] = v) rescue (res[prn] = {k => v})
|
240
|
+
}
|
241
|
+
res
|
242
|
+
}.call(meas.to_a))
|
243
|
+
expect(GPS::Measurement::new(meas.to_a).to_a.sort).to eq(meas.to_a.sort) # accept [[prn, k, v], ...]
|
244
|
+
expect(GPS::Measurement::new(meas.to_hash).to_a.sort).to eq(meas.to_a.sort) # accept {prn => {k => v, ...}, ...}
|
245
|
+
expect{GPS::Measurement::new({:sym => {1 => 2}})}.to raise_error
|
246
|
+
expect{GPS::Measurement::new({1 => {:sym => 2}})}.to raise_error
|
247
|
+
expect{GPS::Measurement::new({1 => [2, 3]})}.to raise_error
|
248
|
+
|
249
|
+
t_meas = GPS::Time::new(1849, 172413)
|
250
|
+
puts "Measurement time: #{t_meas.to_a} (a.k.a #{"%d/%d/%d %02d:%02d:%02d UTC"%[*t_meas.c_tm]})"
|
251
|
+
expect(t_meas.c_tm).to eq([2015, 6, 15, 23, 53, 33])
|
252
|
+
|
253
|
+
sn.update_all_ephemeris(t_meas)
|
254
|
+
|
255
|
+
[:alpha, :beta].each{|k|
|
256
|
+
puts "Iono #{k}: #{sn.iono_utc.send(k)}"
|
257
|
+
}
|
258
|
+
puts solver.gps_options.ionospheric_models
|
259
|
+
|
260
|
+
meas.each{|prn, k, v|
|
261
|
+
eph = sn.ephemeris(prn)
|
262
|
+
puts "XYZ(PRN:#{prn}): #{eph.constellation(t_meas)[0].to_a} (iodc: #{eph.iodc}, iode: #{eph.iode})"
|
263
|
+
}
|
264
|
+
|
265
|
+
run_solver = proc{
|
266
|
+
pvt = solver.solve(meas, t_meas)
|
267
|
+
[
|
268
|
+
:error_code,
|
269
|
+
:position_solved?,
|
270
|
+
[:receiver_time, proc{|v| v.to_a}],
|
271
|
+
:used_satellite_list,
|
272
|
+
[:llh, proc{|llh| llh.to_a.zip([180.0 / Math::PI] * 2 + [1]).collect{|v, sf| v * sf}}],
|
273
|
+
:receiver_error,
|
274
|
+
[:velocity, proc{|xyz| xyz.to_a}],
|
275
|
+
:receiver_error_rate,
|
276
|
+
[:G_enu, proc{|mat| mat.to_s}],
|
277
|
+
:fd,
|
278
|
+
:fde_min,
|
279
|
+
:fde_2nd,
|
280
|
+
].each{|fun, task|
|
281
|
+
task ||= proc{|v| v}
|
282
|
+
puts "pvt.#{fun}: #{task.call(pvt.send(fun))}"
|
283
|
+
}
|
284
|
+
pvt
|
285
|
+
}
|
286
|
+
|
287
|
+
puts "Normal solution ..."
|
288
|
+
pvt = run_solver.call
|
289
|
+
puts
|
290
|
+
|
291
|
+
expect(pvt.position_solved?).to be(true)
|
292
|
+
expect(pvt.receiver_time.to_a).to eq([1849, 172413])
|
293
|
+
expect(pvt.llh.to_a).to eq([:lat, :lng, :alt].collect{|k| pvt.llh.send(k)})
|
294
|
+
expect(pvt.llh.lat / Math::PI * 180).to be_within(1E-9).of(35.6992591268) # latitude
|
295
|
+
expect(pvt.llh.lng / Math::PI * 180).to be_within(1E-9).of(139.541502292) # longitude
|
296
|
+
expect(pvt.llh.alt) .to be_within(1E-4).of(104.279402455) # altitude
|
297
|
+
expect(pvt.receiver_error).to be_within(1E-4).of(1259087.83603)
|
298
|
+
expect(pvt.gdop).to be_within(1E-10).of(3.83282723293)
|
299
|
+
expect(pvt.pdop).to be_within(1E-10).of(3.30873220653)
|
300
|
+
expect(pvt.hdop).to be_within(1E-10).of(2.05428293774)
|
301
|
+
expect(pvt.vdop).to be_within(1E-10).of(2.59376761222)
|
302
|
+
expect(pvt.tdop).to be_within(1E-10).of(1.9346461648)
|
303
|
+
expect(pvt.velocity.to_a).to eq([:e, :n, :u].collect{|k| pvt.velocity.send(k)})
|
304
|
+
expect(pvt.velocity.north).to be_within(1E-7).of(-0.839546227836) # north
|
305
|
+
expect(pvt.velocity.east) .to be_within(1E-7).of(-1.05805616381) # east
|
306
|
+
expect(pvt.velocity.down) .to be_within(1E-7).of(-0.12355474006) # down
|
307
|
+
expect(pvt.receiver_error_rate).to be_within(1E-7).of(-1061.92654151)
|
308
|
+
expect(pvt.G.rows).to eq(6)
|
309
|
+
expect(pvt.W.rows).to eq(6)
|
310
|
+
expect(pvt.delta_r.rows).to eq(6)
|
311
|
+
expect(pvt.G_enu.rows).to eq(6)
|
312
|
+
expect(Math::sqrt(pvt.C[3, 3])).to be_within(1E-10).of(pvt.tdop)
|
313
|
+
expect(Math::sqrt(pvt.C_enu[2, 2])).to be_within(1E-10).of(pvt.vdop)
|
314
|
+
pvt.S.to_a.flatten.zip(
|
315
|
+
((pvt.G.t * pvt.W * pvt.G).inv * (pvt.G.t * pvt.W)).to_a.flatten).each{|a, b|
|
316
|
+
expect(a).to be_within(1E-10).of(b)
|
317
|
+
}
|
318
|
+
pvt.S_enu.to_a.flatten.zip(
|
319
|
+
((pvt.G_enu.t * pvt.W * pvt.G_enu).inv * (pvt.G_enu.t * pvt.W)).to_a.flatten).each{|a, b|
|
320
|
+
expect(a).to be_within(1E-10).of(b)
|
321
|
+
}
|
322
|
+
expect([:rows, :columns].collect{|f| pvt.slope_HV_enu.send(f)}).to eq([6, 2])
|
323
|
+
expect(pvt.used_satellites).to eq(6)
|
324
|
+
expect(pvt.used_satellite_list).to eq([12,18, 24, 25, 29, 31])
|
325
|
+
|
326
|
+
meas.each{|prn, k, v|
|
327
|
+
solver.gps_options.exclude(prn)
|
328
|
+
puts "Excluded(PRN: #{solver.gps_options.excluded.join(', ')}) solution ..."
|
329
|
+
run_solver.call
|
330
|
+
solver.gps_options.excluded.each{|prn|
|
331
|
+
solver.gps_options.include(prn)
|
332
|
+
}
|
333
|
+
puts
|
334
|
+
}
|
335
|
+
end
|
336
|
+
|
337
|
+
it 'can be modified through hooks' do
|
338
|
+
sn = solver.gps_space_node
|
339
|
+
sn.read(input[:rinex_nav])
|
340
|
+
t_meas = GPS::Time::new(1849, 172413)
|
341
|
+
sn.update_all_ephemeris(t_meas)
|
342
|
+
solver.hooks[:relative_property] = proc{|prn, rel_prop, rcv_e, t_arv, usr_pos, usr_vel|
|
343
|
+
expect(input[:measurement]).to include(prn)
|
344
|
+
expect(t_arv).to be_a_kind_of(GPS::Time)
|
345
|
+
expect(usr_pos).to be_a_kind_of(Coordinate::XYZ)
|
346
|
+
expect(usr_vel).to be_a_kind_of(Coordinate::XYZ)
|
347
|
+
weight, range_c, range_r, rate_rel_neg, *los_neg = rel_prop
|
348
|
+
weight = 1
|
349
|
+
[weight, range_c, range_r, rate_rel_neg] + los_neg
|
350
|
+
}
|
351
|
+
solver.hooks[:update_position_solution] = proc{|*mats|
|
352
|
+
mats.each{|mat|
|
353
|
+
expect(mat).to be_a_kind_of(SylphideMath::MatrixD)
|
354
|
+
}
|
355
|
+
mat_G, mat_W, mat_delta_r = mats
|
356
|
+
}
|
357
|
+
pvt = solver.solve(
|
358
|
+
input[:measurement].collect{|prn, items|
|
359
|
+
items.collect{|k, v| [prn, k, v]}
|
360
|
+
}.flatten(1),
|
361
|
+
t_meas)
|
362
|
+
expect(pvt.W).to eq(SylphideMath::MatrixD::I(pvt.W.rows))
|
363
|
+
end
|
364
|
+
|
365
|
+
it 'calculates position without any error with RINEX obs file' do
|
366
|
+
sn = solver.gps_space_node
|
367
|
+
puts "RINEX NAV read: %d items."%[sn.read(input[:rinex_nav])]
|
368
|
+
GPS::RINEX_Observation::read(input[:rinex_obs]){|item|
|
369
|
+
t_meas = item[:time]
|
370
|
+
puts "Measurement time: #{t_meas.to_a} (a.k.a #{"%d/%d/%d %02d:%02d:%02d UTC"%[*t_meas.c_tm]})"
|
371
|
+
sn.update_all_ephemeris(t_meas)
|
372
|
+
|
373
|
+
meas = GPS::Measurement::new
|
374
|
+
types = (item[:meas_types]['G'] || item[:meas_types][' ']).collect.with_index{|type_, i|
|
375
|
+
case type_
|
376
|
+
when "C1"
|
377
|
+
[i, GPS::Measurement::L1_PSEUDORANGE]
|
378
|
+
when "D1"
|
379
|
+
[i, GPS::Measurement::L1_RANGE_RATE]
|
380
|
+
else
|
381
|
+
nil
|
382
|
+
end
|
383
|
+
}.compact
|
384
|
+
item[:meas].each{|k, v|
|
385
|
+
sys, prn = k
|
386
|
+
next unless sys == 'G' # GPS only
|
387
|
+
types.each{|i, type_|
|
388
|
+
meas.add(prn, type_, v[i][0]) if v[i]
|
389
|
+
}
|
390
|
+
}
|
391
|
+
|
392
|
+
pvt = solver.solve(meas, t_meas)
|
393
|
+
expect(pvt.position_solved?).to eq(true)
|
394
|
+
|
395
|
+
puts pvt.llh.to_a.zip([180.0 / Math::PI] * 2 + [1]).collect{|v, sf| v * sf}.inspect
|
396
|
+
if approx_pos = proc{
|
397
|
+
next false unless res = item[:header].select{|k, v| k =~ /APPROX POSITION XYZ/}.values[0]
|
398
|
+
next false unless res = res.collect{|item|
|
399
|
+
item.scan(/([+-]?\d+(?:\.\d+)?)\s*/).flatten
|
400
|
+
}.reject{|item|
|
401
|
+
item.empty?
|
402
|
+
}[0]
|
403
|
+
Coordinate::XYZ::new(*(res.collect{|str| str.to_f}))
|
404
|
+
}.call then
|
405
|
+
approx_pos.to_a.zip(pvt.xyz.to_a).each{|a, b|
|
406
|
+
expect(a).to be_within(1E+1).of(b) # 10 m
|
407
|
+
}
|
408
|
+
end
|
409
|
+
|
410
|
+
pvt.used_satellite_list.each{|prn|
|
411
|
+
eph = sn.ephemeris(prn)
|
412
|
+
puts "XYZ(PRN:#{prn}): #{eph.constellation(t_meas)[0].to_a} (iodc: #{eph.iodc}, iode: #{eph.iode})"
|
413
|
+
}
|
414
|
+
}
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|