gps_pvt 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -159,6 +159,14 @@ static std::string inspect_str(const VALUE &v){
159
159
  *week = self->week;
160
160
  *seconds = self->seconds;
161
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
162
170
  }
163
171
 
164
172
  %define MAKE_ACCESSOR(name, type)
@@ -413,15 +421,10 @@ struct GPS_Ephemeris : public GPS_SpaceNode<FloatT>::SatelliteProperties::Epheme
413
421
  %append_output(swig::from($1.latitude));
414
422
  %append_output(swig::from($1.longitude));
415
423
  }
416
- %ignore iono_correction() const;
417
- %ignore tropo_correction() const;
418
424
  int read(const char *fname) {
419
425
  std::fstream fin(fname, std::ios::in | std::ios::binary);
420
- typename RINEX_NAV_Reader<FloatT>::space_node_list_t space_nodes = {
421
- self, // GPS
422
- NULL, // SBAS
423
- self, // QZSS
424
- };
426
+ typename RINEX_NAV_Reader<FloatT>::space_node_list_t space_nodes = {self};
427
+ space_nodes.qzss = self;
425
428
  return RINEX_NAV_Reader<FloatT>::read_all(fin, space_nodes);
426
429
  }
427
430
  }
@@ -476,7 +479,8 @@ struct SBAS_Ephemeris : public SBAS_SpaceNode<FloatT>::SatelliteProperties::Ephe
476
479
  }
477
480
  int read(const char *fname) {
478
481
  std::fstream fin(fname, std::ios::in | std::ios::binary);
479
- RINEX_NAV_Reader<FloatT>::space_node_list_t space_nodes = {NULL, self};
482
+ RINEX_NAV_Reader<FloatT>::space_node_list_t space_nodes = {NULL};
483
+ space_nodes.sbas = self;
480
484
  return RINEX_NAV_Reader<FloatT>::read_all(fin, space_nodes);
481
485
  }
482
486
  MAKE_ARRAY_INPUT(const unsigned int, buf, SWIG_AsVal(unsigned int));
@@ -662,23 +666,6 @@ struct GPS_User_PVT
662
666
  }
663
667
  }
664
668
  }
665
- #ifdef SWIGRUBY
666
- VALUE to_hash() const {
667
- VALUE res(rb_hash_new());
668
- for(typename GPS_Measurement<FloatT>::items_t::const_iterator
669
- it(self->items.begin()), it_end(self->items.end());
670
- it != it_end; ++it){
671
- VALUE per_sat(rb_hash_new());
672
- rb_hash_aset(res, SWIG_From(int)(it->first), per_sat);
673
- for(typename GPS_Measurement<FloatT>::items_t::mapped_type::const_iterator
674
- it2(it->second.begin()), it2_end(it->second.end());
675
- it2 != it2_end; ++it2){
676
- rb_hash_aset(per_sat, SWIG_From(int)(it2->first), swig::from(it2->second));
677
- }
678
- }
679
- return res;
680
- }
681
- #endif
682
669
  %fragment(SWIG_Traits_frag(GPS_Measurement<FloatT>), "header",
683
670
  fragment=SWIG_Traits_frag(FloatT)){
684
671
  namespace swig {
@@ -762,9 +749,32 @@ struct GPS_User_PVT
762
749
  #endif
763
750
  return SWIG_ERROR;
764
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
765
764
  }
766
765
  }
