gps_pvt 0.2.1 → 0.2.3
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.
- checksums.yaml +4 -4
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +434 -434
- data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +277 -14
- data/ext/ninja-scan-light/tool/navigation/GPS.h +8 -43
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +61 -147
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +54 -0
- data/ext/ninja-scan-light/tool/navigation/SBAS.h +2 -2
- data/ext/ninja-scan-light/tool/navigation/SBAS_Solver.h +55 -78
- data/ext/ninja-scan-light/tool/param/bit_array.h +4 -3
- data/ext/ninja-scan-light/tool/swig/GPS.i +167 -61
- data/ext/ninja-scan-light/tool/swig/SylphideMath.i +53 -6
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +19 -5
- data/ext/ninja-scan-light/tool/swig/spec/SylphideMath_spec.rb +38 -4
- data/gps_pvt.gemspec +63 -0
- data/lib/gps_pvt/receiver.rb +39 -27
- data/lib/gps_pvt/version.rb +1 -1
- metadata +4 -3
@@ -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,8 +421,6 @@ 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
426
|
typename RINEX_NAV_Reader<FloatT>::space_node_list_t space_nodes = {self};
|
@@ -800,6 +806,7 @@ struct GPS_Measurement {
|
|
800
806
|
L1_RANGE_RATE_SIGMA,
|
801
807
|
L1_SIGNAL_STRENGTH_dBHz,
|
802
808
|
L1_LOCK_SEC,
|
809
|
+
L1_FREQUENCY,
|
803
810
|
ITEMS_PREDEFINED,
|
804
811
|
};
|
805
812
|
void add(const int &prn, const int &key, const FloatT &value){
|
@@ -821,71 +828,15 @@ const type &get_ ## name () const {
|
|
821
828
|
%enddef
|
822
829
|
MAKE_ACCESSOR2(elevation_mask, FloatT);
|
823
830
|
MAKE_ACCESSOR2(residual_mask, FloatT);
|
824
|
-
MAKE_ACCESSOR2(f_10_7, FloatT);
|
825
831
|
#undef MAKE_ACCESSOR2
|
826
832
|
MAKE_VECTOR2ARRAY(int);
|
827
833
|
%ignore cast_base;
|
828
|
-
#ifdef SWIGRUBY
|
829
|
-
%rename("ionospheric_models=") set_ionospheric_models;
|
830
|
-
%rename("ionospheric_models") get_ionospheric_models;
|
831
|
-
#endif
|
832
|
-
%typemap(in) const std::vector<int> &models (std::vector<int> temp) {
|
833
|
-
$1 = &temp;
|
834
|
-
#ifdef SWIGRUBY
|
835
|
-
if(RB_TYPE_P($input, T_ARRAY)){
|
836
|
-
for(int i(0), i_max(RARRAY_LEN($input)); i < i_max; ++i){
|
837
|
-
SWIG_Object obj(RARRAY_AREF($input, i));
|
838
|
-
int v;
|
839
|
-
if(SWIG_IsOK(SWIG_AsVal(int)(obj, &v))){
|
840
|
-
temp.push_back(v);
|
841
|
-
}else{
|
842
|
-
SWIG_exception(SWIG_TypeError, "$*1_ltype is expected");
|
843
|
-
}
|
844
|
-
}
|
845
|
-
}
|
846
|
-
#endif
|
847
|
-
}
|
848
834
|
}
|
849
835
|
%inline %{
|
850
836
|
template <class FloatT>
|
851
837
|
struct GPS_SolverOptions_Common {
|
852
|
-
enum {
|
853
|
-
IONOSPHERIC_KLOBUCHAR,
|
854
|
-
IONOSPHERIC_SBAS,
|
855
|
-
IONOSPHERIC_NTCM_GL,
|
856
|
-
IONOSPHERIC_NONE, // which allows no correction
|
857
|
-
IONOSPHERIC_MODELS,
|
858
|
-
IONOSPHERIC_SKIP = IONOSPHERIC_MODELS, // which means delegating the next slot
|
859
|
-
};
|
860
838
|
virtual GPS_Solver_GeneralOptions<FloatT> *cast_general() = 0;
|
861
839
|
virtual const GPS_Solver_GeneralOptions<FloatT> *cast_general() const = 0;
|
862
|
-
std::vector<int> get_ionospheric_models() const {
|
863
|
-
typedef GPS_Solver_GeneralOptions<FloatT> general_t;
|
864
|
-
const general_t *general(this->cast_general());
|
865
|
-
std::vector<int> res;
|
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;}
|
869
|
-
res.push_back(v);
|
870
|
-
}
|
871
|
-
return res;
|
872
|
-
}
|
873
|
-
std::vector<int> set_ionospheric_models(const std::vector<int> &models){
|
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);
|
879
|
-
if(j < j_max){
|
880
|
-
if((models[j] >= 0) && (models[j] < general_t::IONOSPHERIC_SKIP)){
|
881
|
-
v = (model_t)models[j];
|
882
|
-
}
|
883
|
-
++j;
|
884
|
-
}
|
885
|
-
general->ionospheric_models[i] = v;
|
886
|
-
}
|
887
|
-
return get_ionospheric_models();
|
888
|
-
}
|
889
840
|
};
|
890
841
|
%}
|
891
842
|
|
@@ -1022,7 +973,9 @@ struct SBAS_SolverOptions
|
|
1022
973
|
SWIG_NewPointerObj(&geomat_.W,
|
1023
974
|
$descriptor(Matrix<FloatT, Array2D_Dense<FloatT>, MatrixViewBase<> > *), 0),
|
1024
975
|
SWIG_NewPointerObj(&geomat_.delta_r,
|
1025
|
-
$descriptor(Matrix<FloatT, Array2D_Dense<FloatT>, MatrixViewBase<> > *), 0)
|
976
|
+
$descriptor(Matrix<FloatT, Array2D_Dense<FloatT>, MatrixViewBase<> > *), 0),
|
977
|
+
SWIG_NewPointerObj(&res,
|
978
|
+
$descriptor(GPS_User_PVT<FloatT> *), 0)};
|
1026
979
|
proc_call_throw_if_error(hook, sizeof(values) / sizeof(values[0]), values);
|
1027
980
|
}while(false);
|
1028
981
|
#endif
|
@@ -1075,6 +1028,116 @@ struct SBAS_SolverOptions
|
|
1075
1028
|
}
|
1076
1029
|
}
|
1077
1030
|
%fragment("hook"{GPS_Solver<FloatT>});
|
1031
|
+
%ignore update_correction;
|
1032
|
+
#ifdef SWIGRUBY
|
1033
|
+
%fragment("correction"{GPS_Solver<FloatT>}, "header",
|
1034
|
+
fragment=SWIG_From_frag(int),
|
1035
|
+
fragment=SWIG_Traits_frag(FloatT)){
|
1036
|
+
template<>
|
1037
|
+
VALUE GPS_Solver<FloatT>::update_correction(
|
1038
|
+
const bool &update, const VALUE &hash){
|
1039
|
+
typedef range_correction_list_t list_t;
|
1040
|
+
static const VALUE k_root[] = {
|
1041
|
+
ID2SYM(rb_intern("gps_ionospheric")),
|
1042
|
+
ID2SYM(rb_intern("gps_tropospheric")),
|
1043
|
+
ID2SYM(rb_intern("sbas_ionospheric")),
|
1044
|
+
ID2SYM(rb_intern("sbas_tropospheric")),
|
1045
|
+
};
|
1046
|
+
static const VALUE k_opt(ID2SYM(rb_intern("options")));
|
1047
|
+
static const VALUE k_f_10_7(ID2SYM(rb_intern("f_10_7")));
|
1048
|
+
static const VALUE k_known(ID2SYM(rb_intern("known")));
|
1049
|
+
struct {
|
1050
|
+
VALUE sym;
|
1051
|
+
list_t::mapped_type::value_type obj;
|
1052
|
+
} item[] = {
|
1053
|
+
{ID2SYM(rb_intern("no_correction")), &base_t::no_correction},
|
1054
|
+
{ID2SYM(rb_intern("klobuchar")), &this->gps.solver.ionospheric_klobuchar},
|
1055
|
+
{ID2SYM(rb_intern("ntcm_gl")), &this->gps.solver.ionospheric_ntcm_gl},
|
1056
|
+
{ID2SYM(rb_intern("hopfield")), &this->gps.solver.tropospheric_simplified},
|
1057
|
+
{ID2SYM(rb_intern("sbas_igp")), &this->sbas.solver.ionospheric_sbas},
|
1058
|
+
{ID2SYM(rb_intern("sbas_tropo")), &this->sbas.solver.tropospheric_sbas},
|
1059
|
+
};
|
1060
|
+
list_t input;
|
1061
|
+
if(update){
|
1062
|
+
if(!RB_TYPE_P(hash, T_HASH)){
|
1063
|
+
throw std::runtime_error(
|
1064
|
+
std::string("Hash is expected, however ").append(inspect_str(hash)));
|
1065
|
+
}
|
1066
|
+
for(std::size_t i(0); i < sizeof(k_root) / sizeof(k_root[0]); ++i){
|
1067
|
+
VALUE ary = rb_hash_lookup(hash, k_root[i]);
|
1068
|
+
if(NIL_P(ary)){continue;}
|
1069
|
+
if(!RB_TYPE_P(ary, T_ARRAY)){
|
1070
|
+
ary = rb_ary_new_from_values(1, &ary);
|
1071
|
+
}
|
1072
|
+
for(int j(0); j < RARRAY_LEN(ary); ++j){
|
1073
|
+
std::size_t k(0);
|
1074
|
+
VALUE v(rb_ary_entry(ary, j));
|
1075
|
+
for(; k < sizeof(item) / sizeof(item[0]); ++k){
|
1076
|
+
if(v == item[k].sym){break;}
|
1077
|
+
}
|
1078
|
+
if(k >= sizeof(item) / sizeof(item[0])){
|
1079
|
+
continue; // TODO other than symbol
|
1080
|
+
}
|
1081
|
+
input[i].push_back(item[k].obj);
|
1082
|
+
}
|
1083
|
+
}
|
1084
|
+
VALUE opt(rb_hash_lookup(hash, k_opt));
|
1085
|
+
if(RB_TYPE_P(opt, T_HASH)){
|
1086
|
+
swig::asval(rb_hash_lookup(opt, k_f_10_7), // ntcm_gl
|
1087
|
+
&this->gps.solver.ionospheric_ntcm_gl.f_10_7);
|
1088
|
+
}
|
1089
|
+
}
|
1090
|
+
list_t output(update_correction(update, input));
|
1091
|
+
VALUE res = rb_hash_new();
|
1092
|
+
for(list_t::const_iterator it(output.begin()), it_end(output.end());
|
1093
|
+
it != it_end; ++it){
|
1094
|
+
VALUE k;
|
1095
|
+
if((it->first < 0) || (it->first >= (int)(sizeof(k_root) / sizeof(k_root[0])))){
|
1096
|
+
k = SWIG_From(int)(it->first);
|
1097
|
+
}else{
|
1098
|
+
k = k_root[it->first];
|
1099
|
+
}
|
1100
|
+
VALUE v = rb_ary_new();
|
1101
|
+
for(list_t::mapped_type::const_iterator
|
1102
|
+
it2(it->second.begin()), it2_end(it->second.end());
|
1103
|
+
it2 != it2_end; ++it2){
|
1104
|
+
std::size_t i(0);
|
1105
|
+
for(; i < sizeof(item) / sizeof(item[0]); ++i){
|
1106
|
+
if(*it2 == item[i].obj){break;}
|
1107
|
+
}
|
1108
|
+
if(i >= sizeof(item) / sizeof(item[0])){
|
1109
|
+
continue; // TODO other than built-in corrector
|
1110
|
+
}
|
1111
|
+
rb_ary_push(v, item[i].sym);
|
1112
|
+
}
|
1113
|
+
rb_hash_aset(res, k, v);
|
1114
|
+
}
|
1115
|
+
{ // common options
|
1116
|
+
VALUE opt = rb_hash_new();
|
1117
|
+
rb_hash_aset(res, k_opt, opt);
|
1118
|
+
rb_hash_aset(opt, k_f_10_7, // ntcm_gl
|
1119
|
+
swig::from(this->gps.solver.ionospheric_ntcm_gl.f_10_7));
|
1120
|
+
}
|
1121
|
+
{ // known models
|
1122
|
+
VALUE ary = rb_ary_new_capa((int)(sizeof(item) / sizeof(item[0])));
|
1123
|
+
for(std::size_t i(0); i < sizeof(item) / sizeof(item[0]); ++i){
|
1124
|
+
rb_ary_push(ary, item[i].sym);
|
1125
|
+
}
|
1126
|
+
rb_hash_aset(res, k_known, ary);
|
1127
|
+
}
|
1128
|
+
return res;
|
1129
|
+
}
|
1130
|
+
}
|
1131
|
+
%fragment("correction"{GPS_Solver<FloatT>});
|
1132
|
+
%rename("correction") get_correction;
|
1133
|
+
%rename("correction=") set_correction;
|
1134
|
+
VALUE get_correction() const {
|
1135
|
+
return const_cast<GPS_Solver<FloatT> *>(self)->update_correction(false, Qnil);
|
1136
|
+
}
|
1137
|
+
VALUE set_correction(VALUE hash){
|
1138
|
+
return self->update_correction(true, hash);
|
1139
|
+
}
|
1140
|
+
#endif
|
1078
1141
|
}
|
1079
1142
|
%inline {
|
1080
1143
|
template <class FloatT>
|
@@ -1105,11 +1168,20 @@ struct GPS_Solver
|
|
1105
1168
|
}
|
1106
1169
|
#endif
|
1107
1170
|
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;
|
1110
1171
|
#ifdef SWIGRUBY
|
1111
1172
|
hooks = rb_hash_new();
|
1112
1173
|
#endif
|
1174
|
+
typename base_t::range_correction_t ionospheric, tropospheric;
|
1175
|
+
ionospheric.push_back(&sbas.solver.ionospheric_sbas);
|
1176
|
+
ionospheric.push_back(&gps.solver.ionospheric_klobuchar);
|
1177
|
+
tropospheric.push_back(&sbas.solver.tropospheric_sbas);
|
1178
|
+
tropospheric.push_back(&gps.solver.tropospheric_simplified);
|
1179
|
+
gps.solver.ionospheric_correction
|
1180
|
+
= sbas.solver.ionospheric_correction
|
1181
|
+
= ionospheric;
|
1182
|
+
gps.solver.tropospheric_correction
|
1183
|
+
= sbas.solver.tropospheric_correction
|
1184
|
+
= tropospheric;
|
1113
1185
|
}
|
1114
1186
|
GPS_SpaceNode<FloatT> &gps_space_node() {return gps.space_node;}
|
1115
1187
|
GPS_SolverOptions<FloatT> &gps_options() {return gps.options;}
|
@@ -1149,6 +1221,40 @@ struct GPS_Solver
|
|
1149
1221
|
const_cast<sbas_t &>(sbas).solver.update_options(sbas.options);
|
1150
1222
|
return super_t::solve().user_pvt(measurement.items, receiver_time);
|
1151
1223
|
}
|
1224
|
+
typedef
|
1225
|
+
std::map<int, std::vector<const typename base_t::range_corrector_t *> >
|
1226
|
+
range_correction_list_t;
|
1227
|
+
range_correction_list_t update_correction(
|
1228
|
+
const bool &update,
|
1229
|
+
const range_correction_list_t &list = range_correction_list_t()){
|
1230
|
+
range_correction_list_t res;
|
1231
|
+
typename base_t::range_correction_t *root[] = {
|
1232
|
+
&gps.solver.ionospheric_correction,
|
1233
|
+
&gps.solver.tropospheric_correction,
|
1234
|
+
&sbas.solver.ionospheric_correction,
|
1235
|
+
&sbas.solver.tropospheric_correction,
|
1236
|
+
};
|
1237
|
+
for(std::size_t i(0); i < sizeof(root) / sizeof(root[0]); ++i){
|
1238
|
+
do{
|
1239
|
+
if(!update){break;}
|
1240
|
+
typename range_correction_list_t::const_iterator it(list.find(i));
|
1241
|
+
if(it == list.end()){break;}
|
1242
|
+
root[i]->clear();
|
1243
|
+
for(typename range_correction_list_t::mapped_type::const_iterator
|
1244
|
+
it2(it->second.begin()), it2_end(it->second.end());
|
1245
|
+
it2 != it2_end; ++it2){
|
1246
|
+
root[i]->push_back(*it2);
|
1247
|
+
}
|
1248
|
+
}while(false);
|
1249
|
+
for(typename base_t::range_correction_t::const_iterator
|
1250
|
+
it(root[i]->begin()), it_end(root[i]->end());
|
1251
|
+
it != it_end; ++it){
|
1252
|
+
res[i].push_back(*it);
|
1253
|
+
}
|
1254
|
+
}
|
1255
|
+
return res;
|
1256
|
+
}
|
1257
|
+
SWIG_Object update_correction(const bool &update, const SWIG_Object &hash);
|
1152
1258
|
};
|
1153
1259
|
}
|
1154
1260
|
|
@@ -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
|
-
|
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
|
968
|
-
|| !SWIG_IsOK(SWIG_AsVal(int)(v_c, &c)) || (c
|
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);
|
@@ -221,7 +221,11 @@ __RINEX_OBS_TEXT__
|
|
221
221
|
f.path
|
222
222
|
},
|
223
223
|
}}
|
224
|
-
let(:solver){
|
224
|
+
let(:solver){
|
225
|
+
res = GPS::Solver::new
|
226
|
+
res.correction = {:gps_ionospheric => :klobuchar, :gps_tropospheric => :hopfield}
|
227
|
+
res
|
228
|
+
}
|
225
229
|
|
226
230
|
describe 'demo' do
|
227
231
|
it 'calculates position without any error' do
|
@@ -255,7 +259,6 @@ __RINEX_OBS_TEXT__
|
|
255
259
|
[:alpha, :beta].each{|k|
|
256
260
|
puts "Iono #{k}: #{sn.iono_utc.send(k)}"
|
257
261
|
}
|
258
|
-
puts solver.gps_options.ionospheric_models
|
259
262
|
|
260
263
|
meas.each{|prn, k, v|
|
261
264
|
eph = sn.ephemeris(prn)
|
@@ -336,6 +339,15 @@ __RINEX_OBS_TEXT__
|
|
336
339
|
|
337
340
|
it 'can be modified through hooks' do
|
338
341
|
sn = solver.gps_space_node
|
342
|
+
expect(solver.correction[:gps_ionospheric]).to include(:klobuchar)
|
343
|
+
expect(solver.correction[:gps_tropospheric]).to include(:hopfield)
|
344
|
+
expect{solver.correction = nil}.to raise_error(RuntimeError)
|
345
|
+
expect{solver.correction = {
|
346
|
+
:gps_ionospheric => [:klobuchar, :no_correction],
|
347
|
+
:options => {:f_10_7 => 10},
|
348
|
+
}}.not_to raise_error
|
349
|
+
expect(solver.correction[:gps_ionospheric]).to include(:no_correction)
|
350
|
+
expect(solver.correction[:options][:f_10_7]).to eq(10)
|
339
351
|
sn.read(input[:rinex_nav])
|
340
352
|
t_meas = GPS::Time::new(1849, 172413)
|
341
353
|
sn.update_all_ephemeris(t_meas)
|
@@ -349,11 +361,13 @@ __RINEX_OBS_TEXT__
|
|
349
361
|
weight = 1
|
350
362
|
[weight, range_c, range_r, rate_rel_neg] + los_neg
|
351
363
|
}
|
352
|
-
solver.hooks[:update_position_solution] = proc{
|
353
|
-
|
364
|
+
solver.hooks[:update_position_solution] = proc{|mat_G, mat_W, mat_delta_r, temp_pvt|
|
365
|
+
expect(temp_pvt).to be_a_kind_of(GPS::PVT)
|
366
|
+
[mat_G, mat_W, mat_delta_r].each{|mat|
|
354
367
|
expect(mat).to be_a_kind_of(SylphideMath::MatrixD)
|
368
|
+
expect(mat.rows).to be >= temp_pvt.used_satellites
|
369
|
+
expect(mat).to respond_to(:resize!)
|
355
370
|
}
|
356
|
-
mat_G, mat_W, mat_delta_r = mats
|
357
371
|
}
|
358
372
|
solver.hooks[:satellite_position] = proc{
|
359
373
|
i = 0
|
@@ -19,6 +19,12 @@ shared_examples 'Matrix' do
|
|
19
19
|
expect( mat_type::new(*params[:rc]).rows ).to equal(params[:rc][0])
|
20
20
|
expect( mat_type::new(*params[:rc]).columns ).to equal(params[:rc][1])
|
21
21
|
end
|
22
|
+
it 'declines negative number argument' do
|
23
|
+
[[-1, 1], [1, -1]].each{|sf|
|
24
|
+
r, c = params[:rc].zip(sf).collect{|v1, v2| v1 * v2}
|
25
|
+
expect{ mat_type::new(r, c) }.to raise_error(ArgumentError)
|
26
|
+
}
|
27
|
+
end
|
22
28
|
it 'accepts ([[]])' do
|
23
29
|
expect{ mat_type::new(compare_with) }.not_to raise_error
|
24
30
|
expect( mat_type::new(compare_with).rows ).to equal(params[:rc][0])
|
@@ -44,9 +50,11 @@ shared_examples 'Matrix' do
|
|
44
50
|
a.define_singleton_method(:[]){|i, j| raise(IndexError) if i != j; 0}
|
45
51
|
expect{ mat_type::new(a) }.to raise_error(IndexError)
|
46
52
|
|
47
|
-
|
48
|
-
|
49
|
-
|
53
|
+
[:row_size, :column_size].each{|f|
|
54
|
+
a = a_gen.call
|
55
|
+
a.define_singleton_method(f){-1}
|
56
|
+
expect{ mat_type::new(a) }.to raise_error(RuntimeError)
|
57
|
+
}
|
50
58
|
end
|
51
59
|
it 'is invoked with I, identity, unit' do
|
52
60
|
[:I, :identity, :unit].each{|f|
|
@@ -132,7 +140,7 @@ shared_examples 'Matrix' do
|
|
132
140
|
expect(mat[:square].sum).to eq(Matrix[*mat[:square].to_a].sum)
|
133
141
|
expect(mat[:not_square].sum).to eq(Matrix[*mat[:not_square].to_a].sum)
|
134
142
|
end
|
135
|
-
it '
|
143
|
+
it 'determinant, det' do
|
136
144
|
[:determinant, :det].each{|f|
|
137
145
|
#expect(mat[:square].send(f)).to eq(Matrix[*mat[:square].to_a].det)
|
138
146
|
expect{mat[:not_square].send(f)}.to raise_error(RuntimeError)
|
@@ -163,6 +171,15 @@ shared_examples 'Matrix' do
|
|
163
171
|
}
|
164
172
|
}
|
165
173
|
end
|
174
|
+
it 'is inaccessible and unchangeable with negative number arguments' do
|
175
|
+
[[-1, 0], [0, -1]].each{|i, j|
|
176
|
+
[[:[], i, j], [:[]=, i, j, 0]].each{|args|
|
177
|
+
expect{ mat[0].send(*args) }.to raise_error{|err|
|
178
|
+
expect(err).to be_a(RangeError).or be_a(ArgumentError)
|
179
|
+
}
|
180
|
+
}
|
181
|
+
}
|
182
|
+
end
|
166
183
|
end
|
167
184
|
|
168
185
|
describe 'elements' do
|
@@ -394,6 +411,23 @@ shared_examples 'Matrix' do
|
|
394
411
|
}
|
395
412
|
expect{mat[2] / mat[3]}.to raise_error(RuntimeError)
|
396
413
|
end
|
414
|
+
it 'have resize!' do
|
415
|
+
[-1, :sym].each{|arg|
|
416
|
+
[[arg, nil], [nil, arg]].each{|args|
|
417
|
+
expect{mat[0].resize!(*args)}.to raise_error{|err|
|
418
|
+
expect(err).to be_a(TypeError).or be_a(ArgumentError)
|
419
|
+
}
|
420
|
+
}
|
421
|
+
}
|
422
|
+
mat_orig = mat[0].to_a
|
423
|
+
r, c = [:rows, :columns].collect{|f| mat[0].send(f)}
|
424
|
+
expect(mat[0].resize!(r, c).to_a).to eq(mat_orig)
|
425
|
+
expect(mat[0].resize!(r, nil).to_a).to eq(mat_orig)
|
426
|
+
expect(mat[0].resize!(nil, c).to_a).to eq(mat_orig)
|
427
|
+
expect(mat[0].resize!(nil, nil).to_a).to eq(mat_orig)
|
428
|
+
expect(mat[0].resize!(r * 2, c * 2).to_a).to \
|
429
|
+
eq(Matrix::build(r * 2, c * 2){|i, j| (i < r && j < c) ? mat_orig[i][j] : 0}.to_a)
|
430
|
+
end
|
397
431
|
end
|
398
432
|
|
399
433
|
describe 'decomposition' do
|
data/gps_pvt.gemspec
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/gps_pvt/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "gps_pvt"
|
7
|
+
spec.version = GPS_PVT::VERSION
|
8
|
+
spec.authors = ["fenrir(M.Naruoka)"]
|
9
|
+
spec.email = ["fenrir.naru@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "GPS position, velocity, and time (PVT) solver"
|
12
|
+
spec.description = "This module calculate PVT by using raw observation obtained from a GPS receiver"
|
13
|
+
spec.homepage = "https://github.com/fenrir-naru/gps_pvt"
|
14
|
+
spec.required_ruby_version = ">= 2.3.0"
|
15
|
+
|
16
|
+
#spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
|
17
|
+
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
19
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
20
|
+
#spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
21
|
+
|
22
|
+
spec.extensions = ["ext/gps_pvt/extconf.rb"]
|
23
|
+
|
24
|
+
# Specify which files should be added to the gem when it is released.
|
25
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
26
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
27
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
28
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
29
|
+
end
|
30
|
+
end
|
31
|
+
spec.bindir = "exe"
|
32
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
33
|
+
spec.require_paths = ["lib"]
|
34
|
+
|
35
|
+
spec.files += proc{
|
36
|
+
require 'pathname'
|
37
|
+
base_dir = Pathname::new(File::absolute_path(File.dirname(__FILE__)))
|
38
|
+
# get an array of submodule dirs by executing 'pwd' inside each submodule
|
39
|
+
`git submodule --quiet foreach pwd`.split($/).collect{|dir|
|
40
|
+
# issue git ls-files in submodule's directory
|
41
|
+
`git -C #{dir} ls-files -v`.split($/).collect{|f|
|
42
|
+
next nil unless f =~ /^H */ # consider git sparse checkout
|
43
|
+
# get relative path
|
44
|
+
f = Pathname::new(File::join(dir, $'))
|
45
|
+
begin
|
46
|
+
(f.relative? ? f : f.relative_path_from(base_dir)).to_s
|
47
|
+
rescue
|
48
|
+
# Patch for Windows drive letter problem
|
49
|
+
base_dir = Pathname::new(base_dir.to_s.sub(/^([^\/])+:\//){"/#{$1}/"})
|
50
|
+
f.relative_path_from(base_dir).to_s
|
51
|
+
end
|
52
|
+
}.compact
|
53
|
+
}.flatten
|
54
|
+
}.call
|
55
|
+
|
56
|
+
# Uncomment to register a new dependency of your gem
|
57
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
58
|
+
spec.add_development_dependency "rake"
|
59
|
+
spec.add_development_dependency "rake-compiler"
|
60
|
+
|
61
|
+
# For more information and examples about making a new gem, checkout our
|
62
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
63
|
+
end
|