gps_pvt 0.6.3 → 0.7.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.
@@ -22,6 +22,7 @@
22
22
  #include "navigation/QZSS.h"
23
23
  #include "navigation/GLONASS.h"
24
24
  #include "navigation/RINEX.h"
25
+ #include "navigation/RINEX_Clock.h"
25
26
  #include "navigation/SP3.h"
26
27
  #include "navigation/ANTEX.h"
27
28
 
@@ -228,12 +229,10 @@ struct GPS_Ionospheric_UTC_Parameters : public GPS_SpaceNode<FloatT>::Ionospheri
228
229
  %}
229
230
  %extend GPS_Ionospheric_UTC_Parameters {
230
231
  %fragment(SWIG_Traits_frag(FloatT));
231
- %typemap(in,numinputs=0) FloatT values[4] (FloatT temp[4]) %{
232
- $1 = temp;
233
- %}
234
- %typemap(argout) FloatT values[4] {
232
+ %typemap(in,numinputs=0) const FloatT *values[4] (FloatT *temp) "$1 = &temp;"
233
+ %typemap(argout) const FloatT *values[4] {
235
234
  for(int i(0); i < 4; ++i){
236
- %append_output(swig::from($1[i]));
235
+ %append_output(swig::from((*$1)[i]));
237
236
  }
238
237
  }
239
238
  MAKE_ARRAY_INPUT(const FloatT, values, swig::asval);
@@ -245,11 +244,7 @@ struct GPS_Ionospheric_UTC_Parameters : public GPS_SpaceNode<FloatT>::Ionospheri
245
244
  }
246
245
  }
247
246
  %rename("alpha") get_alpha;
248
- void get_alpha(FloatT values[4]) const {
249
- for(int i(0); i < 4; ++i){
250
- values[i] = self->alpha[i];
251
- }
252
- }
247
+ void get_alpha(const FloatT *values[4]) const {*values = self->alpha;}
253
248
  %rename("beta=") set_beta;
254
249
  void set_beta(const FloatT values[4]){
255
250
  for(int i(0); i < 4; ++i){
@@ -257,11 +252,7 @@ struct GPS_Ionospheric_UTC_Parameters : public GPS_SpaceNode<FloatT>::Ionospheri
257
252
  }
258
253
  }
259
254
  %rename("beta") get_beta;
260
- void get_beta(FloatT values[4]) const {
261
- for(int i(0); i < 4; ++i){
262
- values[i] = self->beta[i];
263
- }
264
- }
255
+ void get_beta(const FloatT *values[4]) const {*values = self->beta;}
265
256
  MAKE_ACCESSOR(A1, FloatT);
266
257
  MAKE_ACCESSOR(A0, FloatT);
267
258
  MAKE_ACCESSOR(t_ot, unsigned int);
@@ -1006,6 +997,7 @@ const type &get_ ## name () const {
1006
997
  %inline %{
1007
998
  template <class FloatT>
1008
999
  struct GPS_SolverOptions_Common {
1000
+ virtual ~GPS_SolverOptions_Common() {}
1009
1001
  virtual GPS_Solver_GeneralOptions<FloatT> *cast_general() = 0;
1010
1002
  virtual const GPS_Solver_GeneralOptions<FloatT> *cast_general() const = 0;
1011
1003
  };
@@ -1206,7 +1198,10 @@ struct GPS_RangeCorrector
1206
1198
  if(!res.is_available()){
1207
1199
  static const VALUE key(ID2SYM(rb_intern("relative_property")));
1208
1200
  VALUE hook(rb_hash_lookup(hooks, key));
1209
- if(!NIL_P(hook)){res.impl = this;}
1201
+ if(!NIL_P(hook)){
1202
+ if(!res.impl_xyz){res.impl_xyz = this;}
1203
+ if(!res.impl_t){res.impl_t = this;}
1204
+ }
1210
1205
  }
1211
1206
  #endif
1212
1207
  return res;
@@ -1361,6 +1356,28 @@ struct GPS_RangeCorrector
1361
1356
  return self->update_correction(true, hash);
1362
1357
  }