767
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
768
778
  %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) const GPS_Measurement<FloatT> & {
769
779
  $1 = SWIG_CheckState(SWIG_ConvertPtr($input, (void **)0, $1_descriptor, 0))
770
780
  || swig::check<GPS_Measurement<FloatT> >($input);
@@ -796,6 +806,7 @@ struct GPS_Measurement {
796
806
  L1_RANGE_RATE_SIGMA,
797
807
  L1_SIGNAL_STRENGTH_dBHz,
798
808
  L1_LOCK_SEC,
809
+ L1_FREQUENCY,
799
810
  ITEMS_PREDEFINED,
800
811
  };
801
812
  void add(const int &prn, const int &key, const FloatT &value){
@@ -817,71 +828,15 @@ const type &get_ ## name () const {
817
828
  %enddef
818
829
  MAKE_ACCESSOR2(elevation_mask, FloatT);
819
830
  MAKE_ACCESSOR2(residual_mask, FloatT);
820
- MAKE_ACCESSOR2(f_10_7, FloatT);
821
831
  #undef MAKE_ACCESSOR2
822
832
  MAKE_VECTOR2ARRAY(int);
823
833
  %ignore cast_base;
824
- #ifdef SWIGRUBY
825
- %rename("ionospheric_models=") set_ionospheric_models;
826
- %rename("ionospheric_models") get_ionospheric_models;
827
- #endif
828
- %typemap(in) const std::vector<int> &models (std::vector<int> temp) {
829
- $1 = &temp;
830
- #ifdef SWIGRUBY
831
- if(RB_TYPE_P($input, T_ARRAY)){
832
- for(int i(0), i_max(RARRAY_LEN($input)); i < i_max; ++i){
833
- SWIG_Object obj(RARRAY_AREF($input, i));
834
- int v;
835
- if(SWIG_IsOK(SWIG_AsVal(int)(obj, &v))){
836
- temp.push_back(v);
837
- }else{
838
- SWIG_exception(SWIG_TypeError, "$*1_ltype is expected");
839
- }
840
- }
841
- }
842
- #endif
843
- }
844
834
  }
845
835
  %inline %{
846
836
  template <class FloatT>
847
837
  struct GPS_SolverOptions_Common {
848
- enum {
849
- IONOSPHERIC_KLOBUCHAR,
850
- IONOSPHERIC_SBAS,
851
- IONOSPHERIC_NTCM_GL,
852
- IONOSPHERIC_NONE, // which allows no correction
853
- IONOSPHERIC_MODELS,
854
- IONOSPHERIC_SKIP = IONOSPHERIC_MODELS, // which means delegating the next slot
855
- };
856
838
  virtual GPS_Solver_GeneralOptions<FloatT> *cast_general() = 0;
857
839
  virtual const GPS_Solver_GeneralOptions<FloatT> *cast_general() const = 0;
858
- std::vector<int> get_ionospheric_models() const {
859
- typedef GPS_Solver_GeneralOptions<FloatT> general_t;
860
- const general_t *general(this->cast_general());
861
- std::vector<int> res;
862
- for(int i(0); i < general_t::IONOSPHERIC_MODELS; ++i){
863
- int v((int)(general->ionospheric_models[i]));
864
- if(v == general_t::IONOSPHERIC_SKIP){break;}
865
- res.push_back(v);
866
- }
867
- return res;
868
- }
869
- std::vector<int> set_ionospheric_models(const std::vector<int> &models){
870
- typedef GPS_Solver_GeneralOptions<FloatT> general_t;
871
- general_t *general(this->cast_general());
872
- typedef typename general_t::ionospheric_model_t model_t;
873
- for(int i(0), j(0), j_max(models.size()); i < general_t::IONOSPHERIC_MODELS; ++i){
874
- model_t v(general_t::IONOSPHERIC_SKIP);
875
- if(j < j_max){
876
- if((models[j] >= 0) && (models[j] < general_t::IONOSPHERIC_SKIP)){
877
- v = (model_t)models[j];
878
- }
879
- ++j;
880
- }
881
- general->ionospheric_models[i] = v;
882
- }
883
- return get_ionospheric_models();
884
- }
885
840
  };
886
841
  %}
887
842
 
@@ -923,6 +878,27 @@ struct SBAS_SolverOptions
923
878
  };
924
879
  %}
925
880
 
