gps_pvt 0.2.3 → 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 +20 -4
- data/Rakefile +0 -0
- data/exe/gps_pvt +0 -0
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +85 -8
- data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +0 -0
- data/ext/ninja-scan-light/tool/navigation/GPS.h +0 -0
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +0 -0
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +2 -2
- data/ext/ninja-scan-light/tool/navigation/SBAS.h +0 -0
- data/ext/ninja-scan-light/tool/navigation/SBAS_Solver.h +0 -0
- data/ext/ninja-scan-light/tool/param/bit_array.h +0 -0
- data/ext/ninja-scan-light/tool/swig/GPS.i +88 -8
- data/ext/ninja-scan-light/tool/swig/SylphideMath.i +0 -0
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +6 -1
- data/ext/ninja-scan-light/tool/swig/spec/SylphideMath_spec.rb +0 -0
- data/gps_pvt.gemspec +0 -0
- data/lib/gps_pvt/receiver.rb +36 -11
- data/lib/gps_pvt/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ceeb392e9d4a3df9a3b6af1ed6b19a92fec4fae110c9c89118602f3213d6905
|
4
|
+
data.tar.gz: c91c94043d2e39dde8ea0909dbd862f0194b15a4f2baa3030b48d760f933a147
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bcf702f83fd0df488470b385df370c3639e953b064a6acd9cdc4418a98b03ffab9c15dc9af0ad79185177bc3feb03e74b0ee0c9dba667bf73af1e1afabdca7be
|
7
|
+
data.tar.gz: eac046233bfd52db17a3fb94d2c74fcf01c8cd3200d0d5dce2546a669bb9313cccda4bdb74e2b991f1397d27325ec87d79d8c0e87be36b05fa6856daf0342ad0
|
data/README.md
CHANGED
@@ -41,7 +41,7 @@ From version 0.2.0, SBAS and QZSS are supported in addition to GPS. QZSS ranging
|
|
41
41
|
|
42
42
|
$ gps_pvt --with=137 RINEX_or_UBX_file(s)
|
43
43
|
|
44
|
-
For developer, this library will be used
|
44
|
+
For developer, this library will be used like:
|
45
45
|
|
46
46
|
```ruby
|
47
47
|
require 'gps_pvt'
|
@@ -81,25 +81,41 @@ receiver.parse_rinex_obs(rinex_obs_file){|pvt, meas| # per epoch
|
|
81
81
|
}
|
82
82
|
}
|
83
83
|
|
84
|
-
|
84
|
+
## Further customization
|
85
|
+
# General options
|
85
86
|
receiver.solver.gps_options.exclude(prn) # Exclude satellite; the default is to use every satellite if visible
|
86
87
|
receiver.solver.gps_options.include(prn) # Discard previous setting of exclusion
|
87
88
|
receiver.solver.gps_options.elevation_mask = Math::PI / 180 * 10 # example 10 [deg] elevation mask
|
89
|
+
# receiver.solver.sbas_options is for SBAS.
|
90
|
+
|
91
|
+
# Precise control of properties for each satellite and for each iteration
|
88
92
|
receiver.solver.hooks[:relative_property] = proc{|prn, rel_prop, meas, rcv_e, t_arv, usr_pos, usr_vel|
|
89
|
-
# control weight per satellite per iteration
|
90
93
|
weight, range_c, range_r, rate_rel_neg, *los_neg = rel_prop # relative property
|
91
94
|
# meas is measurement represented by pseudo range of the selected satellite.
|
92
95
|
# rcv_e, t_arv, usr_pos, usr_vel are temporary solution of
|
93
96
|
# receiver clock error [m], time of arrival [s], user position and velocity in ECEF, respectively.
|
94
97
|
|
95
98
|
weight = 1 # same as default; identical weight for each visible satellite
|
96
|
-
# or weight based on elevation
|
99
|
+
# or weight based on elevation, for example:
|
97
100
|
# elv = GPS_PVT::Coordinate::ENU::relative_rel(GPS_PVT::Coordinate::XYZ::new(*los_neg), usr_pos).elevation
|
98
101
|
# weight = (Math::sin(elv)/0.8)**2
|
99
102
|
|
100
103
|
[weight, range_c, range_r, rate_rel_neg] + los_neg # must return relative property
|
101
104
|
}
|
102
105
|
|
106
|
+
# Range correction (since v0.3.0)
|
107
|
+
receiver.solver.correction = { # provide by using a Hash
|
108
|
+
# ionospheric and transpheric models are changeable, and current configuration
|
109
|
+
# can be obtained by receiver.solver.correction without assigner.
|
110
|
+
:gps_ionospheric => proc{|t, usr_pos_xyz, sat_pos_enu|
|
111
|
+
# t, usr_pos_xyz, sat_pos_enu are temporary solution of
|
112
|
+
# time of arrival [s], user position in ECEF,
|
113
|
+
# and satellite position in ENU respectively.
|
114
|
+
0 # must return correction value, delaying is negative.
|
115
|
+
},
|
116
|
+
# combination of (gps or sbas) and (ionospheric or tropospheric) are available
|
117
|
+
}
|
118
|
+
|
103
119
|
# Dynamic customization of weight for each epoch
|
104
120
|
(class << receiver; self; end).instance_eval{ # do before parse_XXX
|
105
121
|
alias_method(:run_orig, :run)
|
data/Rakefile
CHANGED
File without changes
|
data/exe/gps_pvt
CHANGED
File without changes
|
@@ -2507,6 +2507,26 @@ struct SBAS_SolverOptions
|
|
2507
2507
|
};
|
2508
2508
|
|
2509
2509
|
|
2510
|
+
template <class FloatT>
|
2511
|
+
struct GPS_RangeCorrector
|
2512
|
+
: public GPS_Solver_Base<FloatT>::range_corrector_t {
|
2513
|
+
VALUE callback;
|
2514
|
+
GPS_RangeCorrector(const VALUE &callback_)
|
2515
|
+
: GPS_Solver_Base<FloatT>::range_corrector_t(),
|
2516
|
+
callback(callback_) {}
|
2517
|
+
bool is_available(const typename GPS_Solver_Base<FloatT>::gps_time_t &t) const {
|
2518
|
+
return false;
|
2519
|
+
}
|
2520
|
+
FloatT *calculate(
|
2521
|
+
const typename GPS_Solver_Base<FloatT>::gps_time_t &t,
|
2522
|
+
const typename GPS_Solver_Base<FloatT>::pos_t &usr_pos,
|
2523
|
+
const typename GPS_Solver_Base<FloatT>::enu_t &sat_rel_pos,
|
2524
|
+
FloatT &buf) const {
|
2525
|
+
return NULL;
|
2526
|
+
}
|
2527
|
+
};
|
2528
|
+
|
2529
|
+
|
2510
2530
|
template <class FloatT>
|
2511
2531
|
struct GPS_Solver
|
2512
2532
|
: public GPS_Solver_RAIM_LSR<FloatT,
|
@@ -2527,14 +2547,22 @@ struct GPS_Solver
|
|
2527
2547
|
sbas_t() : space_node(), options(), solver(space_node) {}
|
2528
2548
|
} sbas;
|
2529
2549
|
VALUE hooks;
|
2550
|
+
typedef std::vector<GPS_RangeCorrector<FloatT> > user_correctors_t;
|
2551
|
+
user_correctors_t user_correctors;
|
2530
2552
|
|
2531
2553
|
static void mark(void *ptr){
|
2532
2554
|
GPS_Solver<FloatT> *solver = (GPS_Solver<FloatT> *)ptr;
|
2533
|
-
if(solver->hooks == Qnil){return;}
|
2534
2555
|
rb_gc_mark(solver->hooks);
|
2556
|
+
for(typename user_correctors_t::const_iterator
|
2557
|
+
it(solver->user_correctors.begin()), it_end(solver->user_correctors.end());
|
2558
|
+
it != it_end; ++it){
|
2559
|
+
rb_gc_mark(it->callback);
|
2560
|
+
}
|
2535
2561
|
}
|
2536
2562
|
|
2537
|
-
GPS_Solver() : super_t(),
|
2563
|
+
GPS_Solver() : super_t(),
|
2564
|
+
gps(), sbas(),
|
2565
|
+
hooks(), user_correctors() {
|
2538
2566
|
|
2539
2567
|
hooks = rb_hash_new();
|
2540
2568
|
|
@@ -2606,6 +2634,19 @@ struct GPS_Solver
|
|
2606
2634
|
if(!update){break;}
|
2607
2635
|
typename range_correction_list_t::const_iterator it(list.find(i));
|
2608
2636
|
if(it == list.end()){break;}
|
2637
|
+
|
2638
|
+
// Remove user defined unused correctors
|
2639
|
+
for(typename base_t::range_correction_t::const_iterator
|
2640
|
+
it2(root[i]->begin()), it2_end(root[i]->end());
|
2641
|
+
it2 != it2_end; ++it2){
|
2642
|
+
for(typename user_correctors_t::const_iterator
|
2643
|
+
it3(user_correctors.begin()), it3_end(user_correctors.end());
|
2644
|
+
it3 != it3_end; ++it3){
|
2645
|
+
if(*it2 != &(*it3)){continue;}
|
2646
|
+
user_correctors.erase(it3);
|
2647
|
+
}
|
2648
|
+
}
|
2649
|
+
|
2609
2650
|
root[i]->clear();
|
2610
2651
|
for(typename range_correction_list_t::mapped_type::const_iterator
|
2611
2652
|
it2(it->second.begin()), it2_end(it->second.end());
|
@@ -3794,6 +3835,38 @@ SWIGINTERN double const &GPS_SolverOptions_Common_Sl_double_Sg__get_residual_mas
|
|
3794
3835
|
}
|
3795
3836
|
|
3796
3837
|
|
3838
|
+
template <>
|
3839
|
+
bool GPS_RangeCorrector<double>::is_available(
|
3840
|
+
const typename GPS_Solver_Base<double>::gps_time_t &t) const {
|
3841
|
+
VALUE values[] = {
|
3842
|
+
SWIG_NewPointerObj(
|
3843
|
+
const_cast< GPS_Time<double> * >(&t), SWIGTYPE_p_GPS_TimeT_double_t, 0),
|
3844
|
+
};
|
3845
|
+
VALUE res(proc_call_throw_if_error(
|
3846
|
+
callback, sizeof(values) / sizeof(values[0]), values));
|
3847
|
+
return RTEST(res) ? true : false;
|
3848
|
+
}
|
3849
|
+
template <>
|
3850
|
+
double *GPS_RangeCorrector<double>::calculate(
|
3851
|
+
const typename GPS_Solver_Base<double>::gps_time_t &t,
|
3852
|
+
const typename GPS_Solver_Base<double>::pos_t &usr_pos,
|
3853
|
+
const typename GPS_Solver_Base<double>::enu_t &sat_rel_pos,
|
3854
|
+
double &buf) const {
|
3855
|
+
VALUE values[] = {
|
3856
|
+
SWIG_NewPointerObj(
|
3857
|
+
const_cast< GPS_Time<double> * >(&t),
|
3858
|
+
SWIGTYPE_p_GPS_TimeT_double_t, 0),
|
3859
|
+
SWIG_NewPointerObj(
|
3860
|
+
(const_cast< System_XYZ<double,WGS84> * >(&usr_pos.xyz)),
|
3861
|
+
SWIGTYPE_p_System_XYZT_double_WGS84_t, 0),
|
3862
|
+
SWIG_NewPointerObj(
|
3863
|
+
(const_cast< System_ENU<double,WGS84> * >(&sat_rel_pos)),
|
3864
|
+
SWIGTYPE_p_System_ENUT_double_WGS84_t, 0),
|
3865
|
+
};
|
3866
|
+
VALUE res(proc_call_throw_if_error(
|
3867
|
+
callback, sizeof(values) / sizeof(values[0]), values));
|
3868
|
+
return SWIG_IsOK(swig::asval(res, &buf)) ? &buf : NULL;
|
3869
|
+
}
|
3797
3870
|
template<>
|
3798
3871
|
VALUE GPS_Solver<double>::update_correction(
|
3799
3872
|
const bool &update, const VALUE &hash){
|
@@ -3836,10 +3909,12 @@ SWIGINTERN double const &GPS_SolverOptions_Common_Sl_double_Sg__get_residual_mas
|
|
3836
3909
|
for(; k < sizeof(item) / sizeof(item[0]); ++k){
|
3837
3910
|
if(v == item[k].sym){break;}
|
3838
3911
|
}
|
3839
|
-
if(k >= sizeof(item) / sizeof(item[0])){
|
3840
|
-
|
3912
|
+
if(k >= sizeof(item) / sizeof(item[0])){ // other than symbol
|
3913
|
+
user_correctors.push_back(GPS_RangeCorrector<double>(v));
|
3914
|
+
input[i].push_back(&user_correctors.back());
|
3915
|
+
}else{
|
3916
|
+
input[i].push_back(item[k].obj);
|
3841
3917
|
}
|
3842
|
-
input[i].push_back(item[k].obj);
|
3843
3918
|
}
|
3844
3919
|
}
|
3845
3920
|
VALUE opt(rb_hash_lookup(hash, k_opt));
|
@@ -3866,10 +3941,12 @@ SWIGINTERN double const &GPS_SolverOptions_Common_Sl_double_Sg__get_residual_mas
|
|
3866
3941
|
for(; i < sizeof(item) / sizeof(item[0]); ++i){
|
3867
3942
|
if(*it2 == item[i].obj){break;}
|
3868
3943
|
}
|
3869
|
-
if(i >= sizeof(item) / sizeof(item[0])){
|
3870
|
-
|
3944
|
+
if(i >= sizeof(item) / sizeof(item[0])){ // other than built-in corrector
|
3945
|
+
rb_ary_push(v,
|
3946
|
+
reinterpret_cast<const GPS_RangeCorrector<double> *>(*it2)->callback);
|
3947
|
+
}else{
|
3948
|
+
rb_ary_push(v, item[i].sym);
|
3871
3949
|
}
|
3872
|
-
rb_ary_push(v, item[i].sym);
|
3873
3950
|
}
|
3874
3951
|
rb_hash_aset(res, k, v);
|
3875
3952
|
}
|
File without changes
|
File without changes
|
File without changes
|
@@ -652,14 +652,14 @@ protected:
|
|
652
652
|
// Least square
|
653
653
|
matrix_t delta_x(geomat.partial(res.used_satellites).least_square());
|
654
654
|
|
655
|
-
xyz_t delta_user_position(delta_x.partial(3, 1
|
655
|
+
xyz_t delta_user_position(delta_x.partial(3, 1));
|
656
656
|
res.user_position.xyz += delta_user_position;
|
657
657
|
res.user_position.llh = res.user_position.xyz.llh();
|
658
658
|
|
659
659
|
const float_t &delta_receiver_error(delta_x(3, 0));
|
660
660
|
res.receiver_error += delta_receiver_error;
|
661
661
|
|
662
|
-
return (
|
662
|
+
return (delta_x.partial(4, 1).norm2F() <= 1E-6); // equivalent to abs(x) <= 1E-3 [m]
|
663
663
|
}
|
664
664
|
|
665
665
|
struct user_pvt_opt_t {
|
File without changes
|
File without changes
|
File without changes
|
@@ -878,6 +878,27 @@ struct SBAS_SolverOptions
|
|
878
878
|
};
|
879
879
|
%}
|
880
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
|
+
|
881
902
|
%extend GPS_Solver {
|
882
903
|
%ignore super_t;
|
883
904
|
%ignore base_t;
|
@@ -889,6 +910,8 @@ struct SBAS_SolverOptions
|
|
889
910
|
%ignore relative_property;
|
890
911
|
%ignore satellite_position;
|
891
912
|
%ignore update_position_solution;
|
913
|
+
%ignore user_correctors_t;
|
914
|
+
%ignore user_correctors;
|
892
915
|
%immutable hooks;
|
893
916
|
%ignore mark;
|
894
917
|
%fragment("hook"{GPS_Solver<FloatT>}, "header",
|
@@ -1033,6 +1056,38 @@ struct SBAS_SolverOptions
|
|
1033
1056
|
%fragment("correction"{GPS_Solver<FloatT>}, "header",
|
1034
1057
|
fragment=SWIG_From_frag(int),
|
1035
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
|
+
}
|
1036
1091
|
template<>
|
1037
1092
|
VALUE GPS_Solver<FloatT>::update_correction(
|
1038
1093
|
const bool &update, const VALUE &hash){
|
@@ -1075,10 +1130,12 @@ struct SBAS_SolverOptions
|
|
1075
1130
|
for(; k < sizeof(item) / sizeof(item[0]); ++k){
|
1076
1131
|
if(v == item[k].sym){break;}
|
1077
1132
|
}
|
1078
|
-
if(k >= sizeof(item) / sizeof(item[0])){
|
1079
|
-
|
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);
|
1080
1138
|
}
|
1081
|
-
input[i].push_back(item[k].obj);
|
1082
1139
|
}
|
1083
1140
|
}
|
1084
1141
|
VALUE opt(rb_hash_lookup(hash, k_opt));
|
@@ -1105,10 +1162,12 @@ struct SBAS_SolverOptions
|
|
1105
1162
|
for(; i < sizeof(item) / sizeof(item[0]); ++i){
|
1106
1163
|
if(*it2 == item[i].obj){break;}
|
1107
1164
|
}
|
1108
|
-
if(i >= sizeof(item) / sizeof(item[0])){
|
1109
|
-
|
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);
|
1110
1170
|
}
|
1111
|
-
rb_ary_push(v, item[i].sym);
|
1112
1171
|
}
|
1113
1172
|
rb_hash_aset(res, k, v);
|
1114
1173
|
}
|
@@ -1160,14 +1219,22 @@ struct GPS_Solver
|
|
1160
1219
|
sbas_t() : space_node(), options(), solver(space_node) {}
|
1161
1220
|
} sbas;
|
1162
1221
|
SWIG_Object hooks;
|
1222
|
+
typedef std::vector<GPS_RangeCorrector<FloatT> > user_correctors_t;
|
1223
|
+
user_correctors_t user_correctors;
|
1163
1224
|
#ifdef SWIGRUBY
|
1164
1225
|
static void mark(void *ptr){
|
1165
1226
|
GPS_Solver<FloatT> *solver = (GPS_Solver<FloatT> *)ptr;
|
1166
|
-
if(solver->hooks == Qnil){return;}
|
1167
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
|
+
}
|
1168
1233
|
}
|
1169
1234
|
#endif
|
1170
|
-
GPS_Solver() : super_t(),
|
1235
|
+
GPS_Solver() : super_t(),
|
1236
|
+
gps(), sbas(),
|
1237
|
+
hooks(), user_correctors() {
|
1171
1238
|
#ifdef SWIGRUBY
|
1172
1239
|
hooks = rb_hash_new();
|
1173
1240
|
#endif
|
@@ -1239,6 +1306,19 @@ struct GPS_Solver
|
|
1239
1306
|
if(!update){break;}
|
1240
1307
|
typename range_correction_list_t::const_iterator it(list.find(i));
|
1241
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
|
+
|
1242
1322
|
root[i]->clear();
|
1243
1323
|
for(typename range_correction_list_t::mapped_type::const_iterator
|
1244
1324
|
it2(it->second.begin()), it2_end(it->second.end());
|
File without changes
|
@@ -343,7 +343,12 @@ __RINEX_OBS_TEXT__
|
|
343
343
|
expect(solver.correction[:gps_tropospheric]).to include(:hopfield)
|
344
344
|
expect{solver.correction = nil}.to raise_error(RuntimeError)
|
345
345
|
expect{solver.correction = {
|
346
|
-
:gps_ionospheric => [
|
346
|
+
:gps_ionospheric => [proc{|t, usr_pos, sat_pos|
|
347
|
+
expect(t).to be_a_kind_of(GPS::Time)
|
348
|
+
expect(usr_pos).to be_a_kind_of(Coordinate::XYZ) unless usr_pos
|
349
|
+
expect(sat_pos).to be_a_kind_of(Coordinate::ENU) unless sat_pos
|
350
|
+
false
|
351
|
+
}, :klobuchar, :no_correction],
|
347
352
|
:options => {:f_10_7 => 10},
|
348
353
|
}}.not_to raise_error
|
349
354
|
expect(solver.correction[:gps_ionospheric]).to include(:no_correction)
|
File without changes
|
data/gps_pvt.gemspec
CHANGED
File without changes
|
data/lib/gps_pvt/receiver.rb
CHANGED
@@ -47,23 +47,31 @@ class Receiver
|
|
47
47
|
]] + [
|
48
48
|
[:used_satellites, proc{|pvt| pvt.used_satellites}],
|
49
49
|
] + opt[:system].collect{|sys, range|
|
50
|
-
|
51
|
-
|
50
|
+
range = range.kind_of?(Array) ? proc{
|
51
|
+
# check whether inputs can be converted to Range
|
52
|
+
next nil if range.empty?
|
53
|
+
a, b = range.minmax
|
54
|
+
((b - a) == (range.length - 1)) ? (a..b) : range
|
55
|
+
}.call : range
|
56
|
+
next nil unless range
|
57
|
+
bit_flip, label = case range
|
58
|
+
when Array
|
59
|
+
[proc{|res, i|
|
52
60
|
res[i] = "1" if i = range.index(i)
|
53
61
|
res
|
54
|
-
}
|
55
|
-
|
62
|
+
}, range.collect{|pen| pen & 0xFF}.reverse.join('+')]
|
63
|
+
when Range
|
56
64
|
base_prn = range.min
|
57
|
-
proc{|res, i|
|
65
|
+
[proc{|res, i|
|
58
66
|
res[i - base_prn] = "1" if range.include?(i)
|
59
67
|
res
|
60
|
-
}
|
68
|
+
}, [:max, :min].collect{|f| range.send(f) & 0xFF}.join('..')]
|
61
69
|
end
|
62
|
-
["#{sys}_PRN", proc{|pvt|
|
70
|
+
["#{sys}_PRN(#{label})", proc{|pvt|
|
63
71
|
pvt.used_satellite_list.inject("0" * range.size, &bit_flip) \
|
64
72
|
.scan(/.{1,8}/).join('_').reverse
|
65
73
|
}]
|
66
|
-
} + [[
|
74
|
+
}.compact + [[
|
67
75
|
opt[:satellites].collect{|prn, label|
|
68
76
|
[:range_residual, :weight, :azimuth, :elevation, :slopeH, :slopeV].collect{|str|
|
69
77
|
"#{str}(#{label || prn})"
|
@@ -138,8 +146,11 @@ class Receiver
|
|
138
146
|
rel_prop
|
139
147
|
}
|
140
148
|
@debug = {}
|
141
|
-
[:gps_options, :sbas_options].
|
142
|
-
|
149
|
+
solver_opts = [:gps_options, :sbas_options].collect{|target|
|
150
|
+
@solver.send(target)
|
151
|
+
}
|
152
|
+
solver_opts.each{|opt|
|
153
|
+
# default solver options
|
143
154
|
opt.elevation_mask = 0.0 / 180 * Math::PI # 0 deg (use satellite over horizon)
|
144
155
|
opt.residual_mask = 1E4 # 10 km (without residual filter, practically)
|
145
156
|
}
|
@@ -168,6 +179,13 @@ class Receiver
|
|
168
179
|
when :identical # same as default
|
169
180
|
next true
|
170
181
|
end
|
182
|
+
when :elevation_mask_deg
|
183
|
+
raise "Unknown elevation mask angle: #{v}" unless elv_deg = (Float(v) rescue nil)
|
184
|
+
$stderr.puts "Elevation mask: #{elv_deg} deg"
|
185
|
+
solver_opts.each{|opt|
|
186
|
+
opt.elevation_mask = elv_deg / 180 * Math::PI # 0 deg (use satellite over horizon)
|
187
|
+
}
|
188
|
+
next true
|
171
189
|
when :base_station
|
172
190
|
crd, sys = v.split(/ *, */).collect.with_index{|item, i|
|
173
191
|
case item
|
@@ -219,12 +237,14 @@ class Receiver
|
|
219
237
|
i = -1
|
220
238
|
output_options[:system] << [sys_target, []]
|
221
239
|
else
|
222
|
-
output_options[:system][i].reject!{|prn| prns.include?(prn)}
|
240
|
+
output_options[:system][i][1].reject!{|prn| prns.include?(prn)}
|
223
241
|
end
|
224
242
|
output_options[:satellites].reject!{|prn, label| prns.include?(prn)}
|
225
243
|
if mode == :include then
|
226
244
|
output_options[:system][i][1] += prns
|
245
|
+
output_options[:system][i][1].sort!
|
227
246
|
output_options[:satellites] += (labels ? prns.zip(labels) : prns)
|
247
|
+
output_options[:satellites].sort!{|a, b| [a].flatten[0] <=> [b].flatten[0]}
|
228
248
|
end
|
229
249
|
}
|
230
250
|
check_sys_svid = proc{|sys_target, range_in_sys, offset|
|
@@ -328,6 +348,11 @@ class Receiver
|
|
328
348
|
[:azimuth, :elevation, :slopeH, :slopeV].each{|k|
|
329
349
|
eval("define_method(:#{k}){@#{k} || self.post_solution(:@#{k})}")
|
330
350
|
}
|
351
|
+
define_method(:other_state){
|
352
|
+
# If a design matrix G has columns larger than 4,
|
353
|
+
# other states excluding position and time are estimated.
|
354
|
+
(self.G.rows <= 4) ? [] : (self.S * self.delta_r).transpose.to_a[0][4..-1]
|
355
|
+
}
|
331
356
|
}
|
332
357
|
|
333
358
|
proc{
|
data/lib/gps_pvt/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gps_pvt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- fenrir(M.Naruoka)
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -100,7 +100,7 @@ licenses: []
|
|
100
100
|
metadata:
|
101
101
|
homepage_uri: https://github.com/fenrir-naru/gps_pvt
|
102
102
|
source_code_uri: https://github.com/fenrir-naru/gps_pvt
|
103
|
-
post_install_message:
|
103
|
+
post_install_message:
|
104
104
|
rdoc_options: []
|
105
105
|
require_paths:
|
106
106
|
- lib
|
@@ -115,8 +115,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
115
115
|
- !ruby/object:Gem::Version
|
116
116
|
version: '0'
|
117
117
|
requirements: []
|
118
|
-
rubygems_version: 3.
|
119
|
-
signing_key:
|
118
|
+
rubygems_version: 3.1.2
|
119
|
+
signing_key:
|
120
120
|
specification_version: 4
|
121
121
|
summary: GPS position, velocity, and time (PVT) solver
|
122
122
|
test_files: []
|