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