881
+ %header {
882
+ template <class FloatT>
883
+ struct GPS_RangeCorrector
884
+ : public GPS_Solver_Base<FloatT>::range_corrector_t {
885
+ SWIG_Object callback;
886
+ GPS_RangeCorrector(const SWIG_Object &callback_)
887
+ : GPS_Solver_Base<FloatT>::range_corrector_t(),
888
+ callback(callback_) {}
889
+ bool is_available(const typename GPS_Solver_Base<FloatT>::gps_time_t &t) const {
890
+ return false;
891
+ }
892
+ FloatT *calculate(
893
+ const typename GPS_Solver_Base<FloatT>::gps_time_t &t,
894
+ const typename GPS_Solver_Base<FloatT>::pos_t &usr_pos,
895
+ const typename GPS_Solver_Base<FloatT>::enu_t &sat_rel_pos,
896
+ FloatT &buf) const {
897
+ return NULL;
898
+ }
899
+ };
900
+ }
901
+
926
902
  %extend GPS_Solver {
927
903
  %ignore super_t;
928
904
  %ignore base_t;
@@ -934,22 +910,25 @@ struct SBAS_SolverOptions
934
910
  %ignore relative_property;
935
911
  %ignore satellite_position;
936
912
  %ignore update_position_solution;
913
+ %ignore user_correctors_t;
914
+ %ignore user_correctors;
937
915
  %immutable hooks;
938
916
  %ignore mark;
939
917
  %fragment("hook"{GPS_Solver<FloatT>}, "header",
940
918
  fragment=SWIG_From_frag(int),
941
- fragment=SWIG_Traits_frag(FloatT)){
919
+ fragment=SWIG_Traits_frag(FloatT),
920
+ fragment=SWIG_Traits_frag(GPS_Measurement<FloatT>)){
942
921
  template <>
943
- typename GPS_Solver<FloatT>::base_t::relative_property_t
922
+ GPS_Solver<FloatT>::base_t::relative_property_t
944
923
  GPS_Solver<FloatT>::relative_property(
945
- const typename GPS_Solver<FloatT>::base_t::prn_t &prn,
946
- const typename GPS_Solver<FloatT>::base_t::measurement_t::mapped_type &measurement,
947
- const typename GPS_Solver<FloatT>::base_t::float_t &receiver_error,
948
- const typename GPS_Solver<FloatT>::base_t::gps_time_t &time_arrival,
949
- const typename GPS_Solver<FloatT>::base_t::pos_t &usr_pos,
950
- const typename GPS_Solver<FloatT>::base_t::xyz_t &usr_vel) const {
924
+ const GPS_Solver<FloatT>::base_t::prn_t &prn,
925
+ const GPS_Solver<FloatT>::base_t::measurement_t::mapped_type &measurement,
926
+ const GPS_Solver<FloatT>::base_t::float_t &receiver_error,
927
+ const GPS_Solver<FloatT>::base_t::gps_time_t &time_arrival,
928
+ const GPS_Solver<FloatT>::base_t::pos_t &usr_pos,
929
+ const GPS_Solver<FloatT>::base_t::xyz_t &usr_vel) const {
951
930
  union {
952
- typename base_t::relative_property_t prop;
931
+ base_t::relative_property_t prop;
953
932
  FloatT values[7];
954
933
  } res = {
955
934
  select_solver(prn).relative_property(
@@ -971,6 +950,7 @@ struct SBAS_SolverOptions
971
950
  swig::from(res.prop.los_neg[0]),
972
951
  swig::from(res.prop.los_neg[1]),
973
952
  swig::from(res.prop.los_neg[2])),
953
+ swig::from(measurement), // measurement => Hash
974
954
  swig::from(receiver_error), // receiver_error
975
955
  SWIG_NewPointerObj( // time_arrival
976
956
  new base_t::gps_time_t(time_arrival), $descriptor(GPS_Time<FloatT> *), SWIG_POINTER_OWN),
@@ -1001,29 +981,222 @@ struct SBAS_SolverOptions
1001
981
  }
1002
982
  template <>
1003
983
  bool GPS_Solver<FloatT>::update_position_solution(
1004
- const typename GPS_Solver<FloatT>::base_t::geometric_matrices_t &geomat,
1005
- typename GPS_Solver<FloatT>::base_t::user_pvt_t &res) const {
984
+ const GPS_Solver<FloatT>::base_t::geometric_matrices_t &geomat,
985
+ GPS_Solver<FloatT>::base_t::user_pvt_t &res) const {
1006
986
  #ifdef SWIGRUBY
1007
987
  do{
1008
988
  static const VALUE key(ID2SYM(rb_intern("update_position_solution")));
1009
989
  VALUE hook(rb_hash_lookup(hooks, key));
1010
990
  if(NIL_P(hook)){break;}
1011
- typename base_t::geometric_matrices_t &geomat_(
1012
- %const_cast(geomat, typename base_t::geometric_matrices_t &));
991
+ base_t::geometric_matrices_t &geomat_(
992
+ %const_cast(geomat, base_t::geometric_matrices_t &));
1013
993
  VALUE values[] = {
1014
994
  SWIG_NewPointerObj(&geomat_.G,
1015
995
  $descriptor(Matrix<FloatT, Array2D_Dense<FloatT>, MatrixViewBase<> > *), 0),
1016
996
  SWIG_NewPointerObj(&geomat_.W,
1017
997
  $descriptor(Matrix<FloatT, Array2D_Dense<FloatT>, MatrixViewBase<> > *), 0),
1018
998
  SWIG_NewPointerObj(&geomat_.delta_r,
1019
- $descriptor(Matrix<FloatT, Array2D_Dense<FloatT>, MatrixViewBase<> > *), 0)};
999
+ $descriptor(Matrix<FloatT, Array2D_Dense<FloatT>, MatrixViewBase<> > *), 0),
1000
+ SWIG_NewPointerObj(&res,
1001
+ $descriptor(GPS_User_PVT<FloatT> *), 0)};
1020
1002
  proc_call_throw_if_error(hook, sizeof(values) / sizeof(values[0]), values);
1021
1003
  }while(false);
1022
1004
  #endif
1023
1005
  return super_t::update_position_solution(geomat, res);
1024
1006
  }
1007
+ template <>
1008
+ GPS_Solver<FloatT>::base_t::xyz_t *GPS_Solver<FloatT>::satellite_position(
1009
+ const GPS_Solver<FloatT>::base_t::prn_t &prn,
1010
+ const GPS_Solver<FloatT>::base_t::gps_time_t &time,
1011
+ GPS_Solver<FloatT>::base_t::xyz_t &buf) const {
1012
+ GPS_Solver<FloatT>::base_t::xyz_t *res(
1013
+ select_solver(prn).satellite_position(prn, time, buf));
1014
+ #ifdef SWIGRUBY
1015
+ do{
1016
+ static const VALUE key(ID2SYM(rb_intern("satellite_position")));
1017
+ VALUE hook(rb_hash_lookup(hooks, key));
1018
+ if(NIL_P(hook)){break;}
1019
+ VALUE values[] = {
1020
+ SWIG_From(int)(prn), // prn
1021
+ SWIG_NewPointerObj( // time
1022
+ new base_t::gps_time_t(time), $descriptor(GPS_Time<FloatT> *), SWIG_POINTER_OWN),
1023
+ (res // position (internally calculated)
1024
+ ? SWIG_NewPointerObj(res, $descriptor(System_XYZ<FloatT, WGS84> *), 0)
1025
+ : Qnil)};
1026
+ VALUE res_hook(proc_call_throw_if_error(hook, sizeof(values) / sizeof(values[0]), values));
1027
+ if(NIL_P(res_hook)){ // unknown position
1028
+ res = NULL;
1029
+ break;
1030
+ }else if(RB_TYPE_P(res_hook, T_ARRAY) && (RARRAY_LEN(res_hook) == 3)){
1031
+ int i(0);
1032
+ for(; i < 3; ++i){
1033
+ VALUE v(RARRAY_AREF(res_hook, i));
1034
+ if(!SWIG_IsOK(swig::asval(v, &buf[i]))){break;}
1035
+ }
1036
+ if(i == 3){
1037
+ res = &buf;
1038
+ break;
1039
+ }
1040
+ }else if(SWIG_IsOK(SWIG_ConvertPtr(
1041
+ res_hook, (void **)&res, $descriptor(System_XYZ<FloatT, WGS84> *), 0))){
1042
+ res = &(buf = *res);
1043
+ break;
1044
+ }
1045
+ throw std::runtime_error(
1046
+ std::string("System_XYZ or [d * 3] is expected (d: " %str(FloatT) "), however ")
1047
+ .append(inspect_str(res_hook)));
1048
+ }while(false);
1049
+ #endif
1050
+ return res;
1051
+ }
1025
1052
  }
