gps_pvt 0.8.0 → 0.8.1

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.
@@ -765,9 +765,70 @@ __RINEX_CLK_TEXT__
765
765
  [:alpha, :beta].each{|k|
766
766
  puts "Iono #{k}: #{sn.iono_utc.send(k)}"
767
767
  }
768
+ proc{|raw|
769
+ expect(raw.size).to eq(10)
770
+ puts "Raw(IONO): #{raw.collect{|v| "0x%08X" % [v]}.join(', ')}"
771
+ iono2 = GPS::Ionospheric_UTC_Parameters::parse(raw)
772
+ [:alpha, :beta].collect{|f|
773
+ sn.iono_utc.send(f).zip(iono2.send(f))
774
+ }.flatten(1).zip([-30, -27, -24, -24, 11, 14, 16, 16]).each{|(a, b), sf|
775
+ expect(a).to be_within((2 ** sf) * 2).of(b)
776
+ }
777
+ [
778
+ [:A1, 2 ** -50], [:A0, 2 ** -30],
779
+ ].each{|k, sf|
780
+ #p [k, sf.to_f, sn.iono_utc.send(k) - iono2.send(k), sn.iono_utc.send(k), iono2.send(k)]
781
+ expect(sn.iono_utc.send(k)).to be_within((sf || 1).to_f * 2).of(iono2.send(k))
782
+ }
783
+ }.call(sn.iono_utc.dump(t_meas))
768
784
 
769
785
  meas.each{|prn, k, v|
770
786
  eph = sn.ephemeris(prn)
787
+ expect(eph.valid?(t_meas)).to eq(true)
788
+ sc2rad = 3.1415926535898
789
+ proc{|raw|
790
+ expect(raw.size).to eq(30)
791
+ eph2 = GPS::Ephemeris::new
792
+ raw.each_slice(10).with_index{|subframe, i|
793
+ puts "Raw(PRN:#{prn},SF:#{i+1}): #{subframe.collect{|v| "0x%08X" % [v]}.join(', ')}"
794
+ eph2.parse(subframe)
795
+ }
796
+ expect(eph.WN % 1024).to be(eph2.WN % 1024)
797
+ [
798
+ #:URA,
799
+ :SV_health, :iodc,
800
+ [:t_GD, 2 ** -31], [:t_oc, 2 ** 4], # SF1
801
+ [:a_f0, 2 ** -31], [:a_f1, 2 ** -43], [:a_f2, 2 ** -55], # SF1
802
+ :iode, # SF2
803
+ [:c_rs, 2 ** -5], [:delta_n, sc2rad * 2 ** -43], # SF2
804
+ [:M0, sc2rad * 2 ** -31], [:c_uc, 2 ** -29], [:e, 2 ** -33], # SF2
805
+ [:c_us, 2 ** -29], [:sqrt_A, 2 ** -19], [:t_oe, 2 ** 4], # SF2
806
+ :fit_interval, # SF2
807
+ [:c_ic, 2 ** -29], [:Omega0, sc2rad * 2 ** -31], [:c_is, 2 ** -29], # SF3
808
+ [:i0, sc2rad * 2 ** -31], [:c_rc, 2 ** -5], [:omega, sc2rad * 2 ** -31], # SF3
809
+ [:dot_Omega0, sc2rad * 2 ** -43], [:dot_i0, sc2rad * 2 ** -43], # SF3
810
+ ].each{|k, sf|
811
+ #p [k, sf.to_f, eph.send(k) - eph2.send(k), eph.send(k), eph2.send(k)]
812
+ expect(eph.send(k)).to be_within((sf || 1).to_f * 2).of(eph2.send(k))
813
+ }
814
+ }.call(eph.dump(t_meas))
815
+ proc{|raw| # Almanac -> Ephemeris
816
+ expect(raw.size).to eq(10)
817
+ puts "Raw(PRN:#{prn},Almanac): #{raw.collect{|v| "0x%08X" % [v]}.join(', ')}"
818
+ eph2 = GPS::Ephemeris::new
819
+ eph2.parse_almanac(raw)
820
+ [
821
+ :SV_health,
822
+ [:t_oc, 2 ** 12], [:a_f0, 2 ** -20], [:a_f1, 2 ** -38],
823
+ [:M0, sc2rad * 2 ** -23], [:e, 2 ** -21],
824
+ [:sqrt_A, 2 ** -11], [:t_oe, 2 ** 12],
825
+ [:Omega0, sc2rad * 2 ** -23], [:i0, sc2rad * 2 ** -19],
826
+ [:omega, sc2rad * 2 ** -23], [:dot_Omega0, sc2rad * 2 ** -38],
827
+ ].each{|k, sf|
828
+ #p [k, sf.to_f, eph.send(k) - eph2.send(k), eph.send(k), eph2.send(k)]
829
+ expect(eph.send(k)).to be_within((sf || 1).to_f * 2).of(eph2.send(k))
830
+ }
831
+ }.call(eph.dump_almanac(t_meas))
771
832
  puts "XYZ(PRN:#{prn}): #{eph.constellation(t_meas)[0].to_a} (iodc: #{eph.iodc}, iode: #{eph.iode})"
772
833
  }
