gps_pvt 0.2.0 → 0.3.0

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.
@@ -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);