1026
1053
  %fragment("hook"{GPS_Solver<FloatT>});
1054
+ %ignore update_correction;
1055
+ #ifdef SWIGRUBY
1056
+ %fragment("correction"{GPS_Solver<FloatT>}, "header",
1057
+ fragment=SWIG_From_frag(int),
1058
+ fragment=SWIG_Traits_frag(FloatT)){
1059
+ template <>
1060
+ bool GPS_RangeCorrector<FloatT>::is_available(
1061
+ const typename GPS_Solver_Base<FloatT>::gps_time_t &t) const {
1062
+ VALUE values[] = {
1063
+ SWIG_NewPointerObj(
1064
+ %const_cast(&t, GPS_Time<FloatT> *), $descriptor(GPS_Time<FloatT> *), 0),
1065
+ };
1066
+ VALUE res(proc_call_throw_if_error(
1067
+ callback, sizeof(values) / sizeof(values[0]), values));
1068
+ return RTEST(res) ? true : false;
1069
+ }
1070
+ template <>
1071
+ FloatT *GPS_RangeCorrector<FloatT>::calculate(
1072
+ const typename GPS_Solver_Base<FloatT>::gps_time_t &t,
1073
+ const typename GPS_Solver_Base<FloatT>::pos_t &usr_pos,
1074
+ const typename GPS_Solver_Base<FloatT>::enu_t &sat_rel_pos,
1075
+ FloatT &buf) const {
1076
+ VALUE values[] = {
1077
+ SWIG_NewPointerObj(
1078
+ %const_cast(&t, GPS_Time<FloatT> *),
1079
+ $descriptor(GPS_Time<FloatT> *), 0),
1080
+ SWIG_NewPointerObj(
1081
+ (%const_cast(&usr_pos.xyz, System_XYZ<FloatT, WGS84> *)),
1082
+ $descriptor(System_XYZ<FloatT, WGS84> *), 0),
1083
+ SWIG_NewPointerObj(
1084
+ (%const_cast(&sat_rel_pos, System_ENU<FloatT, WGS84> *)),
1085
+ $descriptor(System_ENU<FloatT, WGS84> *), 0),
1086
+ };
1087
+ VALUE res(proc_call_throw_if_error(
1088
+ callback, sizeof(values) / sizeof(values[0]), values));
1089
+ return SWIG_IsOK(swig::asval(res, &buf)) ? &buf : NULL;
1090
+ }
1091
+ template<>
1092
+ VALUE GPS_Solver<FloatT>::update_correction(
1093
+ const bool &update, const VALUE &hash){
1094
+ typedef range_correction_list_t list_t;
1095
+ static const VALUE k_root[] = {
1096
+ ID2SYM(rb_intern("gps_ionospheric")),
1097
+ ID2SYM(rb_intern("gps_tropospheric")),
1098
+ ID2SYM(rb_intern("sbas_ionospheric")),
1099
+ ID2SYM(rb_intern("sbas_tropospheric")),
1100
+ };
1101
+ static const VALUE k_opt(ID2SYM(rb_intern("options")));
1102
+ static const VALUE k_f_10_7(ID2SYM(rb_intern("f_10_7")));
1103
+ static const VALUE k_known(ID2SYM(rb_intern("known")));
1104
+ struct {
1105
+ VALUE sym;
1106
+ list_t::mapped_type::value_type obj;
1107
+ } item[] = {
1108
+ {ID2SYM(rb_intern("no_correction")), &base_t::no_correction},
1109
+ {ID2SYM(rb_intern("klobuchar")), &this->gps.solver.ionospheric_klobuchar},
1110
+ {ID2SYM(rb_intern("ntcm_gl")), &this->gps.solver.ionospheric_ntcm_gl},
1111
+ {ID2SYM(rb_intern("hopfield")), &this->gps.solver.tropospheric_simplified},
1112
+ {ID2SYM(rb_intern("sbas_igp")), &this->sbas.solver.ionospheric_sbas},
1113
+ {ID2SYM(rb_intern("sbas_tropo")), &this->sbas.solver.tropospheric_sbas},
1114
+ };
1115
+ list_t input;
1116
+ if(update){
1117
+ if(!RB_TYPE_P(hash, T_HASH)){
1118
+ throw std::runtime_error(
1119
+ std::string("Hash is expected, however ").append(inspect_str(hash)));
1120
+ }
1121
+ for(std::size_t i(0); i < sizeof(k_root) / sizeof(k_root[0]); ++i){
1122
+ VALUE ary = rb_hash_lookup(hash, k_root[i]);
1123
+ if(NIL_P(ary)){continue;}
1124
+ if(!RB_TYPE_P(ary, T_ARRAY)){
1125
+ ary = rb_ary_new_from_values(1, &ary);
1126
+ }
1127
+ for(int j(0); j < RARRAY_LEN(ary); ++j){
1128
+ std::size_t k(0);
1129
+ VALUE v(rb_ary_entry(ary, j));
1130
+ for(; k < sizeof(item) / sizeof(item[0]); ++k){
1131
+ if(v == item[k].sym){break;}
1132
+ }
1133
+ if(k >= sizeof(item) / sizeof(item[0])){ // other than symbol
1134
+ user_correctors.push_back(GPS_RangeCorrector<FloatT>(v));
1135
+ input[i].push_back(&user_correctors.back());
1136
+ }else{
1137
+ input[i].push_back(item[k].obj);
1138
+ }
1139
+ }
1140
+ }
1141
+ VALUE opt(rb_hash_lookup(hash, k_opt));
1142
+ if(RB_TYPE_P(opt, T_HASH)){
1143
+ swig::asval(rb_hash_lookup(opt, k_f_10_7), // ntcm_gl
1144
+ &this->gps.solver.ionospheric_ntcm_gl.f_10_7);
1145
+ }
1146
+ }
1147
+ list_t output(update_correction(update, input));
1148
+ VALUE res = rb_hash_new();
1149
+ for(list_t::const_iterator it(output.begin()), it_end(output.end());
1150
+ it != it_end; ++it){
1151
+ VALUE k;
1152
+ if((it->first < 0) || (it->first >= (int)(sizeof(k_root) / sizeof(k_root[0])))){
1153
+ k = SWIG_From(int)(it->first);
1154
+ }else{
1155
+ k = k_root[it->first];
1156
+ }
1157
+ VALUE v = rb_ary_new();
1158
+ for(list_t::mapped_type::const_iterator
1159
+ it2(it->second.begin()), it2_end(it->second.end());
1160
+ it2 != it2_end; ++it2){
1161
+ std::size_t i(0);
1162
+ for(; i < sizeof(item) / sizeof(item[0]); ++i){
1163
+ if(*it2 == item[i].obj){break;}
1164
+ }
1165
+ if(i >= sizeof(item) / sizeof(item[0])){ // other than built-in corrector
1166
+ rb_ary_push(v,
1167
+ reinterpret_cast<const GPS_RangeCorrector<FloatT> *>(*it2)->callback);
1168
+ }else{
1169
+ rb_ary_push(v, item[i].sym);
1170
+ }
1171
+ }
1172
+ rb_hash_aset(res, k, v);
1173
+ }
1174
+ { // common options
1175
+ VALUE opt = rb_hash_new();
1176
+ rb_hash_aset(res, k_opt, opt);
1177
+ rb_hash_aset(opt, k_f_10_7, // ntcm_gl
1178
+ swig::from(this->gps.solver.ionospheric_ntcm_gl.f_10_7));
1179
+ }
1180
+ { // known models
1181
+ VALUE ary = rb_ary_new_capa((int)(sizeof(item) / sizeof(item[0])));
1182
+ for(std::size_t i(0); i < sizeof(item) / sizeof(item[0]); ++i){
1183
+ rb_ary_push(ary, item[i].sym);
1184
+ }
1185
+ rb_hash_aset(res, k_known, ary);
1186
+ }
1187
+ return res;
1188
+ }
1189
+ }
1190
+ %fragment("correction"{GPS_Solver<FloatT>});
1191
+ %rename("correction") get_correction;
1192
+ %rename("correction=") set_correction;
1193
+ VALUE get_correction() const {
1194
+ return const_cast<GPS_Solver<FloatT> *>(self)->update_correction(false, Qnil);
1195
+ }
1196
+ VALUE set_correction(VALUE hash){
1197
+ return self->update_correction(true, hash);
1198
+ }
1199
+ #endif
1027
1200
  }