773
834
 
@@ -0,0 +1,84 @@
1
+ #ifndef __BIT_COUNTER__
2
+ #define __BIT_COUNTER__
3
+
4
+ #include <climits>
5
+
6
+ using namespace std;
7
+
8
+ /**
9
+ * Counting bits utility
10
+ */
11
+ template <class T>
12
+ struct BitCounter {
13
+
14
+ static const int num_of_bits = CHAR_BIT * sizeof(T);
15
+
16
+ private:
17
+ template <int Interval>
18
+ static T make_mask(){
19
+ /*
20
+ * @see http://www.nminoru.jp/~nminoru/programming/bitcount.html
21
+ *
22
+ * 01010101010101010101010101010101 1 32
23
+ * 00110011001100110011001100110011 2 32
24
+ * 00001111000011110000111100001111 4 32
25
+ * 00000000111111110000000011111111 8 32
26
+ * 00000000000000001111111111111111 16 32
27
+ */
28
+
29
+ T mask(1);
30
+ for(int i(1); i < Interval; i++){
31
+ mask <<= 1;
32
+ mask |= 0x01;
33
+ }
34
+ /*
35
+ // Equivalent to the following if T is built-in type
36
+ mask <<= Interval;
37
+ mask = (mask & (-mask)) - 1;
38
+ */
39
+
40
+ T res(mask);
41
+ for(unsigned int i(1); i < num_of_bits / Interval / 2; i++){
42
+ res <<= Interval;
43
+ res <<= Interval;
44
+ res |= mask;
45
+ }
46
+ return res;
47
+ }
48
+
49
+ template <int Interval, class U = void>
50
+ struct count_loop {
51
+ static T run(T bits){
52
+ bits = count_loop<(Interval >> 1)>::run(bits);
53
+ static const T mask(make_mask<Interval>());
54
+ // bit shift and add operators are required at least
55
+ return (bits & mask) + ((bits >> Interval) & mask);
56
+ }
57
+ };
58
+ template <class U>
59
+ struct count_loop<1, U> {
60
+ static T run(T bits){
61
+ static const T mask(make_mask<1>());
62
+ return (bits & mask) + ((bits >> 1) & mask);
63
+ }
64
+ };
65
+
66
+ public:
67
+ /**
68
+ * Count bits in a value
69
+ * @param results
70
+ */
71
+ static T count(const T &v) {
72
+ return count_loop<(num_of_bits >> 1)>::run(v);
73
+ }
74
+
75
+ /**
76
+ * Count rightmost zeros before the first one (Number of trailing zeros)
77
+ * @param bits results
78
+ */
79
+ static T ntz(const T &v) {
80
+ return count((T)((~v) & (v - 1)));
81
+ }
82
+ };
83
+
84
+ #endif /* __BIT_COUNTER__ */
@@ -0,0 +1,51 @@
1
+ =begin
2
+ Receiver extension
3
+ =end
4
+
5
+ module GPS_PVT
6
+ class Receiver
7
+
8
+ # shortcut to access ephemeris registered in receiver
9
+ def ephemeris(t, sys, prn)
10
+ eph = case sys
11
+ when :GPS, :QZSS
12
+ critical{
13
+ @solver.gps_space_node.update_all_ephemeris(t)
14
+ @solver.gps_space_node.ephemeris(prn)
15
+ }
16
+ when :SBAS
17
+ critical{
18
+ @solver.sbas_space_node.update_all_ephemeris(t)
19
+ @solver.sbas_space_node.ephemeris(prn)
20
+ }
21
+ when :GLONASS
22
+ critical{
23
+ @solver.glonass_space_node.update_all_ephemeris(t)
24
+ @solver.glonass_space_node.ephemeris(prn)
25
+ }
26
+ else
27
+ return nil
28
+ end
29
+ return (eph.valid?(t) ? eph : nil)
30
+ end
31
+
32
+ def attach_online_ephemeris(uri_template = nil)
33
+ if (!uri_template) || (uri_template =~ /^\s*$/) then
34
+ uri_template = "ftp://gssc.esa.int/gnss/data/daily/%Y/brdc/BRDC00IGS_R_%Y%j0000_01D_MN.rnx.gz"
35
+ end
36
+ loader = proc{|t_meas|
37
+ utc = Time::utc(*t_meas.c_tm)
38
+ uri = URI::parse(utc.strftime(uri_template))
39
+ self.parse_rinex_nav(uri)
40
+ uri
41
+ }
42
+ run_orig = self.method(:run)
43
+ eph_list = {}
44
+ self.define_singleton_method(:run){|meas, t_meas, *args|
45
+ w_d = [t_meas.week, (t_meas.seconds.to_i / 86400)]
46
+ eph_list[w_d] ||= loader.call(t_meas)
47
+ run_orig.call(meas, t_meas, *args)
48
+ }
49
+ end
50
+ end
51
+ end
@@ -3,7 +3,7 @@ Receiver class to be an top level interface to a user
3
3
  (The origin is ninja-scan-light/tool/misc/receiver_debug.rb)
