gps_pvt 0.3.3 → 0.5.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.
@@ -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(