1028
1201
  %inline {
1029
1202
  template <class FloatT>
@@ -1046,19 +1219,36 @@ struct GPS_Solver
1046
1219
  sbas_t() : space_node(), options(), solver(space_node) {}
1047
1220
  } sbas;
1048
1221
  SWIG_Object hooks;
1222
+ typedef std::vector<GPS_RangeCorrector<FloatT> > user_correctors_t;
1223
+ user_correctors_t user_correctors;
1049
1224
  #ifdef SWIGRUBY
1050
1225
  static void mark(void *ptr){
1051
1226
  GPS_Solver<FloatT> *solver = (GPS_Solver<FloatT> *)ptr;
1052
- if(solver->hooks == Qnil){return;}
1053
1227
  rb_gc_mark(solver->hooks);
1228
+ for(typename user_correctors_t::const_iterator
1229
+ it(solver->user_correctors.begin()), it_end(solver->user_correctors.end());
1230
+ it != it_end; ++it){
1231
+ rb_gc_mark(it->callback);
1232
+ }
1054
1233
  }
1055
1234
  #endif
1056
- GPS_Solver() : super_t(), gps(), sbas(), hooks() {
1057
- gps.solver.space_node_sbas = &sbas.space_node;
1058
- sbas.solver.space_node_gps = &gps.space_node;
1235
+ GPS_Solver() : super_t(),
1236
+ gps(), sbas(),
1237
+ hooks(), user_correctors() {
1059
1238
  #ifdef SWIGRUBY
1060
1239
  hooks = rb_hash_new();
1061
1240
  #endif
1241
+ typename base_t::range_correction_t ionospheric, tropospheric;
1242
+ ionospheric.push_back(&sbas.solver.ionospheric_sbas);
1243
+ ionospheric.push_back(&gps.solver.ionospheric_klobuchar);
1244
+ tropospheric.push_back(&sbas.solver.tropospheric_sbas);
1245
+ tropospheric.push_back(&gps.solver.tropospheric_simplified);
1246
+ gps.solver.ionospheric_correction
1247
+ = sbas.solver.ionospheric_correction
1248
+ = ionospheric;
1249
+ gps.solver.tropospheric_correction
1250
+ = sbas.solver.tropospheric_correction
1251
+ = tropospheric;
1062
1252
  }
1063
1253
  GPS_SpaceNode<FloatT> &gps_space_node() {return gps.space_node;}
1064
1254
  GPS_SolverOptions<FloatT> &gps_options() {return gps.options;}
@@ -1069,7 +1259,11 @@ struct GPS_Solver
1069
1259
  if(prn > 0 && prn <= 32){return gps.solver;}
1070
1260
  if(prn >= 120 && prn <= 158){return sbas.solver;}
1071
1261
  if(prn > 192 && prn <= 202){return gps.solver;}
1072
- return *this;
1262
+ // call order: base_t::solve => this returned by select()
1263
+ // => relative_property() => select_solver()
1264
+ // For not supported satellite, call loop prevention is required.
1265
+ static const base_t dummy;
1266
+ return dummy;
1073
1267
  }
