[hamradio-commits] [gnss-sdr] 39/126: working on the RTCM printer
Carles Fernandez
carles_fernandez-guest at moszumanska.debian.org
Sat Dec 26 18:37:59 UTC 2015
This is an automated email from the git hooks/post-receive script.
carles_fernandez-guest pushed a commit to branch next
in repository gnss-sdr.
commit 60dd9b4f282de06a2d7c1df4c88fbc79287bb277
Author: Carles Fernandez <carles.fernandez at gmail.com>
Date: Sat Nov 21 13:01:50 2015 +0100
working on the RTCM printer
---
src/algorithms/PVT/libs/rtcm_printer.cc | 304 +---
src/algorithms/PVT/libs/rtcm_printer.h | 166 +--
src/core/system_parameters/CMakeLists.txt | 1 +
src/core/system_parameters/galileo_ephemeris.cc | 2 +
src/core/system_parameters/galileo_ephemeris.h | 2 +
src/core/system_parameters/galileo_fnav_message.cc | 8 +-
src/core/system_parameters/galileo_fnav_message.h | 4 +-
src/core/system_parameters/rtcm.cc | 1577 ++++++++++++++++++++
src/core/system_parameters/rtcm.h | 416 ++++++
src/tests/gnss_block/rtcm_printer_test.cc | 83 ++
10 files changed, 2148 insertions(+), 415 deletions(-)
diff --git a/src/algorithms/PVT/libs/rtcm_printer.cc b/src/algorithms/PVT/libs/rtcm_printer.cc
index 1c84239..5183144 100644
--- a/src/algorithms/PVT/libs/rtcm_printer.cc
+++ b/src/algorithms/PVT/libs/rtcm_printer.cc
@@ -34,18 +34,11 @@
#include "rtcm_printer.h"
#include <fcntl.h> // for O_RDWR
#include <termios.h> // for tcgetattr
-#include <algorithm> // for std::reverse
-#include <sstream> // for std::stringstream
-#include <boost/algorithm/string.hpp> // for to_upper_copy
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/dynamic_bitset.hpp>
#include <gflags/gflags.h>
#include <glog/logging.h>
-
using google::LogMessage;
-//DEFINE_string(RTCM_version, "3.2", "Specifies the RTCM Version");
Rtcm_Printer::Rtcm_Printer(std::string filename, bool flag_rtcm_tty_port, std::string rtcm_dump_devname)
{
@@ -69,9 +62,7 @@ Rtcm_Printer::Rtcm_Printer(std::string filename, bool flag_rtcm_tty_port, std::s
{
rtcm_dev_descriptor = -1;
}
- Rtcm_Printer::reset_data_fields();
- preamble = std::bitset<8>("11010011");
- reserved_field = std::bitset<6>("000000");
+ rtcm = std::make_shared<Rtcm>();
}
@@ -93,6 +84,27 @@ Rtcm_Printer::~Rtcm_Printer()
}
+bool Rtcm_Printer::Print_Rtcm_M1001(const Gps_Ephemeris& gps_eph, double obs_time, const std::map<int, Gnss_Synchro> & pseudoranges)
+{
+ std::string m1001 = rtcm->print_M1001( gps_eph, obs_time, pseudoranges);
+ Rtcm_Printer::Print_Message(m1001);
+ return true;
+}
+
+bool Rtcm_Printer::Print_Rtcm_M1019(const Gps_Ephemeris & gps_eph)
+{
+ std::string m1019 = rtcm->print_M1019(gps_eph);
+ Rtcm_Printer::Print_Message(m1019);
+ return true;
+}
+
+bool Rtcm_Printer::Print_Rtcm_M1045(const Galileo_Ephemeris & gal_eph)
+{
+ std::string m1045 = rtcm->print_M1045(gal_eph);
+ Rtcm_Printer::Print_Message(m1045);
+ return true;
+}
+
int Rtcm_Printer::init_serial(std::string serial_device)
{
@@ -140,255 +152,39 @@ void Rtcm_Printer::close_serial()
}
}
-void Rtcm_Printer::reset_data_fields()
-{
- //DF001.reset();
- DF002.reset();
- DF003.reset();
- DF004.reset();
- DF005.reset();
- DF006.reset();
- DF007.reset();
- DF008.reset();
- DF009.reset();
- DF010.reset();
- DF011.reset();
- DF012.reset();
- DF013.reset();
- DF014.reset();
- DF015.reset();
-
- // Contents of GPS Satellite Ephemeris Data, Message Type 1019
- DF071.reset();
- DF076.reset();
- DF077.reset();
- DF078.reset();
- DF079.reset();
- DF081.reset();
- DF082.reset();
- DF083.reset();
- DF084.reset();
- DF085.reset();
- DF086.reset();
- DF087.reset();
-
- DF088.reset();
- DF089.reset();
- DF090.reset();
- DF091.reset();
- DF092.reset();
- DF093.reset();
- DF094.reset();
- DF095.reset();
- DF096.reset();
- DF097.reset();
- DF098.reset();
- DF099.reset();
- DF100.reset();
- DF101.reset();
- DF102.reset();
- DF103.reset();
- DF137.reset();
-
- // Contents of Galileo F/NAV Satellite Ephemeris Data, Message Type 1045
- DF252.reset();
- DF289.reset();
- DF290.reset();
- DF291.reset();
- DF292.reset();
- DF293.reset();
- DF294.reset();
- DF295.reset();
- DF296.reset();
- DF297.reset();
- DF298.reset();
- DF299.reset();
- DF300.reset();
- DF301.reset();
- DF302.reset();
- DF303.reset();
- DF304.reset();
- DF305.reset();
- DF306.reset();
- DF307.reset();
- DF308.reset();
- DF309.reset();
- DF310.reset();
- DF311.reset();
- DF312.reset();
- DF314.reset();
- DF315.reset();
-}
-
-/* Stationary Antenna Reference Point, No Height Information
- * Reference Station Id = 2003
- GPS Service supported, but not GLONASS or Galileo
- ARP ECEF-X = 1114104.5999 meters
- ARP ECEF-Y = -4850729.7108 meters
- ARP ECEF-Z = 3975521.4643 meters
- Expected output: D3 00 13 3E D7 D3 02 02 98 0E DE EF 34 B4 BD 62
- AC 09 41 98 6F 33 36 0B 98
- */
-std::bitset<152> Rtcm_Printer::get_M1005_test ()
-{
- unsigned int m1005 = 1005;
- unsigned int reference_station_id = 2003; // Max: 4095
- long long int ECEF_X = 11141045999; // Resolution 0.0001 m
- long long int ECEF_Y = -48507297108; // Resolution 0.0001 m
- long long int ECEF_Z = 39755214643; // Resolution 0.0001 m
- unsigned int itrf_realization_year = 0; // Reserved
- std::bitset<1> DF001;
-
- DF002 = std::bitset<12>(m1005);
- DF003 = std::bitset<12>(reference_station_id);
- DF021 = std::bitset<6>(itrf_realization_year);
- DF022 = std::bitset<1>("1"); // GPS
- DF023 = std::bitset<1>("0"); // Glonass
- DF024 = std::bitset<1>("0"); // Galileo
- DF141 = std::bitset<1>("0"); // 0: Real, physical reference station
- DF001 = std::bitset<1>("0"); // Reserved, set to 0
- DF025 = std::bitset<38>(ECEF_X); // ECEF-X in 0.0001 m
- DF142 = std::bitset<1>("0"); // Single Receiver Oscillator Indicator
- DF026 = std::bitset<38>(ECEF_Y); // ECEF-Y in 0.0001 m
- DF364 = std::bitset<2>("00"); // Quarter Cycle Indicator
- DF027 = std::bitset<38>(ECEF_Z); // ECEF-Z in 0.0001 m
-
- std::string message = DF002.to_string() +
- DF003.to_string() +
- DF021.to_string() +
- DF022.to_string() +
- DF023.to_string() +
- DF024.to_string() +
- DF141.to_string() +
- DF025.to_string() +
- DF142.to_string() +
- DF001.to_string() +
- DF026.to_string() +
- DF364.to_string() +
- DF027.to_string() ;
-
- std::bitset<152> test_msg(message);
- return test_msg;
-}
-
-
-
-std::string Rtcm_Printer::print_M1005_test ()
-{
- std::bitset<152> m1005 = get_M1005_test();
- unsigned int msg_length_bits = m1005.to_string().length();
- unsigned int msg_length_bytes = std::ceil(static_cast<float>(msg_length_bits) / 8.0);
- message_length = std::bitset<10>(msg_length_bytes);
- unsigned int zeros_to_fill = 8*msg_length_bytes - msg_length_bits;
- std::string b(zeros_to_fill, '0');
- std::string msg_content = m1005.to_string() + b;
- std::string msg_without_crc = preamble.to_string() +
- reserved_field.to_string() +
- message_length.to_string() +
- msg_content;
- return Rtcm_Printer::add_CRC(msg_without_crc);
-}
-
-
-
-std::bitset<122> Rtcm_Printer::get_M1001()
+bool Rtcm_Printer::Print_Message(std::string message)
{
- unsigned int m1001 = 1001;
- unsigned int reference_station_id = 1234; // Max: 4095
- DF002 = std::bitset<12>(m1001);
- DF003 = std::bitset<12>(reference_station_id);
- //DF004 = std::bitset<30>
- //DF005 = std::bitset<1>
- //DF006 = std::bitset<5>
- DF007 = std::bitset<1>("0");
- //DF008 = std::bitset<3>
- std::bitset<122> fake_msg;
- fake_msg.reset();
- return fake_msg;
-}
-
-
-
-void Rtcm_Printer::print_M1001 ()
-{
- std::bitset<122> m1001 = get_M1001();
- unsigned int msg_length_bits = m1001.to_string().length();
- unsigned int msg_length_bytes = std::ceil(static_cast<float>(msg_length_bits) / 8.0);
- message_length = std::bitset<10>(msg_length_bytes);
- unsigned int zeros_to_fill = 8*msg_length_bytes - msg_length_bits;
- std::string b(zeros_to_fill, '0');
- message_length = std::bitset<10>(static_cast<int>(msg_length_bytes));
- std::string msg_content = m1001.to_string() + b;
- std::string msg_without_crc = preamble.to_string() +
- reserved_field.to_string() +
- message_length.to_string() +
- msg_content;
- std::string message = Rtcm_Printer::add_CRC(msg_without_crc);
-}
-
-
-
-std::bitset<138> Rtcm_Printer::get_M1002 ()
-{
- std::bitset<138> fake_msg;
- fake_msg.reset();
- return fake_msg;
-}
-
-std::bitset<488> Rtcm_Printer::get_M1019 ()
-{
- std::bitset<488> fake_msg;
- fake_msg.reset();
- return fake_msg;
-}
-
-
-
-std::bitset<496> Rtcm_Printer::get_M1045 ()
-{
- std::bitset<496> fake_msg;
- fake_msg.reset();
- return fake_msg;
-}
-
-
-
-
-
-std::string Rtcm_Printer::add_CRC (const std::string& message_without_crc)
-{
- // ****** Computes Qualcomm CRC-24Q ******
- // 1) Converts the string to a vector of unsigned char:
- boost::dynamic_bitset<unsigned char> frame_bits(message_without_crc);
- std::vector<unsigned char> bytes;
- boost::to_block_range(frame_bits, std::back_inserter(bytes));
- std::reverse(bytes.begin(),bytes.end());
-
- // 2) Computes CRC
- CRC_RTCM.process_bytes(bytes.data(), bytes.size());
- crc_frame = std::bitset<24>(CRC_RTCM.checksum());
-
- // 3) Builds the complete message
- std::string complete_message = message_without_crc + crc_frame.to_string();
- return bin_to_hex(complete_message);
-}
-
-
-std::string Rtcm_Printer::bin_to_hex(const std::string& s)
-{
- std::string s_aux;
- std::stringstream ss;
- for(int i = 0; i < s.length() - 1; i = i + 32)
+ try
+ {
+ rtcm_file_descriptor << message << std::endl;
+
+ }
+ catch(std::exception ex)
+ {
+ DLOG(INFO) << "RTCM printer can not write on output file" << rtcm_filename.c_str();
+ }
+
+ //write to serial device
+ if (rtcm_dev_descriptor!=-1)
{
- s_aux.assign(s, i, 32);
- std::bitset<32> bs(s_aux);
- unsigned n = bs.to_ulong();
- ss << std::hex << n;
+ try
+ {
+ int n_bytes_written;
+ n_bytes_written = write(rtcm_dev_descriptor, message.c_str(), message.length());
+ }
+ catch(std::exception ex)
+ {
+ DLOG(INFO) << "RTCM printer can not write on serial device" << rtcm_filename.c_str();;
+ }
}
- //return ss.str();
- return boost::to_upper_copy(ss.str());
+ return true;
}
+std::string Rtcm_Printer::print_M1005_test()
+{
+ std::string test = rtcm->print_M1005_test();
+ return test;
+}
diff --git a/src/algorithms/PVT/libs/rtcm_printer.h b/src/algorithms/PVT/libs/rtcm_printer.h
index 2ce08dc..bc0a540 100644
--- a/src/algorithms/PVT/libs/rtcm_printer.h
+++ b/src/algorithms/PVT/libs/rtcm_printer.h
@@ -34,13 +34,9 @@
#ifndef GNSS_SDR_RTCM_PRINTER_H_
#define GNSS_SDR_RTCM_PRINTER_H_
-#include <bitset> // std::bitset
#include <fstream> // std::ofstream
#include <iostream> // std::cout
-#include <string> // std::string
-#include <vector>
-#include <boost/crc.hpp>
-
+#include "rtcm.h"
/*!
* \brief This class provides a implementation of a subset of the RTCM Standard 10403.2 messages
@@ -54,169 +50,25 @@ public:
Rtcm_Printer(std::string filename, bool flag_rtcm_tty_port, std::string rtcm_dump_filename);
/*!
- * \brief Print RTCM 3.2 messages to the initialized device
- */
- //bool Print_Nmea_Line(gps_l1_ca_ls_pvt* position, bool print_average_values);
-
- /*!
* \brief Default destructor.
*/
~Rtcm_Printer();
- void print_M1001();
- std::string print_M1005_test();
+ bool Print_Rtcm_M1001(const Gps_Ephemeris& gps_eph, double obs_time, const std::map<int, Gnss_Synchro> & pseudoranges);
+ bool Print_Rtcm_M1019(const Gps_Ephemeris & gps_eph); //<! GPS Ephemeris, should be broadcast in the event that the IODC does not match the IODE, and every 2 minutes.
+ bool Print_Rtcm_M1045(const Galileo_Ephemeris & gal_eph); //<! Galileo Ephemeris, should be broadcast every 2 minutes
+
+ std::string print_M1005_test(); //<! For testing purposes
+
private:
std::string rtcm_filename; // String with the RTCM log filename
std::ofstream rtcm_file_descriptor; // Output file stream for RTCM log file
std::string rtcm_devname;
int rtcm_dev_descriptor; // RTCM serial device descriptor (i.e. COM port)
- //gps_l1_ca_ls_pvt* d_PVT_data;
int init_serial (std::string serial_device); //serial port control
void close_serial ();
-
- //std::bitset<8> DF001;
- std::bitset<12> DF002;
- std::bitset<12> DF003;
- std::bitset<30> DF004;
- std::bitset<1> DF005;
- std::bitset<5> DF006;
- std::bitset<1> DF007;
- std::bitset<3> DF008;
- std::bitset<6> DF009;
- std::bitset<1> DF010;
- std::bitset<24> DF011;
- std::bitset<20> DF012;
- std::bitset<7> DF013;
- std::bitset<8> DF014;
- std::bitset<8> DF015;
-
-
- std::bitset<6> DF021;
- std::bitset<1> DF022;
- std::bitset<1> DF023;
- std::bitset<1> DF024;
- std::bitset<38> DF025;
- std::bitset<38> DF026;
- std::bitset<38> DF027;
-
- // Contents of GPS Satellite Ephemeris Data, Message Type 1019
- std::bitset<8> DF071;
- std::bitset<10> DF076;
- std::bitset<4> DF077;
- std::bitset<2> DF078;
- std::bitset<14> DF079;
- std::bitset<16> DF081;
- std::bitset<8> DF082;
- std::bitset<16> DF083;
- std::bitset<22> DF084;
- std::bitset<10> DF085;
- std::bitset<16> DF086;
- std::bitset<16> DF087;
-
- std::bitset<32> DF088;
- std::bitset<16> DF089;
- std::bitset<32> DF090;
- std::bitset<16> DF091;
- std::bitset<32> DF092;
- std::bitset<16> DF093;
- std::bitset<16> DF094;
- std::bitset<32> DF095;
- std::bitset<16> DF096;
- std::bitset<32> DF097;
- std::bitset<16> DF098;
- std::bitset<32> DF099;
- std::bitset<24> DF100;
- std::bitset<8> DF101;
- std::bitset<6> DF102;
- std::bitset<1> DF103;
- std::bitset<1> DF137;
-
-
- std::bitset<1> DF141;
- std::bitset<1> DF142;
-
- // Contents of Galileo F/NAV Satellite Ephemeris Data, Message Type 1045
- std::bitset<6> DF252;
- std::bitset<12> DF289;
- std::bitset<10> DF290;
- std::bitset<8> DF291;
- std::bitset<14> DF292;
- std::bitset<14> DF293;
- std::bitset<6> DF294;
- std::bitset<21> DF295;
- std::bitset<31> DF296;
- std::bitset<16> DF297;
- std::bitset<32> DF298;
- std::bitset<14> DF299;
- std::bitset<16> DF300;
- std::bitset<32> DF301;
- std::bitset<16> DF302;
- std::bitset<32> DF303;
- std::bitset<14> DF304;
- std::bitset<16> DF305;
- std::bitset<32> DF306;
- std::bitset<16> DF307;
- std::bitset<32> DF308;
- std::bitset<16> DF309;
- std::bitset<32> DF310;
- std::bitset<24> DF311;
- std::bitset<10> DF312;
- std::bitset<2> DF314;
- std::bitset<1> DF315;
-
- std::bitset<2> DF364;
-
- // Content of message header for MSM1, MSM2, MSM3, MSM4, MSM5, MSM6 and MSM7
- std::bitset<1> DF393;
- std::bitset<1> DF394;
- std::bitset<1> DF395;
- std::bitset<1> DF396; //variable
- std::bitset<1> DF409;
- std::bitset<1> DF411;
- std::bitset<1> DF412;
- std::bitset<1> DF417;
- std::bitset<1> DF418;
-
- // Content of Satellite data for MSM4 and MSM6
- std::vector<std::bitset<8> > DF397; // 8*NSAT
- std::vector<std::bitset<10> > DF398; // 10*NSAT
-
- // Content of Satellite data for MSM5 and MSM7
- std::vector<std::bitset<14> > DF399; // 14*NSAT
-
- // Messages
- std::bitset<64> message1001_header;
- std::bitset<58> message1001_content;
- std::bitset<64> message1002_header;
- std::bitset<74> message1002_content;
-
- std::bitset<488> message1019_content;
-
- std::bitset<496> message1045_content;
-
- std::bitset<169> MSM_header; // 169+X
-
- std::vector<std::bitset<18> > MSM4_content; // 18 * Nsat
-
- std::vector<std::bitset<36> > MSM5_content; // 36 * Nsat
-
- std::bitset<122> get_M1001();
- std::bitset<138> get_M1002(); // GPS observables
- std::bitset<488> get_M1019(); // GPS ephemeris
- std::bitset<496> get_M1045(); // Galileo ephemeris
- std::bitset<152> get_M1005_test();
-
- void reset_data_fields ();
-
- // Transport Layer
- std::bitset<8> preamble;
- std::bitset<6> reserved_field;
- std::bitset<10> message_length;
- std::bitset<24> crc_frame;
- typedef boost::crc_optimal<24, 0x1864CFBu, 0x0, 0x0, false, false> crc_24_q_type;
- crc_24_q_type CRC_RTCM;
- std::string add_CRC(const std::string& m);
- std::string bin_to_hex(const std::string& s);
+ std::shared_ptr<Rtcm> rtcm;
+ bool Print_Message(std::string message);
};
#endif
diff --git a/src/core/system_parameters/CMakeLists.txt b/src/core/system_parameters/CMakeLists.txt
index bc6949d..e46e1ad 100644
--- a/src/core/system_parameters/CMakeLists.txt
+++ b/src/core/system_parameters/CMakeLists.txt
@@ -41,6 +41,7 @@ set(SYSTEM_PARAMETERS_SOURCES
gps_cnav_navigation_message.cc
gps_cnav_iono.cc
gps_cnav_utc_model.cc
+ rtcm.cc
)
diff --git a/src/core/system_parameters/galileo_ephemeris.cc b/src/core/system_parameters/galileo_ephemeris.cc
index b69a40d..bff3ded 100644
--- a/src/core/system_parameters/galileo_ephemeris.cc
+++ b/src/core/system_parameters/galileo_ephemeris.cc
@@ -63,8 +63,10 @@ Galileo_Ephemeris::Galileo_Ephemeris()
TOW_5 = 0;
// SV status
SISA_3 = 0;
+ E5a_HS = 0;
E5b_HS_5 = 0;
E1B_HS_5 = 0;
+ E5a_DVS = false;
E5b_DVS_5 = 0;
E1B_DVS_5 = 0;
BGD_E1E5a_5 = 0; // E1-E5a Broadcast Group Delay [s]
diff --git a/src/core/system_parameters/galileo_ephemeris.h b/src/core/system_parameters/galileo_ephemeris.h
index c206973..61b6afc 100644
--- a/src/core/system_parameters/galileo_ephemeris.h
+++ b/src/core/system_parameters/galileo_ephemeris.h
@@ -85,8 +85,10 @@ public:
// SV status
double SISA_3;
+ unsigned int E5a_HS; //!< E5a Signal Health Status
double E5b_HS_5; //!< E5b Signal Health Status
double E1B_HS_5; //!< E1B Signal Health Status
+ bool E5a_DVS; //!< E5a Data Validity Status
double E5b_DVS_5; //!< E5b Data Validity Status
double E1B_DVS_5; //!< E1B Data Validity Status
diff --git a/src/core/system_parameters/galileo_fnav_message.cc b/src/core/system_parameters/galileo_fnav_message.cc
index 776e4d5..e8a34ad 100644
--- a/src/core/system_parameters/galileo_fnav_message.cc
+++ b/src/core/system_parameters/galileo_fnav_message.cc
@@ -270,10 +270,10 @@ void Galileo_Fnav_Message::decode_page(std::string data)
FNAV_region5_1 = static_cast<bool>(read_navigation_unsigned(data_bits, FNAV_region5_1_bit));
FNAV_BGD_1 = static_cast<double>(read_navigation_signed(data_bits, FNAV_BGD_1_bit));
FNAV_BGD_1 *= FNAV_BGD_1_LSB;
- FNAV_E5ahs_1 = static_cast<double>(read_navigation_unsigned(data_bits, FNAV_E5ahs_1_bit));
+ FNAV_E5ahs_1 = static_cast<unsigned int>(read_navigation_unsigned(data_bits, FNAV_E5ahs_1_bit));
FNAV_WN_1 = static_cast<double>(read_navigation_unsigned(data_bits, FNAV_WN_1_bit));
FNAV_TOW_1 = static_cast<double>(read_navigation_unsigned(data_bits, FNAV_TOW_1_bit));
- FNAV_E5advs_1 = static_cast<double>(read_navigation_unsigned(data_bits, FNAV_E5advs_1_bit));
+ FNAV_E5advs_1 = static_cast<bool>(read_navigation_unsigned(data_bits, FNAV_E5advs_1_bit));
flag_TOW_1 = true;
flag_TOW_set = true;
@@ -628,6 +628,10 @@ Galileo_Ephemeris Galileo_Fnav_Message::get_ephemeris()
/*GST*/
ephemeris.WN_5 = FNAV_WN_3; // Week number
ephemeris.TOW_5 = FNAV_TOW_3; // Time of Week
+
+ /* Health status */
+ ephemeris.E5a_HS = FNAV_E5ahs_1;
+ ephemeris.E5a_DVS = FNAV_E5advs_1;
return ephemeris;
}
diff --git a/src/core/system_parameters/galileo_fnav_message.h b/src/core/system_parameters/galileo_fnav_message.h
index 6e39809..4534735 100644
--- a/src/core/system_parameters/galileo_fnav_message.h
+++ b/src/core/system_parameters/galileo_fnav_message.h
@@ -127,7 +127,7 @@ public:
double FNAV_E5ahs_1;
double FNAV_WN_1;
double FNAV_TOW_1;
- double FNAV_E5advs_1;
+ bool FNAV_E5advs_1;
// WORD 2 Ephemeris (1/3) and GST
int FNAV_IODnav_2;
@@ -186,7 +186,7 @@ public:
double FNAV_M0_1_5;
double FNAV_af0_1_5;
double FNAV_af1_1_5;
- double FNAV_E5ahs_1_5;
+ unsigned int FNAV_E5ahs_1_5;
int FNAV_SVID2_5;
double FNAV_Deltaa12_2_5;
double FNAV_e_2_5;
diff --git a/src/core/system_parameters/rtcm.cc b/src/core/system_parameters/rtcm.cc
new file mode 100644
index 0000000..6a0a2c3
--- /dev/null
+++ b/src/core/system_parameters/rtcm.cc
@@ -0,0 +1,1577 @@
+/*!
+ * \file rtcm.cc
+ * \brief Implementation of RTCM 3.2 Standard
+ * \author Carles Fernandez-Prades, 2015. cfernandez(at)cttc.es
+ *
+ * -------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
+ *
+ * GNSS-SDR is a software defined Global Navigation
+ * Satellite Systems receiver
+ *
+ * This file is part of GNSS-SDR.
+ *
+ * GNSS-SDR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNSS-SDR is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include "rtcm.h"
+#include <algorithm> // for std::reverse
+#include <cstdlib> // for strtol
+#include <sstream> // for std::stringstream
+#include <boost/algorithm/string.hpp> // for to_upper_copy
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/dynamic_bitset.hpp>
+#include <gflags/gflags.h>
+#include <glog/logging.h>
+#include "GPS_L1_CA.h"
+
+
+
+using google::LogMessage;
+
+DEFINE_int32(RTCM_Ref_Station_ID, 1234, "Reference Station ID in RTCM messages");
+
+
+
+Rtcm::Rtcm()
+{
+ Rtcm::reset_data_fields();
+ preamble = std::bitset<8>("11010011");
+ reserved_field = std::bitset<6>("000000");
+}
+
+
+
+
+// *****************************************************************************************************
+//
+// TRANSPORT LAYER AS DEFINED AT RTCM STANDARD 10403.2
+//
+// *****************************************************************************************************
+
+std::string Rtcm::add_CRC (const std::string& message_without_crc)
+{
+ // ****** Computes Qualcomm CRC-24Q ******
+ // 1) Converts the string to a vector of unsigned char:
+ boost::dynamic_bitset<unsigned char> frame_bits(message_without_crc);
+ std::vector<unsigned char> bytes;
+ boost::to_block_range(frame_bits, std::back_inserter(bytes));
+ std::reverse(bytes.begin(),bytes.end());
+
+ // 2) Computes CRC
+ CRC_RTCM.process_bytes(bytes.data(), bytes.size());
+ crc_frame = std::bitset<24>(CRC_RTCM.checksum());
+
+ // 3) Builds the complete message
+ std::string complete_message = message_without_crc + crc_frame.to_string();
+ return bin_to_hex(complete_message);
+}
+
+
+bool Rtcm::check_CRC(const std::string & message)
+{
+ // Convert message to binary
+ std::string message_bin = Rtcm::hex_to_bin(message);
+ // Check CRC
+ std::string crc = message_bin.substr(message_bin.length() - 24, 24);
+ std::bitset<24> read_crc = std::bitset<24>(crc);
+ std::string msg_without_crc = message_bin.substr(0, message_bin.length() - 24);
+
+ boost::dynamic_bitset<unsigned char> frame_bits(msg_without_crc);
+ std::vector<unsigned char> bytes;
+ boost::to_block_range(frame_bits, std::back_inserter(bytes));
+ std::reverse(bytes.begin(),bytes.end());
+
+ CRC_RTCM.process_bytes(bytes.data(), bytes.size());
+ std::bitset<24> computed_crc = std::bitset<24>(CRC_RTCM.checksum());
+ if(read_crc == computed_crc)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+std::string Rtcm::bin_to_hex(const std::string& s)
+{
+ std::string s_aux;
+ std::stringstream ss;
+ for(int i = 0; i < s.length() - 1; i = i + 32)
+ {
+ s_aux.assign(s, i, 32);
+ std::bitset<32> bs(s_aux);
+ unsigned n = bs.to_ulong();
+ ss << std::hex << n;
+ }
+ return boost::to_upper_copy(ss.str());
+}
+
+std::string Rtcm::hex_to_bin(const std::string& s)
+{
+ std::string s_aux;
+ s_aux.clear();
+ std::stringstream ss;
+ ss << s;
+ std::string s_lower = boost::to_upper_copy(ss.str());
+ for(int i = 0; i < s.length(); i++)
+ {
+ unsigned long int n;
+ std::istringstream(s_lower.substr(i,1)) >> std::hex >> n;
+ std::bitset<4> bs(n);
+ s_aux += bs.to_string();
+ }
+ return s_aux;
+}
+
+unsigned long int Rtcm::bin_to_uint(const std::string& s)
+{
+ if(s.length() > 32)
+ {
+ LOG(WARNING) << "Cannot convert to a unsigned long int";
+ return 0;
+ }
+ unsigned long int reading = strtoul(s.c_str(), NULL, 2);
+ return reading;
+}
+
+long int Rtcm::bin_to_int(const std::string& s)
+{
+ if(s.length() > 32)
+ {
+ LOG(WARNING) << "Cannot convert to a long int";
+ return 0;
+ }
+ long int reading = strtol(s.c_str(), NULL, 2);
+ return reading;
+}
+
+
+double Rtcm::bin_to_double(const std::string& s)
+{
+ double reading;
+ if(s.length() > 64)
+ {
+ LOG(WARNING) << "Cannot convert to a double";
+ return 0;
+ }
+
+ long long int reading_int = strtoll(s.c_str(), NULL, 2);
+
+ // Handle negative numbers
+ if(s.substr(0,1).compare("0"))
+ {
+ // Computing two's complement
+ boost::dynamic_bitset<> original_bitset(s);
+ original_bitset.flip();
+ reading_int = - (original_bitset.to_ulong() + 1);
+ }
+
+ reading = static_cast<double>(reading_int);
+ return reading;
+}
+
+
+unsigned long int Rtcm::hex_to_uint(const std::string& s)
+{
+ if(s.length() > 32)
+ {
+ LOG(WARNING) << "Cannot convert to a unsigned long int";
+ return 0;
+ }
+ unsigned long int reading = strtoul(s.c_str(), NULL, 16);
+ return reading;
+}
+
+
+long int Rtcm::hex_to_int(const std::string& s)
+{
+ if(s.length() > 32)
+ {
+ LOG(WARNING) << "Cannot convert to a long int";
+ return 0;
+ }
+ long int reading = strtol(s.c_str(), NULL, 16);
+ return reading;
+}
+
+
+std::string Rtcm::build_message(std::string data)
+{
+ unsigned int msg_length_bits = data.length();
+ unsigned int msg_length_bytes = std::ceil(static_cast<float>(msg_length_bits) / 8.0);
+ message_length = std::bitset<10>(msg_length_bytes);
+ unsigned int zeros_to_fill = 8 * msg_length_bytes - msg_length_bits;
+ std::string b(zeros_to_fill, '0');
+ std::string msg_content = data + b;
+ std::string msg_without_crc = preamble.to_string() +
+ reserved_field.to_string() +
+ message_length.to_string() +
+ msg_content;
+ return Rtcm::add_CRC(msg_without_crc);
+}
+
+
+
+// *****************************************************************************************************
+//
+// MESSAGES AS DEFINED AT RTCM STANDARD 10403.2
+//
+// *****************************************************************************************************
+
+
+/* Stationary Antenna Reference Point, No Height Information
+ * Reference Station Id = 2003
+ GPS Service supported, but not GLONASS or Galileo
+ ARP ECEF-X = 1114104.5999 meters
+ ARP ECEF-Y = -4850729.7108 meters
+ ARP ECEF-Z = 3975521.4643 meters
+ Expected output: D3 00 13 3E D7 D3 02 02 98 0E DE EF 34 B4 BD 62
+ AC 09 41 98 6F 33 36 0B 98
+ */
+std::bitset<152> Rtcm::get_M1005_test ()
+{
+ unsigned int m1005 = 1005;
+ unsigned int reference_station_id = 2003; // Max: 4095
+ double ECEF_X = 1114104.5999; // units: m
+ double ECEF_Y = -4850729.7108; // units: m
+ double ECEF_Z = 3975521.4643; // units: m
+
+ std::bitset<1> DF001_;
+
+ Rtcm::set_DF002(m1005);
+ Rtcm::set_DF003(reference_station_id);
+ Rtcm::set_DF021();
+ Rtcm::set_DF022(true); // GPS
+ Rtcm::set_DF023(false); // Glonass
+ Rtcm::set_DF024(false); // Galileo
+ DF141 = std::bitset<1>("0"); // 0: Real, physical reference station
+ DF001_ = std::bitset<1>("0"); // Reserved, set to 0
+ Rtcm::set_DF025(ECEF_X);
+ DF142 = std::bitset<1>("0"); // Single Receiver Oscillator Indicator
+ Rtcm::set_DF026(ECEF_Y);
+ DF364 = std::bitset<2>("00"); // Quarter Cycle Indicator
+ Rtcm::set_DF027(ECEF_Z);
+
+ std::string message = DF002.to_string() +
+ DF003.to_string() +
+ DF021.to_string() +
+ DF022.to_string() +
+ DF023.to_string() +
+ DF024.to_string() +
+ DF141.to_string() +
+ DF025.to_string() +
+ DF142.to_string() +
+ DF001_.to_string() +
+ DF026.to_string() +
+ DF364.to_string() +
+ DF027.to_string() ;
+
+ std::bitset<152> test_msg(message);
+ return test_msg;
+}
+
+
+int Rtcm::read_M1005(const std::string & message, unsigned int & ref_id, double & ecef_x, double & ecef_y, double & ecef_z, bool & gps, bool & glonass, bool & galileo)
+{
+ // Convert message to binary
+ std::string message_bin = Rtcm::hex_to_bin(message);
+
+ if(!Rtcm::check_CRC(message) )
+ {
+ LOG(WARNING) << " Bad CRC detected in RTCM message M1005";
+ std::cout << " ----- Bad CRC detected in RTCM message M1005 " << std::endl;
+ return 1;
+ }
+
+ // Check than the message number is correct
+ unsigned int preamble_length = 8;
+ unsigned int reserved_field_length = 6;
+ unsigned int index = preamble_length + reserved_field_length;
+
+ unsigned int read_message_length = static_cast<unsigned int>(Rtcm::bin_to_uint(message_bin.substr(index, 10)));
+ index += 10;
+ if (read_message_length != 19)
+ {
+ LOG(WARNING) << " Message M1005 seems too long (19 bytes expected, " << read_message_length << " received)";
+ std::cout << " -----Message M1005 seems too long (19 bytes expected, " << read_message_length << " received)" << std::endl;
+ return 1;
+ }
+
+ unsigned int msg_number = 1005;
+ Rtcm::set_DF002(msg_number);
+ std::bitset<12> read_msg_number(message_bin.substr(index, 12));
+ index += 12;
+
+ if (DF002 != read_msg_number)
+ {
+ LOG(WARNING) << " This is not a M1005 message";
+ std::cout << " ----- This is not a M1005 message"<< std::endl;
+ return 1;
+ }
+
+
+ ref_id = Rtcm::bin_to_uint(message_bin.substr(index, 12));
+ index += 12;
+
+ index += 6; // ITRF year
+ gps = static_cast<bool>(Rtcm::bin_to_uint(message_bin.substr(index, 1)));
+ index += 1;
+
+ glonass = static_cast<bool>(Rtcm::bin_to_uint(message_bin.substr(index, 1)));
+ index += 1;
+
+ galileo = static_cast<bool>(Rtcm::bin_to_uint(message_bin.substr(index, 1)));
+ index += 1;
+
+ index += 1; // ref_sattion_indicator
+
+ ecef_x = Rtcm::bin_to_double(message_bin.substr(index, 38)) / 10000.0;
+ index += 38;
+
+ index += 1; // single rx oscillator
+ index += 1; // reserved
+
+ ecef_y = Rtcm::bin_to_double(message_bin.substr(index, 38)) / 10000.0;
+ index += 38;
+
+ index += 2; // quarter cycle indicator
+ ecef_z = Rtcm::bin_to_double(message_bin.substr(index, 38)) / 10000.0;
+
+ return 0;
+}
+
+
+std::string Rtcm::print_M1005_test()
+{
+ std::bitset<152> m1005 = get_M1005_test();
+ return Rtcm::build_message(m1005.to_string());
+}
+
+
+std::bitset<64> Rtcm::get_M1001_header(const Gps_Ephemeris & gps_eph, double obs_time, const std::map<int, Gnss_Synchro> & pseudoranges,
+ unsigned int ref_id, unsigned int smooth_int, bool sync_flag, bool divergence_free)
+{
+ unsigned int m1001 = 1001;
+ unsigned int reference_station_id = ref_id; // Max: 4095
+ const std::map<int, Gnss_Synchro> pseudoranges_ = pseudoranges;
+ bool synchronous_GNSS_flag = sync_flag;
+ bool divergence_free_smoothing_indicator = divergence_free;
+ unsigned int smoothing_interval = smooth_int;
+ Rtcm::set_DF002(m1001);
+ Rtcm::set_DF003(reference_station_id);
+ Rtcm::set_DF004(gps_eph, obs_time);
+ Rtcm::set_DF005(synchronous_GNSS_flag);
+ Rtcm::set_DF006(pseudoranges_);
+ Rtcm::set_DF007(divergence_free_smoothing_indicator);
+ Rtcm::set_DF008(smoothing_interval);
+
+ std::string header = DF002.to_string() +
+ DF003.to_string() +
+ DF004.to_string() +
+ DF005.to_string() +
+ DF006.to_string() +
+ DF007.to_string() +
+ DF008.to_string();
+
+ std::bitset<64> header_msg(header);
+ return header_msg;
+}
+
+
+std::bitset<58> Rtcm::get_M1001_sat_content(const Gnss_Synchro & gnss_synchro)
+{
+ Gnss_Synchro gnss_synchro_ = gnss_synchro;
+ bool code_indicator = false; // code indicator 0: C/A code 1: P(Y) code direct
+ Rtcm::set_DF009(gnss_synchro_);
+ Rtcm::set_DF010(code_indicator); // code indicator 0: C/A code 1: P(Y) code direct
+ Rtcm::set_DF011(gnss_synchro_);
+
+ long int gps_L1_phaserange_minus_L1_pseudorange;
+ long int phaserange_m = (gnss_synchro.Carrier_phase_rads * GPS_C_m_s) / (GPS_TWO_PI * GPS_L1_FREQ_HZ);
+ gps_L1_phaserange_minus_L1_pseudorange = phaserange_m; // TODO
+ DF012 = std::bitset<20>(gps_L1_phaserange_minus_L1_pseudorange);
+
+ unsigned int lock_time_indicator = 0; // TODO
+ DF013 = std::bitset<7>(lock_time_indicator);
+
+ std::string content = DF009.to_string() +
+ DF010.to_string() +
+ DF011.to_string() +
+ DF012.to_string() +
+ DF013.to_string();
+
+ std::bitset<58> content_msg(content);
+ return content_msg;
+}
+
+
+
+std::string Rtcm::print_M1001(const Gps_Ephemeris & gps_eph, double obs_time, const std::map<int, Gnss_Synchro> & pseudoranges)
+{
+ unsigned int ref_id = static_cast<unsigned int>(FLAGS_RTCM_Ref_Station_ID);
+ unsigned int smooth_int = 0;
+ bool sync_flag = false;
+ bool divergence_free = false;
+
+ std::bitset<64> header = Rtcm::get_M1001_header(gps_eph, obs_time, pseudoranges, ref_id, smooth_int, sync_flag, divergence_free);
+ std::string data = header.to_string();
+
+ std::map<int, Gnss_Synchro>::const_iterator pseudoranges_iter;
+ for(pseudoranges_iter = pseudoranges.begin();
+ pseudoranges_iter != pseudoranges.end();
+ pseudoranges_iter++)
+ {
+
+ std::bitset<58> content = Rtcm::get_M1001_sat_content(pseudoranges_iter->second);
+ data += content.to_string();
+ }
+
+ return Rtcm::build_message(data);
+}
+
+
+
+std::string Rtcm::print_M1019(const Gps_Ephemeris & gps_eph)
+{
+ unsigned int msg_number = 1019;
+
+ Rtcm::set_DF002(msg_number);
+ Rtcm::set_DF009(gps_eph);
+ Rtcm::set_DF076(gps_eph);
+ Rtcm::set_DF077(gps_eph);
+ Rtcm::set_DF078(gps_eph);
+ Rtcm::set_DF079(gps_eph);
+ Rtcm::set_DF071(gps_eph);
+ Rtcm::set_DF081(gps_eph);
+ Rtcm::set_DF082(gps_eph);
+ Rtcm::set_DF083(gps_eph);
+ Rtcm::set_DF084(gps_eph);
+ Rtcm::set_DF085(gps_eph);
+ Rtcm::set_DF086(gps_eph);
+ Rtcm::set_DF087(gps_eph);
+ Rtcm::set_DF088(gps_eph);
+ Rtcm::set_DF089(gps_eph);
+ Rtcm::set_DF090(gps_eph);
+ Rtcm::set_DF091(gps_eph);
+ Rtcm::set_DF092(gps_eph);
+ Rtcm::set_DF093(gps_eph);
+ Rtcm::set_DF094(gps_eph);
+ Rtcm::set_DF095(gps_eph);
+ Rtcm::set_DF096(gps_eph);
+ Rtcm::set_DF097(gps_eph);
+ Rtcm::set_DF098(gps_eph);
+ Rtcm::set_DF099(gps_eph);
+ Rtcm::set_DF100(gps_eph);
+ Rtcm::set_DF101(gps_eph);
+ Rtcm::set_DF102(gps_eph);
+ Rtcm::set_DF103(gps_eph);
+ Rtcm::set_DF137(gps_eph);
+
+ std::string data;
+ data.clear();
+ data = DF002.to_string() +
+ DF009.to_string() +
+ DF076.to_string() +
+ DF077.to_string() +
+ DF078.to_string() +
+ DF079.to_string() +
+ DF071.to_string() +
+ DF081.to_string() +
+ DF082.to_string() +
+ DF083.to_string() +
+ DF084.to_string() +
+ DF085.to_string() +
+ DF086.to_string() +
+ DF087.to_string() +
+ DF088.to_string() +
+ DF089.to_string() +
+ DF090.to_string() +
+ DF091.to_string() +
+ DF092.to_string() +
+ DF093.to_string() +
+ DF094.to_string() +
+ DF095.to_string() +
+ DF096.to_string() +
+ DF097.to_string() +
+ DF098.to_string() +
+ DF099.to_string() +
+ DF100.to_string() +
+ DF101.to_string() +
+ DF102.to_string() +
+ DF103.to_string() +
+ DF137.to_string();
+
+ if (data.length() != 488)
+ {
+ LOG(WARNING) << "Bad-formatted RTCM M1019 (488 bits expected, found " << data.length() << ")";
+ }
+
+ message1019_content = std::bitset<488>(data);
+ std::string message = build_message(data);
+ return message;
+}
+
+
+int Rtcm::read_M1019(const std::string & message, Gps_Ephemeris & gps_eph)
+{
+ // Convert message to binary
+ std::string message_bin = Rtcm::hex_to_bin(message);
+
+ if(!Rtcm::check_CRC(message) )
+ {
+ LOG(WARNING) << " Bad CRC detected in RTCM message M1019";
+ std::cout << " ----- Bad CRC detected in RTCM message M1019 " << std::endl;
+ return 1;
+ }
+
+ unsigned int preamble_length = 8;
+ unsigned int reserved_field_length = 6;
+ unsigned int index = preamble_length + reserved_field_length - 1;
+
+ unsigned int read_message_length = static_cast<unsigned int>(Rtcm::bin_to_uint(message_bin.substr(index, 10)));
+ index += 10;
+
+ if (read_message_length != 61)
+ {
+ LOG(WARNING) << " Message M1019 seems too long (61 bytes expected, " << read_message_length << " received)";
+ return 1;
+ }
+
+ // Check than the message number is correct
+ unsigned int msg_number = 1019;
+ Rtcm::set_DF002(msg_number);
+ std::bitset<12> read_msg_number(message_bin.substr(index, 12));
+ index += 12;
+
+ if (DF002 != read_msg_number)
+ {
+ LOG(WARNING) << " This is not a M1019 message";
+ return 1;
+ }
+
+ gps_eph.i_satellite_PRN = static_cast<unsigned int>(Rtcm::bin_to_uint(message_bin.substr(index, 6)));
+ index += 6;
+
+ // idea: define get_DFXXX?
+
+// Rtcm::set_DF002(msg_number);
+// Rtcm::set_DF009(gps_eph);
+// Rtcm::set_DF076(gps_eph);
+// Rtcm::set_DF077(gps_eph);
+// Rtcm::set_DF078(gps_eph);
+// Rtcm::set_DF079(gps_eph);
+// Rtcm::set_DF071(gps_eph);
+// Rtcm::set_DF081(gps_eph);
+// Rtcm::set_DF082(gps_eph);
+// Rtcm::set_DF083(gps_eph);
+// Rtcm::set_DF084(gps_eph);
+// Rtcm::set_DF085(gps_eph);
+// Rtcm::set_DF086(gps_eph);
+// Rtcm::set_DF087(gps_eph);
+// Rtcm::set_DF088(gps_eph);
+// Rtcm::set_DF089(gps_eph);
+// Rtcm::set_DF090(gps_eph);
+// Rtcm::set_DF091(gps_eph);
+// Rtcm::set_DF092(gps_eph);
+// Rtcm::set_DF093(gps_eph);
+// Rtcm::set_DF094(gps_eph);
+// Rtcm::set_DF095(gps_eph);
+// Rtcm::set_DF096(gps_eph);
+// Rtcm::set_DF097(gps_eph);
+// Rtcm::set_DF098(gps_eph);
+// Rtcm::set_DF099(gps_eph);
+// Rtcm::set_DF100(gps_eph);
+// Rtcm::set_DF101(gps_eph);
+// Rtcm::set_DF102(gps_eph);
+// Rtcm::set_DF103(gps_eph);
+// Rtcm::set_DF137(gps_eph);
+
+
+ return 0;
+}
+
+
+std::string Rtcm::print_M1045(const Galileo_Ephemeris & gal_eph)
+{
+ unsigned int msg_number = 1045;
+
+ Rtcm::set_DF002(msg_number);
+ Rtcm::set_DF252(gal_eph);
+ Rtcm::set_DF289(gal_eph);
+ Rtcm::set_DF290(gal_eph);
+ Rtcm::set_DF291(gal_eph);
+ Rtcm::set_DF293(gal_eph);
+ Rtcm::set_DF294(gal_eph);
+ Rtcm::set_DF295(gal_eph);
+ Rtcm::set_DF296(gal_eph);
+ Rtcm::set_DF297(gal_eph);
+ Rtcm::set_DF298(gal_eph);
+ Rtcm::set_DF299(gal_eph);
+ Rtcm::set_DF300(gal_eph);
+ Rtcm::set_DF301(gal_eph);
+ Rtcm::set_DF302(gal_eph);
+ Rtcm::set_DF303(gal_eph);
+ Rtcm::set_DF304(gal_eph);
+ Rtcm::set_DF305(gal_eph);
+ Rtcm::set_DF306(gal_eph);
+ Rtcm::set_DF307(gal_eph);
+ Rtcm::set_DF308(gal_eph);
+ Rtcm::set_DF309(gal_eph);
+ Rtcm::set_DF310(gal_eph);
+ Rtcm::set_DF311(gal_eph);
+ Rtcm::set_DF312(gal_eph);
+ Rtcm::set_DF314(gal_eph);
+ Rtcm::set_DF315(gal_eph);
+ unsigned int seven_zero = 0;
+ std::bitset<7> DF001_ = std::bitset<7>(seven_zero);
+
+ std::string data;
+ data.clear();
+ data = DF002.to_string() +
+ DF252.to_string() +
+ DF289.to_string() +
+ DF290.to_string() +
+ DF291.to_string() +
+ DF292.to_string() +
+ DF293.to_string() +
+ DF294.to_string() +
+ DF295.to_string() +
+ DF296.to_string() +
+ DF297.to_string() +
+ DF298.to_string() +
+ DF299.to_string() +
+ DF300.to_string() +
+ DF301.to_string() +
+ DF302.to_string() +
+ DF303.to_string() +
+ DF304.to_string() +
+ DF305.to_string() +
+ DF306.to_string() +
+ DF307.to_string() +
+ DF308.to_string() +
+ DF309.to_string() +
+ DF310.to_string() +
+ DF311.to_string() +
+ DF312.to_string() +
+ DF314.to_string() +
+ DF315.to_string() +
+ DF001_.to_string();
+
+ if (data.length() != 496)
+ {
+ LOG(WARNING) << "Bad-formatted RTCM M1045 (496 bits expected, found " << data.length() << ")";
+ }
+ message1045_content = std::bitset<496>(data);
+ std::string message = build_message(data);
+ return message;
+}
+
+
+
+std::bitset<138> Rtcm::get_M1002 ()
+{
+ std::bitset<138> fake_msg;
+ fake_msg.reset();
+ return fake_msg;
+}
+
+
+
+
+
+// *****************************************************************************************************
+//
+// DATA FIELDS AS DEFINED AT RTCM STANDARD 10403.2
+//
+// *****************************************************************************************************
+
+int Rtcm::reset_data_fields()
+{
+ //DF001.reset();
+ DF002.reset();
+ DF003.reset();
+ DF004.reset();
+ DF005.reset();
+ DF006.reset();
+ DF007.reset();
+ DF008.reset();
+ DF009.reset();
+ DF010.reset();
+ DF011.reset();
+ DF012.reset();
+ DF013.reset();
+ DF014.reset();
+ DF015.reset();
+
+ // Contents of GPS Satellite Ephemeris Data, Message Type 1019
+ DF071.reset();
+ DF076.reset();
+ DF077.reset();
+ DF078.reset();
+ DF079.reset();
+ DF081.reset();
+ DF082.reset();
+ DF083.reset();
+ DF084.reset();
+ DF085.reset();
+ DF086.reset();
+ DF087.reset();
+
+ DF088.reset();
+ DF089.reset();
+ DF090.reset();
+ DF091.reset();
+ DF092.reset();
+ DF093.reset();
+ DF094.reset();
+ DF095.reset();
+ DF096.reset();
+ DF097.reset();
+ DF098.reset();
+ DF099.reset();
+ DF100.reset();
+ DF101.reset();
+ DF102.reset();
+ DF103.reset();
+ DF137.reset();
+
+ // Contents of Galileo F/NAV Satellite Ephemeris Data, Message Type 1045
+ DF252.reset();
+ DF289.reset();
+ DF290.reset();
+ DF291.reset();
+ DF292.reset();
+ DF293.reset();
+ DF294.reset();
+ DF295.reset();
+ DF296.reset();
+ DF297.reset();
+ DF298.reset();
+ DF299.reset();
+ DF300.reset();
+ DF301.reset();
+ DF302.reset();
+ DF303.reset();
+ DF304.reset();
+ DF305.reset();
+ DF306.reset();
+ DF307.reset();
+ DF308.reset();
+ DF309.reset();
+ DF310.reset();
+ DF311.reset();
+ DF312.reset();
+ DF314.reset();
+ DF315.reset();
+
+ DF364.reset();
+
+ DF393.reset();
+ DF394.reset();
+ DF395.reset();
+
+ DF409.reset();
+
+ DF411.reset();
+ DF412.reset();
+ DF417.reset();
+ DF418.reset();
+
+ return 0;
+}
+
+
+int Rtcm::set_DF002(unsigned int message_number)
+{
+ if (message_number > 4095)
+ {
+ LOG(WARNING) << "RTCM message number must be between 0 and 4095, but it has been set to " << message_number;
+ }
+ DF002 = std::bitset<12>(message_number);
+ return 0;
+}
+
+
+int Rtcm::set_DF003(unsigned int ref_station_ID)
+{
+ //unsigned int station_ID = ref_station_ID;
+ if (ref_station_ID > 4095)
+ {
+ LOG(WARNING) << "RTCM reference station ID must be between 0 and 4095, but it has been set to " << ref_station_ID;
+ }
+ DF003 = std::bitset<12>(ref_station_ID);
+ return 0;
+}
+
+
+int Rtcm::set_DF004(const Gps_Ephemeris & gps_eph, double obs_time)
+{
+ // TOW in milliseconds from the beginning of the GPS week, measured in GPS time
+ unsigned long int tow = static_cast<unsigned long int>(std::round((obs_time + 604800 * static_cast<double>(gps_eph.i_GPS_week % 1024)) * 1000));
+ if(tow > 604799999)
+ {
+ LOG(WARNING) << "To large TOW! Set to the last millisecond of the week";
+ tow = 604799999;
+ }
+ DF004 = std::bitset<30>(tow);
+ return 0;
+}
+
+
+int Rtcm::set_DF005(bool sync_flag)
+{
+ // 0 - No further GNSS observables referenced to the same Epoch Time will be transmitted. This enables the receiver to begin processing
+ // the data immediately after decoding the message.
+ // 1 - The next message will contain observables of another GNSS source referenced to the same Epoch Time.
+ DF005 = std::bitset<1>(sync_flag);
+ return 0;
+}
+
+
+int Rtcm::set_DF006(const std::map<int, Gnss_Synchro> & pseudoranges)
+{
+ //Number of satellites observed in current epoch
+ unsigned short int nsats = 0;
+ std::map<int, Gnss_Synchro>::const_iterator pseudoranges_iter;
+ for(pseudoranges_iter = pseudoranges.begin();
+ pseudoranges_iter != pseudoranges.end();
+ pseudoranges_iter++)
+ {
+ nsats++;
+ }
+ if (nsats > 31)
+ {
+ LOG(WARNING) << "The number of processed GPS satellites must be between 0 and 31, but it seems that you are processing " << nsats;
+ nsats = 31;
+ }
+ DF006 = std::bitset<5>(nsats);
+ return 0;
+}
+
+
+int Rtcm::set_DF007(bool divergence_free_smoothing_indicator)
+{
+ // 0 - Divergence-free smoothing not used 1 - Divergence-free smoothing used
+ DF007 = std::bitset<1>(divergence_free_smoothing_indicator);
+ return 0;
+}
+
+
+int Rtcm::set_DF008(short int smoothing_interval)
+{
+ std::bitset<3> DF008_ = std::bitset<3>(smoothing_interval);
+ return 0;
+}
+
+
+int Rtcm::set_DF009(const Gnss_Synchro & gnss_synchro)
+{
+ unsigned int prn_ = gnss_synchro.PRN;
+ if(prn_ > 31)
+ {
+ LOG(WARNING) << "GPS satellite ID must be between 0 and 31, but PRN " << prn_ << " was found";
+ }
+ DF009 = std::bitset<6>(prn_);
+ return 0;
+}
+
+
+int Rtcm::set_DF009(const Gps_Ephemeris & gps_eph)
+{
+ unsigned int prn_ = gps_eph.i_satellite_PRN;
+ if(prn_ > 31)
+ {
+ LOG(WARNING) << "GPS satellite ID must be between 0 and 31, but PRN " << prn_ << " was found";
+ }
+ DF009 = std::bitset<6>(prn_);
+ return 0;
+}
+
+
+int Rtcm::set_DF010(bool code_indicator)
+{
+ DF010 = std::bitset<1>(code_indicator);
+ return 0;
+}
+
+
+int Rtcm::set_DF011(const Gnss_Synchro & gnss_synchro)
+{
+ unsigned long int gps_L1_pseudorange = static_cast<long unsigned int>(std::round(std::fmod(gnss_synchro.Pseudorange_m, 299792.458) / 0.02 ));
+ DF011 = std::bitset<24>(gps_L1_pseudorange);
+ return 0;
+}
+
+
+int Rtcm::set_DF012(const Gnss_Synchro & gnss_synchro)
+{
+ double L1_pseudorange = gnss_synchro.Pseudorange_m;
+ double L1_pseudorange_integers = std::floor(L1_pseudorange / 299792.458);
+ double L1_pseudorange_field = std::fmod(L1_pseudorange, 299792.458);
+
+ long int gps_L1_phaserange_minus_L1_pseudorange = 0; ///////////////////////
+ DF012 = std::bitset<20>(gps_L1_phaserange_minus_L1_pseudorange);
+ return 0;
+}
+
+
+int Rtcm::set_DF014(const Gnss_Synchro & gnss_synchro)
+{
+ unsigned int gps_L1_pseudorange_ambiguity = static_cast<unsigned int>(std::floor(gnss_synchro.Pseudorange_m / 299792.458));
+ DF014 = std::bitset<8>(gps_L1_pseudorange_ambiguity);
+ return 0;
+}
+
+
+int Rtcm::set_DF015(const Gnss_Synchro & gnss_synchro)
+{
+ double CN0_dB_Hz_est = gnss_synchro.CN0_dB_hz;
+ if (CN0_dB_Hz_est > 63.75)
+ {
+ CN0_dB_Hz_est = 63.75;
+ }
+ unsigned int CN0_dB_Hz = static_cast<unsigned int>(std::round(CN0_dB_Hz_est / 0.25 ));
+ DF015 = std::bitset<8>(CN0_dB_Hz);
+ return 0;
+}
+
+
+int Rtcm::set_DF021()
+{
+ unsigned short int itfr_year = 0;
+ DF021 = std::bitset<6>(itfr_year);
+ return 0;
+}
+
+
+int Rtcm::set_DF022(bool gps_indicator)
+{
+ DF022 = std::bitset<1>(gps_indicator);
+ return 0;
+}
+
+
+int Rtcm::set_DF023(bool glonass_indicator)
+{
+ DF023 = std::bitset<1>(glonass_indicator);
+ return 0;
+}
+
+
+int Rtcm::set_DF024(bool galileo_indicator)
+{
+ DF024 = std::bitset<1>(galileo_indicator);
+ return 0;
+}
+
+
+int Rtcm::set_DF025(double antenna_ECEF_X_m)
+{
+ long long int ant_ref_x = static_cast<long long int>(std::round( antenna_ECEF_X_m * 10000));
+ DF025 = std::bitset<38>(ant_ref_x);
+ return 0;
+}
+
+
+int Rtcm::set_DF026(double antenna_ECEF_Y_m)
+{
+ long long int ant_ref_y = static_cast<long long int>(std::round( antenna_ECEF_Y_m * 10000));
+ DF026 = std::bitset<38>(ant_ref_y);
+ return 0;
+}
+
+
+int Rtcm::set_DF027(double antenna_ECEF_Z_m)
+{
+ long long int ant_ref_z = static_cast<long long int>(std::round( antenna_ECEF_Z_m * 10000));
+ DF027 = std::bitset<38>(ant_ref_z);
+ return 0;
+}
+
+
+int Rtcm::set_DF071(const Gps_Ephemeris & gps_eph)
+{
+ unsigned int iode = static_cast<unsigned int>(gps_eph.d_IODE_SF2);
+ DF071 = std::bitset<8>(iode);
+ return 0;
+}
+
+
+int Rtcm::set_DF076(const Gps_Ephemeris & gps_eph)
+{
+ unsigned int week_number = static_cast<unsigned int>(gps_eph.i_GPS_week);
+ DF076 = std::bitset<10>(week_number);
+ return 0;
+}
+
+
+int Rtcm::set_DF077(const Gps_Ephemeris & gps_eph)
+{
+ unsigned short int ura = static_cast<unsigned short int>(gps_eph.i_SV_accuracy);
+ DF077 = std::bitset<4>(ura);
+ return 0;
+}
+
+
+int Rtcm::set_DF078(const Gps_Ephemeris & gps_eph)
+{
+ unsigned short int code_on_L2 = static_cast<unsigned short int>(gps_eph.i_code_on_L2);
+ DF078 = std::bitset<2>(code_on_L2);
+ return 0;
+}
+
+
+int Rtcm::set_DF079(const Gps_Ephemeris & gps_eph)
+{
+ unsigned int idot = static_cast<unsigned int>(std::round(gps_eph.d_IDOT / I_DOT_LSB ));
+ DF079 = std::bitset<14>(idot);
+ return 0;
+}
+
+
+int Rtcm::set_DF080(const Gps_Ephemeris & gps_eph)
+{
+ unsigned short int iode = static_cast<unsigned short int>(gps_eph.d_IODE_SF2);
+ DF080 = std::bitset<8>(iode);
+ return 0;
+}
+
+
+int Rtcm::set_DF081(const Gps_Ephemeris & gps_eph)
+{
+ unsigned int toc = static_cast<unsigned int>(std::round(gps_eph.d_Toc / T_OC_LSB ));
+ DF081 = std::bitset<16>(toc);
+ return 0;
+}
+
+
+int Rtcm::set_DF082(const Gps_Ephemeris & gps_eph)
+{
+ short int af2 = static_cast<short int>(std::round(gps_eph.d_A_f2 / A_F2_LSB ));
+ DF082 = std::bitset<8>(af2);
+ return 0;
+}
+
+
+int Rtcm::set_DF083(const Gps_Ephemeris & gps_eph)
+{
+ int af1 = static_cast<int>(std::round(gps_eph.d_A_f1 / A_F1_LSB ));
+ DF083 = std::bitset<16>(af1);
+ return 0;
+}
+
+
+int Rtcm::set_DF084(const Gps_Ephemeris & gps_eph)
+{
+ long int af0 = static_cast<long int>(std::round(gps_eph.d_A_f0 / A_F0_LSB ));
+ DF084 = std::bitset<22>(af0);
+ return 0;
+}
+
+
+int Rtcm::set_DF085(const Gps_Ephemeris & gps_eph)
+{
+ unsigned int iodc = static_cast<unsigned int>(gps_eph.d_IODC);
+ DF085 = std::bitset<10>(iodc);
+ return 0;
+}
+
+
+int Rtcm::set_DF086(const Gps_Ephemeris & gps_eph)
+{
+ int crs = static_cast<int>(std::round(gps_eph.d_Crs / C_RS_LSB ));
+ DF086 = std::bitset<16>(crs);
+ return 0;
+}
+
+
+int Rtcm::set_DF087(const Gps_Ephemeris & gps_eph)
+{
+ int delta_n = static_cast<int>(std::round(gps_eph.d_Delta_n / DELTA_N_LSB ));
+ DF087 = std::bitset<16>(delta_n);
+ return 0;
+}
+
+
+int Rtcm::set_DF088(const Gps_Ephemeris & gps_eph)
+{
+ long int m0 = static_cast<long int>(std::round(gps_eph.d_M_0 / M_0_LSB ));
+ DF088 = std::bitset<32>(m0);
+ return 0;
+}
+
+
+int Rtcm::set_DF089(const Gps_Ephemeris & gps_eph)
+{
+ int cuc = static_cast<int>(std::round(gps_eph.d_Cuc / C_UC_LSB ));
+ DF089 = std::bitset<16>(cuc);
+ return 0;
+}
+
+int Rtcm::set_DF090(const Gps_Ephemeris & gps_eph)
+{
+ unsigned long int ecc = static_cast<unsigned long int>(std::round(gps_eph.d_e_eccentricity / E_LSB ));
+ DF090 = std::bitset<32>(ecc);
+ return 0;
+}
+
+
+int Rtcm::set_DF091(const Gps_Ephemeris & gps_eph)
+{
+ int cus = static_cast<int>(std::round(gps_eph.d_Cus / C_US_LSB ));
+ DF091 = std::bitset<16>(cus);
+ return 0;
+}
+
+
+int Rtcm::set_DF092(const Gps_Ephemeris & gps_eph)
+{
+ unsigned long int sqr_a = static_cast<unsigned long int>(std::round(gps_eph.d_sqrt_A / SQRT_A_LSB ));
+ DF092 = std::bitset<32>(sqr_a);
+ return 0;
+}
+
+
+int Rtcm::set_DF093(const Gps_Ephemeris & gps_eph)
+{
+ unsigned int toe = static_cast<unsigned int>(std::round(gps_eph.d_Toe / T_OE_LSB ));
+ DF093 = std::bitset<16>(toe);
+ return 0;
+}
+
+
+int Rtcm::set_DF094(const Gps_Ephemeris & gps_eph)
+{
+ int cic = static_cast<int>(std::round(gps_eph.d_Cic / C_IC_LSB ));
+ DF094 = std::bitset<16>(cic);
+ return 0;
+}
+
+
+int Rtcm::set_DF095(const Gps_Ephemeris & gps_eph)
+{
+ long int Omega0 = static_cast<long int>(std::round(gps_eph.d_OMEGA0 / OMEGA_0_LSB ));
+ DF095 = std::bitset<32>(Omega0);
+ return 0;
+}
+
+
+int Rtcm::set_DF096(const Gps_Ephemeris & gps_eph)
+{
+ int cis = static_cast<int>(std::round(gps_eph.d_Cis / C_IS_LSB ));
+ DF096 = std::bitset<16>(cis);
+ return 0;
+}
+
+
+int Rtcm::set_DF097(const Gps_Ephemeris & gps_eph)
+{
+ long int i0 = static_cast<long int>(std::round(gps_eph.d_i_0 / I_0_LSB ));
+ DF097 = std::bitset<32>(i0);
+ return 0;
+}
+
+
+int Rtcm::set_DF098(const Gps_Ephemeris & gps_eph)
+{
+ int crc = static_cast<int>(std::round(gps_eph.d_Crc / C_RC_LSB ));
+ DF098 = std::bitset<16>(crc);
+ return 0;
+}
+
+
+int Rtcm::set_DF099(const Gps_Ephemeris & gps_eph)
+{
+ long int omega = static_cast<long int>(std::round(gps_eph.d_OMEGA / OMEGA_LSB ));
+ DF099 = std::bitset<32>(omega);
+ return 0;
+}
+
+
+int Rtcm::set_DF100(const Gps_Ephemeris & gps_eph)
+{
+ long int omegadot = static_cast<long int>(std::round(gps_eph.d_OMEGA_DOT / OMEGA_DOT_LSB ));
+ DF100 = std::bitset<24>(omegadot);
+ return 0;
+}
+
+
+int Rtcm::set_DF101(const Gps_Ephemeris & gps_eph)
+{
+ short int tgd = static_cast<short int>(std::round(gps_eph.d_TGD / T_GD_LSB ));
+ DF101 = std::bitset<8>(tgd);
+ return 0;
+}
+
+
+int Rtcm::set_DF102(const Gps_Ephemeris & gps_eph)
+{
+ unsigned short int sv_heath = static_cast<unsigned short int>(gps_eph.i_SV_health);
+ DF102 = std::bitset<6>(sv_heath);
+ return 0;
+}
+
+
+int Rtcm::set_DF103(const Gps_Ephemeris & gps_eph)
+{
+ DF103 = std::bitset<1>(gps_eph.b_L2_P_data_flag);
+ return 0;
+}
+
+
+
+
+int Rtcm::set_DF137(const Gps_Ephemeris & gps_eph)
+{
+ DF137 = std::bitset<1>(gps_eph.b_fit_interval_flag);
+ return 0;
+}
+
+
+
+int Rtcm::set_DF252(const Galileo_Ephemeris & gal_eph)
+{
+ unsigned int prn_ = gal_eph.i_satellite_PRN;
+ if(prn_ > 63)
+ {
+ LOG(WARNING) << "Galileo satellite ID must be between 0 and 63, but PRN " << prn_ << " was found";
+ }
+ DF252 = std::bitset<6>(prn_);
+ return 0;
+}
+
+
+int Rtcm::set_DF289(const Galileo_Ephemeris & gal_eph)
+{
+ unsigned int galileo_week_number = static_cast<unsigned int>(gal_eph.WN_5);
+ if(galileo_week_number > 4095)
+ {
+ LOG(WARNING) << "Error decoding Galileo week number (it has a 4096 roll-off, but " << galileo_week_number << " was detected)";
+ }
+ DF289 = std::bitset<12>(galileo_week_number);
+ return 0;
+}
+
+
+int Rtcm::set_DF290(const Galileo_Ephemeris & gal_eph)
+{
+ unsigned int iod_nav = static_cast<unsigned int>(gal_eph.IOD_nav_1);
+ if(iod_nav > 1023)
+ {
+ LOG(WARNING) << "Error decoding Galileo IODnav (it has a max of 1023, but " << iod_nav << " was detected)";
+ }
+ DF290 = std::bitset<10>(iod_nav);
+ return 0;
+}
+
+
+int Rtcm::set_DF291(const Galileo_Ephemeris & gal_eph)
+{
+ unsigned short int SISA = static_cast<unsigned short int>(gal_eph.SISA_3);
+ //SISA = 0; // SIS Accuracy, data content definition not given in Galileo OS SIS ICD, Issue 1.1, Sept 2010
+ DF291 = std::bitset<8>(SISA);
+ return 0;
+}
+
+
+int Rtcm::set_DF292(const Galileo_Ephemeris & gal_eph)
+{
+
+ int idot = static_cast<int>(std::round(gal_eph.iDot_2 / FNAV_idot_2_LSB));
+ DF292 = std::bitset<14>(idot);
+ return 0;
+}
+
+int Rtcm::set_DF293(const Galileo_Ephemeris & gal_eph)
+{
+
+ unsigned int toc = static_cast<unsigned int>(gal_eph.t0c_4);
+ if(toc > 604740)
+ {
+ LOG(WARNING) << "Error decoding Galileo ephemeris time (max of 604740, but " << toc << " was detected)";
+ }
+ DF293 = std::bitset<14>(toc);
+ return 0;
+}
+
+
+int Rtcm::set_DF294(const Galileo_Ephemeris & gal_eph)
+{
+ short int af2 = static_cast<short int>(std::round(gal_eph.af2_4 / FNAV_af2_1_LSB));
+ DF294 = std::bitset<6>(af2);
+ return 0;
+}
+
+
+int Rtcm::set_DF295(const Galileo_Ephemeris & gal_eph)
+{
+ long int af1 = static_cast<long int>(std::round(gal_eph.af1_4 / FNAV_af1_1_LSB));
+ DF295 = std::bitset<21>(af1);
+ return 0;
+}
+
+
+int Rtcm::set_DF296(const Galileo_Ephemeris & gal_eph)
+{
+ long int af0 = static_cast<unsigned int>(std::round(gal_eph.af0_4 / FNAV_af0_1_LSB));
+ DF296 = std::bitset<31>(af0);
+ return 0;
+}
+
+
+int Rtcm::set_DF297(const Galileo_Ephemeris & gal_eph)
+{
+ int crs = static_cast<int>(std::round(gal_eph.C_rs_3 / FNAV_Crs_3_LSB));
+ DF297 = std::bitset<16>(crs);
+ return 0;
+}
+
+
+int Rtcm::set_DF298(const Galileo_Ephemeris & gal_eph)
+{
+ int delta_n = static_cast<int>(std::round(gal_eph.delta_n_3 / FNAV_deltan_3_LSB));
+ DF298 = std::bitset<16>(delta_n);
+ return 0;
+}
+
+
+int Rtcm::set_DF299(const Galileo_Ephemeris & gal_eph)
+{
+ long int m0 = static_cast<long int>(std::round(gal_eph.M0_1 / FNAV_M0_2_LSB));
+ DF299 = std::bitset<32>(m0);
+ return 0;
+}
+
+
+int Rtcm::set_DF300(const Galileo_Ephemeris & gal_eph)
+{
+ int cuc = static_cast<unsigned int>(std::round(gal_eph.C_uc_3 / FNAV_Cuc_3_LSB));
+ DF300 = std::bitset<16>(cuc);
+ return 0;
+}
+
+int Rtcm::set_DF301(const Galileo_Ephemeris & gal_eph)
+{
+ unsigned long int ecc = static_cast<unsigned long int>(std::round(gal_eph.e_1 / FNAV_e_2_LSB));
+ DF301 = std::bitset<32>(ecc);
+ return 0;
+}
+
+
+int Rtcm::set_DF302(const Galileo_Ephemeris & gal_eph)
+{
+ int cus = static_cast<int>(std::round(gal_eph.C_us_3 / FNAV_Cus_3_LSB));
+ DF302 = std::bitset<16>(cus);
+ return 0;
+}
+
+
+int Rtcm::set_DF303(const Galileo_Ephemeris & gal_eph)
+{
+ unsigned long int sqr_a = static_cast<unsigned long int>(std::round(gal_eph.A_1 / FNAV_a12_2_LSB));
+ DF303 = std::bitset<32>(sqr_a);
+ return 0;
+}
+
+
+
+int Rtcm::set_DF304(const Galileo_Ephemeris & gal_eph)
+{
+ unsigned int toe = static_cast<unsigned int>(std::round(gal_eph.t0e_1 / FNAV_t0e_3_LSB));
+ DF304 = std::bitset<14>(toe);
+ return 0;
+}
+
+
+int Rtcm::set_DF305(const Galileo_Ephemeris & gal_eph)
+{
+ int cic = static_cast<int>(std::round(gal_eph.C_ic_4 / FNAV_Cic_4_LSB));
+ DF305 = std::bitset<16>(cic);
+ return 0;
+}
+
+
+int Rtcm::set_DF306(const Galileo_Ephemeris & gal_eph)
+{
+ long int Omega0 = static_cast<long int>(std::round(gal_eph.OMEGA_0_2 / FNAV_omega0_2_LSB));
+ DF306 = std::bitset<32>(Omega0);
+ return 0;
+}
+
+
+int Rtcm::set_DF307(const Galileo_Ephemeris & gal_eph)
+{
+ int cis = static_cast<int>(std::round(gal_eph.C_is_4 / FNAV_Cis_4_LSB));
+ DF307 = std::bitset<16>(cis);
+ return 0;
+}
+
+
+int Rtcm::set_DF308(const Galileo_Ephemeris & gal_eph)
+{
+ long int i0 = static_cast<long int>(std::round(gal_eph.i_0_2 / FNAV_i0_3_LSB));
+ DF308 = std::bitset<32>(i0);
+ return 0;
+}
+
+
+int Rtcm::set_DF309(const Galileo_Ephemeris & gal_eph)
+{
+ int crc = static_cast<unsigned int>(std::round(gal_eph.C_rc_3 / FNAV_Crc_3_LSB));
+ DF309 = std::bitset<16>(crc);
+ return 0;
+}
+
+
+int Rtcm::set_DF310(const Galileo_Ephemeris & gal_eph)
+{
+ int omega = static_cast<int>(std::round(gal_eph.omega_2 / FNAV_omega0_2_LSB));
+ DF310 = std::bitset<32>(omega);
+ return 0;
+}
+
+
+int Rtcm::set_DF311(const Galileo_Ephemeris & gal_eph)
+{
+ long int Omegadot = static_cast<long int>(std::round(gal_eph.OMEGA_dot_3 / FNAV_omegadot_2_LSB));
+ DF311 = std::bitset<24>(Omegadot);
+ return 0;
+}
+
+
+int Rtcm::set_DF312(const Galileo_Ephemeris & gal_eph)
+{
+ int bdg_E1_E5a = static_cast<int>(std::round(gal_eph.BGD_E1E5a_5 / FNAV_BGD_1_LSB));
+ DF312 = std::bitset<10>(bdg_E1_E5a);
+ return 0;
+}
+
+
+int Rtcm::set_DF313(const Galileo_Ephemeris & gal_eph)
+{
+ unsigned int bdg_E5b_E1 = static_cast<unsigned int>(std::round(gal_eph.BGD_E1E5b_5 ));
+ //bdg_E5b_E1 = 0; //reserved
+ DF313 = std::bitset<10>(bdg_E5b_E1);
+ return 0;
+}
+
+
+int Rtcm::set_DF314(const Galileo_Ephemeris & gal_eph)
+{
+ DF314 = std::bitset<2>(gal_eph.E5a_HS);
+ return 0;
+}
+
+
+int Rtcm::set_DF315(const Galileo_Ephemeris & gal_eph)
+{
+ DF315 = std::bitset<1>(gal_eph.E5a_DVS);
+ return 0;
+}
+
+
+
+int Rtcm::set_DF393(bool more_messages)
+{
+ DF393 = std::bitset<1>(more_messages);
+ return 0;
+}
+
+
+int Rtcm::set_DF394(const std::map<int, Gnss_Synchro> & gnss_synchro)
+{
+ DF394.reset();
+ std::map<int, Gnss_Synchro>::const_iterator gnss_synchro_iter;
+ unsigned int mask_position;
+ for(gnss_synchro_iter = gnss_synchro.begin();
+ gnss_synchro_iter != gnss_synchro.end();
+ gnss_synchro_iter++)
+ {
+ mask_position = 65 - gnss_synchro_iter->second.PRN;
+ DF394.set(mask_position, true);
+ }
+ return 0;
+}
+
+
+int Rtcm::set_DF395(const std::map<int, Gnss_Synchro> & gnss_synchro)
+{
+ DF395.reset();
+ std::map<int, Gnss_Synchro>::const_iterator gnss_synchro_iter;
+ std::string sig;
+ unsigned int mask_position;
+ for(gnss_synchro_iter = gnss_synchro.begin();
+ gnss_synchro_iter != gnss_synchro.end();
+ gnss_synchro_iter++)
+ {
+ std::string sig_(gnss_synchro_iter->second.Signal);
+ sig = sig_.substr(0,2);
+
+ std::string sys(gnss_synchro_iter->second.System, 1);
+
+ if ((sig.compare("1C") == 0) && (sys.compare("G") == 0 ) )
+ {
+ mask_position = 33 - 2;
+ DF395.set(mask_position, true);
+ }
+ if ((sig.compare("2S") == 0) && (sys.compare("G") == 0 ) )
+ {
+ mask_position = 33 - 15;
+ DF395.set(mask_position, true);
+ }
+
+ if ((sig.compare("5X") == 0) && (sys.compare("G") == 0 ) )
+ {
+ mask_position = 33 - 24;
+ DF395.set(mask_position, true);
+ }
+ if ((sig.compare("1B") == 0) && (sys.compare("E") == 0 ) )
+ {
+ mask_position = 33 - 4;
+ DF395.set(mask_position, true);
+ }
+
+ if ((sig.compare("5X") == 0) && (sys.compare("E") == 0 ) )
+ {
+ mask_position = 33 - 24;
+ DF395.set(mask_position, true);
+ }
+ if ((sig.compare("7X") == 0) && (sys.compare("E") == 0 ) )
+ {
+ mask_position = 33 - 16;
+ DF395.set(mask_position, true);
+ }
+ }
+ return 0;
+}
+
+
+int Rtcm::set_DF409(unsigned int iods)
+{
+ DF409 = std::bitset<3>(iods);
+ return 0;
+}
+
+
+int Rtcm::set_DF417(bool using_divergence_free_smoothing)
+{
+ DF417 = std::bitset<1>(using_divergence_free_smoothing);
+ return 0;
+}
diff --git a/src/core/system_parameters/rtcm.h b/src/core/system_parameters/rtcm.h
new file mode 100644
index 0000000..dc3d03e
--- /dev/null
+++ b/src/core/system_parameters/rtcm.h
@@ -0,0 +1,416 @@
+/*!
+ * \file rtcm.h
+ * \brief Interface for the RTCM 3.2 Standard
+ * \author Carles Fernandez-Prades, 2015. cfernandez(at)cttc.es
+ *
+ * -------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
+ *
+ * GNSS-SDR is a software defined Global Navigation
+ * Satellite Systems receiver
+ *
+ * This file is part of GNSS-SDR.
+ *
+ * GNSS-SDR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNSS-SDR is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+
+#ifndef GNSS_SDR_RTCM_H_
+#define GNSS_SDR_RTCM_H_
+
+
+#include <bitset> // std::bitset
+#include <map>
+#include <string> // std::string
+#include <vector>
+#include <boost/crc.hpp>
+#include "gnss_synchro.h"
+#include "galileo_fnav_message.h"
+#include "gps_navigation_message.h"
+
+/*!
+ * \brief This class implements the RTCM 3.2 Stardard
+ *
+ */
+class Rtcm
+{
+public:
+ Rtcm();
+
+ std::string print_M1001(const Gps_Ephemeris& gps_eph, double obs_time, const std::map<int, Gnss_Synchro> & pseudoranges);
+
+ std::string print_M1045(const Galileo_Ephemeris & gal_eph); //<! Galileo Ephemeris, should be broadcast every 2 minutes
+
+ /*!
+ * \brief GPS Ephemeris, should be broadcast in the event that the IODC does not match the IODE, and every 2 minutes.
+ */
+ std::string print_M1019(const Gps_Ephemeris & gps_eph);
+ int read_M1019(const std::string & message, Gps_Ephemeris & gps_eph);
+
+
+
+ std::string bin_to_hex(const std::string& s);
+
+ std::string hex_to_bin(const std::string& s);
+
+ unsigned long int bin_to_uint(const std::string& s);
+ long int bin_to_int(const std::string& s);
+
+ unsigned long int hex_to_uint(const std::string& s);
+ long int hex_to_int(const std::string& s);
+
+ double bin_to_double(const std::string& s);
+
+ std::string print_M1005_test(); //<! For testing purposes
+ int read_M1005(const std::string & message, unsigned int & ref_id, double & ecef_x, double & ecef_y, double & ecef_z, bool & gps, bool & glonass, bool & galileo);
+
+private:
+ //
+ // Messages
+ //
+ std::bitset<64> message1001_header;
+ std::bitset<58> message1001_content;
+ std::bitset<64> message1002_header;
+ std::bitset<74> message1002_content;
+
+ std::bitset<488> message1019_content;
+
+ std::bitset<496> message1045_content;
+
+ std::bitset<169> MSM_header; // 169+X
+
+ std::vector<std::bitset<18> > MSM4_content; // 18 * Nsat
+
+ std::vector<std::bitset<36> > MSM5_content; // 36 * Nsat
+
+
+ std::bitset<64> get_M1001_header(const Gps_Ephemeris & gps_eph,
+ double obs_time,
+ const std::map<int, Gnss_Synchro> & pseudoranges,
+ unsigned int ref_id,
+ unsigned int smooth_int,
+ bool sync_flag,
+ bool divergence_free);
+
+ std::bitset<58> get_M1001_sat_content(const Gnss_Synchro & gnss_synchro);
+
+ std::bitset<138> get_M1002(); // GPS observables
+ //std::bitset<488> get_M1019(); // GPS ephemeris
+ //std::bitset<496> get_M1045(); // Galileo ephemeris
+ std::bitset<152> get_M1005_test();
+
+
+
+ //
+ // Transport Layer
+ //
+ std::bitset<8> preamble;
+ std::bitset<6> reserved_field;
+ std::bitset<10> message_length;
+ std::bitset<24> crc_frame;
+ typedef boost::crc_optimal<24, 0x1864CFBu, 0x0, 0x0, false, false> crc_24_q_type;
+ crc_24_q_type CRC_RTCM;
+ std::string add_CRC(const std::string& m);
+ bool check_CRC(const std::string & message);
+
+ std::string build_message(std::string data); // adds 0s to complete a byte and adds the CRC
+
+
+ //
+ // Data Fields
+ //
+ int reset_data_fields();
+
+ std::bitset<12> DF002;
+ int set_DF002(unsigned int message_number);
+
+ std::bitset<12> DF003;
+ int set_DF003(unsigned int ref_station_ID);
+
+ std::bitset<30> DF004;
+ int set_DF004(const Gps_Ephemeris & gps_eph, double obs_time);
+
+ std::bitset<1> DF005;
+ int set_DF005(bool sync_flag);
+
+ std::bitset<5> DF006;
+ int set_DF006(const std::map<int, Gnss_Synchro> & pseudoranges);
+
+ std::bitset<1> DF007;
+ int set_DF007(bool divergence_free_smoothing_indicator); // 0 - Divergence-free smoothing not used 1 - Divergence-free smoothing used
+
+ std::bitset<3> DF008;
+ int set_DF008(short int smoothing_interval);
+
+ std::bitset<6> DF009;
+ int set_DF009(const Gps_Ephemeris & gps_eph);
+ int set_DF009(const Gnss_Synchro & gnss_synchro);
+
+ std::bitset<1> DF010;
+ int set_DF010(bool code_indicator);
+
+ std::bitset<24> DF011;
+ int set_DF011(const Gnss_Synchro & gnss_synchro);
+
+ std::bitset<20> DF012;
+ int set_DF012(const Gnss_Synchro & gnss_synchro);
+
+ std::bitset<7> DF013;
+ std::bitset<8> DF014;
+ int set_DF014(const Gnss_Synchro & gnss_synchro);
+
+ std::bitset<8> DF015;
+ int set_DF015(const Gnss_Synchro & gnss_synchro);
+
+
+ std::bitset<6> DF021;
+ int set_DF021();
+
+ std::bitset<1> DF022;
+ int set_DF022(bool gps_indicator);
+
+ std::bitset<1> DF023;
+ int set_DF023(bool glonass_indicator);
+
+ std::bitset<1> DF024;
+ int set_DF024(bool galileo_indicator);
+
+ std::bitset<38> DF025;
+ int set_DF025(double antenna_ECEF_X_m);
+
+ std::bitset<38> DF026;
+ int set_DF026(double antenna_ECEF_Y_m);
+
+ std::bitset<38> DF027;
+ int set_DF027(double antenna_ECEF_Z_m);
+
+ // Contents of GPS Satellite Ephemeris Data, Message Type 1019
+ std::bitset<8> DF071;
+ int set_DF071(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<10> DF076;
+ int set_DF076(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<4> DF077;
+ int set_DF077(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<2> DF078;
+ int set_DF078(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<14> DF079;
+ int set_DF079(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<8> DF080;
+ int set_DF080(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<16> DF081;
+ int set_DF081(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<8> DF082;
+ int set_DF082(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<16> DF083;
+ int set_DF083(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<22> DF084;
+ int set_DF084(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<10> DF085;
+ int set_DF085(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<16> DF086;
+ int set_DF086(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<16> DF087;
+ int set_DF087(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<32> DF088;
+ int set_DF088(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<16> DF089;
+ int set_DF089(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<32> DF090;
+ int set_DF090(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<16> DF091;
+ int set_DF091(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<32> DF092;
+ int set_DF092(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<16> DF093;
+ int set_DF093(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<16> DF094;
+ int set_DF094(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<32> DF095;
+ int set_DF095(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<16> DF096;
+ int set_DF096(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<32> DF097;
+ int set_DF097(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<16> DF098;
+ int set_DF098(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<32> DF099;
+ int set_DF099(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<24> DF100;
+ int set_DF100(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<8> DF101;
+ int set_DF101(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<6> DF102;
+ int set_DF102(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<1> DF103;
+ int set_DF103(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<1> DF137;
+ int set_DF137(const Gps_Ephemeris & gps_eph);
+
+
+
+ std::bitset<1> DF141;
+ int set_DF141(const Gps_Ephemeris & gps_eph);
+
+ std::bitset<1> DF142;
+ int set_DF142(const Gps_Ephemeris & gps_eph);
+
+ // Contents of Galileo F/NAV Satellite Ephemeris Data, Message Type 1045
+ std::bitset<6> DF252;
+ int set_DF252(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<12> DF289;
+ int set_DF289(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<10> DF290;
+ int set_DF290(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<8> DF291;
+ int set_DF291(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<14> DF292;
+ int set_DF292(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<14> DF293;
+ int set_DF293(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<6> DF294;
+ int set_DF294(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<21> DF295;
+ int set_DF295(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<31> DF296;
+ int set_DF296(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<16> DF297;
+ int set_DF297(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<16> DF298;
+ int set_DF298(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<32> DF299;
+ int set_DF299(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<16> DF300;
+ int set_DF300(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<32> DF301;
+ int set_DF301(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<16> DF302;
+ int set_DF302(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<32> DF303;
+ int set_DF303(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<14> DF304;
+ int set_DF304(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<16> DF305;
+ int set_DF305(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<32> DF306;
+ int set_DF306(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<16> DF307;
+ int set_DF307(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<32> DF308;
+ int set_DF308(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<16> DF309;
+ int set_DF309(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<32> DF310;
+ int set_DF310(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<24> DF311;
+ int set_DF311(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<10> DF312;
+ int set_DF312(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<10> DF313;
+ int set_DF313(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<2> DF314;
+ int set_DF314(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<1> DF315;
+ int set_DF315(const Galileo_Ephemeris & gal_eph);
+
+ std::bitset<2> DF364;
+
+ // Content of message header for MSM1, MSM2, MSM3, MSM4, MSM5, MSM6 and MSM7
+ std::bitset<1> DF393;
+ int set_DF393(bool more_messages); //1 indicates that more MSMs follow for given physical time and reference station ID
+
+ std::bitset<64> DF394;
+ int set_DF394(const std::map<int, Gnss_Synchro> & gnss_synchro);
+
+ std::bitset<32> DF395;
+ int set_DF395(const std::map<int, Gnss_Synchro> & gnss_synchro);
+
+ //std::bitset<1> DF396; //variable
+ std::bitset<3> DF409;
+ int set_DF409(unsigned int iods);
+
+ std::bitset<2> DF411;
+ std::bitset<2> DF412;
+ std::bitset<1> DF417;
+ int set_DF417(bool using_divergence_free_smoothing);
+
+ std::bitset<3> DF418;
+
+ // Content of Satellite data for MSM4 and MSM6
+ std::vector<std::bitset<8> > DF397; // 8*NSAT
+ std::vector<std::bitset<10> > DF398; // 10*NSAT
+
+ // Content of Satellite data for MSM5 and MSM7
+ std::vector<std::bitset<14> > DF399; // 14*NSAT
+};
+
+#endif
diff --git a/src/tests/gnss_block/rtcm_printer_test.cc b/src/tests/gnss_block/rtcm_printer_test.cc
index 7e0d520..bd9f5f2 100644
--- a/src/tests/gnss_block/rtcm_printer_test.cc
+++ b/src/tests/gnss_block/rtcm_printer_test.cc
@@ -37,6 +37,9 @@
#include "gps_ephemeris.h"
+
+
+
TEST(Rtcm_Printer_Test, Instantiate)
{
std::string filename = "hello.rtcm";
@@ -73,3 +76,83 @@ TEST(Rtcm_Printer_Test, Instantiate_and_Run)
EXPECT_EQ(reference_msg, testing_msg);
}
+
+TEST(Rtcm_Printer_Test, Bin_to_hex)
+{
+ auto rtcm = std::make_shared<Rtcm>();
+
+ std::string test1 = "2A";
+ std::string test1_bin = rtcm->hex_to_bin(test1);
+ EXPECT_EQ(0, test1_bin.compare("00101010"));
+
+ std::string test2 = "FF";
+ std::string test2_bin = rtcm->hex_to_bin(test2);
+ EXPECT_EQ(0, test2_bin.compare("11111111"));
+
+ std::string test3 = "ff";
+ std::string test3_bin = rtcm->hex_to_bin(test3);
+ EXPECT_EQ(0, test3_bin.compare("11111111"));
+}
+
+
+
+TEST(Rtcm_Printer_Test, Hex_to_int)
+{
+ auto rtcm = std::make_shared<Rtcm>();
+
+ std::string test1 = "2A";
+ long int test1_int = rtcm->hex_to_int(test1);
+ long int expected1 = 42;
+ EXPECT_EQ(expected1, test1_int);
+}
+
+TEST(Rtcm_Printer_Test, Bin_to_double)
+{
+ auto rtcm = std::make_shared<Rtcm>();
+
+ std::bitset<4> test1(5);
+ long int test1_int = static_cast<long int>(rtcm->bin_to_double(test1.to_string()));
+ long int expected1 = 5;
+ EXPECT_EQ(expected1, test1_int);
+
+ std::bitset<4> test2(-5);
+ long int test2_int = static_cast<long int>(rtcm->bin_to_double(test2.to_string()));
+ long int expected2 = -5;
+ EXPECT_EQ(expected2, test2_int);
+
+ std::bitset<65> test3(-5);
+ long int test3_int = static_cast<long int>(rtcm->bin_to_double(test3.to_string()));
+ long int expected3 = 0;
+ EXPECT_EQ(expected3, test3_int);
+}
+
+
+TEST(Rtcm_Printer_Test, Read_M1005)
+{
+ std::string filename = "hello.rtcm";
+ bool flag_rtcm_tty_port = false;
+ std::string rtcm_dump_devname = "/dev/pts/4";
+
+ auto rtcm = std::make_shared<Rtcm>();
+ auto rtcm_printer = std::make_shared<Rtcm_Printer>(filename, flag_rtcm_tty_port, rtcm_dump_devname);
+ std::string reference_msg = rtcm_printer->print_M1005_test();
+
+ unsigned int ref_id;
+ double ecef_x;
+ double ecef_y;
+ double ecef_z;
+ bool gps;
+ bool glonass;
+ bool galileo;
+
+ rtcm->read_M1005(reference_msg, ref_id, ecef_x, ecef_y, ecef_z, gps, glonass, galileo);
+
+ EXPECT_EQ(true, gps);
+ EXPECT_EQ(false, glonass);
+ EXPECT_EQ(false, galileo);
+
+ EXPECT_EQ(2003, ref_id);
+ EXPECT_DOUBLE_EQ(1114104.5999, ecef_x);
+ EXPECT_DOUBLE_EQ(-4850729.7108, ecef_y);
+ EXPECT_DOUBLE_EQ(3975521.4643, ecef_z);
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hamradio/gnss-sdr.git
More information about the pkg-hamradio-commits
mailing list