gps_pvt 0.2.3 → 0.4.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 +35 -7
- data/Rakefile +2 -0
- data/exe/gps_pvt +65 -2
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +5898 -395
- data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +453 -429
- data/ext/ninja-scan-light/tool/algorithm/integral.h +91 -0
- data/ext/ninja-scan-light/tool/navigation/GLONASS.h +1270 -0
- data/ext/ninja-scan-light/tool/navigation/GLONASS_Solver.h +306 -0
- data/ext/ninja-scan-light/tool/navigation/GPS.h +7 -1
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +0 -0
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +9 -2
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +389 -4
- 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 +310 -13
- data/ext/ninja-scan-light/tool/swig/SylphideMath.i +38 -15
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +7 -1
- data/ext/ninja-scan-light/tool/swig/spec/SylphideMath_spec.rb +13 -3
- data/gps_pvt.gemspec +0 -0
- data/lib/gps_pvt/receiver.rb +101 -20
- data/lib/gps_pvt/version.rb +1 -1
- metadata +9 -6
@@ -20,12 +20,14 @@
|
|
20
20
|
#include "navigation/GPS.h"
|
21
21
|
#include "navigation/SBAS.h"
|
22
22
|
#include "navigation/QZSS.h"
|
23
|
+
#include "navigation/GLONASS.h"
|
23
24
|
#include "navigation/RINEX.h"
|
24
25
|
|
25
26
|
#include "navigation/GPS_Solver_Base.h"
|
26
27
|
#include "navigation/GPS_Solver.h"
|
27
28
|
#include "navigation/GPS_Solver_RAIM.h"
|
28
29
|
#include "navigation/SBAS_Solver.h"
|
30
|
+
#include "navigation/GLONASS_Solver.h"
|
29
31
|
|
30
32
|
#if defined(__cplusplus) && (__cplusplus < 201103L)
|
31
33
|
namespace std {
|
@@ -153,6 +155,12 @@ static std::string inspect_str(const VALUE &v){
|
|
153
155
|
$1 = (TYPE($input) == T_ARRAY) ? 1 : 0;
|
154
156
|
}
|
155
157
|
#endif
|
158
|
+
%ignore canonicalize();
|
159
|
+
%ignore GPS_Time(const int &_week, const float_t &_seconds);
|
160
|
+
%typemap(in, numinputs=0) void *dummy "";
|
161
|
+
GPS_Time(const int &week_, const float_t &seconds_, void *dummy){
|
162
|
+
return &((new GPS_Time<FloatT>(week_, seconds_))->canonicalize());
|
163
|
+
}
|
156
164
|
%apply int *OUTPUT { int *week };
|
157
165
|
%apply FloatT *OUTPUT { FloatT *seconds };
|
158
166
|
void to_a(int *week, FloatT *seconds) const {
|
@@ -500,6 +508,160 @@ struct SBAS_Ephemeris : public SBAS_SpaceNode<FloatT>::SatelliteProperties::Ephe
|
|
500
508
|
|
501
509
|
%include navigation/SBAS.h
|
502
510
|
|
511
|
+
%inline %{
|
512
|
+
template <class FloatT>
|
513
|
+
struct GLONASS_Ephemeris
|
514
|
+
: public GLONASS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris_with_GPS_Time {
|
515
|
+
typedef typename GLONASS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris_with_GPS_Time eph_t;
|
516
|
+
unsigned int super_frame, has_string;
|
517
|
+
typename eph_t::raw_t raw;
|
518
|
+
void invalidate() {
|
519
|
+
super_frame = 0;
|
520
|
+
has_string = 0;
|
521
|
+
}
|
522
|
+
bool is_consistent() const {
|
523
|
+
return has_string == 0x1F;
|
524
|
+
}
|
525
|
+
GLONASS_Ephemeris() : eph_t() {
|
526
|
+
invalidate();
|
527
|
+
}
|
528
|
+
GLONASS_Ephemeris(const eph_t &eph)
|
529
|
+
: eph_t(eph),
|
530
|
+
super_frame(0), has_string(0), raw() {
|
531
|
+
raw = *this;
|
532
|
+
has_string = 0x1F;
|
533
|
+
}
|
534
|
+
};
|
535
|
+
%}
|
536
|
+
%extend GLONASS_Ephemeris {
|
537
|
+
MAKE_ACCESSOR(svid, unsigned int);
|
538
|
+
|
539
|
+
MAKE_ACCESSOR(freq_ch, int); // frequency channel to be configured
|
540
|
+
MAKE_ACCESSOR(t_k, unsigned int);
|
541
|
+
MAKE_ACCESSOR(t_b, unsigned int);
|
542
|
+
MAKE_ACCESSOR(M, unsigned int);
|
543
|
+
MAKE_ACCESSOR(gamma_n, FloatT);
|
544
|
+
MAKE_ACCESSOR(tau_n, FloatT);
|
545
|
+
|
546
|
+
MAKE_ACCESSOR(xn, FloatT); MAKE_ACCESSOR(xn_dot, FloatT); MAKE_ACCESSOR(xn_ddot, FloatT);
|
547
|
+
MAKE_ACCESSOR(yn, FloatT); MAKE_ACCESSOR(yn_dot, FloatT); MAKE_ACCESSOR(yn_ddot, FloatT);
|
548
|
+
MAKE_ACCESSOR(zn, FloatT); MAKE_ACCESSOR(zn_dot, FloatT); MAKE_ACCESSOR(zn_ddot, FloatT);
|
549
|
+
|
550
|
+
MAKE_ACCESSOR(B_n, unsigned int);
|
551
|
+
MAKE_ACCESSOR(p, unsigned int);
|
552
|
+
MAKE_ACCESSOR(N_T, unsigned int);
|
553
|
+
MAKE_ACCESSOR(F_T, FloatT);
|
554
|
+
MAKE_ACCESSOR(n, unsigned int);
|
555
|
+
MAKE_ACCESSOR(delta_tau_n, FloatT);
|
556
|
+
MAKE_ACCESSOR(E_n, unsigned int);
|
557
|
+
MAKE_ACCESSOR(P1, unsigned int);
|
558
|
+
MAKE_ACCESSOR(P2, bool);
|
559
|
+
MAKE_ACCESSOR(P4, bool);
|
560
|
+
|
561
|
+
MAKE_ACCESSOR(tau_c, FloatT);
|
562
|
+
MAKE_ACCESSOR(tau_GPS, FloatT);
|
563
|
+
|
564
|
+
FloatT frequency_L1() const {
|
565
|
+
return self->L1_frequency();
|
566
|
+
};
|
567
|
+
FloatT frequency_L2() const {
|
568
|
+
return self->L2_frequency();
|
569
|
+
};
|
570
|
+
GPS_Time<FloatT> base_time() const {
|
571
|
+
return self->base_time();
|
572
|
+
}
|
573
|
+
|
574
|
+
//MAKE_ACCESSOR(l_n, bool); // exists in both Ephemeris and Time_Properties
|
575
|
+
|
576
|
+
MAKE_ARRAY_INPUT(const unsigned int, buf, SWIG_AsVal(unsigned int));
|
577
|
+
bool parse(const unsigned int buf[4], const unsigned int &leap_seconds = 0){
|
578
|
+
typedef typename GLONASS_SpaceNode<FloatT>
|
579
|
+
::template BroadcastedMessage<unsigned int> parser_t;
|
580
|
+
unsigned int super_frame(buf[3] >> 16), frame(buf[3] & 0xF), string_no(parser_t::m(buf));
|
581
|
+
unsigned int has_string(self->has_string);
|
582
|
+
if((has_string > 0) && (self->super_frame != super_frame)){
|
583
|
+
has_string = 0; // clean up
|
584
|
+
}
|
585
|
+
self->super_frame = super_frame;
|
586
|
+
has_string |= (0x1 << (string_no - 1));
|
587
|
+
switch(string_no){
|
588
|
+
case 1: self->raw.template update_string1<0, 0>(buf); break;
|
589
|
+
case 2: self->raw.template update_string2<0, 0>(buf); break;
|
590
|
+
case 3: self->raw.template update_string3<0, 0>(buf); break;
|
591
|
+
case 4: self->raw.template update_string4<0, 0>(buf); break;
|
592
|
+
case 5: {
|
593
|
+
self->raw.template update_string5<0, 0>(buf);
|
594
|
+
if(frame == 4){
|
595
|
+
// TODO: require special care for 50th frame? @see Table 4.9 note (4)
|
596
|
+
}
|
597
|
+
break;
|
598
|
+
}
|
599
|
+
}
|
600
|
+
bool updated(false);
|
601
|
+
if((has_string == 0x1F) && (has_string != self->has_string)){
|
602
|
+
updated = true;
|
603
|
+
// All ephemeris and time info. in the same super frame has been acquired,
|
604
|
+
// and this block is called once per one same super frame.
|
605
|
+
// Ephemeris_with_Time::raw_t =(cast)=> Ephemeris_with_Time => Ephemeris_with_GPS_Time
|
606
|
+
static_cast<GLONASS_Ephemeris<FloatT>::eph_t &>(*self)
|
607
|
+
= GLONASS_Ephemeris<FloatT>::eph_t(self->raw);
|
608
|
+
self->t_b_gps += leap_seconds;
|
609
|
+
}
|
610
|
+
self->has_string = has_string;
|
611
|
+
return updated;
|
612
|
+
}
|
613
|
+
FloatT clock_error(
|
614
|
+
const GPS_Time<FloatT> &t_arrival, const FloatT &pseudo_range = 0) const {
|
615
|
+
return self->clock_error(t_arrival, pseudo_range);
|
616
|
+
}
|
617
|
+
%typemap(in,numinputs=0) System_XYZ<FloatT, WGS84> & (System_XYZ<FloatT, WGS84> temp) %{
|
618
|
+
$1 = &temp;
|
619
|
+
%}
|
620
|
+
%typemap(argout) System_XYZ<FloatT, WGS84> & {
|
621
|
+
%append_output(SWIG_NewPointerObj((new $*1_ltype(*$1)), $1_descriptor, SWIG_POINTER_OWN));
|
622
|
+
}
|
623
|
+
void constellation(
|
624
|
+
System_XYZ<FloatT, WGS84> &position, System_XYZ<FloatT, WGS84> &velocity,
|
625
|
+
const GPS_Time<FloatT> &t, const FloatT &pseudo_range = 0) const {
|
626
|
+
typename GPS_SpaceNode<FloatT>::SatelliteProperties::constellation_t res(
|
627
|
+
self->constellation(t, pseudo_range));
|
628
|
+
position = res.position;
|
629
|
+
velocity = res.velocity;
|
630
|
+
}
|
631
|
+
#if defined(SWIGRUBY)
|
632
|
+
%rename("consistent?") is_consistent;
|
633
|
+
%rename("in_range?") is_in_range;
|
634
|
+
#endif
|
635
|
+
bool is_in_range(const GPS_Time<FloatT> &t) const {
|
636
|
+
// "invalidate()" is used to make raw and converted data inconsistent.
|
637
|
+
return self->is_valid(t);
|
638
|
+
}
|
639
|
+
}
|
640
|
+
|
641
|
+
%extend GLONASS_SpaceNode {
|
642
|
+
%fragment(SWIG_Traits_frag(FloatT));
|
643
|
+
%ignore satellites() const;
|
644
|
+
%ignore satellite(const int &);
|
645
|
+
%ignore latest_ephemeris() const;
|
646
|
+
void register_ephemeris(
|
647
|
+
const int &prn, const GLONASS_Ephemeris<FloatT> &eph,
|
648
|
+
const int &priority_delta = 1){
|
649
|
+
self->satellite(prn).register_ephemeris(eph, priority_delta);
|
650
|
+
}
|
651
|
+
GLONASS_Ephemeris<FloatT> ephemeris(const int &prn) const {
|
652
|
+
return GLONASS_Ephemeris<FloatT>(
|
653
|
+
%const_cast(self, GLONASS_SpaceNode<FloatT> *)->satellite(prn).ephemeris());
|
654
|
+
}
|
655
|
+
int read(const char *fname) {
|
656
|
+
std::fstream fin(fname, std::ios::in | std::ios::binary);
|
657
|
+
typename RINEX_NAV_Reader<FloatT>::space_node_list_t list = {NULL};
|
658
|
+
list.glonass = self;
|
659
|
+
return RINEX_NAV_Reader<FloatT>::read_all(fin, list);
|
660
|
+
}
|
661
|
+
}
|
662
|
+
|
663
|
+
%include navigation/GLONASS.h
|
664
|
+
|
503
665
|
%extend GPS_User_PVT {
|
504
666
|
%ignore solver_t;
|
505
667
|
%ignore base_t;
|
@@ -591,8 +753,9 @@ struct GPS_User_PVT
|
|
591
753
|
Matrix<FloatT, Array2D_Dense<FloatT> > G_enu() const {
|
592
754
|
return proxy_t::linear_solver_t::rotate_G(base_t::G, base_t::user_position.ecef2enu());
|
593
755
|
}
|
594
|
-
typename proxy_t::linear_solver_t linear_solver() const {
|
595
|
-
return typename proxy_t::linear_solver_t(base_t::G, base_t::W, base_t::delta_r)
|
756
|
+
typename proxy_t::linear_solver_t::partial_t linear_solver() const {
|
757
|
+
return typename proxy_t::linear_solver_t(base_t::G, base_t::W, base_t::delta_r)
|
758
|
+
.partial(used_satellites());
|
596
759
|
}
|
597
760
|
Matrix<FloatT, Array2D_Dense<FloatT> > C() const {
|
598
761
|
return linear_solver().C();
|
@@ -605,14 +768,26 @@ struct GPS_User_PVT
|
|
605
768
|
linear_solver().least_square(res);
|
606
769
|
return res;
|
607
770
|
}
|
771
|
+
Matrix<FloatT, Array2D_Dense<FloatT> > S_enu(
|
772
|
+
const Matrix<FloatT, Array2D_Dense<FloatT> > &s) const {
|
773
|
+
return proxy_t::linear_solver_t::rotate_S(s, base_t::user_position.ecef2enu());
|
774
|
+
}
|
608
775
|
Matrix<FloatT, Array2D_Dense<FloatT> > S_enu() const {
|
609
|
-
return
|
776
|
+
return S_enu(S());
|
777
|
+
}
|
778
|
+
Matrix<FloatT, Array2D_Dense<FloatT> > slope_HV(
|
779
|
+
const Matrix<FloatT, Array2D_Dense<FloatT> > &s) const {
|
780
|
+
return linear_solver().slope_HV(s);
|
610
781
|
}
|
611
782
|
Matrix<FloatT, Array2D_Dense<FloatT> > slope_HV() const {
|
612
|
-
return
|
783
|
+
return slope_HV(S());
|
784
|
+
}
|
785
|
+
Matrix<FloatT, Array2D_Dense<FloatT> > slope_HV_enu(
|
786
|
+
const Matrix<FloatT, Array2D_Dense<FloatT> > &s) const {
|
787
|
+
return linear_solver().slope_HV(s, base_t::user_position.ecef2enu());
|
613
788
|
}
|
614
789
|
Matrix<FloatT, Array2D_Dense<FloatT> > slope_HV_enu() const {
|
615
|
-
return
|
790
|
+
return slope_HV_enu(S());
|
616
791
|
}
|
617
792
|
|
618
793
|
void fd(const typename base_t::detection_t **out) const {*out = &(base_t::FD);}
|
@@ -878,6 +1053,46 @@ struct SBAS_SolverOptions
|
|
878
1053
|
};
|
879
1054
|
%}
|
880
1055
|
|
1056
|
+
%extend GLONASS_SolverOptions {
|
1057
|
+
%ignore base_t;
|
1058
|
+
%ignore cast_general;
|
1059
|
+
MAKE_VECTOR2ARRAY(int);
|
1060
|
+
}
|
1061
|
+
%inline %{
|
1062
|
+
template <class FloatT>
|
1063
|
+
struct GLONASS_SolverOptions
|
1064
|
+
: public GLONASS_SinglePositioning<FloatT>::options_t,
|
1065
|
+
GPS_SolverOptions_Common<FloatT> {
|
1066
|
+
typedef typename GLONASS_SinglePositioning<FloatT>::options_t base_t;
|
1067
|
+
void exclude(const int &prn){base_t::exclude_prn.set(prn);}
|
1068
|
+
void include(const int &prn){base_t::exclude_prn.reset(prn);}
|
1069
|
+
std::vector<int> excluded() const {return base_t::exclude_prn.excluded();}
|
1070
|
+
GPS_Solver_GeneralOptions<FloatT> *cast_general(){return this;}
|
1071
|
+
const GPS_Solver_GeneralOptions<FloatT> *cast_general() const {return this;}
|
1072
|
+
};
|
1073
|
+
%}
|
1074
|
+
|
1075
|
+
%header {
|
1076
|
+
template <class FloatT>
|
1077
|
+
struct GPS_RangeCorrector
|
1078
|
+
: public GPS_Solver_Base<FloatT>::range_corrector_t {
|
1079
|
+
SWIG_Object callback;
|
1080
|
+
GPS_RangeCorrector(const SWIG_Object &callback_)
|
1081
|
+
: GPS_Solver_Base<FloatT>::range_corrector_t(),
|
1082
|
+
callback(callback_) {}
|
1083
|
+
bool is_available(const typename GPS_Solver_Base<FloatT>::gps_time_t &t) const {
|
1084
|
+
return false;
|
1085
|
+
}
|
1086
|
+
FloatT *calculate(
|
1087
|
+
const typename GPS_Solver_Base<FloatT>::gps_time_t &t,
|
1088
|
+
const typename GPS_Solver_Base<FloatT>::pos_t &usr_pos,
|
1089
|
+
const typename GPS_Solver_Base<FloatT>::enu_t &sat_rel_pos,
|
1090
|
+
FloatT &buf) const {
|
1091
|
+
return NULL;
|
1092
|
+
}
|
1093
|
+
};
|
1094
|
+
}
|
1095
|
+
|
881
1096
|
%extend GPS_Solver {
|
882
1097
|
%ignore super_t;
|
883
1098
|
%ignore base_t;
|
@@ -885,10 +1100,14 @@ struct SBAS_SolverOptions
|
|
885
1100
|
%ignore gps;
|
886
1101
|
%ignore sbas_t;
|
887
1102
|
%ignore sbas;
|
1103
|
+
%ignore glonass_t;
|
1104
|
+
%ignore glonass;
|
888
1105
|
%ignore select_solver;
|
889
1106
|
%ignore relative_property;
|
890
1107
|
%ignore satellite_position;
|
891
1108
|
%ignore update_position_solution;
|
1109
|
+
%ignore user_correctors_t;
|
1110
|
+
%ignore user_correctors;
|
892
1111
|
%immutable hooks;
|
893
1112
|
%ignore mark;
|
894
1113
|
%fragment("hook"{GPS_Solver<FloatT>}, "header",
|
@@ -1033,6 +1252,38 @@ struct SBAS_SolverOptions
|
|
1033
1252
|
%fragment("correction"{GPS_Solver<FloatT>}, "header",
|
1034
1253
|
fragment=SWIG_From_frag(int),
|
1035
1254
|
fragment=SWIG_Traits_frag(FloatT)){
|
1255
|
+
template <>
|
1256
|
+
bool GPS_RangeCorrector<FloatT>::is_available(
|
1257
|
+
const typename GPS_Solver_Base<FloatT>::gps_time_t &t) const {
|
1258
|
+
VALUE values[] = {
|
1259
|
+
SWIG_NewPointerObj(
|
1260
|
+
%const_cast(&t, GPS_Time<FloatT> *), $descriptor(GPS_Time<FloatT> *), 0),
|
1261
|
+
};
|
1262
|
+
VALUE res(proc_call_throw_if_error(
|
1263
|
+
callback, sizeof(values) / sizeof(values[0]), values));
|
1264
|
+
return RTEST(res) ? true : false;
|
1265
|
+
}
|
1266
|
+
template <>
|
1267
|
+
FloatT *GPS_RangeCorrector<FloatT>::calculate(
|
1268
|
+
const typename GPS_Solver_Base<FloatT>::gps_time_t &t,
|
1269
|
+
const typename GPS_Solver_Base<FloatT>::pos_t &usr_pos,
|
1270
|
+
const typename GPS_Solver_Base<FloatT>::enu_t &sat_rel_pos,
|
1271
|
+
FloatT &buf) const {
|
1272
|
+
VALUE values[] = {
|
1273
|
+
SWIG_NewPointerObj(
|
1274
|
+
%const_cast(&t, GPS_Time<FloatT> *),
|
1275
|
+
$descriptor(GPS_Time<FloatT> *), 0),
|
1276
|
+
SWIG_NewPointerObj(
|
1277
|
+
(%const_cast(&usr_pos.xyz, System_XYZ<FloatT, WGS84> *)),
|
1278
|
+
$descriptor(System_XYZ<FloatT, WGS84> *), 0),
|
1279
|
+
SWIG_NewPointerObj(
|
1280
|
+
(%const_cast(&sat_rel_pos, System_ENU<FloatT, WGS84> *)),
|
1281
|
+
$descriptor(System_ENU<FloatT, WGS84> *), 0),
|
1282
|
+
};
|
1283
|
+
VALUE res(proc_call_throw_if_error(
|
1284
|
+
callback, sizeof(values) / sizeof(values[0]), values));
|
1285
|
+
return SWIG_IsOK(swig::asval(res, &buf)) ? &buf : NULL;
|
1286
|
+
}
|
1036
1287
|
template<>
|
1037
1288
|
VALUE GPS_Solver<FloatT>::update_correction(
|
1038
1289
|
const bool &update, const VALUE &hash){
|
@@ -1042,6 +1293,8 @@ struct SBAS_SolverOptions
|
|
1042
1293
|
ID2SYM(rb_intern("gps_tropospheric")),
|
1043
1294
|
ID2SYM(rb_intern("sbas_ionospheric")),
|
1044
1295
|
ID2SYM(rb_intern("sbas_tropospheric")),
|
1296
|
+
ID2SYM(rb_intern("glonass_ionospheric")),
|
1297
|
+
ID2SYM(rb_intern("glonass_tropospheric")),
|
1045
1298
|
};
|
1046
1299
|
static const VALUE k_opt(ID2SYM(rb_intern("options")));
|
1047
1300
|
static const VALUE k_f_10_7(ID2SYM(rb_intern("f_10_7")));
|
@@ -1075,10 +1328,12 @@ struct SBAS_SolverOptions
|
|
1075
1328
|
for(; k < sizeof(item) / sizeof(item[0]); ++k){
|
1076
1329
|
if(v == item[k].sym){break;}
|
1077
1330
|
}
|
1078
|
-
if(k >= sizeof(item) / sizeof(item[0])){
|
1079
|
-
|
1331
|
+
if(k >= sizeof(item) / sizeof(item[0])){ // other than symbol
|
1332
|
+
user_correctors.push_back(GPS_RangeCorrector<FloatT>(v));
|
1333
|
+
input[i].push_back(&user_correctors.back());
|
1334
|
+
}else{
|
1335
|
+
input[i].push_back(item[k].obj);
|
1080
1336
|
}
|
1081
|
-
input[i].push_back(item[k].obj);
|
1082
1337
|
}
|
1083
1338
|
}
|
1084
1339
|
VALUE opt(rb_hash_lookup(hash, k_opt));
|
@@ -1105,10 +1360,12 @@ struct SBAS_SolverOptions
|
|
1105
1360
|
for(; i < sizeof(item) / sizeof(item[0]); ++i){
|
1106
1361
|
if(*it2 == item[i].obj){break;}
|
1107
1362
|
}
|
1108
|
-
if(i >= sizeof(item) / sizeof(item[0])){
|
1109
|
-
|
1363
|
+
if(i >= sizeof(item) / sizeof(item[0])){ // other than built-in corrector
|
1364
|
+
rb_ary_push(v,
|
1365
|
+
reinterpret_cast<const GPS_RangeCorrector<FloatT> *>(*it2)->callback);
|
1366
|
+
}else{
|
1367
|
+
rb_ary_push(v, item[i].sym);
|
1110
1368
|
}
|
1111
|
-
rb_ary_push(v, item[i].sym);
|
1112
1369
|
}
|
1113
1370
|
rb_hash_aset(res, k, v);
|
1114
1371
|
}
|
@@ -1159,15 +1416,29 @@ struct GPS_Solver
|
|
1159
1416
|
SBAS_SinglePositioning<FloatT> solver;
|
1160
1417
|
sbas_t() : space_node(), options(), solver(space_node) {}
|
1161
1418
|
} sbas;
|
1419
|
+
struct glonass_t {
|
1420
|
+
GLONASS_SpaceNode<FloatT> space_node;
|
1421
|
+
GLONASS_SolverOptions<FloatT> options;
|
1422
|
+
GLONASS_SinglePositioning<FloatT> solver;
|
1423
|
+
glonass_t() : space_node(), options(), solver(space_node) {}
|
1424
|
+
} glonass;
|
1162
1425
|
SWIG_Object hooks;
|
1426
|
+
typedef std::vector<GPS_RangeCorrector<FloatT> > user_correctors_t;
|
1427
|
+
user_correctors_t user_correctors;
|
1163
1428
|
#ifdef SWIGRUBY
|
1164
1429
|
static void mark(void *ptr){
|
1165
1430
|
GPS_Solver<FloatT> *solver = (GPS_Solver<FloatT> *)ptr;
|
1166
|
-
if(solver->hooks == Qnil){return;}
|
1167
1431
|
rb_gc_mark(solver->hooks);
|
1432
|
+
for(typename user_correctors_t::const_iterator
|
1433
|
+
it(solver->user_correctors.begin()), it_end(solver->user_correctors.end());
|
1434
|
+
it != it_end; ++it){
|
1435
|
+
rb_gc_mark(it->callback);
|
1436
|
+
}
|
1168
1437
|
}
|
1169
1438
|
#endif
|
1170
|
-
GPS_Solver() : super_t(),
|
1439
|
+
GPS_Solver() : super_t(),
|
1440
|
+
gps(), sbas(), glonass(),
|
1441
|
+
hooks(), user_correctors() {
|
1171
1442
|
#ifdef SWIGRUBY
|
1172
1443
|
hooks = rb_hash_new();
|
1173
1444
|
#endif
|
@@ -1178,20 +1449,25 @@ struct GPS_Solver
|
|
1178
1449
|
tropospheric.push_back(&gps.solver.tropospheric_simplified);
|
1179
1450
|
gps.solver.ionospheric_correction
|
1180
1451
|
= sbas.solver.ionospheric_correction
|
1452
|
+
= glonass.solver.ionospheric_correction
|
1181
1453
|
= ionospheric;
|
1182
1454
|
gps.solver.tropospheric_correction
|
1183
1455
|
= sbas.solver.tropospheric_correction
|
1456
|
+
= glonass.solver.tropospheric_correction
|
1184
1457
|
= tropospheric;
|
1185
1458
|
}
|
1186
1459
|
GPS_SpaceNode<FloatT> &gps_space_node() {return gps.space_node;}
|
1187
1460
|
GPS_SolverOptions<FloatT> &gps_options() {return gps.options;}
|
1188
1461
|
SBAS_SpaceNode<FloatT> &sbas_space_node() {return sbas.space_node;}
|
1189
1462
|
SBAS_SolverOptions<FloatT> &sbas_options() {return sbas.options;}
|
1463
|
+
GLONASS_SpaceNode<FloatT> &glonass_space_node() {return glonass.space_node;}
|
1464
|
+
GLONASS_SolverOptions<FloatT> &glonass_options() {return glonass.options;}
|
1190
1465
|
const base_t &select_solver(
|
1191
1466
|
const typename base_t::prn_t &prn) const {
|
1192
1467
|
if(prn > 0 && prn <= 32){return gps.solver;}
|
1193
1468
|
if(prn >= 120 && prn <= 158){return sbas.solver;}
|
1194
1469
|
if(prn > 192 && prn <= 202){return gps.solver;}
|
1470
|
+
if(prn > 0x100 && prn <= (0x100 + 24)){return glonass.solver;}
|
1195
1471
|
// call order: base_t::solve => this returned by select()
|
1196
1472
|
// => relative_property() => select_solver()
|
1197
1473
|
// For not supported satellite, call loop prevention is required.
|
@@ -1219,6 +1495,8 @@ struct GPS_Solver
|
|
1219
1495
|
const_cast<gps_t &>(gps).solver.update_options(gps.options);
|
1220
1496
|
const_cast<sbas_t &>(sbas).space_node.update_all_ephemeris(receiver_time);
|
1221
1497
|
const_cast<sbas_t &>(sbas).solver.update_options(sbas.options);
|
1498
|
+
const_cast<glonass_t &>(glonass).space_node.update_all_ephemeris(receiver_time);
|
1499
|
+
const_cast<glonass_t &>(glonass).solver.update_options(glonass.options);
|
1222
1500
|
return super_t::solve().user_pvt(measurement.items, receiver_time);
|
1223
1501
|
}
|
1224
1502
|
typedef
|
@@ -1233,12 +1511,27 @@ struct GPS_Solver
|
|
1233
1511
|
&gps.solver.tropospheric_correction,
|
1234
1512
|
&sbas.solver.ionospheric_correction,
|
1235
1513
|
&sbas.solver.tropospheric_correction,
|
1514
|
+
&glonass.solver.ionospheric_correction,
|
1515
|
+
&glonass.solver.tropospheric_correction,
|
1236
1516
|
};
|
1237
1517
|
for(std::size_t i(0); i < sizeof(root) / sizeof(root[0]); ++i){
|
1238
1518
|
do{
|
1239
1519
|
if(!update){break;}
|
1240
1520
|
typename range_correction_list_t::const_iterator it(list.find(i));
|
1241
1521
|
if(it == list.end()){break;}
|
1522
|
+
|
1523
|
+
// Remove user defined unused correctors
|
1524
|
+
for(typename base_t::range_correction_t::const_iterator
|
1525
|
+
it2(root[i]->begin()), it2_end(root[i]->end());
|
1526
|
+
it2 != it2_end; ++it2){
|
1527
|
+
for(typename user_correctors_t::const_iterator
|
1528
|
+
it3(user_correctors.begin()), it3_end(user_correctors.end());
|
1529
|
+
it3 != it3_end; ++it3){
|
1530
|
+
if(*it2 != &(*it3)){continue;}
|
1531
|
+
user_correctors.erase(it3);
|
1532
|
+
}
|
1533
|
+
}
|
1534
|
+
|
1242
1535
|
root[i]->clear();
|
1243
1536
|
for(typename range_correction_list_t::mapped_type::const_iterator
|
1244
1537
|
it2(it->second.begin()), it2_end(it->second.end());
|
@@ -1396,6 +1689,10 @@ struct RINEX_Observation {};
|
|
1396
1689
|
%template(SpaceNode_SBAS) SBAS_SpaceNode<type>;
|
1397
1690
|
%template(SolverOptions_SBAS) SBAS_SolverOptions<type>;
|
1398
1691
|
|
1692
|
+
%template(SpaceNode_GLONASS) GLONASS_SpaceNode<type>;
|
1693
|
+
%template(Ephemeris_GLONASS) GLONASS_Ephemeris<type>;
|
1694
|
+
%template(SolverOptions_GLONASS) GLONASS_SolverOptions<type>;
|
1695
|
+
|
1399
1696
|
%template(RINEX_Observation) RINEX_Observation<type>;
|
1400
1697
|
%enddef
|
1401
1698
|
|
@@ -437,8 +437,6 @@ class Matrix : public Matrix_Frozen<T, Array2D_Type, ViewType> {
|
|
437
437
|
#endif
|
438
438
|
|
439
439
|
typedef Matrix<T, Array2D_Type, ViewType> self_t;
|
440
|
-
self_t &swapRows(const unsigned int &row1, const unsigned int &row2);
|
441
|
-
self_t &swapColumns(const unsigned int &column1, const unsigned int &column2);
|
442
440
|
};
|
443
441
|
|
444
442
|
%inline {
|
@@ -995,7 +993,23 @@ MAKE_TO_S(Matrix_Frozen)
|
|
995
993
|
}
|
996
994
|
#endif
|
997
995
|
|
998
|
-
|
996
|
+
/*
|
997
|
+
* Returning (*this) requires special care;
|
998
|
+
* "self_t &func(){return (*this);}" in a C++ file may generate
|
999
|
+
* a new wrapped object deleted by GC in the target language
|
1000
|
+
* unless the care.
|
1001
|
+
*
|
1002
|
+
* Work around 1)
|
1003
|
+
* %typemap(in, numinputs=0) self_t *self_p "";
|
1004
|
+
* %typemap(argout) self_t *self_p "$result = self;";
|
1005
|
+
* void func(self_t *self_p){...}
|
1006
|
+
*
|
1007
|
+
* Work around 2) (useful without overwrite of the original source, but may overfit)
|
1008
|
+
* %typemap(out) self_t & "$result = self;"
|
1009
|
+
* self_t &func(){...; return *$self;}
|
1010
|
+
*/
|
1011
|
+
%typemap(in, numinputs=0) self_t *self_p "";
|
1012
|
+
%typemap(argout) self_t *self_p "$result = self;";
|
999
1013
|
|
1000
1014
|
T &__setitem__(const unsigned int &row, const unsigned int &column, const T &value) {
|
1001
1015
|
return (($self)->operator()(row, column) = value);
|
@@ -1012,41 +1026,50 @@ MAKE_TO_S(Matrix_Frozen)
|
|
1012
1026
|
#endif
|
1013
1027
|
%rename("scalar") getScalar;
|
1014
1028
|
%rename("I") getI;
|
1015
|
-
|
1016
|
-
|
1029
|
+
|
1030
|
+
void swap_rows(
|
1031
|
+
self_t *self_p,
|
1032
|
+
const unsigned int &r1, const unsigned int &r2){
|
1033
|
+
$self->swapRows(r1, r2);
|
1034
|
+
}
|
1035
|
+
void swap_columns(
|
1036
|
+
self_t *self_p,
|
1037
|
+
const unsigned int &c1, const unsigned int &c2){
|
1038
|
+
$self->swapColumns(c1, c2);
|
1039
|
+
}
|
1017
1040
|
|
1018
1041
|
template <class T2, class Array2D_Type2, class ViewType2>
|
1019
|
-
|
1020
|
-
|
1042
|
+
void replace(
|
1043
|
+
self_t *self_p,
|
1044
|
+
const Matrix_Frozen<T2, Array2D_Type2, ViewType2> &matrix){
|
1045
|
+
$self->replace(matrix);
|
1021
1046
|
}
|
1022
1047
|
INSTANTIATE_MATRIX_FUNC(replace, replace);
|
1023
1048
|
|
1024
|
-
|
1049
|
+
void replace(self_t *self_p, const void *replacer = NULL){
|
1025
1050
|
if(!MatrixUtil::replace(*$self, replacer)){
|
1026
1051
|
throw std::runtime_error("Unsupported replacement");
|
1027
1052
|
}
|
1028
|
-
return *$self;
|
1029
1053
|
}
|
1030
1054
|
|
1031
|
-
|
1055
|
+
void replace(self_t *self_p, const T *serialized){
|
1032
1056
|
if(!MatrixUtil::replace(*$self, serialized)){
|
1033
1057
|
throw std::runtime_error("Unsupported replacement");
|
1034
1058
|
}
|
1035
|
-
return *$self;
|
1036
1059
|
}
|
1037
1060
|
|
1038
1061
|
#ifdef SWIGRUBY
|
1039
|
-
%bang
|
1040
|
-
%bang
|
1062
|
+
%bang swap_rows;
|
1063
|
+
%bang swap_columns;
|
1041
1064
|
%rename("replace!") replace;
|
1042
1065
|
|
1043
|
-
|
1066
|
+
void map_bang(
|
1067
|
+
self_t *self_p,
|
1044
1068
|
void (*each_func)(
|
1045
1069
|
const T &src, T *dst,
|
1046
1070
|
const unsigned int &i, const unsigned int &j),
|
1047
1071
|
const typename MatrixUtil::each_which_t &each_which = MatrixUtil::EACH_ALL){
|
1048
1072
|
MatrixUtil::each(*$self, each_func, each_which, $self);
|
1049
|
-
return *$self;
|
1050
1073
|
}
|
1051
1074
|
%rename("map!") map_bang;
|
1052
1075
|
%alias map_bang "collect!,map_with_index!,collect_with_index!";
|
@@ -253,6 +253,7 @@ __RINEX_OBS_TEXT__
|
|
253
253
|
t_meas = GPS::Time::new(1849, 172413)
|
254
254
|
puts "Measurement time: #{t_meas.to_a} (a.k.a #{"%d/%d/%d %02d:%02d:%02d UTC"%[*t_meas.c_tm]})"
|
255
255
|
expect(t_meas.c_tm).to eq([2015, 6, 15, 23, 53, 33])
|
256
|
+
expect(GPS::Time::new(0, t_meas.serialize)).to eq(t_meas)
|
256
257
|
|
257
258
|
sn.update_all_ephemeris(t_meas)
|
258
259
|
|
@@ -343,7 +344,12 @@ __RINEX_OBS_TEXT__
|
|
343
344
|
expect(solver.correction[:gps_tropospheric]).to include(:hopfield)
|
344
345
|
expect{solver.correction = nil}.to raise_error(RuntimeError)
|
345
346
|
expect{solver.correction = {
|
346
|
-
:gps_ionospheric => [
|
347
|
+
:gps_ionospheric => [proc{|t, usr_pos, sat_pos|
|
348
|
+
expect(t).to be_a_kind_of(GPS::Time)
|
349
|
+
expect(usr_pos).to be_a_kind_of(Coordinate::XYZ) unless usr_pos
|
350
|
+
expect(sat_pos).to be_a_kind_of(Coordinate::ENU) unless sat_pos
|
351
|
+
false
|
352
|
+
}, :klobuchar, :no_correction],
|
347
353
|
:options => {:f_10_7 => 10},
|
348
354
|
}}.not_to raise_error
|
349
355
|
expect(solver.correction[:gps_ionospheric]).to include(:no_correction)
|
@@ -214,9 +214,19 @@ shared_examples 'Matrix' do
|
|
214
214
|
it 'is swappable with swap_rows! or swap_cloumns!' do
|
215
215
|
mat_builtin = Matrix[*compare_with[0]]
|
216
216
|
[:swap_rows!, :swap_columns!].each.with_index{|func, i|
|
217
|
-
params[:rc][i].times.to_a.combination(2).to_a{|a, b|
|
218
|
-
mat[0].send(func, a, b)
|
219
|
-
|
217
|
+
params[:rc][i].times.to_a.combination(2).to_a.each{|a, b|
|
218
|
+
mat_mod = mat[0].send(func, a, b)
|
219
|
+
case func
|
220
|
+
when :swap_rows!
|
221
|
+
idxs = mat_builtin.row_count.times.to_a
|
222
|
+
idxs[a], idxs[b] = [b, a]
|
223
|
+
mat_builtin = Matrix::rows(mat_builtin.row_vectors.values_at(*idxs))
|
224
|
+
when :swap_columns!
|
225
|
+
idxs = mat_builtin.column_count.times.to_a
|
226
|
+
idxs[a], idxs[b] = [b, a]
|
227
|
+
mat_builtin = Matrix::columns(mat_builtin.column_vectors.values_at(*idxs))
|
228
|
+
end
|
229
|
+
expect(mat_mod).to equal(mat[0])
|
220
230
|
expect(mat[0].to_a).to eq(mat_builtin.to_a)
|
221
231
|
}
|
222
232
|
}
|
data/gps_pvt.gemspec
CHANGED
File without changes
|