1363
1358
  #endif
1359
+ #ifdef SWIGRUBY
1360
+ %typemap(out) typename super_t::options_t {
1361
+ VALUE res(rb_hash_new());
1362
+ rb_hash_aset(res, ID2SYM(rb_intern("skip_exclusion")), SWIG_From(bool)($1.skip_exclusion));
1363
+ %set_output(res);
1364
+ }
1365
+ #endif
1366
+ %rename("options") get_options;
1367
+ typename super_t::options_t get_options() const {
1368
+ return self->available_options();
1369
+ }
1370
+ %rename("options=") set_options;
1371
+ typename super_t::options_t set_options(SWIG_Object obj) {
1372
+ GPS_Solver<FloatT>::super_t::options_t opt(self->available_options());
1373
+ #ifdef SWIGRUBY
1374
+ if(!RB_TYPE_P(obj, T_HASH)){SWIG_exception(SWIG_TypeError, "Hash is expected");}
1375
+ SWIG_AsVal(bool)(
1376
+ rb_hash_lookup(obj, ID2SYM(rb_intern("skip_exclusion"))),
1377
+ &opt.skip_exclusion);
1378
+ #endif
1379
+ return self->update_options(opt);
1380
+ }
1364
1381
  }
1365
1382
  %inline {
1366
1383
  template <class FloatT>
@@ -1653,31 +1670,8 @@ template <class FloatT>
1653
1670
  struct RINEX_Observation {};
1654
1671
  }
1655
1672
 
