gps_pvt 0.1.5 → 0.2.1

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){
@@ -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]}