gps_pvt 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a75bed6b9453e7fe5b435eb2c10bd82e7c736654b6d34461368b79274ee223e3
4
- data.tar.gz: 55577769f09988ce63809f52b14a82bfa7fd958f68547f36263647b147559831
3
+ metadata.gz: 27cf7edda7d1df217cef7291fffdd3ab5837c8c09854dc8bb169b2bbe2880339
4
+ data.tar.gz: 2d818aa2d59114445a03417a5382fbc19994bca67cd62c48c9d5a86cbcb05dac
5
5
  SHA512:
6
- metadata.gz: 01c350f1e321119d0b4693a9b96bc99003b92e37783cdc53f0779e02111ec880d2b26e30e1f1ccec81faaaca16d730b8e17a5d24eb9bacd2934fe0ffaf083284
7
- data.tar.gz: 6cab5c290099b0dd7604940822c9399dc93d7656651fe4c38003202745c8b5f561c68cb452ece7c2d9b35740d7621b47e809341cec2228d3551e3238e2648c23
6
+ metadata.gz: f7f9a5ae7a47195eebf77d8c403cc6ec96596a9389b388aae1f8ec3f0d97c8086505e4c851c09db5aa2469a97b24325d8a644456fc602d931aa234dfaf7f4739
7
+ data.tar.gz: 191293262a0b1990292416be5c53f65699bd8d8e152534e3ca4b5dd155be665bc73fd6de94a72bcb18fd8f4e24185a612e8a1a6fdbf7899c65cb879923f59bc7
data/README.md CHANGED
@@ -42,7 +42,7 @@ The format of file is automatically determined with its extension, such as .ubx
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
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) |
45
- | <a name=opt_rtcm3>--rtcm3=file_or_URI</a> | [RTCM 10403.x](https://rtcm.myshopify.com/collections/differential-global-navigation-satellite-dgnss-standards), ephemeris and MSM7 are used. (supported gps_pvt version >= 0.9.0) |
45
+ | <a name=opt_rtcm3>--rtcm3=file_or_URI</a> | [RTCM 10403.x](https://rtcm.myshopify.com/collections/differential-global-navigation-satellite-dgnss-standards). (supported gps_pvt version >= 0.9.0) The latest version uses message type Observation(GPS: 1002, 1004; GLONASS: 1010, 1012), Epehemris(GPS: 1019; GLOANSS: 1020; SBAS: 1043; QZSS: 1044), MSM(GPS: 1074..1077; GLONASS: 1084..1087; SBAS: 1104..1107; QZSS: 1114..1117) |
46
46
 
47
47
  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
48
48
 
@@ -2406,6 +2406,10 @@ struct GLONASS_Ephemeris
2406
2406
  bool is_consistent() const {
2407
2407
  return has_string == 0x1F;
2408
2408
  }
2409
+ bool is_in_range(const GPS_Time<FloatT> &t) const {
2410
+ // "invalidate()" is used to make raw and converted data inconsistent.
2411
+ return eph_t::is_valid(t);
2412
+ }
2409
2413
  bool is_valid(const GPS_Time<FloatT> &t) const {
2410
2414
  return is_consistent() && eph_t::is_valid(t);
2411
2415
  }
@@ -4375,10 +4379,10 @@ SWIGINTERN double SBAS_Ephemeris_Sl_double_Sg__set_t_0(SBAS_Ephemeris< double >
4375
4379
  SWIGINTERN double const &SBAS_Ephemeris_Sl_double_Sg__get_t_0(SBAS_Ephemeris< double > const *self){
4376
4380
  return self->t_0;
4377
4381
  }
4378
- SWIGINTERN int SBAS_Ephemeris_Sl_double_Sg__set_URA(SBAS_Ephemeris< double > *self,int const &v){
4382
+ SWIGINTERN double SBAS_Ephemeris_Sl_double_Sg__set_URA(SBAS_Ephemeris< double > *self,double const &v){
4379
4383
  return self->URA= v;
4380
4384
  }
4381
- SWIGINTERN int const &SBAS_Ephemeris_Sl_double_Sg__get_URA(SBAS_Ephemeris< double > const *self){
4385
+ SWIGINTERN double const &SBAS_Ephemeris_Sl_double_Sg__get_URA(SBAS_Ephemeris< double > const *self){
4382
4386
  return self->URA;
4383
4387
  }
4384
4388
  SWIGINTERN double SBAS_Ephemeris_Sl_double_Sg__set_x(SBAS_Ephemeris< double > *self,double const &v){
@@ -4750,10 +4754,6 @@ SWIGINTERN GPS_Ephemeris< double >::constellation_res_t GLONASS_Ephemeris_Sl_dou
4750
4754
  pv.position, pv.velocity, self->clock_error(t_tx), self->clock_error_dot()};
4751
4755
  return res;
4752
4756
  }
4753
- SWIGINTERN bool GLONASS_Ephemeris_Sl_double_Sg__is_in_range(GLONASS_Ephemeris< double > const *self,GPS_Time< double > const &t){
4754
- // "invalidate()" is used to make raw and converted data inconsistent.
4755
- return self->is_valid(t);
4756
- }
4757
4757
  SWIGINTERN void RINEX_Observation_Sl_double_Sg__read(char const *fname){
4758
4758
  std::fstream fin(fname, std::ios::in | std::ios::binary);
4759
4759
  struct reader_t : public RINEX_OBS_Reader<double> {
@@ -18732,7 +18732,7 @@ fail:
18732
18732
  Document-method: GPS_PVT::GPS::Ephemeris_SBAS.URA=
18733
18733
 
18734
18734
  call-seq:
18735
- URA=(int const & v) -> int
18735
+ URA=(double const & v) -> double
18736
18736
 
18737
18737
  An instance method.
18738
18738
 
@@ -18740,13 +18740,13 @@ An instance method.
18740
18740
  SWIGINTERN VALUE
18741
18741
  _wrap_Ephemeris_SBAS_URAe___(int argc, VALUE *argv, VALUE self) {
18742
18742
  SBAS_Ephemeris< double > *arg1 = (SBAS_Ephemeris< double > *) 0 ;
18743
- int *arg2 = 0 ;
18743
+ double *arg2 = 0 ;
18744
18744
  void *argp1 = 0 ;
18745
18745
  int res1 = 0 ;
18746
- int temp2 ;
18747
- int val2 ;
18746
+ double temp2 ;
18747
+ double val2 ;
18748
18748
  int ecode2 = 0 ;
18749
- int result;
18749
+ double result;
18750
18750
  VALUE vresult = Qnil;
18751
18751
 
18752
18752
  if ((argc < 1) || (argc > 1)) {
@@ -18757,15 +18757,15 @@ _wrap_Ephemeris_SBAS_URAe___(int argc, VALUE *argv, VALUE self) {
18757
18757
  SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "SBAS_Ephemeris< double > *","set_URA", 1, self ));
18758
18758
  }
18759
18759
  arg1 = reinterpret_cast< SBAS_Ephemeris< double > * >(argp1);
18760
- ecode2 = SWIG_AsVal_int(argv[0], &val2);
18760
+ ecode2 = SWIG_AsVal_double(argv[0], &val2);
18761
18761
  if (!SWIG_IsOK(ecode2)) {
18762
- SWIG_exception_fail(SWIG_ArgError(ecode2), Ruby_Format_TypeError( "", "int","set_URA", 2, argv[0] ));
18762
+ SWIG_exception_fail(SWIG_ArgError(ecode2), Ruby_Format_TypeError( "", "double","set_URA", 2, argv[0] ));
18763
18763
  }
18764
- temp2 = static_cast< int >(val2);
18764
+ temp2 = static_cast< double >(val2);
18765
18765
  arg2 = &temp2;
18766
18766
  {
18767
18767
  try {
18768
- result = (int)SBAS_Ephemeris_Sl_double_Sg__set_URA(arg1,(int const &)*arg2);
18768
+ result = (double)SBAS_Ephemeris_Sl_double_Sg__set_URA(arg1,(double const &)*arg2);
18769
18769
  } catch (const native_exception &e) {
18770
18770
  e.regenerate();
18771
18771
  SWIG_fail;
@@ -18773,7 +18773,7 @@ _wrap_Ephemeris_SBAS_URAe___(int argc, VALUE *argv, VALUE self) {
18773
18773
  SWIG_exception_fail(SWIG_RuntimeError, e.what());
18774
18774
  }
18775
18775
  }
18776
- vresult = SWIG_From_int(static_cast< int >(result));
18776
+ vresult = SWIG_From_double(static_cast< double >(result));
18777
18777
  return vresult;
18778
18778
  fail:
18779
18779
  return Qnil;
@@ -18784,7 +18784,7 @@ fail:
18784
18784
  Document-method: GPS_PVT::GPS::Ephemeris_SBAS.URA
18785
18785
 
18786
18786
  call-seq:
18787
- URA -> int const &
18787
+ URA -> double const &
18788
18788
 
18789
18789
  An instance method.
18790
18790
 
@@ -18794,7 +18794,7 @@ _wrap_Ephemeris_SBAS_URA(int argc, VALUE *argv, VALUE self) {
18794
18794
  SBAS_Ephemeris< double > *arg1 = (SBAS_Ephemeris< double > *) 0 ;
18795
18795
  void *argp1 = 0 ;
18796
18796
  int res1 = 0 ;
18797
- int *result = 0 ;
18797
+ double *result = 0 ;
18798
18798
  VALUE vresult = Qnil;
18799
18799
 
18800
18800
  if ((argc < 0) || (argc > 0)) {
@@ -18807,7 +18807,7 @@ _wrap_Ephemeris_SBAS_URA(int argc, VALUE *argv, VALUE self) {
18807
18807
  arg1 = reinterpret_cast< SBAS_Ephemeris< double > * >(argp1);
18808
18808
  {
18809
18809
  try {
18810
- result = (int *) &SBAS_Ephemeris_Sl_double_Sg__get_URA((SBAS_Ephemeris< double > const *)arg1);
18810
+ result = (double *) &SBAS_Ephemeris_Sl_double_Sg__get_URA((SBAS_Ephemeris< double > const *)arg1);
18811
18811
  } catch (const native_exception &e) {
18812
18812
  e.regenerate();
18813
18813
  SWIG_fail;
@@ -18815,7 +18815,7 @@ _wrap_Ephemeris_SBAS_URA(int argc, VALUE *argv, VALUE self) {
18815
18815
  SWIG_exception_fail(SWIG_RuntimeError, e.what());
18816
18816
  }
18817
18817
  }
18818
- vresult = SWIG_From_int(static_cast< int >(*result));
18818
+ vresult = SWIG_From_double(static_cast< double >(*result));
18819
18819
  return vresult;
18820
18820
  fail:
18821
18821
  return Qnil;
@@ -22603,6 +22603,59 @@ fail:
22603
22603
  }
22604
22604
 
22605
22605
 
22606
+ /*
22607
+ Document-method: GPS_PVT::GPS::Ephemeris_GLONASS.in_range?
22608
+
22609
+ call-seq:
22610
+ in_range?(Time t) -> bool
22611
+
22612
+ An instance method.
22613
+
22614
+ */
22615
+ SWIGINTERN VALUE
22616
+ _wrap_Ephemeris_GLONASS_in_rangeq___(int argc, VALUE *argv, VALUE self) {
22617
+ GLONASS_Ephemeris< double > *arg1 = (GLONASS_Ephemeris< double > *) 0 ;
22618
+ GPS_Time< double > *arg2 = 0 ;
22619
+ void *argp1 = 0 ;
22620
+ int res1 = 0 ;
22621
+ void *argp2 ;
22622
+ int res2 = 0 ;
22623
+ bool result;
22624
+ VALUE vresult = Qnil;
22625
+
22626
+ if ((argc < 1) || (argc > 1)) {
22627
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)",argc); SWIG_fail;
22628
+ }
22629
+ res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_GLONASS_EphemerisT_double_t, 0 | 0 );
22630
+ if (!SWIG_IsOK(res1)) {
22631
+ SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "GLONASS_Ephemeris< double > const *","is_in_range", 1, self ));
22632
+ }
22633
+ arg1 = reinterpret_cast< GLONASS_Ephemeris< double > * >(argp1);
22634
+ res2 = SWIG_ConvertPtr(argv[0], &argp2, SWIGTYPE_p_GPS_TimeT_double_t, 0 );
22635
+ if (!SWIG_IsOK(res2)) {
22636
+ SWIG_exception_fail(SWIG_ArgError(res2), Ruby_Format_TypeError( "", "GPS_Time< double > const &","is_in_range", 2, argv[0] ));
22637
+ }
22638
+ if (!argp2) {
22639
+ SWIG_exception_fail(SWIG_ValueError, Ruby_Format_TypeError("invalid null reference ", "GPS_Time< double > const &","is_in_range", 2, argv[0]));
22640
+ }
22641
+ arg2 = reinterpret_cast< GPS_Time< double > * >(argp2);
22642
+ {
22643
+ try {
22644
+ result = (bool)((GLONASS_Ephemeris< double > const *)arg1)->is_in_range((GPS_Time< double > const &)*arg2);
22645
+ } catch (const native_exception &e) {
22646
+ e.regenerate();
22647
+ SWIG_fail;
22648
+ } catch (const std::exception& e) {
22649
+ SWIG_exception_fail(SWIG_RuntimeError, e.what());
22650
+ }
22651
+ }
22652
+ vresult = SWIG_From_bool(static_cast< bool >(result));
22653
+ return vresult;
22654
+ fail:
22655
+ return Qnil;
22656
+ }
22657
+
22658
+
22606
22659
  /*
22607
22660
  Document-method: GPS_PVT::GPS::Ephemeris_GLONASS.valid?
22608
22661
 
@@ -26483,59 +26536,6 @@ fail:
26483
26536
  }
26484
26537
 
26485
26538
 
26486
- /*
26487
- Document-method: GPS_PVT::GPS::Ephemeris_GLONASS.in_range?
26488
-
26489
- call-seq:
26490
- in_range?(Time t) -> bool
26491
-
26492
- An instance method.
26493
-
26494
- */
26495
- SWIGINTERN VALUE
26496
- _wrap_Ephemeris_GLONASS_in_rangeq___(int argc, VALUE *argv, VALUE self) {
26497
- GLONASS_Ephemeris< double > *arg1 = (GLONASS_Ephemeris< double > *) 0 ;
26498
- GPS_Time< double > *arg2 = 0 ;
26499
- void *argp1 = 0 ;
26500
- int res1 = 0 ;
26501
- void *argp2 ;
26502
- int res2 = 0 ;
26503
- bool result;
26504
- VALUE vresult = Qnil;
26505
-
26506
- if ((argc < 1) || (argc > 1)) {
26507
- rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)",argc); SWIG_fail;
26508
- }
26509
- res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_GLONASS_EphemerisT_double_t, 0 | 0 );
26510
- if (!SWIG_IsOK(res1)) {
26511
- SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "GLONASS_Ephemeris< double > const *","is_in_range", 1, self ));
26512
- }
26513
- arg1 = reinterpret_cast< GLONASS_Ephemeris< double > * >(argp1);
26514
- res2 = SWIG_ConvertPtr(argv[0], &argp2, SWIGTYPE_p_GPS_TimeT_double_t, 0 );
26515
- if (!SWIG_IsOK(res2)) {
26516
- SWIG_exception_fail(SWIG_ArgError(res2), Ruby_Format_TypeError( "", "GPS_Time< double > const &","is_in_range", 2, argv[0] ));
26517
- }
26518
- if (!argp2) {
26519
- SWIG_exception_fail(SWIG_ValueError, Ruby_Format_TypeError("invalid null reference ", "GPS_Time< double > const &","is_in_range", 2, argv[0]));
26520
- }
26521
- arg2 = reinterpret_cast< GPS_Time< double > * >(argp2);
26522
- {
26523
- try {
26524
- result = (bool)GLONASS_Ephemeris_Sl_double_Sg__is_in_range((GLONASS_Ephemeris< double > const *)arg1,(GPS_Time< double > const &)*arg2);
26525
- } catch (const native_exception &e) {
26526
- e.regenerate();
26527
- SWIG_fail;
26528
- } catch (const std::exception& e) {
26529
- SWIG_exception_fail(SWIG_RuntimeError, e.what());
26530
- }
26531
- }
26532
- vresult = SWIG_From_bool(static_cast< bool >(result));
26533
- return vresult;
26534
- fail:
26535
- return Qnil;
26536
- }
26537
-
26538
-
26539
26539
  SWIGINTERN void
26540
26540
  free_GLONASS_Ephemeris_Sl_double_Sg_(void *self) {
26541
26541
  GLONASS_Ephemeris< double > *arg1 = (GLONASS_Ephemeris< double > *)self;
@@ -28978,6 +28978,7 @@ SWIGEXPORT void Init_GPS(void) {
28978
28978
  rb_define_method(SwigClassEphemeris_GLONASS.klass, "raw", VALUEFUNC(_wrap_Ephemeris_GLONASS_raw_get), -1);
28979
28979
  rb_define_method(SwigClassEphemeris_GLONASS.klass, "invalidate", VALUEFUNC(_wrap_Ephemeris_GLONASS_invalidate), -1);
28980
28980
  rb_define_method(SwigClassEphemeris_GLONASS.klass, "consistent?", VALUEFUNC(_wrap_Ephemeris_GLONASS_consistentq___), -1);
28981
+ rb_define_method(SwigClassEphemeris_GLONASS.klass, "in_range?", VALUEFUNC(_wrap_Ephemeris_GLONASS_in_rangeq___), -1);
28981
28982
  rb_define_method(SwigClassEphemeris_GLONASS.klass, "valid?", VALUEFUNC(_wrap_Ephemeris_GLONASS_validq___), -1);
28982
28983
  rb_define_method(SwigClassEphemeris_GLONASS.klass, "rehash", VALUEFUNC(_wrap_Ephemeris_GLONASS_rehash), -1);
28983
28984
  rb_define_method(SwigClassEphemeris_GLONASS.klass, "svid=", VALUEFUNC(_wrap_Ephemeris_GLONASS_svide___), -1);
@@ -29047,7 +29048,6 @@ SWIGEXPORT void Init_GPS(void) {
29047
29048
  rb_define_method(SwigClassEphemeris_GLONASS.klass, "parse", VALUEFUNC(_wrap_Ephemeris_GLONASS_parse), -1);
29048
29049
  rb_define_method(SwigClassEphemeris_GLONASS.klass, "dump", VALUEFUNC(_wrap_Ephemeris_GLONASS_dump), -1);
29049
29050
  rb_define_method(SwigClassEphemeris_GLONASS.klass, "constellation", VALUEFUNC(_wrap_Ephemeris_GLONASS_constellation), -1);
29050
- rb_define_method(SwigClassEphemeris_GLONASS.klass, "in_range?", VALUEFUNC(_wrap_Ephemeris_GLONASS_in_rangeq___), -1);
29051
29051
  SwigClassEphemeris_GLONASS.mark = 0;
29052
29052
  SwigClassEphemeris_GLONASS.destroy = (void (*)(void *)) free_GLONASS_Ephemeris_Sl_double_Sg_;
29053
29053
  SwigClassEphemeris_GLONASS.trackObjects = 0;
@@ -571,7 +571,7 @@ struct SBAS_Ephemeris : public SBAS_SpaceNode<FloatT>::SatelliteProperties::Ephe
571
571
 
572
572
  MAKE_ACCESSOR(WN, unsigned int);
573
573
  MAKE_ACCESSOR(t_0, FloatT);
574
- MAKE_ACCESSOR(URA, int);
574
+ MAKE_ACCESSOR(URA, FloatT);
575
575
  MAKE_ACCESSOR( x, FloatT); MAKE_ACCESSOR( y, FloatT); MAKE_ACCESSOR( z, FloatT);
576
576
  MAKE_ACCESSOR( dx, FloatT); MAKE_ACCESSOR( dy, FloatT); MAKE_ACCESSOR( dz, FloatT);
577
577
  MAKE_ACCESSOR(ddx, FloatT); MAKE_ACCESSOR(ddy, FloatT); MAKE_ACCESSOR(ddz, FloatT);
@@ -654,6 +654,10 @@ struct GLONASS_Ephemeris
654
654
  bool is_consistent() const {
655
655
  return has_string == 0x1F;
656
656
  }
657
+ bool is_in_range(const GPS_Time<FloatT> &t) const {
658
+ // "invalidate()" is used to make raw and converted data inconsistent.
659
+ return eph_t::is_valid(t);
660
+ }
657
661
  bool is_valid(const GPS_Time<FloatT> &t) const {
658
662
  return is_consistent() && eph_t::is_valid(t);
659
663
  }
@@ -800,10 +804,6 @@ struct GLONASS_Ephemeris
800
804
  %rename("valid?") is_valid;
801
805
  %rename("in_range?") is_in_range;
802
806
  #endif
803
- bool is_in_range(const GPS_Time<FloatT> &t) const {
804
- // "invalidate()" is used to make raw and converted data inconsistent.
805
- return self->is_valid(t);
806
- }
807
807
  }
808
808
 
809
809
  %extend GLONASS_SpaceNode {
@@ -19,13 +19,88 @@ class Receiver
19
19
  end
20
20
  leap_sec = ref_time.leap_seconds
21
21
  after_run = b || proc{|pvt| puts pvt.to_s if pvt}
22
- t_meas, meas = [nil, GPS::Measurement::new]
22
+ t_meas, meas = [nil, {}]
23
+ # meas := {msg_num => [[], ...]} due to duplicated observation such as 1074 and 1077
24
+ run_proc = proc{
25
+ meas_ = GPS::Measurement::new
26
+ meas.sort.each{|k, values| # larger msg_num entries have higher priority
27
+ values.each{|prn_k_v| meas_.add(*prn_k_v)}
28
+ }
29
+ after_run.call(run(meas_, t_meas), [meas_, ref_time = t_meas]) if t_meas
30
+ t_meas, meas = [nil, {}]
31
+ }
23
32
  dt_threshold = GPS::Time::Seconds_week / 2
33
+ tow2t = proc{|tow_sec|
34
+ dt = tow_sec - ref_time.seconds
35
+ GPS::Time::new(ref_time.week + if dt <= -dt_threshold then; 1
36
+ elsif dt >= dt_threshold then; -1
37
+ else; 0; end, tow_sec)
38
+ }
39
+ utc2t = proc{|utc_tod|
40
+ if t_meas then
41
+ delta = (t_meas.seconds - utc_tod).to_i % (60 * 60 * 24)
42
+ leap_sec = (delta >= (60 * 60 * 12)) ? delta - (60 * 60 * 12) : delta
43
+ t_meas
44
+ else
45
+ ref_dow, ref_tod = ref_time.seconds.divmod(60 * 60 * 24)
46
+ tod = utc_tod + leap_sec
47
+ tod_delta = ref_tod - tod
48
+ if tod_delta > 12 * 60 * 60 then
49
+ ref_dow -= 1
50
+ elsif tod_delta < -12 * 60 * 60 then
51
+ ref_dow += 1
52
+ end
53
+ GPS::Time::new(ref_time.week, 0) + tod + 60 * 60 * 24 * ref_dow
54
+ end
55
+ }
24
56
 
25
57
  while packet = rtcm3.read_packet
26
58
  msg_num = packet.message_number
27
59
  parsed = packet.parse
60
+ t_meas2, meas2 = [nil, []] # per_packet
61
+ add_proc = proc{
62
+ t_meas ||= t_meas2
63
+ meas[msg_num] = meas2 unless meas2.empty?
64
+ }
28
65
  case msg_num
66
+ when 1001..1004
67
+ t_meas2 = tow2t.call(parsed[2][0]) # DF004
68
+ ranges = parsed.ranges
69
+ item_size = ranges[:sat].size
70
+ [:sat, :pseudo_range, :phase_range, :cn].collect{|k|
71
+ ranges[k] || ([nil] * item_size)
72
+ }.transpose.each{|svid, pr, cpr, cn|
73
+ case svid
74
+ when 1..32; # GPS
75
+ when 40..58; svid += 80 # SBAS
76
+ else; next
77
+ end
78
+ meas2 << [svid, :L1_PSEUDORANGE, pr] if pr
79
+ meas2 << [svid, :L1_CARRIER_PHASE, cpr / GPS::SpaceNode.L1_WaveLength] if cpr
80
+ meas2 << [svid, :L1_SIGNAL_STRENGTH_dBHz, cn] if cn
81
+ }
82
+ when 1009..1012
83
+ t_meas2 = utc2t.call(parsed[2][0] - 60 * 60 * 3) # DF034 UTC(SU)+3hr, time of day[sec]
84
+ ranges = parsed.ranges
85
+ item_size = ranges[:sat].size
86
+ [:sat, :freq_ch, :pseudo_range, :phase_range, :cn].collect{|k|
87
+ ranges[k] || ([nil] * item_size)
88
+ }.transpose.each{|svid, freq_ch, pr, cpr, cn|
89
+ case svid
90
+ when 1..24 # GLONASS
91
+ svid += 0x100
92
+ freq = GPS::SpaceNode_GLONASS::L1_frequency(freq_ch)
93
+ len = GPS::SpaceNode_GLONASS.light_speed / freq
94
+ meas2 << [svid, :L1_FREQUENCY, freq]
95
+ meas2 << [svid, :L1_CARRIER_PHASE, cpr / len] if cpr
96
+ when 40..58
97
+ svid += 80 # SBAS
98
+ meas2 << [svid, :L1_CARRIER_PHASE, cpr / GPS::SpaceNode.L1_WaveLength] if cpr
99
+ else; next
100
+ end
101
+ meas2 << [svid, :L1_PSEUDORANGE, pr] if pr
102
+ meas2 << [svid, :L1_SIGNAL_STRENGTH_dBHz, cn] if cn
103
+ }
29
104
  when 1019, 1044
30
105
  params = parsed.params
31
106
  if msg_num == 1044
@@ -55,55 +130,77 @@ class Receiver
55
130
  critical{
56
131
  @solver.glonass_space_node.register_ephemeris(eph.svid, eph)
57
132
  }
58
- when 1077, 1087, 1097, 1117
133
+ when 1043
134
+ params = parsed.params
135
+ eph = GPS::Ephemeris_SBAS::new
136
+ tod_delta = params[:tod] - (ref_time.seconds % (24 * 60 * 60))
137
+ if tod_delta > (12 * 60 * 60) then
138
+ tod_delta -= (24 * 60 * 60)
139
+ elsif tod_delta < -(12 * 60 * 60) then
140
+ tod_delta += (24 * 60 * 60)
141
+ end
142
+ toe = ref_time + tod_delta
143
+ eph.WN, eph.t_0 = [:week, :seconds].collect{|k| toe.send(k)}
144
+ params.each{|k, v| eph.send("#{k}=".to_sym, v) unless [:iodn, :tod].include?(k)}
145
+ critical{
146
+ @solver.sbas_space_node.register_ephemeris(eph.svid, eph)
147
+ }
148
+ when 1071..1077, 1081..1087, 1101..1107, 1111..1117
59
149
  ranges = parsed.ranges
60
- sig_list, svid_offset = case msg_num
61
- when 1077 # GPS
62
- t_meas ||= proc{ # update time of measurement
63
- t_meas_sec = parsed[2][0] # DF004
64
- dt = t_meas_sec - ref_time.seconds
65
- GPS::Time::new(ref_time.week + if dt <= -dt_threshold then; 1
66
- elsif dt >= dt_threshold then; -1
67
- else; 0; end, t_meas_sec)
68
- }.call
150
+ glonass_freq = nil
151
+ case msg_num / 10 # check time of measurement
152
+ when 107, 110, 111 # GPS, SBAS, QZSS
153
+ t_meas2 = tow2t.call(parsed[2][0]) # DF004
154
+ when 108 # GLONASS
155
+ t_meas2 = utc2t.call(parsed[3][0] - 60 * 60 * 3) # DF034 UTC(SU)+3hr, time of day[sec]
156
+ glonass_freq = critical{
157
+ @solver.glonass_space_node.update_all_ephemeris(t_meas2)
158
+ Hash[*(ranges[:sat_sig].collect{|svid, sig| svid}.uniq.collect{|svid|
159
+ eph = @solver.glonass_space_node.ephemeris(svid)
160
+ next nil unless eph.in_range?(t_meas2)
161
+ [svid, {:L1 => eph.frequency_L1}]
162
+ }.compact.flatten(1))]
163
+ }
164
+ end
165
+ sig_list, svid_offset = case msg_num / 10
166
+ when 107 # GPS
69
167
  [{2 => [:L1, GPS::SpaceNode.L1_WaveLength],
70
168
  15 => [:L2CM, GPS::SpaceNode.L2_WaveLength],
71
169
  16 => [:L2CL, GPS::SpaceNode.L2_WaveLength]}, 0]
72
- when 1087 # GLONASS
73
- proc{
74
- utc = parsed[3][0] - 60 * 60 * 3 # DF034 UTC(SU)+3hr
75
- delta = (t_meas.seconds - utc).to_i % (60 * 60 * 24)
76
- leap_sec = (delta >= (60 * 60 * 12)) ? delta - (60 * 60 * 12) : delta
77
- }.call if t_meas
78
- [{2 => [:L1, GPS::SpaceNode_GLONASS.light_speed / GPS::SpaceNode_GLONASS.L1_frequency_base]}, 0x100]
79
- when 1117 # QZSS
170
+ when 108 # GLONASS
171
+ [{2 => [:L1, nil]}, 0x100]
172
+ when 110 # SBAS
173
+ [{2 => [:L1, GPS::SpaceNode.L1_WaveLength]}, 120]
174
+ when 111 # QZSS
80
175
  [{2 => [:L1, GPS::SpaceNode.L1_WaveLength],
81
176
  15 => [:L2CM, GPS::SpaceNode.L2_WaveLength],
82
177
  16 => [:L2CL, GPS::SpaceNode.L2_WaveLength]}, 192]
83
178
  else; [{}, 0]
84
179
  end
85
- [:sat_sig, :pseudo_range, :phase_range, :phase_range_rate].collect{|k|
86
- ranges[k]
87
- }.transpose.each{|(svid, sig), pr, cpr, dr|
180
+ item_size = ranges[:sat_sig].size
181
+ [:sat_sig, :pseudo_range, :phase_range, :phase_range_rate, :cn].collect{|k|
182
+ ranges[k] || ([nil] * item_size)
183
+ }.transpose.each{|(svid, sig), pr, cpr, dr, cn|
88
184
  prefix, len = sig_list[sig]
89
185
  next unless prefix
90
- if svid_offset > 0 then
91
- @solver.glonass_space_node.update_all_ephemeris(t_meas)
92
- eph = @solver.glonass_space_node.ephemeris(svid)
93
- end
186
+ proc{
187
+ next unless freq = (glonass_freq[svid] || {})[prefix]
188
+ meas2 << [svid, "#{prefix}_FREQUENCY".to_sym, freq]
189
+ len = GPS::SpaceNode_GLONASS.light_speed / freq
190
+ }.call if glonass_freq
94
191
  svid += svid_offset
95
- meas.add(svid, "#{prefix}_PSEUDORANGE".to_sym, pr) if pr
96
- meas.add(svid, "#{prefix}_RANGE_RATE".to_sym, dr) if dr
97
- meas.add(svid, "#{prefix}_CARRIER_PHASE".to_sym, cpr / len) if cpr
192
+ meas2 << [svid, "#{prefix}_PSEUDORANGE".to_sym, pr] if pr
193
+ meas2 << [svid, "#{prefix}_RANGE_RATE".to_sym, dr] if dr
194
+ meas2 << [svid, "#{prefix}_CARRIER_PHASE".to_sym, cpr / len] if cpr && len
195
+ meas2 << [svid, "#{prefix}_SIGNAL_STRENGTH_dBHz".to_sym, cn] if cn
98
196
  }
99
197
  else
100
198
  #p({msg_num => parsed})
101
199
  end
102
- if (1070..1229).include?(msg_num) &&
103
- (!parsed.more_data? rescue (packet.decode([1], 24 + 54)[0] == 0)) then
104
- after_run.call(run(meas, t_meas), [meas, ref_time = t_meas]) if t_meas
105
- t_meas, meas = [nil, GPS::Measurement::new]
106
- end
200
+
201
+ run_proc.call if t_meas && t_meas2 && ((t_meas - t_meas2).abs > 1E-3) # fallback for incorrect more_data flag
202
+ add_proc.call
203
+ run_proc.call if (1070..1229).include?(msg_num) && (!parsed.more_data?)
107
204
  end
108
205
  end
109
206
  end
data/lib/gps_pvt/rtcm3.rb CHANGED
@@ -13,6 +13,7 @@ class RTCM3
13
13
  end
14
14
  module Packet
15
15
  def decode(bits_list, offset = nil)
16
+ # 24 is offset of header in transport layer
16
17
  Util::BitOp::extract(self, bits_list, offset || 24)
17
18
  end
18
19
  def message_number
@@ -56,15 +57,44 @@ class RTCM3
56
57
  2 => 12,
57
58
  3 => 12,
58
59
  4 => unum_gen.call(30, Rational(1, 1000)), # [sec]
60
+ 5 => 1,
61
+ 6 => 5,
62
+ 7 => 1,
63
+ 8 => 3,
59
64
  9 => 6,
65
+ 10 => 1,
66
+ 11 => invalidate.call(unum_gen.call(24, Rational(2, 100)), 0x800000), # [m]
67
+ 12 => invalidate.call(num_gen.call(20, Rational(5, 10000)), 0x80000), # [m]
68
+ 13 => 7,
69
+ 14 => unum_gen.call(8, 299_792.458), # [m]
70
+ 15 => invalidate.call(unum_gen.call(8, Rational(1, 4)), 0), # [db-Hz],
71
+ 16 => 2,
72
+ 17 => invalidate.call(num_gen.call(14, Rational(2, 100)), 0x2000), # [m]
73
+ 18 => num_gen.call(20, Rational(5, 10000)), # [m]
74
+ 19 => 7,
75
+ 20 => invalidate.call(unum_gen.call(8, Rational(1, 4)), 0), # [db-Hz]
60
76
  21 => 6,
61
77
  22 => 1,
62
78
  23 => 1,
63
79
  24 => 1,
64
80
  25 => num_gen.call(38, Rational(1, 10000)), # [m]
65
81
  34 => unum_gen.call(27, Rational(1, 1000)), # [sec]
82
+ 35 => 5,
83
+ 36 => 1,
84
+ 37 => 3,
66
85
  38 => 6,
67
- 40 => 5,
86
+ 39 => 1,
87
+ 40 => [5, proc{|v| v - 7}],
88
+ 41 => invalidate.call(unum_gen.call(25, Rational(2, 100)), 0x1000000), # [m]
89
+ 42 => invalidate.call(num_gen.call(20, Rational(5, 10000)), 0x80000), # [m]
90
+ 43 => 7,
91
+ 44 => unum_gen.call(7, 599_584.916), # [m]
92
+ 45 => invalidate.call(unum_gen.call(8, Rational(1, 4)), 0), # [db-Hz],
93
+ 46 => 2,
94
+ 47 => invalidate.call(num_gen.call(14, Rational(2, 100)), 0x2000), # [m]
95
+ 48 => invalidate.call(num_gen.call(20, Rational(5, 10000)), 0x80000), # [m]
96
+ 49 => 7,
97
+ 50 => invalidate.call(unum_gen.call(8, Rational(1, 4)), 0), # [db-Hz]
68
98
  71 => 8,
69
99
  76 => 10,
70
100
  77 => proc{
@@ -146,11 +176,15 @@ class RTCM3
146
176
  397 => invalidate.call(unum_gen.call(8, Rational(1, 1000)), 0xFF), # [sec]
147
177
  398 => unum_gen.call(10, Rational(1, 1000 << 10)), # [sec]
148
178
  399 => invalidate.call(num_gen.call(14), 0x2000), # [m/s]
179
+ 400 => invalidate.call(num_gen.call(15, Rational(1, 1000 << 24)), 0x4000), # [sec],
180
+ 401 => invalidate.call(num_gen.call(22, Rational(1, 1000 << 29)), 0x200000), # [sec],
181
+ 402 => 4,
182
+ 403 => invalidate.call(unum_gen.call(6), 0), # [dB-Hz],
149
183
  404 => invalidate.call(num_gen.call(15, Rational(1, 10000)), 0x4000), # [m/s]
150
184
  405 => invalidate.call(num_gen.call(20, Rational(1, 1000 << 29)), 0x80000), # [sec]
151
185
  406 => invalidate.call(num_gen.call(24, Rational(1, 1000 << 31)), 0x800000), # [sec]
152
186
  407 => 10,
153
- 408 => unum_gen.call(10, Rational(1, 1 << 4)), # [dB-Hz]
187
+ 408 => invalidate.call(unum_gen.call(10, Rational(1, 1 << 4)), 0), # [dB-Hz]
154
188
  409 => 3,
155
189
  411 => 2,
156
190
  412 => 2,
@@ -171,6 +205,20 @@ class RTCM3
171
205
  src = (src.to_a rescue [src]).flatten
172
206
  (dst.to_a rescue ([dst] * src.size)).flatten.zip(src).each{|i, j| df[i] = df[j]}
173
207
  }
208
+ df.merge!({
209
+ :SBAS_prn => [6, proc{|v| v + 120}],
210
+ :SBAS_iodn => 8,
211
+ :SBAS_tod => num_gen.call(13, 1 << 4),
212
+ :SBAS_ura => df[77],
213
+ :SBAS_xy => num_gen.call(30, Rational(8, 100)),
214
+ :SBAS_z => num_gen.call(25, Rational(4, 10)),
215
+ :SBAS_dxy => num_gen.call(17, Rational(1, 1600)),
216
+ :SBAS_dz => num_gen.call(18, Rational(1, 250)),
217
+ :SBAS_ddxy => num_gen.call(10, Rational(1, 80000)),
218
+ :SBAS_ddz => num_gen.call(10, Rational(1, 16000)),
219
+ :SBAS_agf0 => num_gen.call(12, Rational(1, 1 << 31)),
220
+ :SBAS_agf1 => num_gen.call(8, Rational(1, 1 << 40)),
221
+ })
174
222
  df.define_singleton_method(:generate_prop){|idx_list|
175
223
  hash = Hash[*([:bits, :op].collect.with_index{|k, i|
176
224
  [k, idx_list.collect{|idx, *args|
@@ -180,21 +228,79 @@ class RTCM3
180
228
  [prop].flatten(1)[i]
181
229
  }]
182
230
  }.flatten(1))].merge({:df => idx_list})
183
- hash[:bits_total] = hash[:bits].inject{|a, b| a + b}
231
+ hash[:bits_total] = hash[:bits].inject{|a, b| a + b} || 0
184
232
  hash
185
233
  }
186
234
  df
187
235
  }.call
188
236
  MessageType = Hash[*({
237
+ 1001..1004 => (2..8).to_a,
189
238
  1005 => [2, 3, 21, 22, 23, 24, 141, 25, 142, [1, 1], 26, 364, 27],
239
+ 1009..1012 => [2, 3, 34, 5, 35, 36, 37],
190
240
  1019 => [2, 9, (76..79).to_a, 71, (81..103).to_a, 137].flatten, # 488 bits @see Table 3.5-21
191
241
  1020 => [2, 38, 40, (104..136).to_a].flatten, # 360 bits @see Table 3.5-21
242
+ 1043 => [2] + [:prn, :iodn, :tod, :ura,
243
+ [:xy] * 2, :z, [:dxy] * 2, :dz, [:ddxy] * 2, :ddz,
244
+ :agf0, :agf1].flatten.collect{|k| "SBAS_#{k}".to_sym}, # @see BNC Ntrip client RTCM3Decorder.cpp
192
245
  1044 => [2, (429..457).to_a].flatten, # 485 bits
193
- 1077 => [2, 3, 4, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-78
194
- 1087 => [2, 3, 416, 34, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-93
195
- 1097 => [2, 3, 248, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-98
196
- 1117 => [2, 3, 4, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits
197
- }.collect{|mt, df_list| [mt, DataFrame.generate_prop(df_list)]}.flatten(1))]
246
+ 1071..1077 => [2, 3, 4, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-78
247
+ 1081..1087 => [2, 3, 416, 34, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-93
248
+ 1091..1097 => [2, 3, 248, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-98
249
+ 1101..1107 => [2, 3, 4, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits
250
+ 1111..1117 => [2, 3, 4, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits
251
+ 1121..1127 => [2, 3, 4, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits
252
+ }.collect{|mt_list, df_list|
253
+ (mt_list.to_a rescue [mt_list]).collect{|mt|
254
+ [mt, DataFrame.generate_prop(df_list)]
255
+ }
256
+ }.flatten(2))]
257
+ module GPS_Observation
258
+ def ranges
259
+ res = {
260
+ :sat => select{|v, df| df == 9}.transpose[0],
261
+ :pseudo_range_rem => select{|v, df| df == 11}.transpose[0],
262
+ }
263
+ add_proc = proc{|k, df, base|
264
+ values = select{|v, df_| df_ == df}
265
+ next if values.empty?
266
+ res[k] = values.transpose[0]
267
+ res[k] = res[k].zip(res[base]).collect{|a, b| (a + b) rescue nil} if base
268
+ }
269
+ add_proc.call(:pseudo_range, 14, :pseudo_range_rem)
270
+ suffix = res[:pseudo_range] ? "" : "_rem"
271
+ base = "pseudo_range#{suffix}".to_sym
272
+ add_proc.call("phase_range#{suffix}".to_sym, 12, base)
273
+ add_proc.call(:cn, 15)
274
+ add_proc.call("pseudo_range_L2#{suffix}".to_sym, 17, base)
275
+ add_proc.call("phase_range_L2#{suffix}".to_sym, 18, base)
276
+ add_proc.call(:cn_L2, 20)
277
+ res
278
+ end
279
+ end
280
+ module GLONASS_Observation
281
+ def ranges
282
+ res = {
283
+ :sat => select{|v, df| df == 38}.transpose[0],
284
+ :freq_ch => select{|v, df| df == 40}.transpose[0],
285
+ :pseudo_range_rem => select{|v, df| df == 41}.transpose[0],
286
+ }
287
+ add_proc = proc{|k, df, base|
288
+ values = select{|v, df_| df_ == df}
289
+ next if values.empty?
290
+ res[k] = values.transpose[0]
291
+ res[k] = res[k].zip(res[base]).collect{|a, b| (a + b) rescue nil} if base
292
+ }
293
+ add_proc.call(:pseudo_range, 44, :pseudo_range_rem)
294
+ suffix = res[:pseudo_range] ? "" : "_rem"
295
+ base = "pseudo_range#{suffix}".to_sym
296
+ add_proc.call("phase_range#{suffix}".to_sym, 42, base)
297
+ add_proc.call(:cn, 45)
298
+ add_proc.call("pseudo_range_L2#{suffix}".to_sym, 47, base)
299
+ add_proc.call("phase_range_L2#{suffix}".to_sym, 48, base)
300
+ add_proc.call(:cn_L2, 50)
301
+ res
302
+ end
303
+ end
198
304
  module GPS_Ephemeris
199
305
  KEY2IDX = {:svid => 1, :WN => 2, :URA => 3, :dot_i0 => 5, :iode => 6, :t_oc => 7,
200
306
  :a_f2 => 8, :a_f1 => 9, :a_f0 => 10, :iodc => 11, :c_rs => 12, :delta_n => 13,
@@ -218,6 +324,17 @@ class RTCM3
218
324
  res
219
325
  end
220
326
  end
327
+ module SBAS_Ephemeris
328
+ KEY2IDX = {:svid => 1, :iodn => 2, :tod => 3, :URA => 4,
329
+ :x => 5, :y => 6, :z => 7,
330
+ :dx => 8, :dy => 9, :dz => 10,
331
+ :ddx => 11, :ddy => 12, :ddz => 13,
332
+ :a_Gf0 => 14, :a_Gf1 => 15}
333
+ def params
334
+ # TODO WN is required to provide
335
+ Hash[*(KEY2IDX.collect{|k, i| [k, self[i][0]]}.flatten(1))]
336
+ end
337
+ end
221
338
  module GLONASS_Ephemeris
222
339
  def params
223
340
  # TODO insufficient: :n => ?(String4); extra: :P3
@@ -259,30 +376,63 @@ class RTCM3
259
376
  def more_data?
260
377
  self.find{|v| v[1] == 393}[0] == 1
261
378
  end
379
+ def property
380
+ idx_sat = self.find_index{|v| v[1] == 394}
381
+ {
382
+ :sats => self[idx_sat][0],
383
+ :cells => self[idx_sat + 2][0], # DF396
384
+ :header_items => idx_sat + 3,
385
+ }
386
+ end
262
387
  end
263
- module MSM7
388
+ module MSM
389
+ include MSM_Header
390
+ def ranges
391
+ {:sat_sig => property[:cells]} # expect to be overriden
392
+ end
264
393
  SPEED_OF_LIGHT = 299_792_458
394
+ end
395
+ module MSM4_6
396
+ include MSM
265
397
  def ranges
266
- idx_sat = self.find_index{|v| v[1] == 394}
267
- sats = self[idx_sat][0]
268
- nsat = sats.size
269
- cells = self[idx_sat + 2][0] # DF396
270
- ncell = cells.size
271
- offset = idx_sat + 3
398
+ sats, cells, offset = property.values_at(:sats, :cells, :header_items)
399
+ nsat, ncell = [sats.size, cells.size]
400
+ range_rough = self[offset, nsat] # DF397
401
+ range_rough2 = self[offset + (nsat * 1), nsat] # DF398
402
+ range_fine = self[offset + (nsat * 2), ncell] # DF400/405
403
+ phase_fine = self[offset + (nsat * 2) + (ncell * 1), ncell] # DF401/406
404
+ cn = self[offset + (nsat * 2) + (ncell * 4), ncell] # DF403/408
405
+ Hash[*([:sat_sig, :pseudo_range, :phase_range, :cn].zip(
406
+ [cells] + cells.collect.with_index{|(sat, sig), i|
407
+ i2 = sats.find_index(sat)
408
+ rough_ms = (range_rough2[i2][0] + range_rough[i2][0]) rescue nil
409
+ [(((range_fine[i][0] + rough_ms) * SPEED_OF_LIGHT) rescue nil),
410
+ (((phase_fine[i][0] + rough_ms) * SPEED_OF_LIGHT) rescue nil),
411
+ cn[i][0]]
412
+ }.transpose).flatten(1))]
413
+ end
414
+ end
415
+ module MSM5_7
416
+ include MSM
417
+ def ranges
418
+ sats, cells, offset = property.values_at(:sats, :cells, :header_items)
419
+ nsat, ncell = [sats.size, cells.size]
272
420
  range_rough = self[offset, nsat] # DF397
273
421
  range_rough2 = self[offset + (nsat * 2), nsat] # DF398
274
422
  delta_rough = self[offset + (nsat * 3), nsat] # DF399
275
- range_fine = self[offset + (nsat * 4), ncell] # DF405
276
- phase_fine = self[offset + (nsat * 4) + (ncell * 1), ncell] # DF406
423
+ range_fine = self[offset + (nsat * 4), ncell] # DF400/405
424
+ phase_fine = self[offset + (nsat * 4) + (ncell * 1), ncell] # DF401/406
425
+ cn = self[offset + (nsat * 4) + (ncell * 4), ncell] # DF403/408
277
426
  delta_fine = self[offset + (nsat * 4) + (ncell * 5), ncell] # DF404
278
- Hash[*([:pseudo_range, :phase_range, :phase_range_rate, :sat_sig].zip(
279
- cells.collect.with_index{|(sat, sig), i|
427
+ Hash[*([:sat_sig, :pseudo_range, :phase_range, :phase_range_rate, :cn].zip(
428
+ [cells] + cells.collect.with_index{|(sat, sig), i|
280
429
  i2 = sats.find_index(sat)
281
- rough_ms = (range_rough2[i2][0] + range_rough[i2][0]) rescue nil
430
+ rough_ms = (range_rough2[i2][0] + range_rough[i2][0]) rescue nil
282
431
  [(((range_fine[i][0] + rough_ms) * SPEED_OF_LIGHT) rescue nil),
283
432
  (((phase_fine[i][0] + rough_ms) * SPEED_OF_LIGHT) rescue nil),
284
- ((delta_fine[i][0] + delta_rough[i2][0]) rescue nil)]
285
- }.transpose + [cells]).flatten(1))]
433
+ ((delta_fine[i][0] + delta_rough[i2][0]) rescue nil),
434
+ cn[i][0]]
435
+ }.transpose).flatten(1))]
286
436
  end
287
437
  end
288
438
  def parse
@@ -298,28 +448,65 @@ class RTCM3
298
448
  }
299
449
  add_proc.call(mt)
300
450
  case msg_num
451
+ when 1001..1004
452
+ nsat = values[4]
453
+ offset = 24 + mt[:bits_total]
454
+ add_proc.call(DataFrame.generate_prop(([{
455
+ 1001 => (9..13).to_a,
456
+ 1002 => (9..15).to_a,
457
+ 1003 => (9..13).to_a + (16..19).to_a,
458
+ 1004 => (9..20).to_a,
459
+ }[msg_num]] * nsat).flatten), offset)
460
+ attributes << GPS_Observation
461
+ when 1009..1012
462
+ nsat = values[4]
463
+ offset = 24 + mt[:bits_total]
464
+ add_proc.call(DataFrame.generate_prop(([{
465
+ 1009 => (38..43).to_a,
466
+ 1010 => (38..45).to_a,
467
+ 1011 => (38..43).to_a + (46..49).to_a,
468
+ 1012 => (38..50).to_a,
469
+ }[msg_num]] * nsat).flatten), offset)
470
+ attributes << GLONASS_Observation
301
471
  when 1019
302
472
  attributes << GPS_Ephemeris
303
473
  when 1020
304
474
  attributes << GLONASS_Ephemeris
475
+ when 1043
476
+ attributes << SBAS_Ephemeris
305
477
  when 1044
306
478
  attributes << QZSS_Ephemeris
307
- when 1077, 1087, 1097, 1117
308
- # 1077(GPS), 1087(GLONASS), 1097(GALILEO), 1117(QZSS)
309
- attributes << MSM7
479
+ when 1071..1077, 1081..1087, 1091..1097, 1101..1107, 1111..1117, 1121..1127
480
+ # 107X(GPS), 108X(GLONASS), 109X(GALILEO), 110X(SBAS), 111X(QZSS), 112X(Beidou)
310
481
  nsat, nsig = [-2, -1].collect{|i| values[i].size}
311
482
  offset = 24 + mt[:bits_total]
312
483
  df396 = DataFrame.generate_prop([[396, values[-2], values[-1]]])
313
484
  add_proc.call(df396, offset)
314
485
  ncell = values[-1].size
315
486
  offset += df396[:bits_total]
316
- msm7_sat = DataFrame.generate_prop(
317
- ([[397, [:uint, 4], 398, 399]] * nsat).transpose.flatten(1))
318
- add_proc.call(msm7_sat, offset)
319
- offset += msm7_sat[:bits_total]
320
- msm7_sig = DataFrame.generate_prop(
321
- ([[405, 406, 407, 420, 408, 404]] * ncell).transpose.flatten(1))
322
- add_proc.call(msm7_sig, offset)
487
+ msm_proc = proc{|sat_data, signal_data|
488
+ msm_sat = DataFrame.generate_prop(([sat_data] * nsat).transpose.flatten(1))
489
+ add_proc.call(msm_sat, offset)
490
+ offset += msm_sat[:bits_total]
491
+ msm_sig = DataFrame.generate_prop(([signal_data] * ncell).transpose.flatten(1))
492
+ add_proc.call(msm_sig, offset)
493
+ }
494
+ case msg_num % 10
495
+ when 4
496
+ attributes << MSM4_6
497
+ msm_proc.call([397, 398], [400, 401, 402, 420, 403])
498
+ when 5
499
+ attributes << MSM5_7
500
+ msm_proc.call([397, [:uint, 4], 398, 399], [400, 401, 402, 420, 403, 404])
501
+ when 6
502
+ attributes << MSM4_6
503
+ msm_proc.call([397, 398], [405, 406, 407, 420, 408])
504
+ when 7
505
+ attributes << MSM5_7
506
+ msm_proc.call([397, [:uint, 4], 398, 399], [405, 406, 407, 420, 408, 404])
507
+ else
508
+ attributes << MSM # for #range
509
+ end
323
510
  end
324
511
  attributes << MSM_Header if (1070..1229).include?(msg_num)
325
512
  res = values.zip(df_list)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GPS_PVT
4
- VERSION = "0.9.1"
4
+ VERSION = "0.9.2"
5
5
 
6
6
  def GPS_PVT.version_compare(a, b)
7
7
  Gem::Version::new(a) <=> Gem::Version::new(b)
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.9.1
4
+ version: 0.9.2
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: 2023-01-27 00:00:00.000000000 Z
11
+ date: 2023-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyserial