gps_pvt 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -54,6 +54,7 @@
54
54
 
55
55
  #include "GPS.h"
56
56
  #include "SBAS.h"
57
+ #include "GLONASS.h"
57
58
 
58
59
  template <class U = void>
59
60
  class RINEX_Reader {
@@ -548,6 +549,72 @@ struct RINEX_NAV {
548
549
  return eph;
549
550
  }
550
551
  };
552
+ struct message_glonass_t {
553
+ typedef typename GLONASS_SpaceNode<FloatT>
554
+ ::SatelliteProperties::Ephemeris_with_Time eph_t;
555
+ int svid;
556
+ std::tm date_tm;
557
+ int t_year4, t_year2, t_mon12;
558
+ FloatT t_sec;
559
+ FloatT tau_n_neg, gamma_n;
560
+ unsigned int t_k;
561
+ FloatT x_km, dx_km_s, ddx_km_s2;
562
+ FloatT y_km, dy_km_s, ddy_km_s2;
563
+ FloatT z_km, dz_km_s, ddz_km_s2;
564
+ unsigned int B_n, E_n;
565
+ int freq_num; // 1-24(ver.2), -7-13(ver.3)
566
+
567
+ // since ver.3.05
568
+ unsigned int status_flags, urai, health_flags;
569
+ FloatT delta_tau;
570
+
571
+ message_glonass_t(){
572
+ status_flags
573
+ = ((0x01 & 0x3) << 7) // GLONASS-M
574
+ | ((0x3) << 2); // upload/validity interval = 60 min
575
+ urai = 15; // unknown
576
+ health_flags = 0;
577
+ delta_tau = 0;
578
+ }
579
+ message_glonass_t(const eph_t &eph)
580
+ : svid((int)eph.svid),
581
+ date_tm(eph.c_tm_utc()),
582
+ t_year4(date_tm.tm_year + 1900),
583
+ t_year2(date_tm.tm_year % 100),
584
+ t_mon12(date_tm.tm_mon + 1),
585
+ t_sec(date_tm.tm_sec),
586
+ tau_n_neg(-eph.tau_n), gamma_n(eph.gamma_n), t_k(eph.t_k),
587
+ x_km(1E-3 * eph.xn), dx_km_s(1E-3 * eph.xn_dot), ddx_km_s2(1E-3 * eph.xn_ddot),
588
+ y_km(1E-3 * eph.yn), dy_km_s(1E-3 * eph.yn_dot), ddy_km_s2(1E-3 * eph.yn_ddot),
589
+ z_km(1E-3 * eph.zn), dz_km_s(1E-3 * eph.zn_dot), ddz_km_s2(1E-3 * eph.zn_ddot),
590
+ B_n(eph.B_n), E_n(eph.E_n),
591
+ freq_num(eph.freq_ch),
592
+ urai(eph.F_T_index()), delta_tau(eph.delta_tau_n) {
593
+ status_flags
594
+ = ((eph.M & 0x3) << 7)
595
+ | (eph.P4 ? 0x40 : 0)
596
+ | (eph.P2 ? 0x10 : 0)
597
+ | ((eph.P1_index() & 0x3) << 2);
598
+ health_flags = 0;
599
+ }
600
+ operator eph_t() const {
601
+ typename GLONASS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris eph = {0};
602
+ eph.svid = (unsigned int)svid;
603
+ eph.freq_ch = freq_num;
604
+ eph.tau_n = -tau_n_neg; eph.gamma_n = gamma_n; eph.t_k = t_k;
605
+ eph.xn = 1E3 * x_km; eph.xn_dot = 1E3 * dx_km_s; eph.xn_ddot = 1E3 * ddx_km_s2;
606
+ eph.yn = 1E3 * y_km; eph.yn_dot = 1E3 * dy_km_s; eph.yn_ddot = 1E3 * ddy_km_s2;
607
+ eph.zn = 1E3 * z_km; eph.zn_dot = 1E3 * dz_km_s; eph.zn_ddot = 1E3 * ddz_km_s2;
608
+ eph.B_n = B_n; eph.E_n = E_n;
609
+ eph.F_T = eph_t::Ephemeris::raw_t::F_T_value(urai);
610
+ eph.delta_tau_n = (delta_tau > 0.999999999998E+09 ? 0 : delta_tau);
611
+ eph.M = ((status_flags >> 7) & 0x3);
612
+ eph.P4 = (status_flags & 0x40);
613
+ eph.P2 = (status_flags & 0x10);
614
+ eph.P1 = eph_t::Ephemeris::raw_t::P1_value((status_flags >> 2) & 0x03);
615
+ return eph_t(eph, date_tm);
616
+ }
617
+ };
551
618
  };
552
619
 
553
620
  template <class FloatT = double>
@@ -559,6 +626,7 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
559
626
  typedef typename RINEX_NAV<FloatT>::space_node_t space_node_t;
560
627
  typedef typename RINEX_NAV<FloatT>::message_t message_t;
561
628
  typedef typename RINEX_NAV<FloatT>::message_sbas_t message_sbas_t;
629
+ typedef typename RINEX_NAV<FloatT>::message_glonass_t message_glonass_t;
562
630
  typedef typename space_node_t::Ionospheric_UTC_Parameters iono_utc_t;
563
631
 
564
632
  static const typename super_t::convert_item_t eph0_v2[10], eph0_v3[10];
@@ -575,11 +643,18 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
575
643
  static const typename super_t::convert_item_t eph2_sbas_v2[4], eph2_sbas_v3[4];
576
644
  static const typename super_t::convert_item_t eph3_sbas_v2[4], eph3_sbas_v3[4];
577
645
 
646
+ static const typename super_t::convert_item_t eph0_glonass_v2[10], eph0_glonass_v3[10];
647
+ static const typename super_t::convert_item_t eph1_glonass_v2[4], eph1_glonass_v3[4];
648
+ static const typename super_t::convert_item_t eph2_glonass_v2[4], eph2_glonass_v3[4];
649
+ static const typename super_t::convert_item_t eph3_glonass_v2[4], eph3_glonass_v3[4];
650
+ static const typename super_t::convert_item_t eph4_glonass_v305[4];
651
+
578
652
  protected:
579
653
  typename super_t::version_type_t::sat_system_t sys_of_msg;
580
654
  message_t msg;
581
655
  message_sbas_t msg_sbas;
582
-
656
+ message_glonass_t msg_glonass;
657
+
583
658
  void seek_next_v2_gps() {
584
659
  char buf[256];
585
660
 
@@ -616,9 +691,27 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
616
691
  for(int i(0); i < 4; i++){
617
692
  if((!super_t::src.good())
618
693
  || super_t::src.getline(buf, sizeof(buf)).fail()){return;}
694
+ std::string line(buf);
695
+
696
+ switch(i){
697
+ case 0: {
698
+ super_t::convert(eph0_glonass_v2, line, &msg_glonass);
699
+ msg_glonass.date_tm.tm_year = msg_glonass.t_year2 + (msg_glonass.t_year2 < 80 ? 100 : 0); // greater than 1980
700
+ msg_glonass.date_tm.tm_mon = msg_glonass.t_mon12 - 1; // month [0, 11]
701
+ msg_glonass.date_tm.tm_sec = (int)msg_glonass.t_sec;
702
+ break;
703
+ }
704
+ case 1: super_t::convert(eph1_glonass_v2, line, &msg_glonass); break;
705
+ case 2:
706
+ super_t::convert(eph2_glonass_v2, line, &msg_glonass);
707
+ if(super_t::version_type.version < 211){
708
+ //msg_glonass.freq_num; // TODO 1..24? convert to value ranging from -7 to 6?
709
+ }
710
+ break;
711
+ case 3: super_t::convert(eph3_glonass_v2, line, &msg_glonass); break;
712
+ }
619
713
  }
620
- //sys_of_msg = super_t::version_type_t::SYS_GLONASS; // TODO currently not implemented
621
- sys_of_msg = super_t::version_type_t::SYS_UNKNOWN;
714
+ sys_of_msg = super_t::version_type_t::SYS_GLONASS;
622
715
  super_t::_has_next = true;
623
716
  }
624
717
 
@@ -712,6 +805,31 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
712
805
  sys_of_msg = super_t::version_type_t::SYS_QZSS;
713
806
  }
714
807
 