1074
1268
  virtual typename base_t::relative_property_t relative_property(
1075
1269
  const typename base_t::prn_t &prn,
@@ -1081,9 +1275,7 @@ struct GPS_Solver
1081
1275
  virtual typename base_t::xyz_t *satellite_position(
1082
1276
  const typename base_t::prn_t &prn,
1083
1277
  const typename base_t::gps_time_t &time,
1084
- typename base_t::xyz_t &res) const {
1085
- return select_solver(prn).satellite_position(prn, time, res);
1086
- }
1278
+ typename base_t::xyz_t &res) const;
1087
1279
  virtual bool update_position_solution(
1088
1280
  const typename base_t::geometric_matrices_t &geomat,
1089
1281
  typename base_t::user_pvt_t &res) const;
@@ -1096,6 +1288,53 @@ struct GPS_Solver
1096
1288
  const_cast<sbas_t &>(sbas).solver.update_options(sbas.options);
1097
1289
  return super_t::solve().user_pvt(measurement.items, receiver_time);
1098
1290
  }
1291
+ typedef
1292
+ std::map<int, std::vector<const typename base_t::range_corrector_t *> >
1293
+ range_correction_list_t;
1294
+ range_correction_list_t update_correction(
1295
+ const bool &update,
1296
+ const range_correction_list_t &list = range_correction_list_t()){
1297
+ range_correction_list_t res;
1298
+ typename base_t::range_correction_t *root[] = {
1299
+ &gps.solver.ionospheric_correction,
1300
+ &gps.solver.tropospheric_correction,
1301
+ &sbas.solver.ionospheric_correction,
1302
+ &sbas.solver.tropospheric_correction,
1303
+ };
1304
+ for(std::size_t i(0); i < sizeof(root) / sizeof(root[0]); ++i){
1305
+ do{
1306
+ if(!update){break;}
1307
+ typename range_correction_list_t::const_iterator it(list.find(i));
1308
+ if(it == list.end()){break;}
1309
+
1310
+ // Remove user defined unused correctors
1311
+ for(typename base_t::range_correction_t::const_iterator
1312
+ it2(root[i]->begin()), it2_end(root[i]->end());
1313
+ it2 != it2_end; ++it2){
1314
+ for(typename user_correctors_t::const_iterator
1315
+ it3(user_correctors.begin()), it3_end(user_correctors.end());
1316
+ it3 != it3_end; ++it3){
1317
+ if(*it2 != &(*it3)){continue;}
1318
+ user_correctors.erase(it3);
1319
+ }
1320
+ }
1321
+
1322
+ root[i]->clear();
1323
+ for(typename range_correction_list_t::mapped_type::const_iterator
1324
+ it2(it->second.begin()), it2_end(it->second.end());
1325
+ it2 != it2_end; ++it2){
1326
+ root[i]->push_back(*it2);
1327
+ }
1328
+ }while(false);
1329
+ for(typename base_t::range_correction_t::const_iterator
1330
+ it(root[i]->begin()), it_end(root[i]->end());
1331
+ it != it_end; ++it){
1332
+ res[i].push_back(*it);
1333
+ }
1334
+ }
1335
+ return res;
1336
+ }
1337
+ SWIG_Object update_correction(const bool &update, const SWIG_Object &hash);
1099
1338
  };
