gps_pvt 0.1.7 → 0.2.3

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.
@@ -15,16 +15,19 @@
15
15
  #include <iostream>
16
16
  #include <fstream>
17
17
  #include <exception>
18
+ #include <sstream>
18
19
 
19
20
  #include "navigation/GPS.h"
21
+ #include "navigation/SBAS.h"
22
+ #include "navigation/QZSS.h"
20
23
  #include "navigation/RINEX.h"
21
24
 
22
25
  #include "navigation/GPS_Solver_Base.h"
23
26
  #include "navigation/GPS_Solver.h"
24
27
  #include "navigation/GPS_Solver_RAIM.h"
28
+ #include "navigation/SBAS_Solver.h"
25
29
 
26
30
  #if defined(__cplusplus) && (__cplusplus < 201103L)
27
- #include <sstream>
28
31
  namespace std {
29
32
  template <class T>
30
33
  inline std::string to_string(const T &value){
@@ -156,6 +159,14 @@ static std::string inspect_str(const VALUE &v){
156
159
  *week = self->week;
157
160
  *seconds = self->seconds;
158
161
  }
162
+ #if defined(SWIG)
163
+ int __cmp__(const GPS_Time<FloatT> &t) const {
164
+ return ((self->week < t.week) ? -1
165
+ : ((self->week > t.week) ? 1
166
+ : (self->seconds < t.seconds ? -1
167
+ : (self->seconds > t.seconds ? 1 : 0))));
168
+ }
169
+ #endif
159
170
  }
160
171
 
161
172
  %define MAKE_ACCESSOR(name, type)
@@ -180,6 +191,26 @@ const type &get_ ## name () const {
180
191
  }
181
192
  }
182
193
  %enddef
194
+ #if defined(SWIGRUBY)
195
+ %define MAKE_ARRAY_INPUT(type, arg_name, f_conv)
196
+ %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) type arg_name[ANY] {
197
+ $1 = RB_TYPE_P($input, T_ARRAY) ? 1 : 0;
198
+ }
199
+ %typemap(in) type arg_name[ANY] ($*1_ltype temp[$1_dim0]) {
200
+ if(!(RB_TYPE_P($input, T_ARRAY) && (RARRAY_LEN($input) == $1_dim0))){
201
+ SWIG_exception(SWIG_TypeError, "array[$1_dim0] is expected");
202
+ }
203
+ for(int i(0); i < $1_dim0; ++i){
204
+ if(!SWIG_IsOK(f_conv(RARRAY_AREF($input, i), &temp[i]))){
205
+ SWIG_exception(SWIG_TypeError, "$*1_ltype is expected");
206
+ }
207
+ }
208
+ $1 = temp;
209
+ }
210
+ %enddef
211
+ #else
212
+ #define MAKE_ARRAY_INPUT(type, arg_name, f_conv)
213
+ #endif
183
214
 
184
215
  %inline %{
185
216
  template <class FloatT>
@@ -195,34 +226,8 @@ struct GPS_Ionospheric_UTC_Parameters : public GPS_SpaceNode<FloatT>::Ionospheri
195
226
  %append_output(swig::from($1[i]));
196
227
  }
197
228
  }
198
- %typemap(in) const FloatT values[4] (FloatT temp[4]) {
199
- #ifdef SWIGRUBY
200
- if(!(RB_TYPE_P($input, T_ARRAY) && (RARRAY_LEN($input) == 4))){
201
- SWIG_exception(SWIG_TypeError, "array[4] is expected");
202
- }
203
- for(int i(0); i < 4; ++i){
204
- SWIG_Object obj(RARRAY_AREF($input, i));
205
- if(!SWIG_IsOK(swig::asval(obj, &temp[i]))){
206
- SWIG_exception(SWIG_TypeError, "$*1_ltype is expected");
207
- }
208
- }
209
- #endif
210
- $1 = temp;
211
- }
212
- %typemap(in) const unsigned int *buf (unsigned int temp[10]) {
213
- #ifdef SWIGRUBY
214
- if((!RB_TYPE_P($input, T_ARRAY))
215
- || (RARRAY_LEN($input) < sizeof(temp) / sizeof(temp[0]))){
216
- SWIG_exception(SWIG_TypeError, "array is expected, or too short array");
217
- }
218
- $1 = temp;
219
- for(int i(0); i < sizeof(temp) / sizeof(temp[0]); ++i){
220
- if(!SWIG_IsOK(SWIG_AsVal(unsigned int)(RARRAY_AREF($input, i), &($1[i])))){
221
- SWIG_exception(SWIG_TypeError, "$*1_ltype is expected");
222
- }
223
- }
224
- #endif
225
- }
229
+ MAKE_ARRAY_INPUT(const FloatT, values, swig::asval);
230
+ MAKE_ARRAY_INPUT(const unsigned int, buf, SWIG_AsVal(unsigned int));
226
231
  %rename("alpha=") set_alpha;
