gps_pvt 0.1.7 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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