1100
1339
  }
1101
1340
 
@@ -238,6 +238,23 @@ INSTANTIATE_COMPLEX(double, D);
238
238
 
239
239
  #undef INSTANTIATE_COMPLEX
240
240
 
241
+ #if defined(SWIGRUBY)
242
+ /* Work around of miss detection of negative value on Windows Ruby (devkit).
243
+ * This results from SWIG_AsVal(unsigned int) depends on SWIG_AsVal(unsigned long),
244
+ * and sizeof(long) == sizeof(int).
245
+ */
246
+ %fragment("check_value"{unsigned int}, "header"){
247
+ inline bool is_lt_zero_after_asval(const unsigned int &i){
248
+ return ((sizeof(unsigned int) == sizeof(unsigned long)) && ((UINT_MAX >> 1) <= i));
249
+ }
250
+ void raise_if_lt_zero_after_asval(const unsigned int &i){
251
+ if(is_lt_zero_after_asval(i)){
252
+ SWIG_exception(SWIG_ValueError, "Expected positive value.");
253
+ }
254
+ }
255
+ }
256
+ #endif
257
+
241
258
  #define DO_NOT_INSTANTIATE_SCALAR_MATRIX
242
259
  #define USE_MATRIX_VIEW_FILTER
243
260
 
@@ -949,6 +966,7 @@ MAKE_TO_S(Matrix_Frozen)
949
966
  }
950
967
  #if defined(SWIGRUBY)
951
968
  %fragment(SWIG_AsVal_frag(unsigned int));