808
+ template <std::size_t N>
809
+ void seek_next_v3_glonass(char (&buf)[N]) {
810
+ super_t::convert(eph0_glonass_v3, std::string(buf), &msg_glonass);
811
+ msg_glonass.date_tm.tm_year = msg_glonass.t_year4 - 1900; // tm_year base is 1900
812
+ msg_glonass.date_tm.tm_mon = msg_glonass.t_mon12 - 1; // month [0, 11]
813
+ msg_glonass.t_sec = msg_glonass.date_tm.tm_sec;
814
+
815
+ for(int i(1);
816
+ i < ((super_t::version_type.version <= 304) ? 4 : 5);
817
+ i++){
818
+ if((!super_t::src.good())
819
+ || super_t::src.getline(buf, sizeof(buf)).fail()){return;}
820
+ std::string line(buf);
821
+
822
+ switch(i){
823
+ case 1: super_t::convert(eph1_glonass_v3, line, &msg_glonass); break;
824
+ case 2: super_t::convert(eph2_glonass_v3, line, &msg_glonass); break;
825
+ case 3: super_t::convert(eph3_glonass_v3, line, &msg_glonass); break;
826
+ case 4: super_t::convert(eph4_glonass_v305, line, &msg_glonass); break;
827
+ }
828
+ }
829
+ sys_of_msg = super_t::version_type_t::SYS_GLONASS;
830
+ super_t::_has_next = true;
831
+ }
832
+
715
833
  template <std::size_t N>
716
834
  void seek_next_v3_not_implemented(char (&buf)[N], const int &lines) {
717
835
  for(int i(1); i < lines; i++){
@@ -731,7 +849,7 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
731
849
  switch(buf[0]){
732
850
  case 'G': seek_next_v3_gps(buf); return; // GPS
733
851
  case 'E': seek_next_v3_not_implemented(buf, 8); return; // Galileo
734
- case 'R': seek_next_v3_not_implemented(buf, 4); return; // Glonass
852
+ case 'R': seek_next_v3_glonass(buf); return; // Glonass
735
853
  case 'J': seek_next_v3_qzss(buf); return; // QZSS
736
854
  case 'C': seek_next_v3_not_implemented(buf, 8); return; // Beido
737
855
  case 'S': seek_next_v3_sbas(buf); return; // SBAS
@@ -839,10 +957,70 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
839
957
  return alpha && beta && utc && leap;
840
958
  }
841
959
 
960
+ struct t_corr_glonass_t {
961
+ int year, month, day;
962
+ FloatT tau_c_neg, tau_GPS; // TODO check tau_GPS polarity
963
+ int leap_sec;
964
+ };
965
+ static const typename super_t::convert_item_t t_corr_glonass_v2[4];
966
+
967
+ bool extract_t_corr_glonass_v2(t_corr_glonass_t &t_corr_glonass) const {
968
+ bool utc, leap;
969
+ super_t::header_t::const_iterator it;
970
+
971
+ if(utc = ((it = _header.find("CORR TO SYSTEM TIME")) != _header.end())){
972
+ super_t::convert(t_corr_glonass_v2, it->second.front(), &t_corr_glonass);
973
+ }
974
+
975
+ if(leap = ((it = _header.find("LEAP SECONDS")) != _header.end())){
976
+ iono_utc_t iono_utc;
977
+ super_t::convert(utc_leap_v2, it->second.front(), &iono_utc);
978
+ t_corr_glonass.leap_sec = iono_utc.delta_t_LS;
979
+ }
980
+
981
+ return utc && leap;
982
+ }
983
+
984
+ bool extract_t_corr_glonass_v3(t_corr_glonass_t &t_corr_glonass) const {
985
+ iono_utc_t iono_utc;
986
+ bool utc(false), leap(false);
987
+ typedef super_t::header_t::const_iterator it_t;
988
+ typedef super_t::header_t::mapped_type::const_iterator it2_t;
989
+
990
+ it_t it;
991
+
992
+ if((it = _header.find("TIME SYSTEM CORR")) != _header.end()){
993
+ for(it2_t it2(it->second.begin()), it2_end(it->second.end()); it2 != it2_end; ++it2){
994
+ if(it2->find("GLUT") != it2->npos){
995
+ super_t::convert(utc_v3, *it2, &iono_utc);
996
+ t_corr_glonass.year = t_corr_glonass.month = t_corr_glonass.day = 0;
997
+ t_corr_glonass.tau_c_neg = iono_utc.A0;
998
+ }else if(it2->find("GLGP") != it2->npos){
999
+ super_t::convert(utc_v3, *it2, &iono_utc);
1000
+ t_corr_glonass.tau_GPS = iono_utc.A0;
1001
+ }
1002
+ utc = true;
1003
+ }
1004
+ }
1005
+
1006
+ if((it = _header.find("LEAP SECONDS")) != _header.end()){
1007
+ if(version_type.version >= 301){
1008
+ super_t::convert(utc_leap_v301, it->second.front(), &iono_utc);
1009
+ }else{
1010
+ super_t::convert(utc_leap_v2, it->second.front(), &iono_utc);
1011
+ }
1012
+ t_corr_glonass.leap_sec = iono_utc.delta_t_LS;
1013
+ leap = true;
1014
+ }
1015
+
1016
+ return utc && leap;
1017
+ }
1018
+
842
1019
  struct space_node_list_t {
843
1020
  space_node_t *gps;
844
1021
  SBAS_SpaceNode<FloatT> *sbas;
845
1022
  space_node_t *qzss;
1023
+ GLONASS_SpaceNode<FloatT> *glonass;
846
1024
  };
847
1025
 
848
1026
  static int read_all(std::istream &in, space_node_list_t &space_nodes = {0}){
@@ -859,6 +1037,12 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
859
1037
  && (reader.version_type.version >= 302)){
860
1038
  reader.extract_iono_utc_v3(*space_nodes.qzss);
861
1039
  }
1040
+ t_corr_glonass_t t_corr_glonass = {0};
1041
+ if(space_nodes.glonass){
1042
+ (reader.version_type.version >= 300)
1043
+ ? reader.extract_t_corr_glonass_v3(t_corr_glonass)
1044
+ : reader.extract_t_corr_glonass_v2(t_corr_glonass);
1045
+ }
862
1046
  int res(0);
863
1047
  for(; reader.has_next(); reader.next()){
864
1048
  switch(reader.sys_of_msg){
@@ -881,6 +1065,17 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
881
1065
  res++;
882
1066
  break;
883
1067
  }
1068
+ case super_t::version_type_t::SYS_GLONASS: {
1069
+ if(!space_nodes.glonass){break;}
1070
+ typename message_glonass_t::eph_t eph0(reader.msg_glonass);
1071
+ eph0.tau_c = -t_corr_glonass.tau_c_neg;
1072
+ eph0.tau_GPS = t_corr_glonass.tau_GPS;
1073
+ typename GLONASS_SpaceNode<FloatT>
1074
+ ::SatelliteProperties::Ephemeris_with_GPS_Time eph(eph0, t_corr_glonass.leap_sec);
1075
+ space_nodes.glonass->satellite(reader.msg_glonass.svid).register_ephemeris(eph);
1076
+ res++;
1077
+ break;
1078
+ }
884
1079
  default: break;
885
1080
  }
886
1081
  }
@@ -1425,6 +1620,86 @@ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>
1425
1620
  };
