gps_pvt 0.1.5 → 0.2.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.
@@ -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){
@@ -180,6 +183,26 @@ const type &get_ ## name () const {
180
183
  }
181
184
  }
182
185
  %enddef
186
+ #if defined(SWIGRUBY)
187
+ %define MAKE_ARRAY_INPUT(type, arg_name, f_conv)
188
+ %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) type arg_name[ANY] {
189
+ $1 = RB_TYPE_P($input, T_ARRAY) ? 1 : 0;
190
+ }
191
+ %typemap(in) type arg_name[ANY] ($*1_ltype temp[$1_dim0]) {
192
+ if(!(RB_TYPE_P($input, T_ARRAY) && (RARRAY_LEN($input) == $1_dim0))){
193
+ SWIG_exception(SWIG_TypeError, "array[$1_dim0] is expected");
194
+ }
195
+ for(int i(0); i < $1_dim0; ++i){
196
+ if(!SWIG_IsOK(f_conv(RARRAY_AREF($input, i), &temp[i]))){
197
+ SWIG_exception(SWIG_TypeError, "$*1_ltype is expected");
198
+ }
199
+ }
200
+ $1 = temp;
201
+ }
202
+ %enddef
203
+ #else
204
+ #define MAKE_ARRAY_INPUT(type, arg_name, f_conv)
205
+ #endif
183
206
 
184
207
  %inline %{
185
208
  template <class FloatT>
@@ -195,34 +218,8 @@ struct GPS_Ionospheric_UTC_Parameters : public GPS_SpaceNode<FloatT>::Ionospheri
195
218
  %append_output(swig::from($1[i]));
196
219
  }
197
220
  }
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
- }
221
+ MAKE_ARRAY_INPUT(const FloatT, values, swig::asval);
222
+ MAKE_ARRAY_INPUT(const unsigned int, buf, SWIG_AsVal(unsigned int));
226
223
  %rename("alpha=") set_alpha;
