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.
- checksums.yaml +4 -4
- data/README.md +33 -6
- data/Rakefile +0 -0
- data/exe/gps_pvt +28 -19
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +596 -467
- 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 +83 -22
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +15 -5
- 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 +342 -103
- data/ext/ninja-scan-light/tool/swig/SylphideMath.i +53 -6
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +42 -6
- 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 +86 -41
- data/lib/gps_pvt/version.rb +1 -1
- metadata +7 -6
@@ -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
|
-
|
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
|
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
|
-
|
922
|
+
GPS_Solver<FloatT>::base_t::relative_property_t
|
944
923
|
GPS_Solver<FloatT>::relative_property(
|
945
|
-
const
|
946
|
-
const
|
947
|
-
const
|
948
|
-
const
|
949
|
-
const
|
950
|
-
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
|
-
|
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
|
1005
|
-
|
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
|
-
|
1012
|
-
%const_cast(geomat,
|
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(),
|
1057
|
-
|
1058
|
-
|
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
|
-
|
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
|
-
|
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);
|