GNSS-SDR  0.0.13
An Open Source GNSS Software Defined Receiver
rinex_printer.h
Go to the documentation of this file.
1 /*!
2  * \file rinex_printer.h
3  * \brief Interface of a RINEX 2.11 / 3.01 printer
4  * See ftp://igs.org/pub/data/format/rinex301.pdf
5  *
6  * Receiver Independent EXchange Format (RINEX):
7  * The first proposal for the Receiver Independent Exchange Format RINEX
8  * was developed by the Astronomical Institute of the University of Berne
9  * for the easy exchange of the GPS data to be collected during the large
10  * European GPS campaign EUREF 89, which involved more than 60 GPS receivers
11  * of 4 different manufacturers.
12  * The governing aspect during the development was the fact that most geodetic
13  * processing software for GPS data use a well-defined set of observables:
14  * 1) The carrier-phase measurement at one or both carriers (actually being a
15  * measurement on the beat frequency between the received carrier of the
16  * satellite signal and a receiver-generated reference frequency).
17  * 2) The pseudorange (code) measurement , equivalent to the difference
18  * of the time of reception (expressed in the time frame of the receiver)
19  * and the time of transmission (expressed in the time frame of the satellite)
20  * of a distinct satellite signal.
21  * 3) The observation time being the reading of the receiver clock at the
22  * instant of validity of the carrier-phase and/or the code measurements.
23  * Note: A collection of the formats currently used by the IGS can be found
24  * here: https://kb.igs.org/hc/en-us/articles/201096516-IGS-Formats
25  * \author Carles Fernandez Prades, 2011. cfernandez(at)cttc.es
26  * -----------------------------------------------------------------------------
27  *
28  * Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
29  *
30  * GNSS-SDR is a software defined Global Navigation
31  * Satellite Systems receiver
32  *
33  * This file is part of GNSS-SDR.
34  *
35  * SPDX-License-Identifier: GPL-3.0-or-later
36  *
37  * -----------------------------------------------------------------------------
38  */
39 
40 #ifndef GNSS_SDR_RINEX_PRINTER_H
41 #define GNSS_SDR_RINEX_PRINTER_H
42 
43 #include <boost/date_time/posix_time/posix_time.hpp>
44 #include <cstdint> // for int32_t
45 #include <cstdlib> // for strtol, strtod
46 #include <fstream> // for fstream
47 #include <iomanip> // for setprecision
48 #include <map> // for map
49 #include <sstream> // for stringstream
50 #include <string> // for string
51 
53 class Beidou_Dnav_Iono;
55 class Galileo_Ephemeris;
56 class Galileo_Iono;
57 class Galileo_Utc_Model;
61 class Gnss_Synchro;
62 class Gps_CNAV_Ephemeris;
63 class Gps_CNAV_Iono;
64 class Gps_CNAV_Utc_Model;
65 class Gps_Ephemeris;
66 class Gps_Iono;
68 class Gps_Utc_Model;
69 
70 
71 /*!
72  * \brief Class that handles the generation of Receiver
73  * INdependent EXchange format (RINEX) files
74  */
76 {
77 public:
78  /*!
79  * \brief Default constructor. Creates GNSS Navigation and Observables RINEX files and their headers
80  */
81  explicit Rinex_Printer(int version = 0, const std::string& base_path = ".", const std::string& base_name = "-");
82 
83  /*!
84  * \brief Default destructor. Closes GNSS Navigation and Observables RINEX files
85  */
87 
88  /*!
89  * \brief Generates the GPS L1 C/A Navigation Data header
90  */
91  void rinex_nav_header(std::fstream& out, const Gps_Iono& iono, const Gps_Utc_Model& utc_model, const Gps_Ephemeris& eph) const;
92 
93  /*!
94  * \brief Generates the GPS L2C(M) Navigation Data header
95  */
96  void rinex_nav_header(std::fstream& out, const Gps_CNAV_Iono& iono, const Gps_CNAV_Utc_Model& utc_model) const;
97 
98  /*!
99  * \brief Generates the Galileo Navigation Data header
100  */
101  void rinex_nav_header(std::fstream& out, const Galileo_Iono& iono, const Galileo_Utc_Model& utc_model) const;
102 
103  /*!
104  * \brief Generates the Mixed (GPS/Galileo) Navigation Data header
105  */
106  void rinex_nav_header(std::fstream& out, const Gps_Iono& gps_iono, const Gps_Utc_Model& gps_utc_model, const Gps_Ephemeris& eph, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model) const;
107 
108  /*!
109  * \brief Generates the Mixed (GPS CNAV/Galileo) Navigation Data header
110  */
111  void rinex_nav_header(std::fstream& out, const Gps_CNAV_Iono& iono, const Gps_CNAV_Utc_Model& utc_model, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model) const;
112 
113  /*!
114  * \brief Generates the GLONASS L1, L2 C/A Navigation Data header
115  */
116  void rinex_nav_header(std::fstream& out, const Glonass_Gnav_Utc_Model& utc_model, const Glonass_Gnav_Ephemeris& glonass_gnav_eph);
117 
118  /*!
119  * \brief Generates the Mixed (Galileo/GLONASS) Navigation Data header
120  */
121  void rinex_nav_header(std::fstream& out, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) const;
122 
123  /*!
124  * \brief Generates the Mixed (GPS L1 C/A/GLONASS L1, L2) Navigation Data header
125  */
126  void rinex_nav_header(std::fstream& out, const Gps_Iono& gps_iono, const Gps_Utc_Model& gps_utc_model, const Gps_Ephemeris& eph, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac);
127 
128  /*!
129  * \brief Generates the Mixed (GPS L2C C/A/GLONASS L1, L2) Navigation Data header
130  */
131  void rinex_nav_header(std::fstream& out, const Gps_CNAV_Iono& gps_iono, const Gps_CNAV_Utc_Model& gps_utc_model, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac);
132 
133  /*!
134  * \brief Generates the BDS B1I or B3I Navigation Data header
135  */
136  void rinex_nav_header(std::fstream& out, const Beidou_Dnav_Iono& iono, const Beidou_Dnav_Utc_Model& utc_model) const;
137 
138  /*!
139  * \brief Generates the Mixed GPS L1,L5 + BDS B1I, B3I Navigation Data header
140  */
141  void rinex_nav_header(std::fstream& out, const Gps_Iono& gps_iono, const Gps_Utc_Model& gps_utc_model, const Gps_Ephemeris& eph, const Beidou_Dnav_Iono& bds_dnav_iono, const Beidou_Dnav_Utc_Model& bds_dnav_utc_model) const;
142 
143  /*!
144  * \brief Generates the Mixed GPS L2C + BDS B1I, B3I Navigation Data header
145  */
146  void rinex_nav_header(std::fstream& out, const Gps_CNAV_Iono& gps_cnav_iono, const Gps_CNAV_Utc_Model& gps_cnav_utc_model, const Beidou_Dnav_Iono& bds_dnav_iono, const Beidou_Dnav_Utc_Model& bds_dnav_utc_model);
147 
148  /*!
149  * \brief Generates the Mixed GLONASS L1,L2 + BDS B1I, B3I Navigation Data header
150  */
151  void rinex_nav_header(std::fstream& out, const Glonass_Gnav_Utc_Model& glo_gnav_utc_model, const Beidou_Dnav_Iono& bds_dnav_iono, const Beidou_Dnav_Utc_Model& bds_dnav_utc_model) const;
152 
153  /*!
154  * \brief Generates the Mixed (Galileo/BDS B1I, B3I) Navigation Data header
155  */
156  void rinex_nav_header(std::fstream& out, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model, const Beidou_Dnav_Iono& bds_dnav_iono, const Beidou_Dnav_Utc_Model& bds_dnav_utc_model) const;
157 
158  /*!
159  * \brief Generates the GPS Observation data header
160  */
161  void rinex_obs_header(std::fstream& out, const Gps_Ephemeris& eph, double d_TOW_first_observation);
162 
163  /*!
164  * \brief Generates the GPS L2 Observation data header
165  */
166  void rinex_obs_header(std::fstream& out, const Gps_CNAV_Ephemeris& eph, double d_TOW_first_observation, const std::string& gps_bands = "2S");
167 
168  /*!
169  * \brief Generates the dual frequency GPS L1 & L2/L5 Observation data header
170  */
171  void rinex_obs_header(std::fstream& out, const Gps_Ephemeris& eph, const Gps_CNAV_Ephemeris& eph_cnav, double d_TOW_first_observation, const std::string& gps_bands = "1C 2S");
172 
173  /*!
174  * \brief Generates the Galileo Observation data header. Example: bands("1B"), bands("1B 5X"), bands("5X"), ... Default: "1B".
175  */
176  void rinex_obs_header(std::fstream& out, const Galileo_Ephemeris& eph, double d_TOW_first_observation, const std::string& bands = "1B");
177 
178  /*!
179  * \brief Generates the Mixed (GPS/Galileo) Observation data header. Example: galileo_bands("1B"), galileo_bands("1B 5X"), galileo_bands("5X"), ... Default: "1B".
180  */
181  void rinex_obs_header(std::fstream& out, const Gps_Ephemeris& gps_eph, const Galileo_Ephemeris& galileo_eph, double d_TOW_first_observation, const std::string& galileo_bands = "1B");
182 
183  /*!
184  * \brief Generates the Mixed (GPS/Galileo) Observation data header. Example: galileo_bands("1B"), galileo_bands("1B 5X"), galileo_bands("5X"), ... Default: "1B".
185  */
186  void rinex_obs_header(std::fstream& out, const Gps_Ephemeris& gps_eph, const Gps_CNAV_Ephemeris& eph_cnav, const Galileo_Ephemeris& galileo_eph, double d_TOW_first_observation, const std::string& gps_bands = "1C 2S", const std::string& galileo_bands = "1B");
187 
188  /*!
189  * \brief Generates the Mixed (GPS/Galileo) Observation data header. Example: galileo_bands("1B"), galileo_bands("1B 5X"), galileo_bands("5X"), ... Default: "1B".
190  */
191  void rinex_obs_header(std::fstream& out, const Gps_CNAV_Ephemeris& eph_cnav, const Galileo_Ephemeris& galileo_eph, double d_TOW_first_observation, const std::string& gps_bands = "2S", const std::string& galileo_bands = "1B");
192 
193  /*!
194  * \brief Generates the GLONASS GNAV Observation data header. Example: bands("1C"), bands("1C 2C"), bands("2C"), ... Default: "1C".
195  */
196  void rinex_obs_header(std::fstream& out, const Glonass_Gnav_Ephemeris& eph, double d_TOW_first_observation, const std::string& bands = "1G");
197 
198  /*!
199  * \brief Generates the Mixed (GPS L1 C/A /GLONASS) Observation data header. Example: galileo_bands("1C"), galileo_bands("1B 5X"), galileo_bands("5X"), ... Default: "1B".
200  */
201  void rinex_obs_header(std::fstream& out, const Gps_Ephemeris& gps_eph, const Glonass_Gnav_Ephemeris& glonass_gnav_eph, double d_TOW_first_observation, const std::string& glonass_bands = "1C");
202 
203  /*!
204  * \brief Generates the Mixed (Galileo/GLONASS) Observation data header. Example: galileo_bands("1C"), galileo_bands("1B 5X"), galileo_bands("5X"), ... Default: "1B".
205  */
206  void rinex_obs_header(std::fstream& out, const Galileo_Ephemeris& galileo_eph, const Glonass_Gnav_Ephemeris& glonass_gnav_eph, double d_TOW_first_observation, const std::string& galileo_bands = "1B", const std::string& glonass_bands = "1C");
207 
208  /*!
209  * \brief Generates the Mixed (GPS L2C/GLONASS) Observation data header. Example: galileo_bands("1G")... Default: "1G".
210  */
211  void rinex_obs_header(std::fstream& out, const Gps_CNAV_Ephemeris& gps_cnav_eph, const Glonass_Gnav_Ephemeris& glonass_gnav_eph, double d_TOW_first_observation, const std::string& glonass_bands = "1G");
212 
213  /*!
214  * \brief Generates the a Beidou B1I Observation data header. Example: beidou_bands("B1")
215  */
216  void rinex_obs_header(std::fstream& out, const Beidou_Dnav_Ephemeris& eph, double d_TOW_first_observation, const std::string& bands);
217 
218  /*!
219  * \brief Generates the SBAS raw data header
220  */
221  void rinex_sbs_header(std::fstream& out) const;
222 
223  /*!
224  * \brief Computes the BDS Time and returns a boost::posix_time::ptime object
225  * \details Function used to convert the observation time into BDT time which is used
226  * as the default time for RINEX files
227  * \param eph BeiDou DNAV Ephemeris object
228  * \param obs_time Observation time in BDT seconds of week
229  */
230  boost::posix_time::ptime compute_BDS_time(const Beidou_Dnav_Ephemeris& eph, double obs_time) const;
231 
232  /*!
233  * \brief Computes the UTC time and returns a boost::posix_time::ptime object
234  */
235  boost::posix_time::ptime compute_UTC_time(const Gps_Navigation_Message& nav_msg) const;
236 
237  /*!
238  * \brief Computes the GPS time and returns a boost::posix_time::ptime object
239  */
240  boost::posix_time::ptime compute_GPS_time(const Gps_Ephemeris& eph, double obs_time) const;
241 
242  /*!
243  * \brief Computes the GPS time and returns a boost::posix_time::ptime object
244  */
245  boost::posix_time::ptime compute_GPS_time(const Gps_CNAV_Ephemeris& eph, double obs_time) const;
246 
247  /*!
248  * \brief Computes the Galileo time and returns a boost::posix_time::ptime object
249  */
250  boost::posix_time::ptime compute_Galileo_time(const Galileo_Ephemeris& eph, double obs_time) const;
251 
252  /*!
253  * \brief Computes the UTC Time and returns a boost::posix_time::ptime object
254  * \details Function used as a method to convert the observation time into UTC time which is used
255  * as the default time for RINEX files
256  * \param eph GLONASS GNAV Ephemeris object
257  * \param obs_time Observation time in GPS seconds of week
258  */
259  boost::posix_time::ptime compute_UTC_time(const Glonass_Gnav_Ephemeris& eph, double obs_time) const;
260 
261  /*!
262  * \brief Computes number of leap seconds of GPS relative to UTC
263  * \param eph GLONASS GNAV Ephemeris object
264  * \param gps_obs_time Observation time in GPS seconds of week
265  */
266  double get_leap_second(const Glonass_Gnav_Ephemeris& eph, double gps_obs_time) const;
267 
268  /*!
269  * \brief Writes data from the GPS L1 C/A navigation message into the RINEX file
270  */
271  void log_rinex_nav(std::fstream& out, const std::map<int32_t, Gps_Ephemeris>& eph_map) const;
272 
273  /*!
274  * \brief Writes data from the GPS L2 navigation message into the RINEX file
275  */
276  void log_rinex_nav(std::fstream& out, const std::map<int32_t, Gps_CNAV_Ephemeris>& eph_map);
277 
278  /*!
279  * \brief Writes data from the Galileo navigation message into the RINEX file
280  */
281  void log_rinex_nav(std::fstream& out, const std::map<int32_t, Galileo_Ephemeris>& eph_map) const;
282 
283  /*!
284  * \brief Writes data from the Mixed (GPS/Galileo) navigation message into the RINEX file
285  */
286  void log_rinex_nav(std::fstream& out, const std::map<int32_t, Gps_Ephemeris>& gps_eph_map, const std::map<int32_t, Galileo_Ephemeris>& galileo_eph_map);
287 
288  /*!
289  * \brief Writes data from the Mixed (GPS/Galileo) navigation message into the RINEX file
290  */
291  void log_rinex_nav(std::fstream& out, const std::map<int32_t, Gps_CNAV_Ephemeris>& gps_cnav_eph_map, const std::map<int32_t, Galileo_Ephemeris>& galileo_eph_map);
292 
293  /*!
294  * \brief Writes data from the GLONASS GNAV navigation message into the RINEX file
295  */
296  void log_rinex_nav(std::fstream& out, const std::map<int32_t, Glonass_Gnav_Ephemeris>& eph_map) const;
297 
298  /*!
299  * \brief Writes data from the Mixed (GPS/GLONASS GNAV) navigation message into the RINEX file
300  */
301  void log_rinex_nav(std::fstream& out, const std::map<int32_t, Gps_Ephemeris>& gps_eph_map, const std::map<int32_t, Glonass_Gnav_Ephemeris>& glonass_gnav_eph_map) const;
302 
303  /*!
304  * \brief Writes data from the Mixed (GPS/GLONASS GNAV) navigation message into the RINEX file
305  */
306  void log_rinex_nav(std::fstream& out, const std::map<int32_t, Gps_CNAV_Ephemeris>& gps_cnav_eph_map, const std::map<int32_t, Glonass_Gnav_Ephemeris>& glonass_gnav_eph_map);
307 
308  /*!
309  * \brief Writes data from the Mixed (Galileo/ GLONASS GNAV) navigation message into the RINEX file
310  */
311  void log_rinex_nav(std::fstream& out, const std::map<int32_t, Galileo_Ephemeris>& galileo_eph_map, const std::map<int32_t, Glonass_Gnav_Ephemeris>& glonass_gnav_eph_map);
312 
313  /*!
314  * \brief Writes data from the Beidou B1I navigation message into the RINEX file
315  */
316  void log_rinex_nav(std::fstream& out, const std::map<int32_t, Beidou_Dnav_Ephemeris>& eph_map) const;
317 
318  /*!
319  * \brief Writes GPS L1 observables into the RINEX file
320  */
321  void log_rinex_obs(std::fstream& out, const Gps_Ephemeris& eph, double obs_time, const std::map<int32_t, Gnss_Synchro>& observables) const;
322 
323  /*!
324  * \brief Writes GPS L2 observables into the RINEX file
325  */
326  void log_rinex_obs(std::fstream& out, const Gps_CNAV_Ephemeris& eph, double obs_time, const std::map<int32_t, Gnss_Synchro>& observables) const;
327 
328  /*!
329  * \brief Writes dual frequency GPS L1 and L2 observables into the RINEX file
330  */
331  void log_rinex_obs(std::fstream& out, const Gps_Ephemeris& eph, const Gps_CNAV_Ephemeris& eph_cnav, double obs_time, const std::map<int32_t, Gnss_Synchro>& observables, bool triple_band = false) const;
332 
333  /*!
334  * \brief Writes Galileo observables into the RINEX file. Example: galileo_bands("1B"), galileo_bands("1B 5X"), galileo_bands("5X"), ... Default: "1B".
335  */
336  void log_rinex_obs(std::fstream& out, const Galileo_Ephemeris& eph, double obs_time, const std::map<int32_t, Gnss_Synchro>& observables, const std::string& galileo_bands = "1B") const;
337 
338  /*!
339  * \brief Writes Mixed GPS / Galileo observables into the RINEX file
340  */
341  void log_rinex_obs(std::fstream& out, const Gps_Ephemeris& gps_eph, const Galileo_Ephemeris& galileo_eph, double gps_obs_time, const std::map<int32_t, Gnss_Synchro>& observables) const;
342 
343  /*!
344  * \brief Writes Mixed GPS / Galileo observables into the RINEX file
345  */
346  void log_rinex_obs(std::fstream& out, const Gps_CNAV_Ephemeris& eph, const Galileo_Ephemeris& galileo_eph, double gps_obs_time, const std::map<int32_t, Gnss_Synchro>& observables) const;
347 
348  /*!
349  * \brief Writes Mixed GPS / Galileo observables into the RINEX file
350  */
351  void log_rinex_obs(std::fstream& out, const Gps_Ephemeris& gps_eph, const Gps_CNAV_Ephemeris& gps_cnav_eph, const Galileo_Ephemeris& galileo_eph, double gps_obs_time, const std::map<int32_t, Gnss_Synchro>& observables, bool triple_band = false) const;
352 
353  /*!
354  * \brief Writes GLONASS GNAV observables into the RINEX file. Example: glonass_bands("1C"), galileo_bands("1B 5X"), galileo_bands("5X"), ... Default: "1B".
355  */
356  void log_rinex_obs(std::fstream& out, const Glonass_Gnav_Ephemeris& eph, double obs_time, const std::map<int32_t, Gnss_Synchro>& observables, const std::string& glonass_bands = "1C") const;
357 
358  /*!
359  * \brief Writes Mixed GPS L1 C/A - GLONASS observables into the RINEX file
360  */
361  void log_rinex_obs(std::fstream& out, const Gps_Ephemeris& gps_eph, const Glonass_Gnav_Ephemeris& glonass_gnav_eph, double gps_obs_time, const std::map<int32_t, Gnss_Synchro>& observables) const;
362 
363  /*!
364  * \brief Writes Mixed GPS L2C - GLONASS observables into the RINEX file
365  */
366  void log_rinex_obs(std::fstream& out, const Gps_CNAV_Ephemeris& gps_eph, const Glonass_Gnav_Ephemeris& glonass_gnav_eph, double gps_obs_time, const std::map<int32_t, Gnss_Synchro>& observables) const;
367 
368  /*!
369  * \brief Writes Mixed Galileo/GLONASS observables into the RINEX file
370  */
371  void log_rinex_obs(std::fstream& out, const Galileo_Ephemeris& galileo_eph, const Glonass_Gnav_Ephemeris& glonass_gnav_eph, double galileo_obs_time, const std::map<int32_t, Gnss_Synchro>& observables) const;
372 
373  /*!
374  * \brief Writes BDS B1I observables into the RINEX file
375  */
376  void log_rinex_obs(std::fstream& out, const Beidou_Dnav_Ephemeris& eph, double obs_time, const std::map<int32_t, Gnss_Synchro>& observables, const std::string& bds_bands) const;
377 
378 
379  /*!
380  * \brief Represents GPS time in the date time format. Leap years are considered, but leap seconds are not.
381  */
382  void to_date_time(int gps_week, int gps_tow, int& year, int& month, int& day, int& hour, int& minute, int& second) const;
383 
384  /*!
385  * \brief Writes raw SBAS messages into the RINEX file
386  */
387  // void log_rinex_sbs(std::fstream & out, const Sbas_Raw_Msg & sbs_message);
388 
389  void update_nav_header(std::fstream& out, const Gps_Utc_Model& utc_model, const Gps_Iono& gps_iono, const Gps_Ephemeris& eph) const;
390 
391  void update_nav_header(std::fstream& out, const Gps_CNAV_Utc_Model& utc_model, const Gps_CNAV_Iono& iono) const;
392 
393  void update_nav_header(std::fstream& out, const Gps_Iono& gps_iono, const Gps_Utc_Model& gps_utc_model, const Gps_Ephemeris& eph, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model) const;
394 
395  void update_nav_header(std::fstream& out, const Gps_CNAV_Utc_Model& utc_model, const Gps_CNAV_Iono& iono, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model) const;
396 
397  void update_nav_header(std::fstream& out, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& utc_model) const;
398 
399  void update_nav_header(std::fstream& out, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) const;
400 
401  void update_nav_header(std::fstream& out, const Gps_Iono& gps_iono, const Gps_Utc_Model& gps_utc, const Gps_Ephemeris& eph, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) const;
402 
403  void update_nav_header(std::fstream& out, const Gps_CNAV_Iono& gps_iono, const Gps_CNAV_Utc_Model& gps_utc_model, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) const;
404 
405  void update_nav_header(std::fstream& out, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) const;
406 
407  void update_nav_header(std::fstream& out, const Beidou_Dnav_Utc_Model& utc_model, const Beidou_Dnav_Iono& beidou_dnav_iono) const;
408 
409  void update_obs_header(std::fstream& out, const Gps_Utc_Model& utc_model) const;
410 
411  void update_obs_header(std::fstream& out, const Gps_CNAV_Utc_Model& utc_model) const;
412 
413  void update_obs_header(std::fstream& out, const Galileo_Utc_Model& galileo_utc_model) const;
414 
415  void update_obs_header(std::fstream& out, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model) const;
416 
417  void update_obs_header(std::fstream& out, const Beidou_Dnav_Utc_Model& utc_model) const;
418 
419  void set_pre_2009_file(bool pre_2009_file);
420 
421  std::fstream obsFile; //!< Output file stream for RINEX observation file
422  std::fstream navFile; //!< Output file stream for RINEX navigation data file
423  std::fstream sbsFile; //!< Output file stream for RINEX SBAS raw data file
424  std::fstream navGalFile; //!< Output file stream for RINEX Galileo navigation data file
425  std::fstream navGloFile; //!< Output file stream for RINEX GLONASS navigation data file
426  std::fstream navBdsFile; //!< Output file stream for RINEX Galileo navigation data file
427  std::fstream navMixFile; //!< Output file stream for RINEX Mixed navigation data file
428 
429  std::string navfilename;
430  std::string obsfilename;
431  std::string sbsfilename;
432  std::string navGalfilename;
433  std::string navGlofilename;
434  std::string navBdsfilename;
435  std::string navMixfilename;
436 
437 private:
438  /*
439  * Generation of RINEX signal strength indicators
440  */
441  int signalStrength(double snr) const;
442 
443  /* Creates RINEX file names according to the naming convention
444  *
445  * See ftp://igs.org/pub/data/format/rinex301.pdf
446  * Section 4, page 6
447  *
448  * \param[in] type of RINEX file. Can be:
449  * "RINEX_FILE_TYPE_OBS" - Observation file.
450  * "RINEX_FILE_TYPE_GPS_NAV" - GPS navigation message file.
451  * "RINEX_FILE_TYPE_MET" - Meteorological data file.
452  * "RINEX_FILE_TYPE_GLO_NAV" - GLONASS navigation file.
453  * "RINEX_FILE_TYPE_GAL_NAV" - Galileo navigation message file.
454  * "RINEX_FILE_TYPE_MIXED_NAV" - Mixed GNSS navigation message file.
455  * "RINEX_FILE_TYPE_GEO_NAV" - SBAS Payload navigation message file.
456  * "RINEX_FILE_TYPE_SBAS" - SBAS broadcast data file.
457  * "RINEX_FILE_TYPE_CLK" - Clock file.
458  */
459  std::string createFilename(const std::string& type, const std::string& base_name) const;
460 
461  /*
462  * Generates the data for the PGM / RUN BY / DATE line
463  */
464  std::string getLocalTime() const;
465 
466  /*
467  * Checks that the line is 80 characters length
468  */
469  void lengthCheck(const std::string& line) const;
470 
471  /*
472  * If the string is bigger than length, truncate it from the right.
473  * otherwise, add pad characters to its right.
474  *
475  * Left-justifies the input in a string of the specified
476  * length. If the new length (\a length) is larger than the
477  * current length, the string is extended by the pad
478  * character (\a pad). The default pad character is a
479  * blank.
480  * \param[in] s string to be modified.
481  * \param[in] length new desired length of string.
482  * \param[in] pad character to pad string with (blank by default).
483  * \return a reference to \a s. */
484  inline std::string& leftJustify(std::string& s,
485  std::string::size_type length,
486  char pad = ' ') const;
487 
488  /*
489  * If the string is bigger than length, truncate it from the right.
490  * otherwise, add pad characters to its right.
491  *
492  * Left-justifies the receiver in a string of the specified
493  * length (const version). If the new length (\a length) is larger
494  * than the current length, the string is extended by the pad
495  * character (\a pad). The default pad character is a
496  * blank.
497  * \param[in] s string to be modified.
498  * \param[in] length new desired length of string.
499  * \param[in] pad character to pad string with (blank by default).
500  * \return a reference to \a s. */
501  inline std::string leftJustify(const std::string& s,
502  std::string::size_type length,
503  char pad = ' ') const
504  {
505  std::string t(s);
506  return leftJustify(t, length, pad);
507  }
508 
509 
510  /*
511  * Right-justifies the receiver in a string of the specified
512  * length. If the receiver's data is shorter than the
513  * requested length (\a length), it is padded on the left with
514  * the pad character (\a pad). The default pad
515  * character is a blank. */
516  inline std::string& rightJustify(std::string& s,
517  std::string::size_type length,
518  char pad = ' ') const;
519 
520  /*
521  * Right-justifies the receiver in a string of the specified
522  * length (const version). If the receiver's data is shorter than the
523  * requested length (\a length), it is padded on the left with
524  * the pad character (\a pad). The default pad
525  * character is a blank.*/
526  inline std::string rightJustify(const std::string& s,
527  std::string::size_type length,
528  char pad = ' ') const
529  {
530  std::string t(s);
531  return rightJustify(t, length, pad);
532  }
533 
534 
535  /*
536  * Convert a double to a scientific notation number.
537  * @param d the double to convert
538  * @param length length (in characters) of output, including exponent
539  * @param expLen length (in characters) of the exponent, with sign
540  * @param showSign if true, reserves 1 character for +/- sign
541  * @param checkSwitch if true, keeps the exponential sanity check for
542  * exponentials above three characters in length. If false, it removes
543  * that check.
544  */
545  inline std::string doub2sci(double d,
546  std::string::size_type length,
547  std::string::size_type expLen,
548  bool showSign = true,
549  bool checkSwitch = true) const;
550 
551 
552  /*
553  * Convert scientific notation to FORTRAN notation.
554  * As an example, the string "1.5636E5" becomes " .15636D6".
555  * Note that the first character of the string will be '-' if
556  * the number is negative or ' ' if the first character is positive.
557  * @param aStr string with number to convert
558  * @param startPos start position of number in string
559  * @param length length (in characters) of number, including exponent.
560  * @param expLen length (in characters of exponent, not including sign.
561  * @param checkSwitch will keep the method running as originally programmed
562  * when set to true. If false, the method will always resize exponentials,
563  * produce an exponential with an E instead of a D, and always have a leading
564  * zero. For example -> 0.87654E-0004 or -0.1234E00005.
565  */
566  inline std::string& sci2for(std::string& aStr,
567  std::string::size_type startPos = 0,
568  std::string::size_type length = std::string::npos,
569  std::string::size_type expLen = 3,
570  bool checkSwitch = true) const;
571 
572 
573  /*
574  * Convert double precision floating point to a string
575  * containing the number in FORTRAN notation.
576  * As an example, the number 156360 becomes ".15636D6".
577  * @param d number to convert.
578  * @param length length (in characters) of number, including exponent.
579  * @param expLen length (in characters of exponent, including sign.
580  * @param checkSwitch if true, keeps the exponential sanity check for
581  * exponentials above three characters in length. If false, it removes
582  * that check.
583  * @return a string containing \a d in FORTRAN notation.
584  */
585  inline std::string doub2for(double d,
586  std::string::size_type length,
587  std::string::size_type expLen,
588  bool checkSwitch = true) const;
589 
590 
591  /*
592  * Convert a string to a double precision floating point number.
593  * @param s string containing a number.
594  * @return double representation of string.
595  */
596  inline double asDouble(const std::string& s) const
597  {
598  return strtod(s.c_str(), nullptr);
599  }
600 
601 
602  inline int toInt(const std::string& bitString, int sLength) const;
603 
604  /*
605  * Convert a string to an integer.
606  * @param s string containing a number.
607  * @return int64_t integer representation of string.
608  */
609  inline int64_t asInt(const std::string& s) const
610  {
611  return strtol(s.c_str(), nullptr, 10);
612  }
613 
614 
615  /*
616  * Convert a double to a string in fixed notation.
617  * @param x double.
618  * @param precision the number of decimal places you want displayed.
619  * @return string representation of \a x.
620  */
621  inline std::string asString(double x,
622  std::string::size_type precision = 17) const;
623 
624 
625  /*
626  * Convert a long double to a string in fixed notation.
627  * @param x long double.
628  * @param precision the number of decimal places you want displayed.
629  * @return string representation of \a x.
630  */
631  inline std::string asString(long double x,
632  std::string::size_type precision = 21) const;
633 
634 
635  /*
636  * Convert any old object to a string.
637  * The class must have stream operators defined.
638  * @param x object to turn into a string.
639  * @return string representation of \a x.
640  */
641  template <class X>
642  inline std::string asString(const X x) const;
643 
644  inline std::string asFixWidthString(int x, int width, char fill_digit) const;
645 
646  std::map<std::string, std::string> satelliteSystem; // GPS, GLONASS, SBAS payload, Galileo or Beidou
647  std::map<std::string, std::string> observationType; // PSEUDORANGE, CARRIER_PHASE, DOPPLER, SIGNAL_STRENGTH
648  std::map<std::string, std::string> observationCode; // GNSS observation descriptors
649  std::string stringVersion; // RINEX version (2.10/2.11 or 3.01/3.02)
650 
651  double fake_cnav_iode;
652  int version; // RINEX version (2 for 2.10/2.11 and 3 for 3.01)
653  int numberTypesObservations; // Number of available types of observable in the system. Should be public?
654  bool pre_2009_file_;
655 };
656 
657 
658 // Implementation of inline functions (modified versions from GPSTk https://github.com/SGL-UT/GPSTk)
659 
660 inline std::string& Rinex_Printer::leftJustify(std::string& s,
661  std::string::size_type length,
662  char pad) const
663 {
664  if (length < s.length())
665  {
666  s = s.substr(0, length);
667  }
668  else
669  {
670  s.append(length - s.length(), pad);
671  }
672  return s;
673 }
674 
675 
676 // if the string is bigger than length, truncate it from the left.
677 // otherwise, add pad characters to its left.
678 inline std::string& Rinex_Printer::rightJustify(std::string& s,
679  std::string::size_type length,
680  char pad) const
681 {
682  if (length < s.length())
683  {
684  s = s.substr(s.length() - length, std::string::npos);
685  }
686  else
687  {
688  s.insert(static_cast<std::string::size_type>(0), length - s.length(), pad);
689  }
690  return s;
691 }
692 
693 
694 inline std::string Rinex_Printer::doub2for(double d,
695  std::string::size_type length,
696  std::string::size_type expLen,
697  bool checkSwitch) const
698 {
699  int16_t exponentLength = expLen;
700 
701  /* Validate the assumptions regarding the input arguments */
702  if (exponentLength < 0)
703  {
704  exponentLength = 1;
705  }
706 
707  if (exponentLength > 3 && checkSwitch)
708  {
709  exponentLength = 3;
710  }
711 
712  std::string toReturn = doub2sci(d, length, exponentLength, true, checkSwitch);
713  sci2for(toReturn, 0, length, exponentLength, checkSwitch);
714 
715  return toReturn;
716 }
717 
718 
719 inline std::string Rinex_Printer::doub2sci(double d,
720  std::string::size_type length,
721  std::string::size_type expLen,
722  bool showSign,
723  bool checkSwitch) const
724 {
725  std::string toReturn;
726  int16_t exponentLength = expLen;
727 
728  /* Validate the assumptions regarding the input arguments */
729  if (exponentLength < 0)
730  {
731  exponentLength = 1;
732  }
733 
734  if (exponentLength > 3 && checkSwitch)
735  {
736  exponentLength = 3;
737  }
738 
739  std::stringstream c;
740  c.setf(std::ios::scientific, std::ios::floatfield);
741 
742  // length - 3 for special characters ('.', 'e', '+' or '-')
743  // - exponentlength (e04)
744  // - 1 for the digit before the decimal (2.)
745  // and if showSign == true,
746  // an extra -1 for '-' or ' ' if it's positive or negative
747  int expSize = 0;
748  if (showSign)
749  {
750  expSize = 1;
751  }
752 
753  c.precision(length - 3 - exponentLength - 1 - expSize);
754  c << d;
755  c >> toReturn;
756  return toReturn;
757 }
758 
759 
760 inline std::string& Rinex_Printer::sci2for(std::string& aStr,
761  std::string::size_type startPos,
762  std::string::size_type length,
763  std::string::size_type expLen,
764  bool checkSwitch) const
765 {
766  std::string::size_type idx = aStr.find('.', startPos);
767  int expAdd = 0;
768  std::string exp;
769  int64_t iexp;
770  // If checkSwitch is false, always redo the exponential. Otherwise,
771  // set it to false.
772  bool redoexp = !checkSwitch;
773 
774  // Check for decimal place within specified boundaries
775  if ((idx <= 0) || (idx >= (startPos + length - expLen - 1)))
776  {
777  // Error: no decimal point in string
778  return aStr;
779  }
780 
781  // Here, account for the possibility that there are
782  // no numbers to the left of the decimal, but do not
783  // account for the possibility of non-scientific
784  // notation (more than one digit to the left of the
785  // decimal)
786  if (idx > startPos)
787  {
788  redoexp = true;
789  // Swap digit and decimal.
790  aStr[idx] = aStr[idx - 1];
791  aStr[idx - 1] = '.';
792  // Only add one to the exponent if the number is non-zero
793  if (asDouble(aStr.substr(startPos, length)) != 0.0)
794  {
795  expAdd = 1;
796  }
797  }
798 
799  idx = aStr.find('e', startPos);
800  if (idx == std::string::npos)
801  {
802  idx = aStr.find('E', startPos);
803  if (idx == std::string::npos)
804  {
805  // Error: no 'e' or 'E' in string";
806  }
807  }
808 
809  // Change the exponent character to D normally, or E of checkSwitch is false.
810  if (checkSwitch)
811  {
812  aStr[idx] = 'D';
813  }
814  else
815  {
816  aStr[idx] = 'E';
817  }
818 
819  // Change the exponent itself
820  if (redoexp)
821  {
822  exp = aStr.substr(idx + 1, std::string::npos);
823  iexp = asInt(exp);
824  iexp += expAdd;
825 
826  aStr.erase(idx + 1);
827  if (iexp < 0)
828  {
829  aStr += "-";
830  iexp -= iexp * 2;
831  }
832  else
833  {
834  aStr += "+";
835  }
836 
837  aStr += Rinex_Printer::rightJustify(asString(iexp), expLen, '0');
838  }
839 
840  // if the number is positive, append a space
841  // (if it's negative, there's a leading '-'
842  if (aStr[0] == '.')
843  {
844  aStr.insert(static_cast<std::string::size_type>(0), 1, ' ');
845  }
846 
847  // If checkSwitch is false, add on one leading zero to the string
848  if (!checkSwitch)
849  {
850  aStr.insert(static_cast<std::string::size_type>(1), 1, '0');
851  }
852 
853  return aStr;
854 } // end sci2for
855 
856 
857 inline std::string asString(long double x, std::string::size_type precision)
858 {
859  std::ostringstream ss;
860  ss << std::fixed << std::setprecision(precision) << x;
861  return ss.str();
862 }
863 
864 
865 inline std::string Rinex_Printer::asString(double x, std::string::size_type precision) const
866 {
867  std::ostringstream ss;
868  ss << std::fixed << std::setprecision(precision) << x;
869  return ss.str();
870 }
871 
872 
873 inline std::string Rinex_Printer::asFixWidthString(int x, int width, char fill_digit) const
874 {
875  std::ostringstream ss;
876  ss << std::setfill(fill_digit) << std::setw(width) << x;
877  return ss.str().substr(ss.str().size() - width);
878 }
879 
880 
881 inline int64_t asInt(const std::string& s)
882 {
883  return strtol(s.c_str(), nullptr, 10);
884 }
885 
886 
887 inline int Rinex_Printer::toInt(const std::string& bitString, int sLength) const
888 {
889  int tempInt;
890  int num = 0;
891  for (int i = 0; i < sLength; i++)
892  {
893  tempInt = bitString[i] - '0';
894  num |= (1 << (sLength - 1 - i)) * tempInt;
895  }
896  return num;
897 }
898 
899 
900 template <class X>
901 inline std::string Rinex_Printer::asString(const X x) const
902 {
903  std::ostringstream ss;
904  ss << x;
905  return ss.str();
906 }
907 
908 
909 #endif
This class is a storage for the GPS IONOSPHERIC data as described in IS-GPS-200K. ...
Definition: gps_iono.h:33
This class is a storage and orbital model functions for the GPS SV ephemeris data as described in IS-...
This class is a storage for the BeiDou DNAV UTC Model.
This class is a storage and orbital model functions for the GPS SV ephemeris data as described in IS-...
Definition: gps_ephemeris.h:36
void log_rinex_obs(std::fstream &out, const Gps_Ephemeris &eph, double obs_time, const std::map< int32_t, Gnss_Synchro > &observables) const
Writes GPS L1 observables into the RINEX file.
void log_rinex_nav(std::fstream &out, const std::map< int32_t, Gps_Ephemeris > &eph_map) const
Writes data from the GPS L1 C/A navigation message into the RINEX file.
Rinex_Printer(int version=0, const std::string &base_path=".", const std::string &base_name="-")
Default constructor. Creates GNSS Navigation and Observables RINEX files and their headers...
std::fstream navMixFile
Output file stream for RINEX Mixed navigation data file.
This class is a storage for the BEIDOU IONOSPHERIC data as described in ICD v2.1. ...
Class that handles the generation of Receiver INdependent EXchange format (RINEX) files...
Definition: rinex_printer.h:75
void rinex_sbs_header(std::fstream &out) const
Generates the SBAS raw data header.
std::fstream navBdsFile
Output file stream for RINEX Galileo navigation data file.
This class is a storage and orbital model functions for the GLONASS SV ephemeris data as described in...
void rinex_obs_header(std::fstream &out, const Gps_Ephemeris &eph, double d_TOW_first_observation)
Generates the GPS Observation data header.
boost::posix_time::ptime compute_Galileo_time(const Galileo_Ephemeris &eph, double obs_time) const
Computes the Galileo time and returns a boost::posix_time::ptime object.
std::fstream navFile
Output file stream for RINEX navigation data file.
void update_nav_header(std::fstream &out, const Gps_Utc_Model &utc_model, const Gps_Iono &gps_iono, const Gps_Ephemeris &eph) const
Writes raw SBAS messages into the RINEX file.
~Rinex_Printer()
Default destructor. Closes GNSS Navigation and Observables RINEX files.
boost::posix_time::ptime compute_BDS_time(const Beidou_Dnav_Ephemeris &eph, double obs_time) const
Computes the BDS Time and returns a boost::posix_time::ptime object.
This class is a storage and orbital model functions for the GPS SV ephemeris data as described in Bei...
This is the class that contains the information that is shared by the processing blocks.
Definition: gnss_synchro.h:33
boost::posix_time::ptime compute_GPS_time(const Gps_Ephemeris &eph, double obs_time) const
Computes the GPS time and returns a boost::posix_time::ptime object.
std::fstream obsFile
Output file stream for RINEX observation file.
double get_leap_second(const Glonass_Gnav_Ephemeris &eph, double gps_obs_time) const
Computes number of leap seconds of GPS relative to UTC.
This class is a storage for the GPS UTC MODEL data as described in in IS-GPS-200K.
This class decodes a GPS NAV Data message as described in IS-GPS-200K.
This class is a storage for the GALILEO IONOSPHERIC data as described in Galileo ICD paragraph 5...
Definition: galileo_iono.h:32
void to_date_time(int gps_week, int gps_tow, int &year, int &month, int &day, int &hour, int &minute, int &second) const
Represents GPS time in the date time format. Leap years are considered, but leap seconds are not...
void rinex_nav_header(std::fstream &out, const Gps_Iono &iono, const Gps_Utc_Model &utc_model, const Gps_Ephemeris &eph) const
Generates the GPS L1 C/A Navigation Data header.
This class is a storage and orbital model functions for the Galileo SV ephemeris data as described in...
This class is a storage for the GLONASS GNAV UTC MODEL data as described in GLONASS ICD (Edition 5...
This class is a storage for the GPS UTC MODEL data as described in IS-GPS-200K.
Definition: gps_utc_model.h:32
This class is a storage for the GLONASS SV ALMANAC data as described GLONASS ICD (Edition 5...
std::fstream navGalFile
Output file stream for RINEX Galileo navigation data file.
std::fstream navGloFile
Output file stream for RINEX GLONASS navigation data file.
This class is a storage for the GALILEO UTC MODEL data as described in Galileo ICD https://www...
boost::posix_time::ptime compute_UTC_time(const Gps_Navigation_Message &nav_msg) const
Computes the UTC time and returns a boost::posix_time::ptime object.
This class is a storage for the GPS IONOSPHERIC data as described in IS-GPS-200K. ...
Definition: gps_cnav_iono.h:33
std::fstream sbsFile
Output file stream for RINEX SBAS raw data file.