4
4
  =end
5
5
 
6
- require_relative 'GPS'
6
+ require 'gps_pvt/GPS' # in case GPS.so is generated under ext/gps_pvt
7
7
  require_relative 'util'
8
8
 
9
9
  module GPS_PVT
@@ -523,6 +523,8 @@ class Receiver
523
523
  v
524
524
  }
525
525
  sys, svid = gnss_serial.call(*loader.call(36, 2).reverse)
526
+ # sigID check to restrict signal to L1 if version(>0); @see UBX-18010854
527
+ next if (packet[6 + 13] != 0) && (loader.call(38, 1, "C") != 0)
526
528
  case sys
527
529
  when :GPS, :SBAS, :QZSS;
528
530
  when :GLONASS
@@ -556,10 +558,13 @@ class Receiver
556
558
  register_ephemeris(
557
559
  t_meas,
558
560
  sys, svid,
559
- packet.slice(6 + 2, 40).each_slice(4).collect{|v|
560
- res = v.pack("C*").unpack("V")[0]
561
- (sys == :GPS) ? ((res & 0xFFFFFF) << 6) : res
562
- })
561
+ proc{|data|
562
+ case sys # adjust padding
563
+ when :GPS; data.collect!{|v| (v & 0xFFFFFF) << 6}
564
+ when :SBAS; data[7] <<= 6
565
+ end
566
+ data
567
+ }.call(packet.slice(6 + 2, 40).pack("C*").unpack("V*")))
563
568
  when [0x02, 0x13] # RXM-SFRBX
564
569
  sys, svid = gnss_serial.call(packet[6 + 1], packet[6])
565
570
  opt = {}
@@ -567,9 +572,7 @@ class Receiver
567
572
  register_ephemeris(
568
573
  t_meas,
569
574
  sys, svid,
570
- packet.slice(6 + 8, 4 * packet[6 + 4]).each_slice(4).collect{|v|
571
- v.pack("C*").unpack("V")[0]
572
- }, opt)
575
+ packet.slice(6 + 8, 4 * packet[6 + 4]).pack("C*").unpack("V*"), opt)
573
576
  end
574
577
  }
575
578
  $stderr.puts ", found packets are %s"%[ubx_kind.inspect]
@@ -696,3 +699,5 @@ class Receiver
696
699
  end
697
700
  end
698
701
  end
702
+
703
+ require_relative 'receiver/extension'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GPS_PVT
4
- VERSION = "0.8.0"
4
+ VERSION = "0.8.1"
5
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.8.0
4
+ version: 0.8.1
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-09-13 00:00:00.000000000 Z
11
+ date: 2022-11-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyserial
@@ -112,11 +112,13 @@ files:
112
112
  - ext/ninja-scan-light/tool/swig/makefile
113
113
  - ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb
114
114
  - ext/ninja-scan-light/tool/swig/spec/SylphideMath_spec.rb
115
+ - ext/ninja-scan-light/tool/util/bit_counter.h
115
116
  - ext/ninja-scan-light/tool/util/text_helper.h
116
117
  - gps_pvt.gemspec
117
118
  - gps_pvt.rbs
118
119
  - lib/gps_pvt.rb
119
120
  - lib/gps_pvt/receiver.rb
121
+ - lib/gps_pvt/receiver/extension.rb
120
122
  - lib/gps_pvt/ubx.rb
121
123
  - lib/gps_pvt/util.rb
122
124
  - lib/gps_pvt/version.rb