1426
1621
 
1427
1622
 
1623
+ template <class FloatT>
1624
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph0_glonass_v2[] = {
1625
+ GEN_D( 0, 2, message_glonass_t, svid, int),
1626
+ GEN_D( 3, 2, message_glonass_t, t_year2, int),
1627
+ GEN_D( 6, 2, message_glonass_t, t_mon12, int),
1628
+ GEN_D( 9, 2, message_glonass_t, date_tm.tm_mday, int),
1629
+ GEN_D(12, 2, message_glonass_t, date_tm.tm_hour, int),
1630
+ GEN_D(15, 2, message_glonass_t, date_tm.tm_min, int),
1631
+ GEN_F(17, 5, 1, message_glonass_t, t_sec),
1632
+ GEN_E(22, 19, 12, message_glonass_t, tau_n_neg),
1633
+ GEN_E(41, 19, 12, message_glonass_t, gamma_n),
1634
+ GEN_E2(60, 19, 12, message_glonass_t, t_k, unsigned int),
1635
+ };
1636
+ template <class FloatT>
1637
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph0_glonass_v3[] = {
1638
+ GEN_I( 1, 2, message_glonass_t, svid, int),
1639
+ GEN_I( 4, 4, message_glonass_t, t_year4, int),
1640
+ GEN_I( 9, 2, message_glonass_t, t_mon12, int),
1641
+ GEN_I(12, 2, message_glonass_t, date_tm.tm_mday, int),
1642
+ GEN_I(15, 2, message_glonass_t, date_tm.tm_hour, int),
1643
+ GEN_I(18, 2, message_glonass_t, date_tm.tm_min, int),
1644
+ GEN_I(21, 2, message_glonass_t, date_tm.tm_sec, int),
1645
+ GEN_E(23, 19, 12, message_glonass_t, tau_n_neg),
1646
+ GEN_E(42, 19, 12, message_glonass_t, gamma_n),
1647
+ GEN_E2(61, 19, 12, message_glonass_t, t_k, unsigned int),
1648
+ };
1649
+
1650
+ template <class FloatT>
1651
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph1_glonass_v2[] = {
1652
+ GEN_E( 3, 19, 12, message_glonass_t, x_km),
1653
+ GEN_E(22, 19, 12, message_glonass_t, dx_km_s),
1654
+ GEN_E(41, 19, 12, message_glonass_t, ddx_km_s2),
1655
+ GEN_E2(60, 19, 12, message_glonass_t, B_n, unsigned int),
1656
+ };
1657
+ template <class FloatT>
1658
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph1_glonass_v3[] = {
1659
+ GEN_E( 4, 19, 12, message_glonass_t, x_km),
1660
+ GEN_E(23, 19, 12, message_glonass_t, dx_km_s),
1661
+ GEN_E(42, 19, 12, message_glonass_t, ddx_km_s2),
1662
+ GEN_E2(61, 19, 12, message_glonass_t, B_n, unsigned int),
1663
+ };
1664
+
1665
+ template <class FloatT>
1666
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph2_glonass_v2[] = {
1667
+ GEN_E( 3, 19, 12, message_glonass_t, y_km),
1668
+ GEN_E(22, 19, 12, message_glonass_t, dy_km_s),
1669
+ GEN_E(41, 19, 12, message_glonass_t, ddy_km_s2),
1670
+ GEN_E2(60, 19, 12, message_glonass_t, freq_num, int),
1671
+ };
1672
+ template <class FloatT>
1673
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph2_glonass_v3[] = {
1674
+ GEN_E( 4, 19, 12, message_glonass_t, y_km),
1675
+ GEN_E(23, 19, 12, message_glonass_t, dy_km_s),
1676
+ GEN_E(42, 19, 12, message_glonass_t, ddy_km_s2),
1677
+ GEN_E2(61, 19, 12, message_glonass_t, freq_num, int),
1678
+ };
1679
+
1680
+ template <class FloatT>
1681
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph3_glonass_v2[] = {
1682
+ GEN_E( 3, 19, 12, message_glonass_t, z_km),
1683
+ GEN_E(22, 19, 12, message_glonass_t, dz_km_s),
1684
+ GEN_E(41, 19, 12, message_glonass_t, ddz_km_s2),
1685
+ GEN_E2(60, 19, 12, message_glonass_t, E_n, unsigned int),
1686
+ };
1687
+ template <class FloatT>
1688
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph3_glonass_v3[] = {
1689
+ GEN_E( 4, 19, 12, message_glonass_t, z_km),
1690
+ GEN_E(23, 19, 12, message_glonass_t, dz_km_s),
1691
+ GEN_E(42, 19, 12, message_glonass_t, ddz_km_s2),
1692
+ GEN_E2(61, 19, 12, message_glonass_t, E_n, unsigned int),
1693
+ };
1694
+
1695
+ template <class FloatT>
1696
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph4_glonass_v305[] = {
1697
+ GEN_E2( 4, 19, 12, message_glonass_t, status_flags, unsigned int),
1698
+ GEN_E (23, 19, 12, message_glonass_t, delta_tau),
1699
+ GEN_E2(42, 19, 12, message_glonass_t, urai, unsigned int),
1700
+ GEN_E2(61, 19, 12, message_glonass_t, health_flags, unsigned int),
1701
+ };
1702
+
1428
1703
  template <class FloatT>
