gps_pvt 0.2.3 → 0.4.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 +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
|