227
232
  void set_alpha(const FloatT values[4]){
228
233
  for(int i(0); i < 4; ++i){
@@ -255,7 +260,7 @@ struct GPS_Ionospheric_UTC_Parameters : public GPS_SpaceNode<FloatT>::Ionospheri
255
260
  MAKE_ACCESSOR(WN_LSF, unsigned int);
256
261
  MAKE_ACCESSOR(DN, unsigned int);
257
262
  MAKE_ACCESSOR(delta_t_LSF, int);
258
- static GPS_Ionospheric_UTC_Parameters<FloatT> parse(const unsigned int *buf){
263
+ static GPS_Ionospheric_UTC_Parameters<FloatT> parse(const unsigned int buf[10]){
259
264
  typedef typename GPS_SpaceNode<FloatT>
260
265
  ::BroadcastedMessage<unsigned int, 30> parser_t;
261
266
  if((parser_t::subframe_id(buf) != 4) || (parser_t::sv_page_id(buf) != 56)){
@@ -321,22 +326,10 @@ struct GPS_Ephemeris : public GPS_SpaceNode<FloatT>::SatelliteProperties::Epheme
321
326
  MAKE_ACCESSOR(omega, FloatT);
322
327
  MAKE_ACCESSOR(dot_Omega0, FloatT);
323
328
  MAKE_ACCESSOR(dot_i0, FloatT);
324
- %typemap(in) const unsigned int *buf (unsigned int temp[10]) {
325
- #ifdef SWIGRUBY
326
- if((!RB_TYPE_P($input, T_ARRAY))
327
- || (RARRAY_LEN($input) < sizeof(temp) / sizeof(temp[0]))){
328
- SWIG_exception(SWIG_TypeError, "array is expected, or too short array");
329
- }
330
- $1 = temp;
331
- for(int i(0); i < sizeof(temp) / sizeof(temp[0]); ++i){
332
- if(!SWIG_IsOK(SWIG_AsVal(unsigned int)(RARRAY_AREF($input, i), &($1[i])))){
333
- SWIG_exception(SWIG_TypeError, "$*1_ltype is expected");
334
- }
335
- }
336
- #endif
337
- }
329
+
330
+ MAKE_ARRAY_INPUT(const unsigned int, buf, SWIG_AsVal(unsigned int));
338
331
  %apply int *OUTPUT { int *subframe_no, int *iodc_or_iode };
339
- void parse(const unsigned int *buf, int *subframe_no, int *iodc_or_iode){
332
+ void parse(const unsigned int buf[10], int *subframe_no, int *iodc_or_iode){
340
333
  typedef typename GPS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris eph_t;
341
334
  typename eph_t::raw_t raw;
342
335
  eph_t eph;
@@ -428,15 +421,84 @@ struct GPS_Ephemeris : public GPS_SpaceNode<FloatT>::SatelliteProperties::Epheme
428
421
  %append_output(swig::from($1.latitude));
429
422
  %append_output(swig::from($1.longitude));
430
423
  }
431
- %ignore iono_correction() const;
432
- %ignore tropo_correction() const;
433
424
  int read(const char *fname) {
434
425
  std::fstream fin(fname, std::ios::in | std::ios::binary);
435
- return RINEX_NAV_Reader<FloatT>::read_all(fin, *self);
426
+ typename RINEX_NAV_Reader<FloatT>::space_node_list_t space_nodes = {self};
427
+ space_nodes.qzss = self;
428
+ return RINEX_NAV_Reader<FloatT>::read_all(fin, space_nodes);
436
429
  }
437
430
  }
438
431
 
439
432
  %include navigation/GPS.h
433
+ %include navigation/QZSS.h
434
+
435
+ %inline %{
436
+ template <class FloatT>
437
+ struct SBAS_Ephemeris : public SBAS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris {
438
+ SBAS_Ephemeris() : SBAS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris() {}
439
+ SBAS_Ephemeris(const typename SBAS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris &eph)
440
+ : SBAS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris(eph) {}
441
+ };
442
+ %}
443
+ %extend SBAS_Ephemeris {
444
+ MAKE_ACCESSOR(svid, unsigned int);
445
+
446
+ MAKE_ACCESSOR(WN, unsigned int);
447
+ MAKE_ACCESSOR(t_0, FloatT);
448
+ MAKE_ACCESSOR(URA, int);
449
+ MAKE_ACCESSOR( x, FloatT); MAKE_ACCESSOR( y, FloatT); MAKE_ACCESSOR( z, FloatT);
450
+ MAKE_ACCESSOR( dx, FloatT); MAKE_ACCESSOR( dy, FloatT); MAKE_ACCESSOR( dz, FloatT);
451
+ MAKE_ACCESSOR(ddx, FloatT); MAKE_ACCESSOR(ddy, FloatT); MAKE_ACCESSOR(ddz, FloatT);
452
+ MAKE_ACCESSOR(a_Gf0, FloatT);
453
+ MAKE_ACCESSOR(a_Gf1, FloatT);
454
+ %apply GPS_Ephemeris::System_XYZ<FloatT, WGS84> & { System_XYZ<FloatT, WGS84> & }; // TODO ineffective?
455
+ void constellation(
456
+ System_XYZ<FloatT, WGS84> &position, System_XYZ<FloatT, WGS84> &velocity,
457
+ const GPS_Time<FloatT> &t, const FloatT &pseudo_range = 0,
458
+ const bool &with_velocity = true) const {
459
+ typename SBAS_SpaceNode<FloatT>::SatelliteProperties::constellation_t res(
460
+ self->constellation(t, pseudo_range, with_velocity));
461
+ position = res.position;
462
+ velocity = res.velocity;
463
+ }
464
+ }
465
+
466
+ %extend SBAS_SpaceNode {
467
+ %fragment(SWIG_Traits_frag(FloatT));
468
+ %ignore satellites() const;
469
+ %ignore satellite(const int &);
470
+ %ignore available_satellites(const FloatT &lng_deg) const;
471
+ void register_ephemeris(
472
+ const int &prn, const SBAS_Ephemeris<FloatT> &eph,
473
+ const int &priority_delta = 1){
474
+ self->satellite(prn).register_ephemeris(eph, priority_delta);
475
+ }
476
+ SBAS_Ephemeris<FloatT> ephemeris(const int &prn) const {
477
+ return SBAS_Ephemeris<FloatT>(
478
+ %const_cast(self, SBAS_SpaceNode<FloatT> *)->satellite(prn).ephemeris());
479
+ }
480
+ int read(const char *fname) {
481
+ std::fstream fin(fname, std::ios::in | std::ios::binary);
482
+ RINEX_NAV_Reader<FloatT>::space_node_list_t space_nodes = {NULL};
483
+ space_nodes.sbas = self;
484
+ return RINEX_NAV_Reader<FloatT>::read_all(fin, space_nodes);
485
+ }
486
+ MAKE_ARRAY_INPUT(const unsigned int, buf, SWIG_AsVal(unsigned int));
487
+ int decode_message(const unsigned int buf[8],
488
+ const int &prn, const GPS_Time<FloatT> &t_reception,
489
+ const bool &LNAV_VNAV_LP_LPV_approach = false){
490
+ return static_cast<int>(
491
+ self->decode_message(buf, prn, t_reception, LNAV_VNAV_LP_LPV_approach));
492
+ }
493
+ std::string ionospheric_grid_points(const int &prn) const {
494
+ std::ostringstream ss;
495
+ ss << %const_cast(self, SBAS_SpaceNode<FloatT> *)->satellite(prn)
496
+ .ionospheric_grid_points();
497
+ return ss.str();
498
+ }
499
+ }
500
+
501
+ %include navigation/SBAS.h
440
502
 
441
503
  %extend GPS_User_PVT {
442
504
  %ignore solver_t;
@@ -604,23 +666,6 @@ struct GPS_User_PVT
604
666
  }
605
667
  }
606
668
  }
607
- #ifdef SWIGRUBY
608
- VALUE to_hash() const {
609
- VALUE res(rb_hash_new());
610
- for(typename GPS_Measurement<FloatT>::items_t::const_iterator
611
- it(self->items.begin()), it_end(self->items.end());
612
- it != it_end; ++it){
613
- VALUE per_sat(rb_hash_new());
614
- rb_hash_aset(res, SWIG_From(int)(it->first), per_sat);
615
- for(typename GPS_Measurement<FloatT>::items_t::mapped_type::const_iterator
616
- it2(it->second.begin()), it2_end(it->second.end());
617
- it2 != it2_end; ++it2){
618
- rb_hash_aset(per_sat, SWIG_From(int)(it2->first), swig::from(it2->second));
619
- }
620
- }
621
- return res;
622
- }
623
- #endif
624
669
  %fragment(SWIG_Traits_frag(GPS_Measurement<FloatT>), "header",
625
670
  fragment=SWIG_Traits_frag(FloatT)){
626
671
  namespace swig {
@@ -704,9 +749,32 @@ struct GPS_User_PVT
704
749
  #endif
705
750
  return SWIG_ERROR;
706
751
  }
752
+ #ifdef SWIGRUBY
753
+ template <>
754
+ VALUE from(const GPS_Measurement<FloatT>::items_t::mapped_type &val) {
755
+ VALUE per_sat(rb_hash_new());
756
+ for(typename GPS_Measurement<FloatT>::items_t::mapped_type::const_iterator
757
+ it(val.begin()), it_end(val.end());
758
+ it != it_end; ++it){
759
+ rb_hash_aset(per_sat, SWIG_From(int)(it->first), swig::from(it->second));
760
+ }
761
+ return per_sat;
762
+ }
763
+ #endif
707
764
  }
708
765
  }
709
766
  %fragment(SWIG_Traits_frag(GPS_Measurement<FloatT>));
767
+ #ifdef SWIGRUBY
768
+ VALUE to_hash() const {
769
+ VALUE res(rb_hash_new());
770
+ for(typename GPS_Measurement<FloatT>::items_t::const_iterator
771
+ it(self->items.begin()), it_end(self->items.end());
772
+ it != it_end; ++it){
773
+ rb_hash_aset(res, SWIG_From(int)(it->first), swig::from(it->second));
774
+ }
775
+ return res;
776
+ }
777
+ #endif
710
778
  %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) const GPS_Measurement<FloatT> & {
711
779
  $1 = SWIG_CheckState(SWIG_ConvertPtr($input, (void **)0, $1_descriptor, 0))
712
780
  || swig::check<GPS_Measurement<FloatT> >($input);
@@ -738,6 +806,7 @@ struct GPS_Measurement {
738
806
  L1_RANGE_RATE_SIGMA,
739
807
  L1_SIGNAL_STRENGTH_dBHz,
740
808
  L1_LOCK_SEC,
809
+ L1_FREQUENCY,
741
810
  ITEMS_PREDEFINED,
742
811
  };
743
812
  void add(const int &prn, const int &key, const FloatT &value){
@@ -746,70 +815,66 @@ struct GPS_Measurement {
746
815
  };
747
816
  }
748
817
 
818
+ %extend GPS_SolverOptions_Common {
819
+ %define MAKE_ACCESSOR2(name, type)
820
+ %rename(%str(name ## =)) set_ ## name;
821
+ type set_ ## name (const type &v) {
822
+ return self->cast_general()->name = v;
823
+ }
824
+ %rename(%str(name)) get_ ## name;
825
+ const type &get_ ## name () const {
826
+ return self->cast_general()->name;
827
+ }
828
+ %enddef
829
+ MAKE_ACCESSOR2(elevation_mask, FloatT);
830
+ MAKE_ACCESSOR2(residual_mask, FloatT);
831
+ #undef MAKE_ACCESSOR2
832
+ MAKE_VECTOR2ARRAY(int);
833
+ %ignore cast_base;
834
+ }
835
+ %inline %{
836
+ template <class FloatT>
837
+ struct GPS_SolverOptions_Common {
838
+ virtual GPS_Solver_GeneralOptions<FloatT> *cast_general() = 0;
839
+ virtual const GPS_Solver_GeneralOptions<FloatT> *cast_general() const = 0;
840
+ };
841
+ %}
842
+
749
843
  %extend GPS_SolverOptions {
750
844
  %ignore base_t;
751
- MAKE_ACCESSOR(elevation_mask, FloatT);
752
- MAKE_ACCESSOR(residual_mask, FloatT);
753
- MAKE_ACCESSOR(f_10_7, FloatT);
845
+ %ignore cast_general;
754
846
  MAKE_VECTOR2ARRAY(int);
755
- #ifdef SWIGRUBY
756
- %rename("ionospheric_models=") set_ionospheric_models;
757
- %rename("ionospheric_models") get_ionospheric_models;
758
- #endif
759
- %typemap(in) const std::vector<int> &models (std::vector<int> temp) {
760
- $1 = &temp;
761
- #ifdef SWIGRUBY
762
- if(RB_TYPE_P($input, T_ARRAY)){
763
- for(int i(0), i_max(RARRAY_LEN($input)); i < i_max; ++i){
764
- SWIG_Object obj(RARRAY_AREF($input, i));
765
- int v;
766
- if(SWIG_IsOK(SWIG_AsVal(int)(obj, &v))){
767
- temp.push_back(v);
768
- }else{
769
- SWIG_exception(SWIG_TypeError, "$*1_ltype is expected");
770
- }
771
- }
772
- }
773
- #endif
774
- }
775
847
  }
776
848
  %inline %{
777
849
  template <class FloatT>
778
- struct GPS_SolverOptions : public GPS_SinglePositioning<FloatT>::options_t {
850
+ struct GPS_SolverOptions
851
+ : public GPS_SinglePositioning<FloatT>::options_t,
852
+ GPS_SolverOptions_Common<FloatT> {
779
853
  typedef typename GPS_SinglePositioning<FloatT>::options_t base_t;
780
854
  void exclude(const int &prn){base_t::exclude_prn.set(prn);}
781
855
  void include(const int &prn){base_t::exclude_prn.reset(prn);}
782
856
  std::vector<int> excluded() const {return base_t::exclude_prn.excluded();}
783
- enum {
784
- IONOSPHERIC_KLOBUCHAR,
785
- IONOSPHERIC_NTCM_GL,
786
- IONOSPHERIC_NONE, // which allows no correction
787
- IONOSPHERIC_MODELS,
788
- IONOSPHERIC_SKIP = IONOSPHERIC_MODELS, // which means delegating the next slot
789
- };
790
- std::vector<int> get_ionospheric_models() const {
791
- std::vector<int> res;
792
- for(int i(0); i < base_t::IONOSPHERIC_MODELS; ++i){
793
- int v((int)(base_t::ionospheric_models[i]));
794
- if(v == base_t::IONOSPHERIC_SKIP){break;}
795
- res.push_back(v);
796
- }
797
- return res;
798
- }
799
- std::vector<int> set_ionospheric_models(const std::vector<int> &models){
800
- typedef typename base_t::ionospheric_model_t model_t;
801
- for(int i(0), j(0), j_max(models.size()); i < base_t::IONOSPHERIC_MODELS; ++i){
802
- model_t v(base_t::IONOSPHERIC_SKIP);
803
- if(j < j_max){
804
- if((models[j] >= 0) && (models[j] < base_t::IONOSPHERIC_SKIP)){
805
- v = (model_t)models[j];
806
- }
807
- ++j;
808
- }
809
- base_t::ionospheric_models[i] = v;
810
- }
811
- return get_ionospheric_models();
812
- }
857
+ GPS_Solver_GeneralOptions<FloatT> *cast_general(){return this;}
858
+ const GPS_Solver_GeneralOptions<FloatT> *cast_general() const {return this;}
859
+ };
860
+ %}
861
+
862
+ %extend SBAS_SolverOptions {
863
+ %ignore base_t;
864
+ %ignore cast_general;
865
+ MAKE_VECTOR2ARRAY(int);
866
+ }
867
+ %inline %{
868
+ template <class FloatT>
869
+ struct SBAS_SolverOptions
870
+ : public SBAS_SinglePositioning<FloatT>::options_t,
871
+ GPS_SolverOptions_Common<FloatT> {
872
+ typedef typename SBAS_SinglePositioning<FloatT>::options_t base_t;
873
+ void exclude(const int &prn){base_t::exclude_prn.set(prn);}
874
+ void include(const int &prn){base_t::exclude_prn.reset(prn);}
875
+ std::vector<int> excluded() const {return base_t::exclude_prn.excluded();}
876
+ GPS_Solver_GeneralOptions<FloatT> *cast_general(){return this;}
877
+ const GPS_Solver_GeneralOptions<FloatT> *cast_general() const {return this;}
813
878
  };
814
879
  %}
815
880
 
@@ -818,6 +883,8 @@ struct GPS_SolverOptions : public GPS_SinglePositioning<FloatT>::options_t {
818
883
  %ignore base_t;
819
884
  %ignore gps_t;
820
885
  %ignore gps;
886
+ %ignore sbas_t;
887
+ %ignore sbas;
821
888
  %ignore select_solver;
822
889
  %ignore relative_property;
823
890
  %ignore satellite_position;
@@ -826,18 +893,19 @@ struct GPS_SolverOptions : public GPS_SinglePositioning<FloatT>::options_t {
826
893
  %ignore mark;
827
894
  %fragment("hook"{GPS_Solver<FloatT>}, "header",
828
895
  fragment=SWIG_From_frag(int),
829
- fragment=SWIG_Traits_frag(FloatT)){
896
+ fragment=SWIG_Traits_frag(FloatT),
897
+ fragment=SWIG_Traits_frag(GPS_Measurement<FloatT>)){
830
898
  template <>
831
- typename GPS_Solver<FloatT>::base_t::relative_property_t
899
+ GPS_Solver<FloatT>::base_t::relative_property_t
832
900
  GPS_Solver<FloatT>::relative_property(
833
- const typename GPS_Solver<FloatT>::base_t::prn_t &prn,
834
- const typename GPS_Solver<FloatT>::base_t::measurement_t::mapped_type &measurement,
835
- const typename GPS_Solver<FloatT>::base_t::float_t &receiver_error,
836
- const typename GPS_Solver<FloatT>::base_t::gps_time_t &time_arrival,
837
- const typename GPS_Solver<FloatT>::base_t::pos_t &usr_pos,
838
- const typename GPS_Solver<FloatT>::base_t::xyz_t &usr_vel) const {
901
+ const GPS_Solver<FloatT>::base_t::prn_t &prn,
902
+ const GPS_Solver<FloatT>::base_t::measurement_t::mapped_type &measurement,
903
+ const GPS_Solver<FloatT>::base_t::float_t &receiver_error,
904
+ const GPS_Solver<FloatT>::base_t::gps_time_t &time_arrival,
905
+ const GPS_Solver<FloatT>::base_t::pos_t &usr_pos,
906
+ const GPS_Solver<FloatT>::base_t::xyz_t &usr_vel) const {
839
907
  union {
840
- typename base_t::relative_property_t prop;
908
+ base_t::relative_property_t prop;
841
909
  FloatT values[7];
842
910
  } res = {
843
911
  select_solver(prn).relative_property(
@@ -859,6 +927,7 @@ struct GPS_SolverOptions : public GPS_SinglePositioning<FloatT>::options_t {
859
927
  swig::from(res.prop.los_neg[0]),
860
928
  swig::from(res.prop.los_neg[1]),
861
929
  swig::from(res.prop.los_neg[2])),
930
+ swig::from(measurement), // measurement => Hash
862
931
  swig::from(receiver_error), // receiver_error
863
932
  SWIG_NewPointerObj( // time_arrival
864
933
  new base_t::gps_time_t(time_arrival), $descriptor(GPS_Time<FloatT> *), SWIG_POINTER_OWN),
@@ -889,29 +958,186 @@ struct GPS_SolverOptions : public GPS_SinglePositioning<FloatT>::options_t {
889
958
  }
890
959
  template <>
891
960
  bool GPS_Solver<FloatT>::update_position_solution(
892
- const typename GPS_Solver<FloatT>::base_t::geometric_matrices_t &geomat,
893
- typename GPS_Solver<FloatT>::base_t::user_pvt_t &res) const {
961
+ const GPS_Solver<FloatT>::base_t::geometric_matrices_t &geomat,
962
+ GPS_Solver<FloatT>::base_t::user_pvt_t &res) const {
894
963
  #ifdef SWIGRUBY
895
964
  do{
896
965
  static const VALUE key(ID2SYM(rb_intern("update_position_solution")));
897
966
  VALUE hook(rb_hash_lookup(hooks, key));
898
967
  if(NIL_P(hook)){break;}
899
- typename base_t::geometric_matrices_t &geomat_(
900
- %const_cast(geomat, typename base_t::geometric_matrices_t &));
968
+ base_t::geometric_matrices_t &geomat_(
969
+ %const_cast(geomat, base_t::geometric_matrices_t &));
901
970
  VALUE values[] = {
902
971
  SWIG_NewPointerObj(&geomat_.G,
903
972
  $descriptor(Matrix<FloatT, Array2D_Dense<FloatT>, MatrixViewBase<> > *), 0),
904
973
  SWIG_NewPointerObj(&geomat_.W,
905
974
  $descriptor(Matrix<FloatT, Array2D_Dense<FloatT>, MatrixViewBase<> > *), 0),
906
975
  SWIG_NewPointerObj(&geomat_.delta_r,
907
- $descriptor(Matrix<FloatT, Array2D_Dense<FloatT>, MatrixViewBase<> > *), 0)};
976
+ $descriptor(Matrix<FloatT, Array2D_Dense<FloatT>, MatrixViewBase<> > *), 0),
977
+ SWIG_NewPointerObj(&res,
978
+ $descriptor(GPS_User_PVT<FloatT> *), 0)};
908
979
  proc_call_throw_if_error(hook, sizeof(values) / sizeof(values[0]), values);
909
980
  }while(false);
910
981
  #endif
911
982
  return super_t::update_position_solution(geomat, res);
912
983
  }
984
+ template <>
985
+ GPS_Solver<FloatT>::base_t::xyz_t *GPS_Solver<FloatT>::satellite_position(
986
+ const GPS_Solver<FloatT>::base_t::prn_t &prn,
987
+ const GPS_Solver<FloatT>::base_t::gps_time_t &time,
988
+ GPS_Solver<FloatT>::base_t::xyz_t &buf) const {
989
+ GPS_Solver<FloatT>::base_t::xyz_t *res(
990
+ select_solver(prn).satellite_position(prn, time, buf));
991
+ #ifdef SWIGRUBY
992
+ do{
993
+ static const VALUE key(ID2SYM(rb_intern("satellite_position")));
994
+ VALUE hook(rb_hash_lookup(hooks, key));
995
+ if(NIL_P(hook)){break;}
996
+ VALUE values[] = {
997
+ SWIG_From(int)(prn), // prn
998
+ SWIG_NewPointerObj( // time
999
+ new base_t::gps_time_t(time), $descriptor(GPS_Time<FloatT> *), SWIG_POINTER_OWN),
1000
+ (res // position (internally calculated)
1001
+ ? SWIG_NewPointerObj(res, $descriptor(System_XYZ<FloatT, WGS84> *), 0)
1002
+ : Qnil)};
1003
+ VALUE res_hook(proc_call_throw_if_error(hook, sizeof(values) / sizeof(values[0]), values));
1004
+ if(NIL_P(res_hook)){ // unknown position
1005
+ res = NULL;
1006
+ break;
1007
+ }else if(RB_TYPE_P(res_hook, T_ARRAY) && (RARRAY_LEN(res_hook) == 3)){
1008
+ int i(0);
1009
+ for(; i < 3; ++i){
1010
+ VALUE v(RARRAY_AREF(res_hook, i));
1011
+ if(!SWIG_IsOK(swig::asval(v, &buf[i]))){break;}
1012
+ }
1013
+ if(i == 3){
1014
+ res = &buf;
1015
+ break;
1016
+ }
1017
+ }else if(SWIG_IsOK(SWIG_ConvertPtr(
1018
+ res_hook, (void **)&res, $descriptor(System_XYZ<FloatT, WGS84> *), 0))){
1019
+ res = &(buf = *res);
1020
+ break;
1021
+ }
1022
+ throw std::runtime_error(
1023
+ std::string("System_XYZ or [d * 3] is expected (d: " %str(FloatT) "), however ")
1024
+ .append(inspect_str(res_hook)));
1025
+ }while(false);
1026
+ #endif
1027
+ return res;
1028
+ }
913
1029
  }
914
1030
  %fragment("hook"{GPS_Solver<FloatT>});
1031
+ %ignore update_correction;
1032
+ #ifdef SWIGRUBY
1033
+ %fragment("correction"{GPS_Solver<FloatT>}, "header",
1034
+ fragment=SWIG_From_frag(int),
1035
+ fragment=SWIG_Traits_frag(FloatT)){
1036
+ template<>
1037
+ VALUE GPS_Solver<FloatT>::update_correction(
1038
+ const bool &update, const VALUE &hash){
1039
+ typedef range_correction_list_t list_t;
1040
+ static const VALUE k_root[] = {
1041
+ ID2SYM(rb_intern("gps_ionospheric")),
1042
+ ID2SYM(rb_intern("gps_tropospheric")),
1043
+ ID2SYM(rb_intern("sbas_ionospheric")),
1044
+ ID2SYM(rb_intern("sbas_tropospheric")),
1045
+ };
1046
+ static const VALUE k_opt(ID2SYM(rb_intern("options")));
1047
+ static const VALUE k_f_10_7(ID2SYM(rb_intern("f_10_7")));
1048
+ static const VALUE k_known(ID2SYM(rb_intern("known")));
1049
+ struct {
1050
+ VALUE sym;
1051
+ list_t::mapped_type::value_type obj;
1052
+ } item[] = {
1053
+ {ID2SYM(rb_intern("no_correction")), &base_t::no_correction},
1054
+ {ID2SYM(rb_intern("klobuchar")), &this->gps.solver.ionospheric_klobuchar},
1055
+ {ID2SYM(rb_intern("ntcm_gl")), &this->gps.solver.ionospheric_ntcm_gl},
1056
+ {ID2SYM(rb_intern("hopfield")), &this->gps.solver.tropospheric_simplified},
1057
+ {ID2SYM(rb_intern("sbas_igp")), &this->sbas.solver.ionospheric_sbas},
1058
+ {ID2SYM(rb_intern("sbas_tropo")), &this->sbas.solver.tropospheric_sbas},
1059
+ };
1060
+ list_t input;
1061
+ if(update){
1062
+ if(!RB_TYPE_P(hash, T_HASH)){
1063
+ throw std::runtime_error(
1064
+ std::string("Hash is expected, however ").append(inspect_str(hash)));
1065
+ }
1066
+ for(std::size_t i(0); i < sizeof(k_root) / sizeof(k_root[0]); ++i){
1067
+ VALUE ary = rb_hash_lookup(hash, k_root[i]);
1068
+ if(NIL_P(ary)){continue;}
1069
+ if(!RB_TYPE_P(ary, T_ARRAY)){
1070
+ ary = rb_ary_new_from_values(1, &ary);
1071
+ }
1072
+ for(int j(0); j < RARRAY_LEN(ary); ++j){
1073
+ std::size_t k(0);
1074
+ VALUE v(rb_ary_entry(ary, j));
1075
+ for(; k < sizeof(item) / sizeof(item[0]); ++k){
1076
+ if(v == item[k].sym){break;}
1077
+ }
1078
+ if(k >= sizeof(item) / sizeof(item[0])){
1079
+ continue; // TODO other than symbol
1080
+ }
1081
+ input[i].push_back(item[k].obj);
1082
+ }
1083
+ }
1084
+ VALUE opt(rb_hash_lookup(hash, k_opt));
1085
+ if(RB_TYPE_P(opt, T_HASH)){
1086
+ swig::asval(rb_hash_lookup(opt, k_f_10_7), // ntcm_gl
1087
+ &this->gps.solver.ionospheric_ntcm_gl.f_10_7);
1088
+ }
1089
+ }
1090
+ list_t output(update_correction(update, input));
1091
+ VALUE res = rb_hash_new();
1092
+ for(list_t::const_iterator it(output.begin()), it_end(output.end());
1093
+ it != it_end; ++it){
1094
+ VALUE k;
1095
+ if((it->first < 0) || (it->first >= (int)(sizeof(k_root) / sizeof(k_root[0])))){
1096
+ k = SWIG_From(int)(it->first);
1097
+ }else{
1098
+ k = k_root[it->first];
1099
+ }
1100
+ VALUE v = rb_ary_new();
1101
+ for(list_t::mapped_type::const_iterator
1102
+ it2(it->second.begin()), it2_end(it->second.end());
1103
+ it2 != it2_end; ++it2){
1104
+ std::size_t i(0);
1105
+ for(; i < sizeof(item) / sizeof(item[0]); ++i){
1106
+ if(*it2 == item[i].obj){break;}
1107
+ }
1108
+ if(i >= sizeof(item) / sizeof(item[0])){
1109
+ continue; // TODO other than built-in corrector
1110
+ }
1111
+ rb_ary_push(v, item[i].sym);
1112
+ }
1113
+ rb_hash_aset(res, k, v);
1114
+ }
1115
+ { // common options
1116
+ VALUE opt = rb_hash_new();
1117
+ rb_hash_aset(res, k_opt, opt);
1118
+ rb_hash_aset(opt, k_f_10_7, // ntcm_gl
1119
+ swig::from(this->gps.solver.ionospheric_ntcm_gl.f_10_7));
1120
+ }
1121
+ { // known models
1122
+ VALUE ary = rb_ary_new_capa((int)(sizeof(item) / sizeof(item[0])));
1123
+ for(std::size_t i(0); i < sizeof(item) / sizeof(item[0]); ++i){
1124
+ rb_ary_push(ary, item[i].sym);
1125
+ }
1126
+ rb_hash_aset(res, k_known, ary);
1127
+ }
1128
+ return res;
1129
+ }
1130
+ }
1131
+ %fragment("correction"{GPS_Solver<FloatT>});
1132
+ %rename("correction") get_correction;
1133
+ %rename("correction=") set_correction;
1134
+ VALUE get_correction() const {
1135
+ return const_cast<GPS_Solver<FloatT> *>(self)->update_correction(false, Qnil);
1136
+ }
1137
+ VALUE set_correction(VALUE hash){
1138
+ return self->update_correction(true, hash);
1139
+ }
1140
+ #endif
915
1141
  }
916
1142
  %inline {
917
1143
  template <class FloatT>
@@ -927,6 +1153,12 @@ struct GPS_Solver
927
1153
  GPS_SinglePositioning<FloatT> solver;
928
1154
  gps_t() : space_node(), options(), solver(space_node) {}
929
1155
  } gps;
1156
+ struct sbas_t {
1157
+ SBAS_SpaceNode<FloatT> space_node;
1158
+ SBAS_SolverOptions<FloatT> options;
1159
+ SBAS_SinglePositioning<FloatT> solver;
1160
+ sbas_t() : space_node(), options(), solver(space_node) {}
1161
+ } sbas;
930
1162
  SWIG_Object hooks;
931
1163
  #ifdef SWIGRUBY
932
1164
  static void mark(void *ptr){
@@ -935,17 +1167,36 @@ struct GPS_Solver
935
1167
  rb_gc_mark(solver->hooks);
936
1168
  }
937
1169
  #endif
938
- GPS_Solver() : super_t(), gps(), hooks() {
1170
+ GPS_Solver() : super_t(), gps(), sbas(), hooks() {
939
1171
  #ifdef SWIGRUBY
940
1172
  hooks = rb_hash_new();
941
1173
  #endif
1174
+ typename base_t::range_correction_t ionospheric, tropospheric;
1175
+ ionospheric.push_back(&sbas.solver.ionospheric_sbas);
1176
+ ionospheric.push_back(&gps.solver.ionospheric_klobuchar);
1177
+ tropospheric.push_back(&sbas.solver.tropospheric_sbas);
1178
+ tropospheric.push_back(&gps.solver.tropospheric_simplified);
1179
+ gps.solver.ionospheric_correction
1180
+ = sbas.solver.ionospheric_correction
1181
+ = ionospheric;
1182
+ gps.solver.tropospheric_correction
1183
+ = sbas.solver.tropospheric_correction
1184
+ = tropospheric;
942
1185
  }
943
1186
  GPS_SpaceNode<FloatT> &gps_space_node() {return gps.space_node;}
944
1187
  GPS_SolverOptions<FloatT> &gps_options() {return gps.options;}
1188
+ SBAS_SpaceNode<FloatT> &sbas_space_node() {return sbas.space_node;}
1189
+ SBAS_SolverOptions<FloatT> &sbas_options() {return sbas.options;}
945
1190
  const base_t &select_solver(
946
1191
  const typename base_t::prn_t &prn) const {
947
1192
  if(prn > 0 && prn <= 32){return gps.solver;}
948
- return *this;
1193
+ if(prn >= 120 && prn <= 158){return sbas.solver;}
1194
+ if(prn > 192 && prn <= 202){return gps.solver;}
1195
+ // call order: base_t::solve => this returned by select()
1196
+ // => relative_property() => select_solver()
1197
+ // For not supported satellite, call loop prevention is required.
1198
+ static const base_t dummy;
1199
+ return dummy;
949
1200
  }
950
1201
  virtual typename base_t::relative_property_t relative_property(
951
1202
  const typename base_t::prn_t &prn,
@@ -957,9 +1208,7 @@ struct GPS_Solver
957
1208
  virtual typename base_t::xyz_t *satellite_position(
958
1209
  const typename base_t::prn_t &prn,
959
1210
  const typename base_t::gps_time_t &time,
960
- typename base_t::xyz_t &res) const {
961
- return select_solver(prn).satellite_position(prn, time, res);
962
- }
1211
+ typename base_t::xyz_t &res) const;
963
1212
  virtual bool update_position_solution(
964
1213
  const typename base_t::geometric_matrices_t &geomat,
965
1214
  typename base_t::user_pvt_t &res) const;
@@ -968,8 +1217,44 @@ struct GPS_Solver
968
1217
  const GPS_Time<FloatT> &receiver_time) const {
969
1218
  const_cast<gps_t &>(gps).space_node.update_all_ephemeris(receiver_time);
970
1219
  const_cast<gps_t &>(gps).solver.update_options(gps.options);
1220
+ const_cast<sbas_t &>(sbas).space_node.update_all_ephemeris(receiver_time);
1221
+ const_cast<sbas_t &>(sbas).solver.update_options(sbas.options);
971
1222
  return super_t::solve().user_pvt(measurement.items, receiver_time);
972
1223
  }
1224
+ typedef
1225
+ std::map<int, std::vector<const typename base_t::range_corrector_t *> >
1226
+ range_correction_list_t;
1227
+ range_correction_list_t update_correction(
1228
+ const bool &update,
1229
+ const range_correction_list_t &list = range_correction_list_t()){
1230
+ range_correction_list_t res;
1231
+ typename base_t::range_correction_t *root[] = {
1232
+ &gps.solver.ionospheric_correction,
1233
+ &gps.solver.tropospheric_correction,
1234
+ &sbas.solver.ionospheric_correction,
1235
+ &sbas.solver.tropospheric_correction,
1236
+ };
1237
+ for(std::size_t i(0); i < sizeof(root) / sizeof(root[0]); ++i){
1238
+ do{
1239
+ if(!update){break;}
1240
+ typename range_correction_list_t::const_iterator it(list.find(i));
1241
+ if(it == list.end()){break;}
1242
+ root[i]->clear();
1243
+ for(typename range_correction_list_t::mapped_type::const_iterator
1244
+ it2(it->second.begin()), it2_end(it->second.end());
1245
+ it2 != it2_end; ++it2){
1246
+ root[i]->push_back(*it2);
1247
+ }
1248
+ }while(false);
1249
+ for(typename base_t::range_correction_t::const_iterator
1250
+ it(root[i]->begin()), it_end(root[i]->end());
1251
+ it != it_end; ++it){
1252
+ res[i].push_back(*it);
1253
+ }
1254
+ }
1255
+ return res;
1256
+ }
1257
+ SWIG_Object update_correction(const bool &update, const SWIG_Object &hash);
973
1258
  };
974
1259
  }
975
1260
 
@@ -1091,6 +1376,7 @@ struct RINEX_Observation {};
1091
1376
 
1092
1377
  #undef MAKE_ACCESSOR
1093
1378
  #undef MAKE_VECTOR2ARRAY
1379
+ #undef MAKE_ARRAY_INPUT
1094
1380
 
1095
1381
  %define CONCRETIZE(type)
1096
1382
  %template(Time) GPS_Time<type>;
@@ -1099,12 +1385,17 @@ struct RINEX_Observation {};
1099
1385
  %template(Ephemeris) GPS_Ephemeris<type>;
1100
1386
  %template(PVT) GPS_User_PVT<type>;
1101
1387
  %template(Measurement) GPS_Measurement<type>;
1388
+ %template(SolverOptionsCommon) GPS_SolverOptions_Common<type>;
1102
1389
  %template(SolverOptions) GPS_SolverOptions<type>;
1103
1390
  #if defined(SWIGRUBY)
1104
1391
  %markfunc GPS_Solver<type> "GPS_Solver<type>::mark";
1105
1392
  #endif
1106
1393
  %template(Solver) GPS_Solver<type>;
1107
1394
 
1395
+ %template(Ephemeris_SBAS) SBAS_Ephemeris<type>;
1396
+ %template(SpaceNode_SBAS) SBAS_SpaceNode<type>;
1397
+ %template(SolverOptions_SBAS) SBAS_SolverOptions<type>;
1398
+
1108
1399
  %template(RINEX_Observation) RINEX_Observation<type>;
1109
1400
  %enddef
1110
1401