1429
1704
  const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::iono_alpha_v2[] = {
1430
1705
  GEN_E( 2, 12, 4, iono_utc_t, alpha[0]),
@@ -1487,6 +1762,14 @@ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>
1487
1762
  GEN_D(18, 6, iono_utc_t, DN, int),
1488
1763
  };
1489
1764
 
1765
+ template <class FloatT>
1766
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::t_corr_glonass_v2[] = {
1767
+ GEN_D( 0, 6, t_corr_glonass_t, year, int),
1768
+ GEN_D( 6, 6, t_corr_glonass_t, month, int),
1769
+ GEN_D(12, 6, t_corr_glonass_t, day, int),
1770
+ GEN_E(21, 19, 12, t_corr_glonass_t, tau_c_neg),
1771
+ };
1772
+
1490
1773
  template <class FloatT>
1491
1774
  const typename RINEX_OBS_Reader<FloatT>::convert_item_t RINEX_OBS_Reader<FloatT>::epoch_flag_v2[] = {
1492
1775
  GEN_I( 1, 2, epoch_flag_t, epoch_year2, int),
@@ -1724,6 +2007,7 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1724
2007
  typedef typename RINEX_NAV<FloatT>::space_node_t space_node_t;
1725
2008
  typedef typename RINEX_NAV<FloatT>::message_t message_t;
1726
2009
  typedef typename RINEX_NAV<FloatT>::message_sbas_t message_sbas_t;
2010
+ typedef typename RINEX_NAV<FloatT>::message_glonass_t message_glonass_t;
1727
2011
 
1728
2012
  static const typename super_t::header_item_t default_header[];
1729
2013
  static const int default_header_size;
@@ -1856,6 +2140,45 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1856
2140
  dist << buf.str();
1857
2141
  return *this;
1858
2142
  }