227
224
  void set_alpha(const FloatT values[4]){
228
225
  for(int i(0); i < 4; ++i){
@@ -255,7 +252,7 @@ struct GPS_Ionospheric_UTC_Parameters : public GPS_SpaceNode<FloatT>::Ionospheri
255
252
  MAKE_ACCESSOR(WN_LSF, unsigned int);
256
253
  MAKE_ACCESSOR(DN, unsigned int);
257
254
  MAKE_ACCESSOR(delta_t_LSF, int);
258
- static GPS_Ionospheric_UTC_Parameters<FloatT> parse(const unsigned int *buf){
255
+ static GPS_Ionospheric_UTC_Parameters<FloatT> parse(const unsigned int buf[10]){
259
256
  typedef typename GPS_SpaceNode<FloatT>
260
257
  ::BroadcastedMessage<unsigned int, 30> parser_t;
261
258
  if((parser_t::subframe_id(buf) != 4) || (parser_t::sv_page_id(buf) != 56)){
@@ -321,22 +318,10 @@ struct GPS_Ephemeris : public GPS_SpaceNode<FloatT>::SatelliteProperties::Epheme
321
318
  MAKE_ACCESSOR(omega, FloatT);
322
319
  MAKE_ACCESSOR(dot_Omega0, FloatT);
323
320
  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
- }
321
+
322
+ MAKE_ARRAY_INPUT(const unsigned int, buf, SWIG_AsVal(unsigned int));
338
323
  %apply int *OUTPUT { int *subframe_no, int *iodc_or_iode };
339
- void parse(const unsigned int *buf, int *subframe_no, int *iodc_or_iode){
324
+ void parse(const unsigned int buf[10], int *subframe_no, int *iodc_or_iode){
340
325
  typedef typename GPS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris eph_t;
341
326
  typename eph_t::raw_t raw;
342
327
  eph_t eph;
@@ -432,11 +417,82 @@ struct GPS_Ephemeris : public GPS_SpaceNode<FloatT>::SatelliteProperties::Epheme
432
417
  %ignore tropo_correction() const;
433
418
  int read(const char *fname) {
434
419
  std::fstream fin(fname, std::ios::in | std::ios::binary);
435
- return RINEX_NAV_Reader<FloatT>::read_all(fin, *self);
420
+ typename RINEX_NAV_Reader<FloatT>::space_node_list_t space_nodes = {self};
421
+ space_nodes.qzss = self;
422
+ return RINEX_NAV_Reader<FloatT>::read_all(fin, space_nodes);
436
423
  }
437
424
  }
438
425
 
439
426
  %include navigation/GPS.h
427
+ %include navigation/QZSS.h
428
+
429
+ %inline %{
430
+ template <class FloatT>
431
+ struct SBAS_Ephemeris : public SBAS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris {
432
+ SBAS_Ephemeris() : SBAS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris() {}
433
+ SBAS_Ephemeris(const typename SBAS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris &eph)
434
+ : SBAS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris(eph) {}
435
+ };
436
+ %}
437
+ %extend SBAS_Ephemeris {
438
+ MAKE_ACCESSOR(svid, unsigned int);
439
+
440
+ MAKE_ACCESSOR(WN, unsigned int);
441
+ MAKE_ACCESSOR(t_0, FloatT);
442
+ MAKE_ACCESSOR(URA, int);
443
+ MAKE_ACCESSOR( x, FloatT); MAKE_ACCESSOR( y, FloatT); MAKE_ACCESSOR( z, FloatT);
444
+ MAKE_ACCESSOR( dx, FloatT); MAKE_ACCESSOR( dy, FloatT); MAKE_ACCESSOR( dz, FloatT);
445
+ MAKE_ACCESSOR(ddx, FloatT); MAKE_ACCESSOR(ddy, FloatT); MAKE_ACCESSOR(ddz, FloatT);
446
+ MAKE_ACCESSOR(a_Gf0, FloatT);
447
+ MAKE_ACCESSOR(a_Gf1, FloatT);
448
+ %apply GPS_Ephemeris::System_XYZ<FloatT, WGS84> & { System_XYZ<FloatT, WGS84> & }; // TODO ineffective?
449
+ void constellation(
450
+ System_XYZ<FloatT, WGS84> &position, System_XYZ<FloatT, WGS84> &velocity,
451
+ const GPS_Time<FloatT> &t, const FloatT &pseudo_range = 0,
452
+ const bool &with_velocity = true) const {
453
+ typename SBAS_SpaceNode<FloatT>::SatelliteProperties::constellation_t res(
454
+ self->constellation(t, pseudo_range, with_velocity));
455
+ position = res.position;
456
+ velocity = res.velocity;
457
+ }
458
+ }
459
+
460
+ %extend SBAS_SpaceNode {
461
+ %fragment(SWIG_Traits_frag(FloatT));
462
+ %ignore satellites() const;
463
+ %ignore satellite(const int &);
464
+ %ignore available_satellites(const FloatT &lng_deg) const;
465
+ void register_ephemeris(
466
+ const int &prn, const SBAS_Ephemeris<FloatT> &eph,
467
+ const int &priority_delta = 1){
468
+ self->satellite(prn).register_ephemeris(eph, priority_delta);
469
+ }
470
+ SBAS_Ephemeris<FloatT> ephemeris(const int &prn) const {
471
+ return SBAS_Ephemeris<FloatT>(
472
+ %const_cast(self, SBAS_SpaceNode<FloatT> *)->satellite(prn).ephemeris());
473
+ }
474
+ int read(const char *fname) {
475
+ std::fstream fin(fname, std::ios::in | std::ios::binary);
476
+ RINEX_NAV_Reader<FloatT>::space_node_list_t space_nodes = {NULL};
477
+ space_nodes.sbas = self;
478
+ return RINEX_NAV_Reader<FloatT>::read_all(fin, space_nodes);
479
+ }
480
+ MAKE_ARRAY_INPUT(const unsigned int, buf, SWIG_AsVal(unsigned int));
481
+ int decode_message(const unsigned int buf[8],
482
+ const int &prn, const GPS_Time<FloatT> &t_reception,
483
+ const bool &LNAV_VNAV_LP_LPV_approach = false){
484
+ return static_cast<int>(
485
+ self->decode_message(buf, prn, t_reception, LNAV_VNAV_LP_LPV_approach));
486
+ }
487
+ std::string ionospheric_grid_points(const int &prn) const {
488
+ std::ostringstream ss;
489
+ ss << %const_cast(self, SBAS_SpaceNode<FloatT> *)->satellite(prn)
490
+ .ionospheric_grid_points();
491
+ return ss.str();
492
+ }
493
+ }
494
+
495
+ %include navigation/SBAS.h
440
496
 
441
497
  %extend GPS_User_PVT {
442
498
  %ignore solver_t;
@@ -604,23 +660,6 @@ struct GPS_User_PVT
604
660
  }
605
661
  }
606
662
  }
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
663
  %fragment(SWIG_Traits_frag(GPS_Measurement<FloatT>), "header",
625
664
  fragment=SWIG_Traits_frag(FloatT)){
626
665
  namespace swig {
@@ -704,9 +743,32 @@ struct GPS_User_PVT
704
743
  #endif
705
744
  return SWIG_ERROR;
706
745
  }
746
+ #ifdef SWIGRUBY
747
+ template <>
748
+ VALUE from(const GPS_Measurement<FloatT>::items_t::mapped_type &val) {
749
+ VALUE per_sat(rb_hash_new());
750
+ for(typename GPS_Measurement<FloatT>::items_t::mapped_type::const_iterator
751
+ it(val.begin()), it_end(val.end());
752
+ it != it_end; ++it){
753
+ rb_hash_aset(per_sat, SWIG_From(int)(it->first), swig::from(it->second));
754
+ }
755
+ return per_sat;
756
+ }
757
+ #endif
707
758
  }
708
759
  }
709
760
  %fragment(SWIG_Traits_frag(GPS_Measurement<FloatT>));
761
+ #ifdef SWIGRUBY
762
+ VALUE to_hash() const {
763
+ VALUE res(rb_hash_new());
764
+ for(typename GPS_Measurement<FloatT>::items_t::const_iterator
765
+ it(self->items.begin()), it_end(self->items.end());
766
+ it != it_end; ++it){
767
+ rb_hash_aset(res, SWIG_From(int)(it->first), swig::from(it->second));
768
+ }
769
+ return res;
770
+ }
771
+ #endif
710
772
  %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) const GPS_Measurement<FloatT> & {
711
773
  $1 = SWIG_CheckState(SWIG_ConvertPtr($input, (void **)0, $1_descriptor, 0))
712
774
  || swig::check<GPS_Measurement<FloatT> >($input);
@@ -746,12 +808,23 @@ struct GPS_Measurement {
746
808
  };
747
809
  }
748
810
 
749
- %extend GPS_SolverOptions {
750
- %ignore base_t;
751
- MAKE_ACCESSOR(elevation_mask, FloatT);
752
- MAKE_ACCESSOR(residual_mask, FloatT);
753
- MAKE_ACCESSOR(f_10_7, FloatT);
811
+ %extend GPS_SolverOptions_Common {
812
+ %define MAKE_ACCESSOR2(name, type)
813
+ %rename(%str(name ## =)) set_ ## name;
814
+ type set_ ## name (const type &v) {
815
+ return self->cast_general()->name = v;
816
+ }
817
+ %rename(%str(name)) get_ ## name;
818
+ const type &get_ ## name () const {
819
+ return self->cast_general()->name;
820
+ }
821
+ %enddef
822
+ MAKE_ACCESSOR2(elevation_mask, FloatT);
823
+ MAKE_ACCESSOR2(residual_mask, FloatT);
824
+ MAKE_ACCESSOR2(f_10_7, FloatT);
825
+ #undef MAKE_ACCESSOR2
754
826
  MAKE_VECTOR2ARRAY(int);
827
+ %ignore cast_base;
755
828
  #ifdef SWIGRUBY
756
829
  %rename("ionospheric_models=") set_ionospheric_models;
757
830
  %rename("ionospheric_models") get_ionospheric_models;
@@ -775,49 +848,92 @@ struct GPS_Measurement {
775
848
  }
776
849
  %inline %{
777
850
  template <class FloatT>
778
- struct GPS_SolverOptions : public GPS_SinglePositioning<FloatT>::options_t {
779
- typedef typename GPS_SinglePositioning<FloatT>::options_t base_t;
780
- void exclude(const int &prn){base_t::exclude_prn.set(prn);}
781
- void include(const int &prn){base_t::exclude_prn.reset(prn);}
782
- std::vector<int> excluded() const {return base_t::exclude_prn.excluded();}
851
+ struct GPS_SolverOptions_Common {
783
852
  enum {
784
853
  IONOSPHERIC_KLOBUCHAR,
854
+ IONOSPHERIC_SBAS,
785
855
  IONOSPHERIC_NTCM_GL,
786
856
  IONOSPHERIC_NONE, // which allows no correction
787
857
  IONOSPHERIC_MODELS,
788
858
  IONOSPHERIC_SKIP = IONOSPHERIC_MODELS, // which means delegating the next slot
789
859
  };
860
+ virtual GPS_Solver_GeneralOptions<FloatT> *cast_general() = 0;
861
+ virtual const GPS_Solver_GeneralOptions<FloatT> *cast_general() const = 0;
790
862
  std::vector<int> get_ionospheric_models() const {
863
+ typedef GPS_Solver_GeneralOptions<FloatT> general_t;
864
+ const general_t *general(this->cast_general());
791
865
  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;}
866
+ for(int i(0); i < general_t::IONOSPHERIC_MODELS; ++i){
867
+ int v((int)(general->ionospheric_models[i]));
868
+ if(v == general_t::IONOSPHERIC_SKIP){break;}
795
869
  res.push_back(v);
796
870
  }
797
871
  return res;
798
872
  }
799
873
  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);
874
+ typedef GPS_Solver_GeneralOptions<FloatT> general_t;
875
+ general_t *general(this->cast_general());
876
+ typedef typename general_t::ionospheric_model_t model_t;
877
+ for(int i(0), j(0), j_max(models.size()); i < general_t::IONOSPHERIC_MODELS; ++i){
878
+ model_t v(general_t::IONOSPHERIC_SKIP);
803
879
  if(j < j_max){
804
- if((models[j] >= 0) && (models[j] < base_t::IONOSPHERIC_SKIP)){
880
+ if((models[j] >= 0) && (models[j] < general_t::IONOSPHERIC_SKIP)){
805
881
  v = (model_t)models[j];
806
882
  }
807
883
  ++j;
808
884
  }
809
- base_t::ionospheric_models[i] = v;
885
+ general->ionospheric_models[i] = v;
810
886
  }
811
887
  return get_ionospheric_models();
812
888
  }
813
889
  };
814
890
  %}
815
891
 
892
+ %extend GPS_SolverOptions {
893
+ %ignore base_t;
894
+ %ignore cast_general;
895
+ MAKE_VECTOR2ARRAY(int);
896
+ }
897
+ %inline %{
898
+ template <class FloatT>
899
+ struct GPS_SolverOptions
900
+ : public GPS_SinglePositioning<FloatT>::options_t,
901
+ GPS_SolverOptions_Common<FloatT> {
902
+ typedef typename GPS_SinglePositioning<FloatT>::options_t base_t;
903
+ void exclude(const int &prn){base_t::exclude_prn.set(prn);}
904
+ void include(const int &prn){base_t::exclude_prn.reset(prn);}
905
+ std::vector<int> excluded() const {return base_t::exclude_prn.excluded();}
906
+ GPS_Solver_GeneralOptions<FloatT> *cast_general(){return this;}
907
+ const GPS_Solver_GeneralOptions<FloatT> *cast_general() const {return this;}
908
+ };
909
+ %}
910
+
911
+ %extend SBAS_SolverOptions {
912
+ %ignore base_t;
913
+ %ignore cast_general;
914
+ MAKE_VECTOR2ARRAY(int);
915
+ }
916
+ %inline %{
917
+ template <class FloatT>
918
+ struct SBAS_SolverOptions
919
+ : public SBAS_SinglePositioning<FloatT>::options_t,
920
+ GPS_SolverOptions_Common<FloatT> {
921
+ typedef typename SBAS_SinglePositioning<FloatT>::options_t base_t;
922
+ void exclude(const int &prn){base_t::exclude_prn.set(prn);}
923
+ void include(const int &prn){base_t::exclude_prn.reset(prn);}
924
+ std::vector<int> excluded() const {return base_t::exclude_prn.excluded();}
925
+ GPS_Solver_GeneralOptions<FloatT> *cast_general(){return this;}
926
+ const GPS_Solver_GeneralOptions<FloatT> *cast_general() const {return this;}
927
+ };
928
+ %}
929
+
816
930
  %extend GPS_Solver {
817
931
  %ignore super_t;
818
932
  %ignore base_t;
819
933
  %ignore gps_t;
820
934
  %ignore gps;
935
+ %ignore sbas_t;
936
+ %ignore sbas;
821
937
  %ignore select_solver;
822
938
  %ignore relative_property;
823
939
  %ignore satellite_position;
@@ -826,18 +942,19 @@ struct GPS_SolverOptions : public GPS_SinglePositioning<FloatT>::options_t {
826
942
  %ignore mark;
827
943
  %fragment("hook"{GPS_Solver<FloatT>}, "header",
828
944
  fragment=SWIG_From_frag(int),
829
- fragment=SWIG_Traits_frag(FloatT)){
945
+ fragment=SWIG_Traits_frag(FloatT),
946
+ fragment=SWIG_Traits_frag(GPS_Measurement<FloatT>)){
830
947
  template <>
831
- typename GPS_Solver<FloatT>::base_t::relative_property_t
948
+ GPS_Solver<FloatT>::base_t::relative_property_t
832
949
  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 {
950
+ const GPS_Solver<FloatT>::base_t::prn_t &prn,
951
+ const GPS_Solver<FloatT>::base_t::measurement_t::mapped_type &measurement,
952
+ const GPS_Solver<FloatT>::base_t::float_t &receiver_error,
953
+ const GPS_Solver<FloatT>::base_t::gps_time_t &time_arrival,
954
+ const GPS_Solver<FloatT>::base_t::pos_t &usr_pos,
955
+ const GPS_Solver<FloatT>::base_t::xyz_t &usr_vel) const {
839
956
  union {
840
- typename base_t::relative_property_t prop;
957
+ base_t::relative_property_t prop;
841
958
  FloatT values[7];
842
959
  } res = {
843
960
  select_solver(prn).relative_property(
@@ -859,6 +976,7 @@ struct GPS_SolverOptions : public GPS_SinglePositioning<FloatT>::options_t {
859
976
  swig::from(res.prop.los_neg[0]),
860
977
  swig::from(res.prop.los_neg[1]),
861
978
  swig::from(res.prop.los_neg[2])),
979
+ swig::from(measurement), // measurement => Hash
862
980
  swig::from(receiver_error), // receiver_error
863
981
  SWIG_NewPointerObj( // time_arrival
864
982
  new base_t::gps_time_t(time_arrival), $descriptor(GPS_Time<FloatT> *), SWIG_POINTER_OWN),
@@ -889,15 +1007,15 @@ struct GPS_SolverOptions : public GPS_SinglePositioning<FloatT>::options_t {
889
1007
  }
890
1008
  template <>
891
1009
  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 {
1010
+ const GPS_Solver<FloatT>::base_t::geometric_matrices_t &geomat,
1011
+ GPS_Solver<FloatT>::base_t::user_pvt_t &res) const {
894
1012
  #ifdef SWIGRUBY
895
1013
  do{
896
1014
  static const VALUE key(ID2SYM(rb_intern("update_position_solution")));
897
1015
  VALUE hook(rb_hash_lookup(hooks, key));
898
1016
  if(NIL_P(hook)){break;}
899
- typename base_t::geometric_matrices_t &geomat_(
900
- %const_cast(geomat, typename base_t::geometric_matrices_t &));
1017
+ base_t::geometric_matrices_t &geomat_(
1018
+ %const_cast(geomat, base_t::geometric_matrices_t &));
901
1019
  VALUE values[] = {
902
1020
  SWIG_NewPointerObj(&geomat_.G,
903
1021
  $descriptor(Matrix<FloatT, Array2D_Dense<FloatT>, MatrixViewBase<> > *), 0),
@@ -910,6 +1028,51 @@ struct GPS_SolverOptions : public GPS_SinglePositioning<FloatT>::options_t {
910
1028
  #endif
911
1029
  return super_t::update_position_solution(geomat, res);
912
1030
  }
1031
+ template <>
1032
+ GPS_Solver<FloatT>::base_t::xyz_t *GPS_Solver<FloatT>::satellite_position(
1033
+ const GPS_Solver<FloatT>::base_t::prn_t &prn,
1034
+ const GPS_Solver<FloatT>::base_t::gps_time_t &time,
1035
+ GPS_Solver<FloatT>::base_t::xyz_t &buf) const {
1036
+ GPS_Solver<FloatT>::base_t::xyz_t *res(
1037
+ select_solver(prn).satellite_position(prn, time, buf));
1038
+ #ifdef SWIGRUBY
1039
+ do{
1040
+ static const VALUE key(ID2SYM(rb_intern("satellite_position")));
1041
+ VALUE hook(rb_hash_lookup(hooks, key));
1042
+ if(NIL_P(hook)){break;}
1043
+ VALUE values[] = {
1044
+ SWIG_From(int)(prn), // prn
1045
+ SWIG_NewPointerObj( // time
1046
+ new base_t::gps_time_t(time), $descriptor(GPS_Time<FloatT> *), SWIG_POINTER_OWN),
1047
+ (res // position (internally calculated)
1048
+ ? SWIG_NewPointerObj(res, $descriptor(System_XYZ<FloatT, WGS84> *), 0)
1049
+ : Qnil)};
1050
+ VALUE res_hook(proc_call_throw_if_error(hook, sizeof(values) / sizeof(values[0]), values));
1051
+ if(NIL_P(res_hook)){ // unknown position
1052
+ res = NULL;
1053
+ break;
1054
+ }else if(RB_TYPE_P(res_hook, T_ARRAY) && (RARRAY_LEN(res_hook) == 3)){
1055
+ int i(0);
1056
+ for(; i < 3; ++i){
1057
+ VALUE v(RARRAY_AREF(res_hook, i));
1058
+ if(!SWIG_IsOK(swig::asval(v, &buf[i]))){break;}
1059
+ }
1060
+ if(i == 3){
1061
+ res = &buf;
1062
+ break;
1063
+ }
1064
+ }else if(SWIG_IsOK(SWIG_ConvertPtr(
1065
+ res_hook, (void **)&res, $descriptor(System_XYZ<FloatT, WGS84> *), 0))){
1066
+ res = &(buf = *res);
1067
+ break;
1068
+ }
1069
+ throw std::runtime_error(
1070
+ std::string("System_XYZ or [d * 3] is expected (d: " %str(FloatT) "), however ")
1071
+ .append(inspect_str(res_hook)));
1072
+ }while(false);
1073
+ #endif
1074
+ return res;
1075
+ }
913
1076
  }
914
1077
  %fragment("hook"{GPS_Solver<FloatT>});
915
1078
  }
@@ -927,6 +1090,12 @@ struct GPS_Solver
927
1090
  GPS_SinglePositioning<FloatT> solver;
928
1091
  gps_t() : space_node(), options(), solver(space_node) {}
929
1092
  } gps;
1093
+ struct sbas_t {
1094
+ SBAS_SpaceNode<FloatT> space_node;
1095
+ SBAS_SolverOptions<FloatT> options;
1096
+ SBAS_SinglePositioning<FloatT> solver;
1097
+ sbas_t() : space_node(), options(), solver(space_node) {}
1098
+ } sbas;
930
1099
  SWIG_Object hooks;
931
1100
  #ifdef SWIGRUBY
932
1101
  static void mark(void *ptr){
@@ -935,17 +1104,27 @@ struct GPS_Solver
935
1104
  rb_gc_mark(solver->hooks);
936
1105
  }
937
1106
  #endif
938
- GPS_Solver() : super_t(), gps(), hooks() {
1107
+ GPS_Solver() : super_t(), gps(), sbas(), hooks() {
1108
+ gps.solver.space_node_sbas = &sbas.space_node;
1109
+ sbas.solver.space_node_gps = &gps.space_node;
939
1110
  #ifdef SWIGRUBY
940
1111
  hooks = rb_hash_new();
941
1112
  #endif
942
1113
  }
943
1114
  GPS_SpaceNode<FloatT> &gps_space_node() {return gps.space_node;}
944
1115
  GPS_SolverOptions<FloatT> &gps_options() {return gps.options;}
1116
+ SBAS_SpaceNode<FloatT> &sbas_space_node() {return sbas.space_node;}
1117
+ SBAS_SolverOptions<FloatT> &sbas_options() {return sbas.options;}
945
1118
  const base_t &select_solver(
946
1119
  const typename base_t::prn_t &prn) const {
947
1120
  if(prn > 0 && prn <= 32){return gps.solver;}
948
- return *this;
1121
+ if(prn >= 120 && prn <= 158){return sbas.solver;}
1122
+ if(prn > 192 && prn <= 202){return gps.solver;}
1123
+ // call order: base_t::solve => this returned by select()
1124
+ // => relative_property() => select_solver()
1125
+ // For not supported satellite, call loop prevention is required.
1126
+ static const base_t dummy;
1127
+ return dummy;
949
1128
  }
950
1129
  virtual typename base_t::relative_property_t relative_property(
951
1130
  const typename base_t::prn_t &prn,
@@ -957,9 +1136,7 @@ struct GPS_Solver
957
1136
  virtual typename base_t::xyz_t *satellite_position(
958
1137
  const typename base_t::prn_t &prn,
959
1138
  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
- }
1139
+ typename base_t::xyz_t &res) const;
963
1140
  virtual bool update_position_solution(
964
1141
  const typename base_t::geometric_matrices_t &geomat,
965
1142
  typename base_t::user_pvt_t &res) const;
@@ -968,6 +1145,8 @@ struct GPS_Solver
968
1145
  const GPS_Time<FloatT> &receiver_time) const {
969
1146
  const_cast<gps_t &>(gps).space_node.update_all_ephemeris(receiver_time);
970
1147
  const_cast<gps_t &>(gps).solver.update_options(gps.options);
1148
+ const_cast<sbas_t &>(sbas).space_node.update_all_ephemeris(receiver_time);
1149
+ const_cast<sbas_t &>(sbas).solver.update_options(sbas.options);
971
1150
  return super_t::solve().user_pvt(measurement.items, receiver_time);
972
1151
  }
973
1152
  };
@@ -1091,6 +1270,7 @@ struct RINEX_Observation {};
1091
1270
 
1092
1271
  #undef MAKE_ACCESSOR
1093
1272
  #undef MAKE_VECTOR2ARRAY
1273
+ #undef MAKE_ARRAY_INPUT
1094
1274
 
1095
1275
  %define CONCRETIZE(type)
1096
1276
  %template(Time) GPS_Time<type>;
@@ -1099,12 +1279,17 @@ struct RINEX_Observation {};
1099
1279
  %template(Ephemeris) GPS_Ephemeris<type>;
1100
1280
  %template(PVT) GPS_User_PVT<type>;
1101
1281
  %template(Measurement) GPS_Measurement<type>;
1282
+ %template(SolverOptionsCommon) GPS_SolverOptions_Common<type>;
1102
1283
  %template(SolverOptions) GPS_SolverOptions<type>;
1103
1284
  #if defined(SWIGRUBY)
1104
1285
  %markfunc GPS_Solver<type> "GPS_Solver<type>::mark";
1105
1286
  #endif
1106
1287
  %template(Solver) GPS_Solver<type>;
1107
1288
 
1289
+ %template(Ephemeris_SBAS) SBAS_Ephemeris<type>;
1290
+ %template(SpaceNode_SBAS) SBAS_SpaceNode<type>;
1291
+ %template(SolverOptions_SBAS) SBAS_SolverOptions<type>;
1292
+
1108
1293
  %template(RINEX_Observation) RINEX_Observation<type>;
1109
1294
  %enddef
1110
1295
 
@@ -339,8 +339,9 @@ __RINEX_OBS_TEXT__
339
339
  sn.read(input[:rinex_nav])
340
340
  t_meas = GPS::Time::new(1849, 172413)
341
341
  sn.update_all_ephemeris(t_meas)
342
- solver.hooks[:relative_property] = proc{|prn, rel_prop, rcv_e, t_arv, usr_pos, usr_vel|
342
+ solver.hooks[:relative_property] = proc{|prn, rel_prop, meas, rcv_e, t_arv, usr_pos, usr_vel|
343
343
  expect(input[:measurement]).to include(prn)
344
+ expect(meas).to be_a_kind_of(Hash)
344
345
  expect(t_arv).to be_a_kind_of(GPS::Time)
345
346
  expect(usr_pos).to be_a_kind_of(Coordinate::XYZ)
346
347
  expect(usr_vel).to be_a_kind_of(Coordinate::XYZ)
@@ -354,6 +355,22 @@ __RINEX_OBS_TEXT__
354
355
  }
355
356
  mat_G, mat_W, mat_delta_r = mats
356
357
  }
358
+ solver.hooks[:satellite_position] = proc{
359
+ i = 0
360
+ proc{|prn, time, pos|
361
+ expect(input[:measurement]).to include(prn)
362
+ expect(pos).to be_a_kind_of(Coordinate::XYZ).or eq(nil)
363
+ # System_XYZ or [x,y,z] or nil(= unknown position) are acceptable
364
+ case (i += 1) % 5
365
+ when 0
366
+ nil
367
+ when 1
368
+ pos.to_a
369
+ else
370
+ pos
371
+ end
372
+ }
373
+ }.call
357
374
  pvt = solver.solve(
358
375
  input[:measurement].collect{|prn, items|
359
376
  items.collect{|k, v| [prn, k, v]}