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.
@@ -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 proxy_t::linear_solver_t::rotate_S(S(), base_t::user_position.ecef2enu());
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 linear_solver().slope_HV(S());
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 linear_solver().slope_HV(S(), base_t::user_position.ecef2enu());
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
- continue; // TODO other than symbol
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
- continue; // TODO other than built-in corrector
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(), gps(), sbas(), hooks() {
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
- %typemap(out) self_t & "$result = self;"
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
- %rename("swap_rows") swapRows;
1016
- %rename("swap_columns") swapColumns;
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
- self_t &replace(const Matrix_Frozen<T2, Array2D_Type2, ViewType2> &matrix){
1020
- return $self->replace(matrix);
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
- self_t &replace(const void *replacer = NULL){
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
- self_t &replace(const T *serialized){
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 swapRows(const unsigned int &, const unsigned int &);
1040
- %bang swapColumns(const unsigned int &, const unsigned int &);
1062
+ %bang swap_rows;
1063
+ %bang swap_columns;
1041
1064
  %rename("replace!") replace;
1042
1065
 
1043
- self_t &map_bang(
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 => [:klobuchar, :no_correction],
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
- mat_builtin.send(func, a, b)
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