2143
+ self_t &operator<<(const message_glonass_t &msg){
2144
+ std::stringstream buf;
2145
+ switch(super_t::_version_type.version / 100){
2146
+ case 2:
2147
+ for(int i(0); i < 4; ++i){
2148
+ std::string s(80, ' ');
2149
+ switch(i){
2150
+ case 0: super_t::convert(reader_t::eph0_glonass_v2, s, &msg); break;
2151
+ case 1: super_t::convert(reader_t::eph1_glonass_v2, s, &msg); break;
2152
+ case 2:
2153
+ if(super_t::_version_type.version < 211){
2154
+ //msg_glonass.freq_num; // TODO convert to value 1..24?
2155
+ }
2156
+ super_t::convert(reader_t::eph2_glonass_v2, s, &msg);
2157
+ break;
2158
+ case 3: super_t::convert(reader_t::eph3_glonass_v2, s, &msg); break;
2159
+ }
2160
+ buf << s << std::endl;
2161
+ }
2162
+ break;
2163
+ case 3:
2164
+ for(int i(0);
2165
+ i < ((super_t::_version_type.version <= 304) ? 4 : 5);
2166
+ ++i){
2167
+ std::string s(80, ' ');
2168
+ switch(i){
2169
+ case 0: super_t::convert(reader_t::eph0_glonass_v3, s, &msg); s[0] = 'R'; break;
2170
+ case 1: super_t::convert(reader_t::eph1_glonass_v3, s, &msg); break;
2171
+ case 2: super_t::convert(reader_t::eph2_glonass_v3, s, &msg); break;
2172
+ case 3: super_t::convert(reader_t::eph3_glonass_v3, s, &msg); break;
2173
+ case 4: super_t::convert(reader_t::eph4_glonass_v305, s, &msg); break;
2174
+ }
2175
+ buf << s << std::endl;
2176
+ }
2177
+ break;
2178
+ }
2179
+ dist << buf.str();
2180
+ return *this;
2181
+ }
1859
2182
 
1860
2183
  public:
1861
2184
  void set_version(
@@ -1869,6 +2192,7 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1869
2192
  const space_node_t *gps;
1870
2193
  const SBAS_SpaceNode<FloatT> *sbas;
1871
2194
  const space_node_t *qzss;
2195
+ const GLONASS_SpaceNode<FloatT> *glonass;
1872
2196
  };
1873
2197
  int write_all(
1874
2198
  const space_node_list_t &space_nodes,
@@ -1915,6 +2239,53 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1915
2239
  break;
1916
2240
  }
1917
2241
  }while(false);