969
+ %fragment("check_value"{unsigned int});
952
970
  Matrix(const void *replacer){
953
971
  const SWIG_Object *value(static_cast<const SWIG_Object *>(replacer));
954
972
  static const ID id_r(rb_intern("row_size")), id_c(rb_intern("column_size"));
@@ -959,13 +977,10 @@ MAKE_TO_S(Matrix_Frozen)
959
977
  MatrixUtil::replace(res, replacer);
960
978
  return new Matrix<T, Array2D_Type, ViewType>(res);
961
979
  }else if(value && rb_respond_to(*value, id_r) && rb_respond_to(*value, id_c)){
962
- /* "unsigned" is remove because SWIG_AsVal(unsigned int)
963
- * can not detect less than zero in Windows Ruby devkit.
964
- */
965
- int r, c;
980
+ unsigned int r, c;
966
981
  VALUE v_r(rb_funcall(*value, id_r, 0, 0)), v_c(rb_funcall(*value, id_c, 0, 0));
967
- if(!SWIG_IsOK(SWIG_AsVal(int)(v_r, &r)) || (r < 0)
968
- || !SWIG_IsOK(SWIG_AsVal(int)(v_c, &c)) || (c < 0)){
982
+ if(!SWIG_IsOK(SWIG_AsVal(unsigned int)(v_r, &r)) || is_lt_zero_after_asval(r)
983
+ || !SWIG_IsOK(SWIG_AsVal(unsigned int)(v_c, &c)) || is_lt_zero_after_asval(c)){
969
984
  throw std::runtime_error(
970
985
  std::string("Unexpected length [")
971
986
  .append(inspect_str(v_r)).append(", ")
@@ -1147,6 +1162,8 @@ INSTANTIATE_MATRIX_EIGEN2(type, ctype, Array2D_Dense<type >, MatView_pt);
1147
1162
  #endif
1148
1163
 
1149
1164
  %define INSTANTIATE_MATRIX(type, suffix)
1165
+ %typemap(check, fragment="check_value"{unsigned int})
1166
+ const unsigned int & "raise_if_lt_zero_after_asval(*$1);"
1150
1167
  #if !defined(DO_NOT_INSTANTIATE_SCALAR_MATRIX)
1151
1168
  %extend Matrix_Frozen<type, Array2D_ScaledUnit<type >, MatViewBase> {
1152
1169
  const Matrix_Frozen<type, Array2D_ScaledUnit<type >, MatViewBase> &transpose() const {
@@ -1200,6 +1217,35 @@ INSTANTIATE_MATRIX_PARTIAL(type, Array2D_Dense<type >, MatView_pt, MatView_pt);
1200
1217
  %template(Matrix_Frozen ## suffix ## _pt) Matrix_Frozen<type, Array2D_Dense<type >, MatView_pt>;
1201
1218
  #endif
1202
1219
 
1220
+ %extend Matrix<type, Array2D_Dense<type > > {
1221
+ #if defined(SWIGRUBY)
1222
+ %bang resize;
1223
+ #endif
1224
+ %typemap(in, fragment="check_value"{unsigned int})
1225
+ unsigned int *r_p (unsigned int temp), unsigned int *c_p (unsigned int temp) {
1226
+ if(SWIG_IsOK(SWIG_AsVal(unsigned int)($input, &temp))){
1227
+ #if defined(SWIGRUBY)
1228
+ raise_if_lt_zero_after_asval(temp);
1229
+ #endif
1230
+ $1 = &temp;
1231
+ }
1232
+ #if defined(SWIGRUBY)
1233
+ else if(NIL_P($input)){$1 = NULL;}
1234
+ #endif
1235
+ else{SWIG_exception(SWIG_TypeError, "$*1_ltype is expected");}
1236
+ }
1237
+ Matrix<type, Array2D_Dense<type > > &resize(
1238
+ const unsigned int *r_p, const unsigned int *c_p){
1239
+ unsigned int r(r_p ? *r_p : $self->rows()), c(c_p ? *c_p : self->columns());
1240
+ Matrix<type, Array2D_Dense<type > > mat_new(r, c);
1241
+ unsigned int r_min(r), c_min(c);
1242
+ if(r_min > $self->rows()){r_min = $self->rows();}
1243
+ if(c_min > $self->columns()){c_min = $self->columns();}
1244
+ mat_new.partial(r_min, c_min).replace($self->partial(r_min, c_min), false);
1245
+ return (*($self) = mat_new);
1246
+ }
1247
+ };
1248
+
1203
1249
  %template(Matrix ## suffix) Matrix<type, Array2D_Dense<type > >;
1204
1250
  #if defined(SWIGRUBY)
1205
1251
  %fragment("init"{Matrix<type, Array2D_Dense<type > >}, "init") {
@@ -1212,6 +1258,7 @@ INSTANTIATE_MATRIX_PARTIAL(type, Array2D_Dense<type >, MatView_pt, MatView_pt);
1212
1258
  }
1213
1259
  %fragment("init"{Matrix<type, Array2D_Dense<type > >});
1214
1260
  #endif
1261
+ %typemap(check) const unsigned int &;
1215
1262
  %enddef
1216
1263
 
1217
1264
  INSTANTIATE_MATRIX(double, D);