1656
- %extend SP3 {
1657
- %typemap(in,numinputs=0) int count[ANY] (int temp[$1_dim0]) "$1 = temp;"
1658
- %typemap(argout) int count[ANY] {
1659
- for(int i(0); i < $1_dim0; ++i){
1660
- %append_output(SWIG_From(int)($1[i]));
1661
- }
1662
- }
1663
- void satellites(int count[SP3::SYS_SYSTEMS]) const {
1664
- typename SP3_Product<FloatT>::satellite_count_t x(self->satellite_count());
1665
- count[SP3<FloatT>::SYS_GPS] = x.gps;
1666
- count[SP3<FloatT>::SYS_SBAS] = x.sbas;
1667
- count[SP3<FloatT>::SYS_QZSS] = x.qzss;
1668
- count[SP3<FloatT>::SYS_GLONASS] = x.glonass;
1669
- count[SP3<FloatT>::SYS_GALILEO] = x.galileo;
1670
- count[SP3<FloatT>::SYS_BEIDOU] = x.beidou;
1671
- }
1672
-
1673
- }
1674
1673
  %inline {
1675
- template <class FloatT>
1676
- struct SP3 : public SP3_Product<FloatT> {
1677
- int read(const char *fname) {
1678
- std::fstream fin(fname, std::ios::in | std::ios::binary);
1679
- return SP3_Reader<FloatT>::read_all(fin, *this);
1680
- }
1674
+ struct PushableData {
1681
1675
  enum system_t {
1682
1676
  SYS_GPS,
1683
1677
  SYS_SBAS,
@@ -1687,20 +1681,21 @@ struct SP3 : public SP3_Product<FloatT> {
1687
1681
  SYS_BEIDOU,
1688
1682
  SYS_SYSTEMS,
1689
1683
  };
1690
- bool push(GPS_Solver<FloatT> &solver, const system_t &sys) const {
1684
+ template <class DataT, class FloatT>
1685
+ static bool push(DataT &data, GPS_Solver<FloatT> &solver, const system_t &sys){
1691
1686
  switch(sys){
1692
1687
  case SYS_GPS:
1693
- return SP3_Product<FloatT>::push(
1694
- solver.gps.ephemeris_proxy.gps, SP3_Product<FloatT>::SYSTEM_GPS);
1688
+ return data.push(
1689
+ solver.gps.ephemeris_proxy.gps, DataT::SYSTEM_GPS);
1695
1690
  case SYS_SBAS:
1696
- return SP3_Product<FloatT>::push(
1697
- solver.sbas.solver.satellites, SP3_Product<FloatT>::SYSTEM_SBAS);
1691
+ return data.push(
1692
+ solver.sbas.solver.satellites, DataT::SYSTEM_SBAS);
1698
1693
  case SYS_QZSS:
1699
- return SP3_Product<FloatT>::push(
1700
- solver.gps.ephemeris_proxy.qzss, SP3_Product<FloatT>::SYSTEM_QZSS);
1694
+ return data.push(
1695
+ solver.gps.ephemeris_proxy.qzss, DataT::SYSTEM_QZSS);
1701
1696
  case SYS_GLONASS:
1702
- return SP3_Product<FloatT>::push(
1703
- solver.glonass.solver.satellites, SP3_Product<FloatT>::SYSTEM_GLONASS);
1697
+ return data.push(
1698
+ solver.glonass.solver.satellites, DataT::SYSTEM_GLONASS);
1704
1699
  case SYS_GALILEO:
1705
1700
  case SYS_BEIDOU:
1706
1701
  default:
@@ -1708,7 +1703,8 @@ struct SP3 : public SP3_Product<FloatT> {
1708
1703
  }
1709
1704
  return false;
1710
1705
  }
1711
- bool push(GPS_Solver<FloatT> &solver) const {
1706
+ template <class DataT, class FloatT>
1707
+ static bool push(DataT &data, GPS_Solver<FloatT> &solver){
1712
1708
  system_t target[] = {
1713
1709
  SYS_GPS,
1714
1710
  SYS_SBAS,
@@ -1718,10 +1714,39 @@ struct SP3 : public SP3_Product<FloatT> {
1718
1714
  //SYS_BEIDOU,
1719
1715
  };
1720
1716
  for(std::size_t i(0); i < sizeof(target) / sizeof(target[0]); ++i){
1721
- if(!push(solver, target[i])){return false;}
1717
+ if(!push(data, solver, target[i])){return false;}
1722
1718
  }
1723
1719
  return true;
1724
1720
  }
1721
+ };
1722
+ }
1723
+
1724
+ %extend SP3 {
1725
+ %typemap(out) typename SP3_Product<FloatT>::satellite_count_t {
1726
+ %append_output(SWIG_From(int)($1.gps));
1727
+ %append_output(SWIG_From(int)($1.sbas));
1728
+ %append_output(SWIG_From(int)($1.qzss));
1729
+ %append_output(SWIG_From(int)($1.glonass));
1730
+ %append_output(SWIG_From(int)($1.galileo));
1731
+ %append_output(SWIG_From(int)($1.beidou));
1732
+ }
1733
+ }
1734
+ %inline {
1735
+ template <class FloatT>
1736
+ struct SP3 : public SP3_Product<FloatT>, PushableData {
1737
+ int read(const char *fname) {
1738
+ std::fstream fin(fname, std::ios::in | std::ios::binary);
1739
+ return SP3_Reader<FloatT>::read_all(fin, *this);
1740
+ }
1741
+ typename SP3_Product<FloatT>::satellite_count_t satellites() const {
1742
+ return SP3_Product<FloatT>::satellite_count();
1743
+ }
1744
+ bool push(GPS_Solver<FloatT> &solver, const PushableData::system_t &sys) const {
1745
+ return PushableData::push((SP3_Product<FloatT> &)*this, solver, sys);
1746
+ }
1747
+ bool push(GPS_Solver<FloatT> &solver) const {
1748
+ return PushableData::push((SP3_Product<FloatT> &)*this, solver);
1749
+ }
1725
1750
  System_XYZ<FloatT, WGS84> position(
1726
1751
  const int &sat_id, const GPS_Time<FloatT> &t) const {
1727
1752
  return SP3_Product<FloatT>::select(sat_id, t).position(t);
@@ -1748,6 +1773,46 @@ struct SP3 : public SP3_Product<FloatT> {
1748
1773
  };
1749
1774
  }
1750
1775
 
1776
+ %extend RINEX_Clock {
1777
+ %typemap(out) typename RINEX_CLK<FloatT>::satellites_t::count_t {
1778
+ %append_output(SWIG_From(int)($1.gps));
1779
+ %append_output(SWIG_From(int)($1.sbas));
1780
+ %append_output(SWIG_From(int)($1.qzss));
1781
+ %append_output(SWIG_From(int)($1.glonass));
1782
+ %append_output(SWIG_From(int)($1.galileo));
1783
+ %append_output(SWIG_From(int)($1.beidou));
1784
+ }
1785
+ }
1786
+ %inline {
1787
+ template <class FloatT>
1788
+ struct RINEX_Clock : public RINEX_CLK<FloatT>::satellites_t, PushableData {
1789
+ typedef typename RINEX_CLK<FloatT>::satellites_t super_t;
1790
+ int read(const char *fname) {
1791
+ std::fstream fin(fname, std::ios::in | std::ios::binary);
1792
+ return RINEX_CLK_Reader<FloatT>::read_all(fin, *this);
1793
+ }
1794
+ typename RINEX_CLK<FloatT>::satellites_t::count_t satellites() const {
1795
+ return RINEX_CLK<FloatT>::satellites_t::count();
1796
+ }
1797
+ bool push(GPS_Solver<FloatT> &solver, const PushableData::system_t &sys) const {
1798
+ return PushableData::push((typename RINEX_CLK<FloatT>::satellites_t &)*this, solver, sys);
1799
+ }
1800
+ bool push(GPS_Solver<FloatT> &solver) const {
1801
+ return PushableData::push((typename RINEX_CLK<FloatT>::satellites_t &)*this, solver);
1802
+ }
1803
+ FloatT clock_error(const int &sat_id, const GPS_Time<FloatT> &t) const {
1804
+ typename super_t::buf_t::const_iterator it(this->buf.find(sat_id));
1805
+ if(it == this->buf.end()){return super_t::sat_t::unavailable().clock_error(t);}
1806
+ return it->second.clock_error(t);
1807
+ }
1808
+ FloatT clock_error_dot(const int &sat_id, const GPS_Time<FloatT> &t) const {
1809
+ typename super_t::buf_t::const_iterator it(this->buf.find(sat_id));
1810
+ if(it == this->buf.end()){return super_t::sat_t::unavailable().clock_error(t);}
1811
+ return it->second.clock_error_dot(t);
1812
+ }
1813
+ };
1814
+ }
1815
+
1751
1816
  #undef MAKE_ACCESSOR
1752
1817
  #undef MAKE_VECTOR2ARRAY
1753
1818
  #undef MAKE_ARRAY_INPUT
@@ -1776,6 +1841,7 @@ struct SP3 : public SP3_Product<FloatT> {
1776
1841
 
1777
1842
  %template(RINEX_Observation) RINEX_Observation<type>;
1778
1843
  %template(SP3) SP3<type>;
1844
+ %template(RINEX_Clock) RINEX_Clock<type>;
1779
1845
  %enddef
1780
1846
 
1781
1847
  CONCRETIZE(double);
@@ -592,7 +592,6 @@ struct MatrixUtil {
592
592
  }
593
593
  static VALUE read(
594
594
  const VALUE &v, const unsigned int &row = 0, const unsigned int &column = 0) {
595
- int state;
596
595
  VALUE values[3] = {v, UINT2NUM(row), UINT2NUM(column)};
597
596
  return funcall_throw_if_error(run, reinterpret_cast<VALUE>(values));
598
597
  }
@@ -865,7 +864,7 @@ struct MatrixUtil {
865
864
  static const ID with_index[] = {
866
865
  rb_intern("map_with_index"), rb_intern("map_with_index!"),
867
866
  rb_intern("collect_with_index"), rb_intern("collect_with_index!")};
868
- for(int i(0); i < sizeof(with_index) / sizeof(with_index[0]); ++i){
867
+ for(std::size_t i(0); i < sizeof(with_index) / sizeof(with_index[0]); ++i){
869
868
  if(id_callee == with_index[i]){
870
869
  return matrix_yield_get_with_index;
871
870
  }
@@ -658,6 +658,73 @@ __ANTEX_TEXT__
658
658
  # https://files.igs.org/pub/station/general/igs14.atx
659
659
  f.path
660
660
  },
661
+ :rinex_clk => Tempfile::open{|f|
662
+ f.write(<<-__RINEX_CLK_TEXT__)
663
+ 3.00 C RINEX VERSION / TYPE
664
+ CCLOCK IGSACC @ NOAA NGS PGM / RUN BY / DATE
665
+ GPS week: 1849 Day: 2 MJD: 57189 COMMENT
666
+ THE COMBINED CLOCKS ARE A WEIGHTED AVERAGE OF: COMMENT
667
+ cod emr esa gfz grg jpl COMMENT
668
+ THE FOLLOWING REFERENCE CLOCKS WERE USED BY ACs: COMMENT
669
+ WSRT AMC2 BRUX HRAO COMMENT
670
+ THE COMBINED CLOCKS ARE ALIGNED TO GPS TIME COMMENT
671
+ USING THE SATELLITE BROADCAST EPHEMERIDES COMMENT
672
+ All clocks have been re-aligned to the IGS time scale: IGST COMMENT
673
+ 16 LEAP SECONDS
674
+ 1 AS # / TYPES OF DATA
675
+ IGS IGSACC @ NOAA NGS ANALYSIS CENTER
676
+ 6 # OF SOLN SATS
677
+ G12 G18 G24 G25 G29 G31 PRN LIST
678
+ G igs08_1848.atx SYS / PCVS APPLIED
679
+ END OF HEADER
680
+ AS G12 2015 06 15 23 45 0.000000 2 3.017937472687e-04 1.069824072610e-11
681
+ AS G18 2015 06 15 23 45 0.000000 2 4.096815344517e-04 9.225410060960e-12
682
+ AS G24 2015 06 15 23 45 0.000000 2 -4.998574751545e-05 2.372704308220e-11
683
+ AS G25 2015 06 15 23 45 0.000000 2 -2.290169594092e-06 1.683218228880e-11
684
+ AS G29 2015 06 15 23 45 0.000000 2 6.168866864097e-04 1.206217360840e-11
685
+ AS G31 2015 06 15 23 45 0.000000 2 3.128244102077e-04 2.173867579920e-11
686
+ AS G12 2015 06 15 23 50 0.000000 2 3.017948525918e-04 1.300769315700e-11
687
+ AS G18 2015 06 15 23 50 0.000000 2 4.096823340968e-04 8.242414325510e-12
688
+ AS G24 2015 06 15 23 50 0.000000 2 -4.998578937856e-05 3.095238106380e-11
689
+ AS G25 2015 06 15 23 50 0.000000 2 -2.291410963946e-06 2.242880773880e-11
690
+ AS G29 2015 06 15 23 50 0.000000 2 6.168873857128e-04 1.695910016600e-11
691
+ AS G31 2015 06 15 23 50 0.000000 2 3.128241216228e-04 1.904362802980e-11
692
+ AS G12 2015 06 15 23 55 0.000000 2 3.017958412577e-04 1.171495359430e-11
693
+ AS G18 2015 06 15 23 55 0.000000 2 4.096833491457e-04 1.008770038860e-11
694
+ AS G24 2015 06 15 23 55 0.000000 2 -4.998596967628e-05 2.600074192880e-11
695
+ AS G25 2015 06 15 23 55 0.000000 2 -2.292650290468e-06 2.671557682290e-11
696
+ AS G29 2015 06 15 23 55 0.000000 2 6.168880208367e-04 1.729095211710e-11
697
+ AS G31 2015 06 15 23 55 0.000000 2 3.128236493567e-04 1.807462018720e-11
698
+ AS G12 2015 06 16 00 00 0.000000 2 3.017967728708e-04 1.000801049580e-11
699
+ AS G18 2015 06 16 00 00 0.000000 2 4.096840539308e-04 1.041670195750e-11
700
+ AS G24 2015 06 16 00 00 0.000000 2 -4.998614775959e-05 1.699628132880e-11
701
+ AS G25 2015 06 16 00 00 0.000000 2 -2.293760646361e-06 1.805118466830e-11
702
+ AS G29 2015 06 16 00 00 0.000000 2 6.168886213338e-04 2.220055594770e-11
703
+ AS G31 2015 06 16 00 00 0.000000 2 3.128233311248e-04 1.215284180360e-11
704
+ AS G12 2015 06 16 00 05 0.000000 2 3.017980078016e-04 1.152529430320e-11
705
+ AS G18 2015 06 16 00 05 0.000000 2 4.096851745816e-04 1.517949585220e-11
706
+ AS G24 2015 06 16 00 05 0.000000 2 -4.998569129850e-05 1.987308774570e-11
707
+ AS G25 2015 06 16 00 05 0.000000 2 -2.295014987154e-06 1.568891027900e-11
708
+ AS G29 2015 06 16 00 05 0.000000 2 6.168894672506e-04 1.906237292480e-11
709
+ AS G31 2015 06 16 00 05 0.000000 2 3.128231387506e-04 1.007829428500e-11
710
+ AS G12 2015 06 16 00 10 0.000000 2 3.017987334831e-04 8.726251168980e-12
711
+ AS G18 2015 06 16 00 10 0.000000 2 4.096859333261e-04 1.403166740100e-11
712
+ AS G24 2015 06 16 00 10 0.000000 2 -4.998597422529e-05 1.727695888430e-11
713
+ AS G25 2015 06 16 00 10 0.000000 2 -2.296262879345e-06 1.460867818340e-11
714
+ AS G29 2015 06 16 00 10 0.000000 2 6.168900483001e-04 1.556536485070e-11
715
+ AS G31 2015 06 16 00 10 0.000000 2 3.128226535741e-04 1.258498073020e-11
716
+ AS G12 2015 06 16 00 15 0.000000 2 3.017999301583e-04 1.006627990480e-11
717
+ AS G18 2015 06 16 00 15 0.000000 2 4.096864636193e-04 1.460541676660e-11
718
+ AS G24 2015 06 16 00 15 0.000000 2 -4.998605241609e-05 1.970841363000e-11
719
+ AS G25 2015 06 16 00 15 0.000000 2 -2.297477664413e-06 1.598459869060e-11
720
+ AS G29 2015 06 16 00 15 0.000000 2 6.168906691983e-04 1.729396319140e-11
721
+ AS G31 2015 06 16 00 15 0.000000 2 3.128222195893e-04 1.358710059900e-11
722
+ __RINEX_CLK_TEXT__
723
+ # modified version. original data are
724
+ # https://cddis.nasa.gov/archive/gnss/products/1849/igs1849[12].clk.Z
725
+ # mirrored: ftp://garner.ucsd.edu/pub/products/1849/igs1849[12].clk.Z
726
+ f.path
727
+ },
661
728
  }}
662
729
  let(:solver){
663
730
  res = GPS::Solver::new
@@ -778,6 +845,10 @@ __ANTEX_TEXT__
778
845
 
779
846
  it 'can be modified through hooks' do
780
847
  sn = solver.gps_space_node
848
+ expect(solver.options).to be_a_kind_of(Hash)
849
+ expect(solver.options.keys).to include(:skip_exclusion)
850
+ expect{solver.options = {:skip_exclusion => true}}.not_to raise_error
851
+ expect(solver.options[:skip_exclusion]).to eq(true)
781
852
  expect(solver.correction[:gps_ionospheric]).to include(:klobuchar)
782
853
  expect(solver.correction[:gps_tropospheric]).to include(:hopfield)
783
854
  expect{solver.correction = nil}.to raise_error(RuntimeError)
@@ -937,5 +1008,55 @@ __ANTEX_TEXT__
937
1008
  puts ([:lat, :lng].collect{|f| pvt.llh.send(f) / Math::PI * 180} + [pvt.llh.alt]).inspect
938
1009
  }
939
1010
  end
1011
+ it 'calculates satellite clock error based on RINEX clock' do
1012
+ clk, sn = [GPS::RINEX_Clock::new, solver.gps_space_node]
1013
+ expect(clk.read(input[:rinex_clk])).to eq(6 * 7)
1014
+ proc{|sats|
1015
+ expect(sats.kind_of?(Array)).to eq(true)
1016
+ expect(sats[clk.class::SYS_GPS]).to eq(6)
1017
+ }.call(clk.satellites)
1018
+ sn.read(input[:rinex_nav])
1019
+ t0 = GPS::Time::new(1849, 172800)
1020
+ sn.update_all_ephemeris(t0)
1021
+ (-5..5).step(1){|dt_min|
1022
+ t = t0 + (dt_min * 60)
1023
+ [12, 18, 24, 25, 29, 31].each{|sat_id|
1024
+ eph = sn.ephemeris(sat_id).constellation(t)
1025
+ expect(clk.clock_error(sat_id, t)).to be_within(1E-7).of(eph[2]) # 100 ns
1026
+ expect(clk.clock_error_dot(sat_id, t)).to be_within(1E-10).of(eph[3]) # 100 ps
1027
+ }
1028
+ }
1029
+ end
1030
+ it 'calculates position without any error with RINEX NAV and CLK' do
1031
+ sn = solver.gps_space_node
1032
+ sn.read(input[:rinex_nav])
1033
+ clk = GPS::RINEX_Clock::new
1034
+ clk.read(input[:rinex_clk])
1035
+ expect(clk.push(solver, clk.class::SYS_GPS)).to eq(true)
1036
+ GPS::RINEX_Observation::read(input[:rinex_obs]){|item|
1037
+ t_meas = item[:time]
1038
+ sn.update_all_ephemeris(t_meas)
1039
+ meas = GPS::Measurement::new
1040
+ types = (item[:meas_types]['G'] || item[:meas_types][' ']).collect.with_index{|type_, i|
1041
+ type_ = {
1042
+ "C1" => :L1_PSEUDORANGE,
1043
+ "D1" => :L1_RANGE_RATE,
1044
+ }[type_]
1045
+ type_ && [i, GPS::Measurement::const_get(type_)]
1046
+ }.compact
1047
+ item[:meas].each{|k, v|
1048
+ sys, prn = k
1049
+ next unless sys == 'G' # GPS only
1050
+ types.each{|i, type_|
1051
+ meas.add(prn, type_, v[i][0]) if v[i]
1052
+ }
1053
+ }
1054
+ pvt = solver.solve(meas, t_meas)
1055
+ expect(pvt.position_solved?).to eq(true)
1056
+ [-3952590.4754, 3360273.8926, 3697987.2632].zip(pvt.xyz.to_a).each{|a, b|
1057
+ expect(a).to be_within(1E+2).of(b) # 10 m
1058
+ }
1059
+ }
1060
+ end
940
1061
  end
941
1062
  end
@@ -19,6 +19,7 @@ class Receiver
19
19
  opt = {
20
20
  :system => [[:GPS, 1..32]],
21
21
  :satellites => (1..32).to_a,
22
+ :FDE => true,
22
23
  }.merge(opt)
23
24
  [[
24
25
  [:week, :itow_rcv, :year, :month, :mday, :hour, :min, :sec_rcv_UTC],
@@ -106,7 +107,7 @@ class Receiver
106
107
  el_deg = [4, 6].collect{|i| pvt.elevation[fd[i]] / Math::PI * 180}
107
108
  fd[0..4] + [el_deg[0]] + fd[5..6] + [el_deg[1]]
108
109
  }
109
- ]] + [[
110
+ ]] + (opt[:FDE] ? [[
110
111
  [:wssr_FDE_min, :wssr_FDE_min_PRN, :wssr_FDE_2nd, :wssr_FDE_2nd_PRN],
111
112
  proc{|pvt|
112
113
  [:fde_min, :fde_2nd].collect{|f|
@@ -115,7 +116,7 @@ class Receiver
115
116
  [info[0], info[-3]]
116
117
  }.flatten
117
118
  }
118
- ]]
119
+ ]] : [])
119
120
  end
120
121
 
121
122
  def self.meas_items(opt = {})
@@ -153,6 +154,9 @@ class Receiver
153
154
  rel_prop[0] = 1 if rel_prop[0] > 0 # weight = 1
154
155
  rel_prop
155
156
  }
157
+ @solver.options = {
158
+ :skip_exclusion => true, # default is to skip fault exclusion calculation
159
+ }
156
160
  @debug = {}
157
161
  solver_opts = [:gps_options, :sbas_options, :glonass_options].collect{|target|
158
162
  @solver.send(target)
@@ -165,8 +169,10 @@ class Receiver
165
169
  output_options = {
166
170
  :system => [[:GPS, 1..32], [:QZSS, 193..202]],
167
171
  :satellites => (1..32).to_a + (193..202).to_a, # [idx, ...] or [[idx, label], ...] is acceptable
172
+ :FDE => false,
168
173
  }
169
174
  options = options.reject{|k, v|
175
+ def v.to_b; !(self =~ /^(?:false|0|f|off)$/i); end
170
176
  case k
171
177
  when :debug
172
178
  v = v.split(/,/)
@@ -280,6 +286,9 @@ class Receiver
280
286
  $stderr.puts "#{mode.capitalize} satellite: #{[sys, svid].compact.join(':')}"
281
287
  }
282
288
  next true
289
+ when :fault_exclusion
290
+ @solver.options = {:skip_exclusion => !(output_options[:FDE] = v.to_b)}
291
+ next true
283
292
  end
284
293
  false
285
294
  }
@@ -651,5 +660,21 @@ class Receiver
651
660
  raise "Format error! (Not ANTEX) #{src}" unless applied_items >= 0
652
661
  $stderr.puts "SP3 correction with ANTEX file (%s): %d items have been processed."%[src, applied_items]
653
662
  end
663
+
664
+ def attach_rinex_clk(src)
665
+ fname = Util::get_txt(src)
666
+ @clk ||= GPS::RINEX_Clock::new
667
+ read_items = @clk.read(fname)
668
+ raise "Format error! (Not RINEX clock) #{src}" if read_items < 0
669
+ $stderr.puts "Read RINEX clock file (%s): %d items."%[src, read_items]
670
+ sats = @clk.satellites
671
+ @clk.class.constants.each{|sys|
672
+ next unless /^SYS_(?!SYSTEMS)(.*)/ =~ sys.to_s
673
+ idx, sys_name = [@clk.class.const_get(sys), $1]
674
+ next unless sats[idx] > 0
675
+ next unless @clk.push(@solver, idx)
676
+ $stderr.puts "Change clock error source of #{sys_name} to RINEX clock"
677
+ }
678
+ end
654
679
  end
655
680
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GPS_PVT
4
- VERSION = "0.6.3"
4
+ VERSION = "0.7.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.6.3
4
+ version: 0.7.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-08-19 00:00:00.000000000 Z
11
+ date: 2022-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -78,6 +78,7 @@ files:
78
78
  - ext/ninja-scan-light/tool/navigation/NTCM.h
79
79
  - ext/ninja-scan-light/tool/navigation/QZSS.h
80
80
  - ext/ninja-scan-light/tool/navigation/RINEX.h
81
+ - ext/ninja-scan-light/tool/navigation/RINEX_Clock.h
81
82
  - ext/ninja-scan-light/tool/navigation/SBAS.h
82
83
  - ext/ninja-scan-light/tool/navigation/SBAS_Solver.h
83
84
  - ext/ninja-scan-light/tool/navigation/SP3.h