2242
+ while(space_nodes.glonass){
2243
+ ++systems;
2244
+ set_version(version, super_t::version_type_t::SYS_GLONASS);
2245
+ typename GLONASS_SpaceNode<FloatT>::Satellite::eph_t latest(
2246
+ space_nodes.glonass->latest_ephemeris());
2247
+ if(latest.t_b_gps.week <= 0){break;}
2248
+ typename reader_t::iono_utc_t iono_utc = {0};
2249
+ iono_utc.t_ot = latest.t_b_gps.seconds;
2250
+ iono_utc.WN_t = latest.t_b_gps.week;
2251
+ iono_utc.delta_t_LS = (int)std::floor(0.5
2252
+ + typename space_node_t::gps_time_t(latest.c_tm_utc()).interval(latest.t_b_gps));
2253
+ switch(version / 100){
2254
+ case 2:
2255
+ if((_header["CORR TO SYSTEM TIME"].entries() == 0) && (latest.tau_c != 0)){
2256
+ std::tm t_tm(typename space_node_t::gps_time_t(iono_utc.WN_t, iono_utc.t_ot).c_tm());
2257
+ typename reader_t::t_corr_glonass_t t_corr_glonass = {
2258
+ t_tm.tm_year + 1900, t_tm.tm_mon + 1, t_tm.tm_mday, // year, month, day
2259
+ -latest.tau_c,
2260
+ };
2261
+ std::string s(60, ' ');
2262
+ super_t::convert(reader_t::t_corr_glonass_v2, s, &t_corr_glonass);
2263
+ _header["CORR TO SYSTEM TIME"] = s;
2264
+ }
2265
+ break;
2266
+ case 3:
2267
+ if((_header["TIME SYSTEM CORR"].find("GLUT") == _header.end()) && (latest.tau_c != 0)){
2268
+ std::string s(60, ' ');
2269
+ iono_utc.A0 = -latest.tau_c;
2270
+ super_t::convert(reader_t::utc_v3, s, &iono_utc);
2271
+ _header["TIME SYSTEM CORR"] << s.replace(0, 4, "GLUT", 4);
2272
+ }
2273
+ if((_header["TIME SYSTEM CORR"].find("GLGP") == _header.end()) && (latest.tau_GPS != 0)){
2274
+ std::string s(60, ' ');
2275
+ iono_utc.A0 = latest.tau_GPS;
2276
+ super_t::convert(reader_t::utc_v3, s, &iono_utc);
2277
+ _header["TIME SYSTEM CORR"] << s.replace(0, 4, "GLGP", 4);
2278
+ }
2279
+ break;
2280
+ }
2281
+ if((_header["LEAP SECONDS"].entries() == 0) && (iono_utc.delta_t_LS != 0)){
2282
+ // ver.3 can use ver.2 format with blank fields
2283
+ std::string s(60, ' ');
2284
+ super_t::convert(reader_t::utc_leap_v2, s, &iono_utc);
2285
+ _header["LEAP SECONDS"] = s;
2286
+ }
2287
+ break;
2288
+ }
1918
2289
  if(systems > 1){
1919
2290
  set_version(version, super_t::version_type_t::SYS_MIXED);
1920
2291
  }
@@ -1939,6 +2310,10 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1939
2310
  w << message_sbas_t(eph);
1940
2311
  counter++;
1941
2312
  }
2313
+ void operator()(const typename message_glonass_t::eph_t &eph) {
2314
+ w << message_glonass_t(eph);
2315
+ counter++;
2316
+ }
1942
2317
  } functor = {*this, res, false, false};
1943
2318
  if(space_nodes.gps){
1944
2319
  functor.gps = true;
@@ -1972,6 +2347,16 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1972
2347
  space_node_t::Satellite::eph_list_t::EACH_ALL_INVERTED);
1973
2348
  }
1974
2349
  }
2350
+ if(space_nodes.glonass){
2351
+ for(typename GLONASS_SpaceNode<FloatT>::satellites_t::const_iterator
2352
+ it(space_nodes.glonass->satellites().begin()),
2353
+ it_end(space_nodes.glonass->satellites().end());
2354
+ it != it_end; ++it){
2355
+ it->second.each_ephemeris(
2356
+ functor,
2357
+ GLONASS_SpaceNode<FloatT>::Satellite::eph_list_t::EACH_ALL_INVERTED);
2358
+ }
2359
+ }
1975
2360
  return res;
1976
2361
  }
1977
2362
  static int write_all(