Merge branch 'next' of github.com:gnss-sdr/gnss-sdr into pps_lime

This commit is contained in:
Javier Arribas 2022-08-14 12:12:33 +02:00
commit e5d6579e9a
19 changed files with 612 additions and 454 deletions

View File

@ -50,6 +50,8 @@ option(ENABLE_FLEXIBAND "Enable the use of the signal source adater for the Tele
option(ENABLE_ARRAY "Enable the use of CTTC's antenna array front-end as signal source (experimental)" OFF) option(ENABLE_ARRAY "Enable the use of CTTC's antenna array front-end as signal source (experimental)" OFF)
option(ENABLE_ZMQ "Enable GNU Radio ZeroMQ Messaging, requires gr-zeromq" OFF)
# Performance analysis tools # Performance analysis tools
option(ENABLE_GPERFTOOLS "Enable linking to Gperftools libraries (tcmalloc and profiler)" OFF) option(ENABLE_GPERFTOOLS "Enable linking to Gperftools libraries (tcmalloc and profiler)" OFF)
@ -598,7 +600,7 @@ set_package_properties(VOLK PROPERTIES
################################################################################ ################################################################################
# GNU Radio - https://www.gnuradio.org # GNU Radio - https://www.gnuradio.org
################################################################################ ################################################################################
set(GR_REQUIRED_COMPONENTS RUNTIME PMT BLOCKS FFT FILTER ANALOG) list(APPEND GR_REQUIRED_COMPONENTS RUNTIME PMT BLOCKS FFT FILTER ANALOG)
find_package(UHD) find_package(UHD)
set_package_properties(UHD PROPERTIES set_package_properties(UHD PROPERTIES
PURPOSE "Used for communication with front-ends of the USRP family." PURPOSE "Used for communication with front-ends of the USRP family."
@ -608,10 +610,14 @@ if(ENABLE_UHD)
if(NOT UHD_FOUND) if(NOT UHD_FOUND)
set(ENABLE_UHD OFF) set(ENABLE_UHD OFF)
else() else()
set(GR_REQUIRED_COMPONENTS ${GR_REQUIRED_COMPONENTS} UHD) list(APPEND GR_REQUIRED_COMPONENTS UHD)
endif() endif()
endif() endif()
if(ENABLE_ZMQ)
list(APPEND GR_REQUIRED_COMPONENTS ZEROMQ)
endif()
find_package(GNURADIO) find_package(GNURADIO)
set_package_properties(GNURADIO PROPERTIES set_package_properties(GNURADIO PROPERTIES
PURPOSE "Implements flowgraph scheduler, provides some processing blocks and classes to create new ones." PURPOSE "Implements flowgraph scheduler, provides some processing blocks and classes to create new ones."
@ -3406,6 +3412,7 @@ add_feature_info(ENABLE_AD936X_SDR ENABLE_AD9361 "Enables Ad936x_Iio_Signal_Sour
add_feature_info(ENABLE_RAW_UDP ENABLE_RAW_UDP "Enables Custom_UDP_Signal_Source for custom UDP packet sample source. Requires libpcap.") add_feature_info(ENABLE_RAW_UDP ENABLE_RAW_UDP "Enables Custom_UDP_Signal_Source for custom UDP packet sample source. Requires libpcap.")
add_feature_info(ENABLE_FLEXIBAND ENABLE_FLEXIBAND "Enables Flexiband_Signal_Source for using Teleorbit's Flexiband RF front-end. Requires gr-teleorbit.") add_feature_info(ENABLE_FLEXIBAND ENABLE_FLEXIBAND "Enables Flexiband_Signal_Source for using Teleorbit's Flexiband RF front-end. Requires gr-teleorbit.")
add_feature_info(ENABLE_ARRAY ENABLE_ARRAY "Enables Raw_Array_Signal_Source and Array_Signal_Conditioner for using CTTC's antenna array. Requires gr-dbfcttc.") add_feature_info(ENABLE_ARRAY ENABLE_ARRAY "Enables Raw_Array_Signal_Source and Array_Signal_Conditioner for using CTTC's antenna array. Requires gr-dbfcttc.")
add_feature_info(ENABLE_ZMQ ENABLE_ZMQ "Enables ZMQ_Signal_Source for GNU Radio ZeroMQ messages. Requires gr-zeromq.")
add_feature_info(ENABLE_GPERFTOOLS ENABLE_GPERFTOOLS "Enables performance analysis. Requires Gperftools.") add_feature_info(ENABLE_GPERFTOOLS ENABLE_GPERFTOOLS "Enables performance analysis. Requires Gperftools.")
add_feature_info(ENABLE_GPROF ENABLE_GPROF "Enables performance analysis with 'gprof'.") add_feature_info(ENABLE_GPROF ENABLE_GPROF "Enables performance analysis with 'gprof'.")
add_feature_info(ENABLE_CLANG_TIDY ENABLE_CLANG_TIDY "Runs clang-tidy along with the compiler. Requires Clang.") add_feature_info(ENABLE_CLANG_TIDY ENABLE_CLANG_TIDY "Runs clang-tidy along with the compiler. Requires Clang.")

View File

@ -1,7 +1,7 @@
# GNSS-SDR is a Global Navigation Satellite System software-defined receiver. # GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
# This file is part of GNSS-SDR. # This file is part of GNSS-SDR.
# #
# SPDX-FileCopyrightText: 2011-2020 C. Fernandez-Prades cfernandez(at)cttc.es # SPDX-FileCopyrightText: 2011-2022 C. Fernandez-Prades cfernandez(at)cttc.es
# SPDX-License-Identifier: BSD-3-Clause # SPDX-License-Identifier: BSD-3-Clause
######################################################################## ########################################################################
@ -193,6 +193,7 @@ gr_module(TRELLIS gnuradio-trellis gnuradio/trellis/api.h gnuradio-trellis)
gr_module(UHD gnuradio-uhd gnuradio/uhd/api.h gnuradio-uhd) gr_module(UHD gnuradio-uhd gnuradio/uhd/api.h gnuradio-uhd)
gr_module(VOCODER gnuradio-vocoder gnuradio/vocoder/api.h gnuradio-vocoder) gr_module(VOCODER gnuradio-vocoder gnuradio/vocoder/api.h gnuradio-vocoder)
gr_module(WAVELET gnuradio-wavelet gnuradio/wavelet/api.h gnuradio-wavelet) gr_module(WAVELET gnuradio-wavelet gnuradio/wavelet/api.h gnuradio-wavelet)
gr_module(ZEROMQ gnuradio-zeromq gnuradio/zeromq/api.h gnuradio-zeromq)
list(REMOVE_DUPLICATES GNURADIO_ALL_INCLUDE_DIRS) list(REMOVE_DUPLICATES GNURADIO_ALL_INCLUDE_DIRS)

View File

@ -36,6 +36,8 @@ All notable changes to GNSS-SDR will be documented in this file.
and IGM05 (SSR Code Bias). Please note that the content of the HAS messages is and IGM05 (SSR Code Bias). Please note that the content of the HAS messages is
**not** applied to the computed PVT solution. In the Galileo E6B-only **not** applied to the computed PVT solution. In the Galileo E6B-only
receiver, HAS messages are decoded and reported. receiver, HAS messages are decoded and reported.
- Added a `ZMQ_Signal_Source` for working with streams of samples published via
[ZeroMQ](https://zeromq.org/).
### Improvements in Maintainability: ### Improvements in Maintainability:

View File

@ -68,12 +68,23 @@ endif()
target_link_libraries(algorithms_libs_rtklib target_link_libraries(algorithms_libs_rtklib
PRIVATE PRIVATE
core_system_parameters core_system_parameters
algorithms_libs
Gflags::gflags Gflags::gflags
Glog::glog Glog::glog
LAPACK::LAPACK LAPACK::LAPACK
BLAS::BLAS BLAS::BLAS
) )
if(FILESYSTEM_FOUND)
target_compile_definitions(algorithms_libs_rtklib PUBLIC -DHAS_STD_FILESYSTEM=1)
if(find_experimental)
target_compile_definitions(algorithms_libs_rtklib PUBLIC -DHAS_STD_FILESYSTEM_EXPERIMENTAL=1)
endif()
target_link_libraries(algorithms_libs_rtklib PUBLIC std::filesystem)
else()
target_link_libraries(algorithms_libs_rtklib PUBLIC Boost::filesystem Boost::system)
endif()
set_property(TARGET algorithms_libs_rtklib set_property(TARGET algorithms_libs_rtklib
APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>

View File

@ -1108,28 +1108,28 @@ typedef struct
} serial_t; } serial_t;
typedef struct struct file_t
{ /* file control type */ { /* file control type */
FILE *fp; /* file pointer */ FILE *fp = nullptr; /* file pointer */
FILE *fp_tag; /* file pointer of tag file */ FILE *fp_tag = nullptr; /* file pointer of tag file */
FILE *fp_tmp; /* temporary file pointer for swap */ FILE *fp_tmp = nullptr; /* temporary file pointer for swap */
FILE *fp_tag_tmp; /* temporary file pointer of tag file for swap */ FILE *fp_tag_tmp = nullptr; /* temporary file pointer of tag file for swap */
char path[MAXSTRPATH]; /* file path */ std::string path; /* file path */
char openpath[MAXSTRPATH]; /* open file path */ std::string openpath; /* open file path */
int mode; /* file mode */ int mode = 0; /* file mode */
int timetag; /* time tag flag (0:off,1:on) */ int timetag; /* time tag flag (0:off,1:on) */
int repmode; /* replay mode (0:master,1:slave) */ int repmode = 0; /* replay mode (0:master,1:slave) */
int offset; /* time offset (ms) for slave */ int offset = 0; /* time offset (ms) for slave */
gtime_t time; /* start time */ gtime_t time = {}; /* start time */
gtime_t wtime; /* write time */ gtime_t wtime = {}; /* write time */
unsigned int tick; /* start tick */ unsigned int tick = 0; /* start tick */
unsigned int tick_f; /* start tick in file */ unsigned int tick_f = 0; /* start tick in file */
unsigned int fpos; /* current file position */ unsigned int fpos = 0; /* current file position */
double start; /* start offset (s) */ double start = 0; /* start offset (s) */
double speed; /* replay speed (time factor) */ double speed = 0; /* replay speed (time factor) */
double swapintv; /* swap interval (hr) (0: no swap) */ double swapintv = 0; /* swap interval (hr) (0: no swap) */
lock_t lock; /* lock flag */ lock_t lock; /* lock flag */
} file_t; };
typedef struct typedef struct

View File

@ -720,7 +720,6 @@ int raim_fde(const obsd_t *obs, int n, const double *rs,
obsd_t *obs_e; obsd_t *obs_e;
sol_t sol_e = {{0, 0}, {}, {}, {}, '0', '0', '0', 0.0, 0.0, 0.0}; sol_t sol_e = {{0, 0}, {}, {}, {}, '0', '0', '0', 0.0, 0.0, 0.0};
char tstr[32]; char tstr[32];
char name[16];
char msg_e[128]; char msg_e[128];
double *rs_e; double *rs_e;
double *dts_e; double *dts_e;
@ -819,8 +818,8 @@ int raim_fde(const obsd_t *obs, int n, const double *rs,
if (stat) if (stat)
{ {
time2str(obs[0].time, tstr, 2); time2str(obs[0].time, tstr, 2);
satno2id(sat, name); auto name = satno2id(sat);
trace(2, "%s: %s excluded by raim\n", tstr + 11, name); trace(2, "%s: %s excluded by raim\n", tstr + 11, name.data());
} }
free(obs_e); free(obs_e);
free(rs_e); free(rs_e);

View File

@ -747,7 +747,6 @@ void pppoutsolstat(rtk_t *rtk, int level, FILE *fp)
int j; int j;
int week; int week;
int nfreq = 1; int nfreq = 1;
char id[32];
if (level <= 0 || !fp) if (level <= 0 || !fp)
{ {
@ -804,11 +803,11 @@ void pppoutsolstat(rtk_t *rtk, int level, FILE *fp)
{ {
continue; continue;
} }
satno2id(i + 1, id); auto id = satno2id(i + 1);
for (j = 0; j < nfreq; j++) for (j = 0; j < nfreq; j++)
{ {
fprintf(fp, "$SAT,%d,%.3f,%s,%d,%.1f,%.1f,%.4f,%.4f,%d,%.0f,%d,%d,%d,%d,%d,%d\n", fprintf(fp, "$SAT,%d,%.3f,%s,%d,%.1f,%.1f,%.4f,%.4f,%d,%.0f,%d,%d,%d,%d,%d,%d\n",
week, tow, id, j + 1, ssat->azel[0] * R2D, ssat->azel[1] * R2D, week, tow, id.data(), j + 1, ssat->azel[0] * R2D, ssat->azel[1] * R2D,
ssat->resp[j], ssat->resc[j], ssat->vsat[j], ssat->snr[j] * 0.25, ssat->resp[j], ssat->resc[j], ssat->vsat[j], ssat->snr[j] * 0.25,
ssat->fix[j], ssat->slip[j] & 3, ssat->lock[j], ssat->outc[j], ssat->fix[j], ssat->slip[j] & 3, ssat->lock[j], ssat->outc[j],
ssat->slipc[j], ssat->rejc[j]); ssat->slipc[j], ssat->rejc[j]);

View File

@ -35,7 +35,7 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <dirent.h> #include <dirent.h>
#include <iostream> #include <iomanip>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <sys/stat.h> #include <sys/stat.h>
@ -43,7 +43,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <vector> #include <vector>
const double GPST0[] = {1980, 1, 6, 0, 0, 0}; /* gps time reference */ const double GPST0[] = {1980, 1, 6, 0, 0, 0}; /* gps time reference */
const double GST0[] = {1999, 8, 22, 0, 0, 0}; /* galileo system time reference */ const double GST0[] = {1999, 8, 22, 0, 0, 0}; /* galileo system time reference */
const double BDT0[] = {2006, 1, 1, 0, 0, 0}; /* beidou time reference */ const double BDT0[] = {2006, 1, 1, 0, 0, 0}; /* beidou time reference */
@ -460,37 +459,50 @@ int satid2no(const char *id)
* char *id O satellite id (Gnn,Rnn,Enn,Jnn,Cnn,Inn or nnn) * char *id O satellite id (Gnn,Rnn,Enn,Jnn,Cnn,Inn or nnn)
* return : none * return : none
*-----------------------------------------------------------------------------*/ *-----------------------------------------------------------------------------*/
void satno2id(int sat, char *id) std::string satno2id(int sat)
{ {
std::ostringstream ss;
ss << std::setfill('0'); // all PRNs are 0-filled
std::string prefix;
int width = 2;
int prn; int prn;
char id_aux[16];
switch (satsys(sat, &prn)) switch (satsys(sat, &prn))
{ {
case SYS_GPS: case SYS_GPS:
std::snprintf(id, sizeof(id_aux), "G%02d", prn - MINPRNGPS + 1); prefix = "G";
return; prn = prn - MINPRNGPS + 1;
break;
case SYS_GLO: case SYS_GLO:
snprintf(id, sizeof(id_aux), "R%02d", prn - MINPRNGLO + 1); prefix = "R";
return; prn = prn - MINPRNGLO + 1;
break;
case SYS_GAL: case SYS_GAL:
std::snprintf(id, sizeof(id_aux), "E%02d", prn - MINPRNGAL + 1); prefix = "E";
return; prn = prn - MINPRNGAL + 1;
break;
case SYS_QZS: case SYS_QZS:
std::snprintf(id, sizeof(id_aux), "J%02d", prn - MINPRNQZS + 1); prefix = "J";
return; prn = prn - MINPRNQZS + 1;
break;
case SYS_BDS: case SYS_BDS:
std::snprintf(id, sizeof(id_aux), "C%02d", prn - MINPRNBDS + 1); prefix = "C";
return; prn = prn - MINPRNBDS + 1;
break;
case SYS_IRN: case SYS_IRN:
std::snprintf(id, sizeof(id_aux), "I%02d", prn - MINPRNIRN + 1); prefix = "I";
return; prn = prn - MINPRNIRN + 1;
break;
case SYS_LEO: case SYS_LEO:
std::snprintf(id, sizeof(id_aux), "L%02d", prn - MINPRNLEO + 1); prefix = "L";
return; prn = prn - MINPRNLEO + 1;
break;
case SYS_SBS: case SYS_SBS:
std::snprintf(id, sizeof(id_aux), "%03d", prn); width = 3;
return; break;
} }
ss << prefix << std::setw(width) << prn;
return ss.str();
} }
@ -2833,9 +2845,9 @@ int readantex(const char *file, pcvs_t *pcvs)
if (strstr(buff + 60, "TYPE / SERIAL NO")) if (strstr(buff + 60, "TYPE / SERIAL NO"))
{ {
strncpy(pcv.type, buff, 20); strncpy(pcv.type, buff, 20); // MAXANT (64)
pcv.type[20] = '\0'; pcv.type[20] = '\0';
strncpy(pcv.code, buff + 20, 20); strncpy(pcv.code, buff + 20, 20); // MAXANT (64)
pcv.code[20] = '\0'; pcv.code[20] = '\0';
if (!strncmp(pcv.code + 3, " ", 8)) if (!strncmp(pcv.code + 3, " ", 8))
{ {
@ -3090,9 +3102,9 @@ void readpos(const char *file, const char *rcv, double *pos)
{ {
continue; continue;
} }
// strncpy(stas[np], str, 15); This line triggers a warning. Replaced by: auto sta = stas[np++]; // NOLINT(readability-qualified-auto)
memcpy(stas[np], str, 15 * sizeof(stas[np][0])); std::strncpy(sta, str, 16);
stas[np++][15] = '\0'; sta[15] = '\0';
} }
fclose(fp); fclose(fp);
len = static_cast<int>(strlen(rcv)); len = static_cast<int>(strlen(rcv));
@ -3700,7 +3712,6 @@ int savenav(const char *file, const nav_t *nav)
{ {
FILE *fp; FILE *fp;
int i; int i;
char id[32];
trace(3, "savenav: file=%s\n", file); trace(3, "savenav: file=%s\n", file);
@ -3715,12 +3726,12 @@ int savenav(const char *file, const nav_t *nav)
{ {
continue; continue;
} }
satno2id(nav->eph[i].sat, id); auto id = satno2id(nav->eph[i].sat);
fprintf(fp, fprintf(fp,
"%s,%d,%d,%d,%d,%d,%d,%d,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E," "%s,%d,%d,%d,%d,%d,%d,%d,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,"
"%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E," "%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,"
"%.14E,%.14E,%.14E,%.14E,%.14E,%d,%d\n", "%.14E,%.14E,%.14E,%.14E,%.14E,%d,%d\n",
id, nav->eph[i].iode, nav->eph[i].iodc, nav->eph[i].sva, id.data(), nav->eph[i].iode, nav->eph[i].iodc, nav->eph[i].sva,
nav->eph[i].svh, static_cast<int>(nav->eph[i].toe.time), nav->eph[i].svh, static_cast<int>(nav->eph[i].toe.time),
static_cast<int>(nav->eph[i].toc.time), static_cast<int>(nav->eph[i].ttr.time), static_cast<int>(nav->eph[i].toc.time), static_cast<int>(nav->eph[i].ttr.time),
nav->eph[i].A, nav->eph[i].e, nav->eph[i].i0, nav->eph[i].OMG0, nav->eph[i].A, nav->eph[i].e, nav->eph[i].i0, nav->eph[i].OMG0,
@ -3736,11 +3747,11 @@ int savenav(const char *file, const nav_t *nav)
{ {
continue; continue;
} }
satno2id(nav->geph[i].sat, id); auto id = satno2id(nav->geph[i].sat);
fprintf(fp, fprintf(fp,
"%s,%d,%d,%d,%d,%d,%d,%d,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E," "%s,%d,%d,%d,%d,%d,%d,%d,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,"
"%.14E,%.14E,%.14E,%.14E,%.14E,%.14E\n", "%.14E,%.14E,%.14E,%.14E,%.14E,%.14E\n",
id, nav->geph[i].iode, nav->geph[i].frq, nav->geph[i].svh, id.data(), nav->geph[i].iode, nav->geph[i].frq, nav->geph[i].svh,
nav->geph[i].sva, nav->geph[i].age, static_cast<int>(nav->geph[i].toe.time), nav->geph[i].sva, nav->geph[i].age, static_cast<int>(nav->geph[i].toe.time),
static_cast<int>(nav->geph[i].tof.time), static_cast<int>(nav->geph[i].tof.time),
nav->geph[i].pos[0], nav->geph[i].pos[1], nav->geph[i].pos[2], nav->geph[i].pos[0], nav->geph[i].pos[1], nav->geph[i].pos[2],
@ -3841,7 +3852,7 @@ void freenav(nav_t *nav, int opt)
// #ifdef TRACE // #ifdef TRACE
// //
FILE *fp_trace = nullptr; /* file pointer of trace */ FILE *fp_trace = nullptr; /* file pointer of trace */
char file_trace[1024]; /* trace file */ std::string file_trace; /* trace file */
static int level_trace = 0; /* level of trace */ static int level_trace = 0; /* level of trace */
unsigned int tick_trace = 0; /* tick time at traceopen (ms) */ unsigned int tick_trace = 0; /* tick time at traceopen (ms) */
gtime_t time_trace = {0, 0.0}; /* time at traceopen */ gtime_t time_trace = {0, 0.0}; /* time at traceopen */
@ -3850,7 +3861,7 @@ pthread_mutex_t lock_trace; /* lock for trace */
void traceswap() void traceswap()
{ {
gtime_t time = utc2gpst(timeget()); gtime_t time = utc2gpst(timeget());
char path[1024]; std::string path;
rtk_lock(&lock_trace); rtk_lock(&lock_trace);
@ -3872,7 +3883,7 @@ void traceswap()
fclose(fp_trace); fclose(fp_trace);
} }
if (!(fp_trace = fopen(path, "we"))) if (!(fp_trace = fopen(path.data(), "we")))
{ {
fp_trace = stderr; fp_trace = stderr;
} }
@ -3883,22 +3894,15 @@ void traceswap()
void traceopen(const char *file) void traceopen(const char *file)
{ {
gtime_t time = utc2gpst(timeget()); gtime_t time = utc2gpst(timeget());
char path[1024]; std::string path;
reppath(file, path, time, "", ""); reppath(file, path, time, "", "");
if (!*path || !(fp_trace = fopen(path, "we"))) if (path.empty() or (fp_trace = fopen(path.data(), "we")) == nullptr)
{ {
fp_trace = stderr; fp_trace = stderr;
} }
if (strlen(file) < 1025)
{ file_trace = file;
std::strncpy(file_trace, file, 1024);
file_trace[1023] = '\0';
}
else
{
trace(1, "file array is too long");
}
tick_trace = tickget(); tick_trace = tickget();
time_trace = time; time_trace = time;
initlock(&lock_trace); initlock(&lock_trace);
@ -3912,7 +3916,7 @@ void traceclose()
fclose(fp_trace); fclose(fp_trace);
} }
fp_trace = nullptr; fp_trace = nullptr;
file_trace[0] = '\0'; file_trace.clear();
} }
@ -3967,9 +3971,9 @@ void traceobs(int level __attribute__((unused)), const obsd_t *obs __attribute__
// if (!fp_trace||level>level_trace) return; // if (!fp_trace||level>level_trace) return;
// for (i=0;i<n;i++) { // for (i=0;i<n;i++) {
// time2str(obs[i].time,str,3); // time2str(obs[i].time,str,3);
// satno2id(obs[i].sat,id); // auto id = satno2id(obs[i].sat);
// fprintf(fp_trace," (%2d) %s %-3s rcv%d %13.3f %13.3f %13.3f %13.3f %d %d %d %d %3.1f %3.1f\n", // fprintf(fp_trace," (%2d) %s %-3s rcv%d %13.3f %13.3f %13.3f %13.3f %d %d %d %d %3.1f %3.1f\n",
// i+1,str,id,obs[i].rcv,obs[i].L[0],obs[i].L[1],obs[i].P[0], // i+1,str,id.data(),obs[i].rcv,obs[i].L[0],obs[i].L[1],obs[i].P[0],
// obs[i].P[1],obs[i].LLI[0],obs[i].LLI[1],obs[i].code[0], // obs[i].P[1],obs[i].LLI[0],obs[i].LLI[1],obs[i].code[0],
// obs[i].code[1],obs[i].SNR[0]*0.25,obs[i].SNR[1]*0.25); // obs[i].code[1],obs[i].SNR[0]*0.25,obs[i].SNR[1]*0.25);
// } // }
@ -3985,9 +3989,9 @@ void traceobs(int level __attribute__((unused)), const obsd_t *obs __attribute__
// for (i=0;i<nav->n;i++) { // for (i=0;i<nav->n;i++) {
// time2str(nav->eph[i].toe,s1,0); // time2str(nav->eph[i].toe,s1,0);
// time2str(nav->eph[i].ttr,s2,0); // time2str(nav->eph[i].ttr,s2,0);
// satno2id(nav->eph[i].sat,id); // auto id = satno2id(nav->eph[i].sat);
// fprintf(fp_trace,"(%3d) %-3s : %s %s %3d %3d %02x\n",i+1, // fprintf(fp_trace,"(%3d) %-3s : %s %s %3d %3d %02x\n",i+1,
// id,s1,s2,nav->eph[i].iode,nav->eph[i].iodc,nav->eph[i].svh); // id.data(),s1,s2,nav->eph[i].iode,nav->eph[i].iodc,nav->eph[i].svh);
// } // }
// fprintf(fp_trace,"(ion) %9.4e %9.4e %9.4e %9.4e\n",nav->ion_gps[0], // fprintf(fp_trace,"(ion) %9.4e %9.4e %9.4e %9.4e\n",nav->ion_gps[0],
// nav->ion_gps[1],nav->ion_gps[2],nav->ion_gps[3]); // nav->ion_gps[1],nav->ion_gps[2],nav->ion_gps[3]);
@ -4005,9 +4009,9 @@ void traceobs(int level __attribute__((unused)), const obsd_t *obs __attribute__
// for (i=0;i<nav->ng;i++) { // for (i=0;i<nav->ng;i++) {
// time2str(nav->geph[i].toe,s1,0); // time2str(nav->geph[i].toe,s1,0);
// time2str(nav->geph[i].tof,s2,0); // time2str(nav->geph[i].tof,s2,0);
// satno2id(nav->geph[i].sat,id); // auto id = satno2id(nav->geph[i].sat);
// fprintf(fp_trace,"(%3d) %-3s : %s %s %2d %2d %8.3f\n",i+1, // fprintf(fp_trace,"(%3d) %-3s : %s %s %2d %2d %8.3f\n",i+1,
// id,s1,s2,nav->geph[i].frq,nav->geph[i].svh,nav->geph[i].taun*1e6); // id.data(),s1,s2,nav->geph[i].frq,nav->geph[i].svh,nav->geph[i].taun*1e6);
// } // }
// } // }
// extern void tracehnav(int level, const nav_t *nav) // extern void tracehnav(int level, const nav_t *nav)
@ -4019,14 +4023,14 @@ void traceobs(int level __attribute__((unused)), const obsd_t *obs __attribute__
// for (i=0;i<nav->ns;i++) { // for (i=0;i<nav->ns;i++) {
// time2str(nav->seph[i].t0,s1,0); // time2str(nav->seph[i].t0,s1,0);
// time2str(nav->seph[i].tof,s2,0); // time2str(nav->seph[i].tof,s2,0);
// satno2id(nav->seph[i].sat,id); // auto id = satno2id(nav->seph[i].sat);
// fprintf(fp_trace,"(%3d) %-3s : %s %s %2d %2d\n",i+1, // fprintf(fp_trace,"(%3d) %-3s : %s %s %2d %2d\n",i+1,
// id,s1,s2,nav->seph[i].svh,nav->seph[i].sva); // id.data(),s1,s2,nav->seph[i].svh,nav->seph[i].sva);
// } // }
// } // }
// extern void tracepeph(int level, const nav_t *nav) // extern void tracepeph(int level, const nav_t *nav)
// { // {
// char s[64],id[16]; // char s[64];
// int i,j; // int i,j;
// //
// if (!fp_trace||level>level_trace) return; // if (!fp_trace||level>level_trace) return;
@ -4034,9 +4038,9 @@ void traceobs(int level __attribute__((unused)), const obsd_t *obs __attribute__
// for (i=0;i<nav->ne;i++) { // for (i=0;i<nav->ne;i++) {
// time2str(nav->peph[i].time,s,0); // time2str(nav->peph[i].time,s,0);
// for (j=0;j<MAXSAT;j++) { // for (j=0;j<MAXSAT;j++) {
// satno2id(j+1,id); // auto id = satno2id(j+1);
// fprintf(fp_trace,"%-3s %d %-3s %13.3f %13.3f %13.3f %13.3f %6.3f %6.3f %6.3f %6.3f\n", // fprintf(fp_trace,"%-3s %d %-3s %13.3f %13.3f %13.3f %13.3f %6.3f %6.3f %6.3f %6.3f\n",
// s,nav->peph[i].index,id, // s,nav->peph[i].index,id.data(),
// nav->peph[i].pos[j][0],nav->peph[i].pos[j][1], // nav->peph[i].pos[j][0],nav->peph[i].pos[j][1],
// nav->peph[i].pos[j][2],nav->peph[i].pos[j][3]*1e9, // nav->peph[i].pos[j][2],nav->peph[i].pos[j][3]*1e9,
// nav->peph[i].std[j][0],nav->peph[i].std[j][1], // nav->peph[i].std[j][0],nav->peph[i].std[j][1],
@ -4046,7 +4050,7 @@ void traceobs(int level __attribute__((unused)), const obsd_t *obs __attribute__
// } // }
// extern void tracepclk(int level, const nav_t *nav) // extern void tracepclk(int level, const nav_t *nav)
// { // {
// char s[64],id[16]; // char s[64];
// int i,j; // int i,j;
// //
// if (!fp_trace||level>level_trace) return; // if (!fp_trace||level>level_trace) return;
@ -4054,9 +4058,9 @@ void traceobs(int level __attribute__((unused)), const obsd_t *obs __attribute__
// for (i=0;i<nav->nc;i++) { // for (i=0;i<nav->nc;i++) {
// time2str(nav->pclk[i].time,s,0); // time2str(nav->pclk[i].time,s,0);
// for (j=0;j<MAXSAT;j++) { // for (j=0;j<MAXSAT;j++) {
// satno2id(j+1,id); // auto id = satno2id(j+1);
// fprintf(fp_trace,"%-3s %d %-3s %13.3f %6.3f\n", // fprintf(fp_trace,"%-3s %d %-3s %13.3f %6.3f\n",
// s,nav->pclk[i].index,id, // s,nav->pclk[i].index,id.data(),
// nav->pclk[i].clk[j][0]*1e9,nav->pclk[i].std[j][0]*1e9); // nav->pclk[i].clk[j][0]*1e9,nav->pclk[i].std[j][0]*1e9);
// } // }
// } // }
@ -4114,69 +4118,31 @@ int execcmd(const char *cmd)
* return : none * return : none
* notes : not recursive. only one level * notes : not recursive. only one level
*-----------------------------------------------------------------------------*/ *-----------------------------------------------------------------------------*/
void createdir(const char *path) void createdir(fs::path const &path)
{ {
char buff[1024]; errorlib::error_code ec;
char *p;
// tracet(3, "createdir: path=%s\n", path);
if (strlen(path) < 1025) auto created = fs::create_directory(path, ec);
if (not created)
{ {
std::strncpy(buff, path, 1024); trace(1, "Error creating folder: %s", path.c_str());
buff[1023] = '\0';
}
else
{
trace(1, "path is too long");
}
if (!(p = strrchr(buff, FILEPATHSEP)))
{
return;
}
*p = '\0';
if (mkdir(buff, 0777) != 0)
{
trace(1, "Error creating folder");
} }
} }
/* replace string ------------------------------------------------------------*/ /* replace string ------------------------------------------------------------*/
int repstr(char *str, const char *pat, const char *rep) int repstr(std::string &str, std::string const &pat, std::string const &rep)
{ {
int len = static_cast<int>(strlen(pat)); int replaced = 0;
char buff[1024];
char *p;
char *q;
char *r;
for (p = str, r = buff; *p; p = q + len) auto pos = str.find(pat);
if (pos != std::string::npos)
{ {
if (!(q = strstr(p, pat))) str.replace(pos, pat.length(), rep);
{ replaced = 1;
break;
}
strncpy(r, p, q - p);
r += q - p;
r += std::snprintf(r, sizeof(buff), "%s", rep);
}
if (p <= str)
{
return 0;
} }
if (strlen(p) < 1025) return replaced;
{
std::strncpy(r, p, 1024);
r[1023] = '\0';
}
else
{
trace(1, "pat array is too long");
}
std::strncpy(str, buff, 1024);
return 1;
} }
@ -4208,23 +4174,19 @@ int repstr(char *str, const char *pat, const char *rep)
* %r -> rrrr : rover id * %r -> rrrr : rover id
* %b -> bbbb : base station id * %b -> bbbb : base station id
*-----------------------------------------------------------------------------*/ *-----------------------------------------------------------------------------*/
int reppath(const char *path, char *rpath, gtime_t time, const char *rov, int reppath(std::string const &path, std::string &rpath, gtime_t time, const char *rov,
const char *base) const char *base)
{ {
double ep[6];
double ep0[6] = {2000, 1, 1, 0, 0, 0};
int week;
int dow;
int doy;
int stat = 0; int stat = 0;
char rep[64];
std::strncpy(rpath, path, 1024); rpath = path;
// synctactic sugar; implements C++23 std::string::contains()
auto patFind = [](std::string const &s, std::string const &pat) -> bool {
auto pos = s.find(pat);
return pos != s.npos;
};
if (!strstr(rpath, "%"))
{
return 0;
}
if (*rov) if (*rov)
{ {
stat |= repstr(rpath, "%r", rov); stat |= repstr(rpath, "%r", rov);
@ -4235,10 +4197,17 @@ int reppath(const char *path, char *rpath, gtime_t time, const char *rov,
} }
if (time.time != 0) if (time.time != 0)
{ {
char rep[64]; // scratch space for replacement string
double ep[6];
time2epoch(time, ep); time2epoch(time, ep);
ep0[0] = ep[0];
dow = static_cast<int>(floor(time2gpst(time, &week) / 86400.0)); int week = 0;
doy = static_cast<int>(floor(timediff(time, epoch2time(ep0)) / 86400.0)) + 1; auto dow = static_cast<int>(floor(time2gpst(time, &week) / 86400.0));
double ep0[6] = {ep[0], 1, 1, 0, 0, 0};
auto doy = static_cast<int>(floor(timediff(time, epoch2time(ep0)) / 86400.0)) + 1;
std::snprintf(rep, sizeof(rep), "%02d", (static_cast<int>(ep[3]) / 3) * 3); std::snprintf(rep, sizeof(rep), "%02d", (static_cast<int>(ep[3]) / 3) * 3);
stat |= repstr(rpath, "%ha", rep); stat |= repstr(rpath, "%ha", rep);
std::snprintf(rep, sizeof(rep), "%02d", (static_cast<int>(ep[3]) / 6) * 6); std::snprintf(rep, sizeof(rep), "%02d", (static_cast<int>(ep[3]) / 6) * 6);
@ -4270,78 +4239,18 @@ int reppath(const char *path, char *rpath, gtime_t time, const char *rov,
std::snprintf(rep, sizeof(rep), "%02d", (static_cast<int>(ep[4]) / 15) * 15); std::snprintf(rep, sizeof(rep), "%02d", (static_cast<int>(ep[4]) / 15) * 15);
stat |= repstr(rpath, "%t", rep); stat |= repstr(rpath, "%t", rep);
} }
else if (strstr(rpath, "%ha") || strstr(rpath, "%hb") || strstr(rpath, "%hc") || else if (patFind(rpath, "%ha") || patFind(rpath, "%hb") || patFind(rpath, "%hc") ||
strstr(rpath, "%Y") || strstr(rpath, "%y") || strstr(rpath, "%m") || patFind(rpath, "%Y") || patFind(rpath, "%y") || patFind(rpath, "%m") ||
strstr(rpath, "%d") || strstr(rpath, "%h") || strstr(rpath, "%M") || patFind(rpath, "%d") || patFind(rpath, "%h") || patFind(rpath, "%M") ||
strstr(rpath, "%S") || strstr(rpath, "%n") || strstr(rpath, "%W") || patFind(rpath, "%S") || patFind(rpath, "%n") || patFind(rpath, "%W") ||
strstr(rpath, "%D") || strstr(rpath, "%H") || strstr(rpath, "%t")) patFind(rpath, "%D") || patFind(rpath, "%H") || patFind(rpath, "%t"))
{ {
return -1; /* no valid time */ stat = -1; /* no valid time */
} }
return stat; return stat;
} }
/* replace keywords in file path and generate multiple paths -------------------
* replace keywords in file path with date, time, rover and base station id
* generate multiple keywords-replaced paths
* args : char *path I file path (see below)
* char *rpath[] O file paths in which keywords replaced
* int nmax I max number of output file paths
* gtime_t ts I time start (gpst)
* gtime_t te I time end (gpst)
* char *rov I rover id string ("": not replaced)
* char *base I base station id string ("": not replaced)
* return : number of replaced file paths
* notes : see reppath() for replacements of keywords.
* minimum interval of time replaced is 900s.
*-----------------------------------------------------------------------------*/
int reppaths(const char *path, char *rpath[], int nmax, gtime_t ts,
gtime_t te, const char *rov, const char *base)
{
gtime_t time;
double tow;
double tint = 86400.0;
int i;
int n = 0;
int week;
trace(3, "reppaths: path =%s nmax=%d rov=%s base=%s\n", path, nmax, rov, base);
if (ts.time == 0 || te.time == 0 || timediff(ts, te) > 0.0)
{
return 0;
}
if (strstr(path, "%S") || strstr(path, "%M") || strstr(path, "%t"))
{
tint = 900.0;
}
else if (strstr(path, "%h") || strstr(path, "%H"))
{
tint = 3600.0;
}
tow = time2gpst(ts, &week);
time = gpst2time(week, floor(tow / tint) * tint);
while (timediff(time, te) <= 0.0 && n < nmax)
{
reppath(path, rpath[n], time, rov, base);
if (n == 0 || strcmp(rpath[n], rpath[n - 1]) != 0)
{
n++;
}
time = timeadd(time, tint);
}
for (i = 0; i < n; i++)
{
trace(3, "reppaths: rpath=%s\n", rpath[i]);
}
return n;
}
/* satellite carrier wave length ----------------------------------------------- /* satellite carrier wave length -----------------------------------------------
* get satellite carrier wave lengths * get satellite carrier wave lengths
* args : int sat I satellite number * args : int sat I satellite number

View File

@ -62,6 +62,24 @@
#include <cstddef> #include <cstddef>
#include <string> #include <string>
#if HAS_STD_FILESYSTEM
#include <system_error>
namespace errorlib = std;
#if HAS_STD_FILESYSTEM_EXPERIMENTAL
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
#include <filesystem>
namespace fs = std::filesystem;
#endif
#else
#include <boost/filesystem/operations.hpp> // for create_directories, exists
#include <boost/filesystem/path.hpp> // for path, operator<<
#include <boost/filesystem/path_traits.hpp> // for filesystem
#include <boost/system/error_code.hpp> // for error_code
namespace fs = boost::filesystem;
namespace errorlib = boost::system;
#endif
/* coordinate rotation matrix ------------------------------------------------*/ /* coordinate rotation matrix ------------------------------------------------*/
#define Rx(t, X) \ #define Rx(t, X) \
@ -102,7 +120,7 @@ void fatalerr(const char *format, ...);
int satno(int sys, int prn); int satno(int sys, int prn);
int satsys(int sat, int *prn); int satsys(int sat, int *prn);
int satid2no(const char *id); int satid2no(const char *id);
void satno2id(int sat, char *id); std::string satno2id(int sat);
int satexclude(int sat, int svh, const prcopt_t *opt); int satexclude(int sat, int svh, const prcopt_t *opt);
int testsnr(int base, int freq, double el, double snr, const snrmask_t *mask); int testsnr(int base, int freq, double el, double snr, const snrmask_t *mask);
unsigned char obs2code(const char *obs, int *freq); unsigned char obs2code(const char *obs, int *freq);
@ -229,12 +247,9 @@ void traceobs(int level, const obsd_t *obs, int n);
// void traceb (int level, const unsigned char *p, int n); // void traceb (int level, const unsigned char *p, int n);
int execcmd(const char *cmd); int execcmd(const char *cmd);
void createdir(const char *path); void createdir(fs::path const &path);
int repstr(char *str, const char *pat, const char *rep); int reppath(std::string const &path, std::string &rpath, gtime_t time, const char *rov,
int reppath(const char *path, char *rpath, gtime_t time, const char *rov,
const char *base); const char *base);
int reppaths(const char *path, char *rpath[], int nmax, gtime_t ts,
gtime_t te, const char *rov, const char *base);
double satwavelen(int sat, int frq, const nav_t *nav); double satwavelen(int sat, int frq, const nav_t *nav);
double geodist(const double *rs, const double *rr, double *e); double geodist(const double *rs, const double *rr, double *e);
double satazel(const double *pos, const double *e, double *azel); double satazel(const double *pos, const double *e, double *azel);

View File

@ -37,6 +37,7 @@
#include "rtklib_tides.h" #include "rtklib_tides.h"
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
#include <string>
#include <vector> #include <vector>
static int resamb_WLNL(rtk_t *rtk __attribute((unused)), const obsd_t *obs __attribute((unused)), const int *sat __attribute((unused)), static int resamb_WLNL(rtk_t *rtk __attribute((unused)), const obsd_t *obs __attribute((unused)), const int *sat __attribute((unused)),
@ -124,7 +125,7 @@ static gtime_t time_stat = {0, 0}; /* rtk status file time */
int rtkopenstat(const char *file, int level) int rtkopenstat(const char *file, int level)
{ {
gtime_t time = utc2gpst(timeget()); gtime_t time = utc2gpst(timeget());
char path[1024]; std::string path;
trace(3, "rtkopenstat: file=%s level=%d\n", file, level); trace(3, "rtkopenstat: file=%s level=%d\n", file, level);
@ -135,9 +136,9 @@ int rtkopenstat(const char *file, int level)
reppath(file, path, time, "", ""); reppath(file, path, time, "", "");
if (!(fp_stat = fopen(path, "we"))) if (!(fp_stat = fopen(path.data(), "we")))
{ {
trace(1, "rtkopenstat: file open error path=%s\n", path); trace(1, "rtkopenstat: file open error path=%s\n", path.data());
return 0; return 0;
} }
if (strlen(file) < 1025) if (strlen(file) < 1025)
@ -191,7 +192,6 @@ void rtkoutstat(rtk_t *rtk, char *buff __attribute__((unused)))
int est; int est;
int nfreq; int nfreq;
int nf = NF_RTK(&rtk->opt); int nf = NF_RTK(&rtk->opt);
char id[32];
if (statlevel <= 0 || !fp_stat) if (statlevel <= 0 || !fp_stat)
{ {
@ -264,11 +264,11 @@ void rtkoutstat(rtk_t *rtk, char *buff __attribute__((unused)))
{ {
continue; continue;
} }
satno2id(i + 1, id); auto id = satno2id(i + 1);
j = II_RTK(i + 1, &rtk->opt); j = II_RTK(i + 1, &rtk->opt);
xa[0] = j < rtk->na ? rtk->xa[j] : 0.0; xa[0] = j < rtk->na ? rtk->xa[j] : 0.0;
fprintf(fp_stat, "$ION,%d,%.3f,%d,%s,%.1f,%.1f,%.4f,%.4f\n", week, tow, rtk->sol.stat, fprintf(fp_stat, "$ION,%d,%.3f,%d,%s,%.1f,%.1f,%.4f,%.4f\n", week, tow, rtk->sol.stat,
id, ssat->azel[0] * R2D, ssat->azel[1] * R2D, rtk->x[j], xa[0]); id.data(), ssat->azel[0] * R2D, ssat->azel[1] * R2D, rtk->x[j], xa[0]);
} }
} }
/* tropospheric parameters */ /* tropospheric parameters */
@ -306,11 +306,11 @@ void rtkoutstat(rtk_t *rtk, char *buff __attribute__((unused)))
{ {
continue; continue;
} }
satno2id(i + 1, id); auto id = satno2id(i + 1);
for (j = 0; j < nfreq; j++) for (j = 0; j < nfreq; j++)
{ {
fprintf(fp_stat, "$SAT,%d,%.3f,%s,%d,%.1f,%.1f,%.4f,%.4f,%d,%.0f,%d,%d,%d,%d,%d,%d\n", fprintf(fp_stat, "$SAT,%d,%.3f,%s,%d,%.1f,%.1f,%.4f,%.4f,%d,%.0f,%d,%d,%d,%d,%d,%d\n",
week, tow, id, j + 1, ssat->azel[0] * R2D, ssat->azel[1] * R2D, week, tow, id.data(), j + 1, ssat->azel[0] * R2D, ssat->azel[1] * R2D,
ssat->resp[j], ssat->resc[j], ssat->vsat[j], ssat->snr[j] * 0.25, ssat->resp[j], ssat->resc[j], ssat->vsat[j], ssat->snr[j] * 0.25,
ssat->fix[j], ssat->slip[j] & 3, ssat->lock[j], ssat->outc[j], ssat->fix[j], ssat->slip[j] & 3, ssat->lock[j], ssat->outc[j],
ssat->slipc[j], ssat->rejc[j]); ssat->slipc[j], ssat->rejc[j]);
@ -323,7 +323,7 @@ void rtkoutstat(rtk_t *rtk, char *buff __attribute__((unused)))
void swapsolstat() void swapsolstat()
{ {
gtime_t time = utc2gpst(timeget()); gtime_t time = utc2gpst(timeget());
char path[1024]; std::string path;
if (static_cast<int>(time2gpst(time, nullptr) / INT_SWAP_STAT) == if (static_cast<int>(time2gpst(time, nullptr) / INT_SWAP_STAT) ==
static_cast<int>(time2gpst(time_stat, nullptr) / INT_SWAP_STAT)) static_cast<int>(time2gpst(time_stat, nullptr) / INT_SWAP_STAT))
@ -341,12 +341,12 @@ void swapsolstat()
fclose(fp_stat); fclose(fp_stat);
} }
if (!(fp_stat = fopen(path, "we"))) if (!(fp_stat = fopen(path.data(), "we")))
{ {
trace(2, "swapsolstat: file open error path=%s\n", path); trace(2, "swapsolstat: file open error path=%s\n", path.data());
return; return;
} }
trace(3, "swapsolstat: path=%s\n", path); trace(3, "swapsolstat: path=%s\n", path.data());
} }
@ -367,7 +367,6 @@ void outsolstat(rtk_t *rtk)
int est; int est;
int nfreq; int nfreq;
int nf = NF_RTK(&rtk->opt); int nf = NF_RTK(&rtk->opt);
char id[32];
if (statlevel <= 0 || !fp_stat) if (statlevel <= 0 || !fp_stat)
{ {
@ -440,11 +439,11 @@ void outsolstat(rtk_t *rtk)
{ {
continue; continue;
} }
satno2id(i + 1, id); auto id = satno2id(i + 1);
j = II_RTK(i + 1, &rtk->opt); j = II_RTK(i + 1, &rtk->opt);
xa[0] = j < rtk->na ? rtk->xa[j] : 0.0; xa[0] = j < rtk->na ? rtk->xa[j] : 0.0;
fprintf(fp_stat, "$ION,%d,%.3f,%d,%s,%.1f,%.1f,%.4f,%.4f\n", week, tow, rtk->sol.stat, fprintf(fp_stat, "$ION,%d,%.3f,%d,%s,%.1f,%.1f,%.4f,%.4f\n", week, tow, rtk->sol.stat,
id, ssat->azel[0] * R2D, ssat->azel[1] * R2D, rtk->x[j], xa[0]); id.data(), ssat->azel[0] * R2D, ssat->azel[1] * R2D, rtk->x[j], xa[0]);
} }
} }
/* tropospheric parameters */ /* tropospheric parameters */
@ -482,11 +481,11 @@ void outsolstat(rtk_t *rtk)
{ {
continue; continue;
} }
satno2id(i + 1, id); auto id = satno2id(i + 1);
for (j = 0; j < nfreq; j++) for (j = 0; j < nfreq; j++)
{ {
fprintf(fp_stat, "$SAT,%d,%.3f,%s,%d,%.1f,%.1f,%.4f,%.4f,%d,%.0f,%d,%d,%d,%d,%d,%d\n", fprintf(fp_stat, "$SAT,%d,%.3f,%s,%d,%.1f,%.1f,%.4f,%.4f,%d,%.0f,%d,%d,%d,%d,%d,%d\n",
week, tow, id, j + 1, ssat->azel[0] * R2D, ssat->azel[1] * R2D, week, tow, id.data(), j + 1, ssat->azel[0] * R2D, ssat->azel[1] * R2D,
ssat->resp[j], ssat->resc[j], ssat->vsat[j], ssat->snr[j] * 0.25, ssat->resp[j], ssat->resc[j], ssat->vsat[j], ssat->snr[j] * 0.25,
ssat->fix[j], ssat->slip[j] & 3, ssat->lock[j], ssat->outc[j], ssat->fix[j], ssat->slip[j] & 3, ssat->lock[j], ssat->outc[j],
ssat->slipc[j], ssat->rejc[j]); ssat->slipc[j], ssat->rejc[j]);

View File

@ -31,6 +31,8 @@
*/ */
#include "rtklib_stream.h" #include "rtklib_stream.h"
#include "gnss_sdr_make_unique.h" // for std::make:unique in C++11
#include "gnss_sdr_string_literals.h" // for std::string_literals
#include "rtklib_rtkcmn.h" #include "rtklib_rtkcmn.h"
#include "rtklib_solution.h" #include "rtklib_solution.h"
#include <arpa/inet.h> #include <arpa/inet.h>
@ -38,9 +40,13 @@
#include <cerrno> #include <cerrno>
#include <cinttypes> #include <cinttypes>
#include <cstring> #include <cstring>
#include <deque>
#include <fcntl.h> #include <fcntl.h>
#include <memory>
#include <netdb.h> #include <netdb.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <regex>
#include <sstream>
#include <string> #include <string>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -48,6 +54,7 @@
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
using namespace std::string_literals;
/* global options ------------------------------------------------------------*/ /* global options ------------------------------------------------------------*/
@ -118,7 +125,7 @@ serial_t *openserial(const char *path, int mode, char *msg)
} }
parity = static_cast<char>(toupper(static_cast<int>(parity))); parity = static_cast<char>(toupper(static_cast<int>(parity)));
std::string s_aux = "/dev/" + std::string(port); std::string s_aux = "/dev/"s + std::string(port);
s_aux.resize(128, '\0'); s_aux.resize(128, '\0');
int n = s_aux.length(); int n = s_aux.length();
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
@ -228,18 +235,17 @@ int stateserial(serial_t *serial)
int openfile_(file_t *file, gtime_t time, char *msg) int openfile_(file_t *file, gtime_t time, char *msg)
{ {
FILE *fp; FILE *fp;
char *rw;
char tagpath[MAXSTRPATH + 4] = ""; char tagpath[MAXSTRPATH + 4] = "";
char tagh[TIMETAGH_LEN + 1] = ""; char tagh[TIMETAGH_LEN + 1] = "";
tracet(3, "openfile_: path=%s time=%s\n", file->path, time_str(time, 0)); tracet(3, "openfile_: path=%s time=%s\n", file->path.data(), time_str(time, 0));
file->time = utc2gpst(timeget()); file->time = utc2gpst(timeget());
file->tick = file->tick_f = tickget(); file->tick = file->tick_f = tickget();
file->fpos = 0; file->fpos = 0;
/* use stdin or stdout if file path is null */ /* use stdin or stdout if file path is empty */
if (!*file->path) if (file->path.empty())
{ {
file->fp = file->mode & STR_MODE_R ? stdin : stdout; file->fp = file->mode & STR_MODE_R ? stdin : stdout;
return 1; return 1;
@ -250,37 +256,39 @@ int openfile_(file_t *file, gtime_t time, char *msg)
/* create directory */ /* create directory */
if ((file->mode & STR_MODE_W) && !(file->mode & STR_MODE_R)) if ((file->mode & STR_MODE_W) && !(file->mode & STR_MODE_R))
{ {
createdir(file->openpath); createdir(file->openpath.data());
} }
char const *mode;
if (file->mode & STR_MODE_R) if (file->mode & STR_MODE_R)
{ {
rw = const_cast<char *>("rb"); mode = "rb";
} }
else else
{ {
rw = const_cast<char *>("wb"); mode = "wb";
} }
if (!(file->fp = fopen(file->openpath, rw))) if (!(file->fp = fopen(file->openpath.data(), mode)))
{ {
std::snprintf(msg, MAXSTRMSG, "file open error"); std::snprintf(msg, MAXSTRMSG, "file open error");
tracet(1, "openfile: %s\n", msg); tracet(1, "openfile: %s\n", msg);
return 0; return 0;
} }
tracet(4, "openfile_: open file %s (%s)\n", file->openpath, rw); tracet(4, "openfile_: open file %s (%s)\n", file->openpath.data(), mode);
std::snprintf(tagpath, MAXSTRPATH + 4, "%s.tag", file->openpath); std::snprintf(tagpath, MAXSTRPATH + 4, "%s.tag", file->openpath.data());
if (file->timetag) if (file->timetag)
{ /* output/sync time-tag */ { /* output/sync time-tag */
if (!(file->fp_tag = fopen(tagpath, rw))) if (!(file->fp_tag = fopen(tagpath, mode)))
{ {
std::snprintf(msg, MAXSTRMSG, "tag open error"); std::snprintf(msg, MAXSTRMSG, "tag open error");
tracet(1, "openfile: %s\n", msg); tracet(1, "openfile: %s\n", msg);
fclose(file->fp); fclose(file->fp);
return 0; return 0;
} }
tracet(4, "openfile_: open tag file %s (%s)\n", tagpath, rw); tracet(4, "openfile_: open tag file %s (%s)\n", tagpath, mode);
if (file->mode & STR_MODE_R) if (file->mode & STR_MODE_R)
{ {
@ -326,131 +334,132 @@ int openfile_(file_t *file, gtime_t time, char *msg)
/* close file ----------------------------------------------------------------*/ /* close file ----------------------------------------------------------------*/
void closefile_(file_t *file) void closefile_(file_t *file)
{ {
tracet(3, "closefile_: path=%s\n", file->path); tracet(3, "closefile_: path=%s\n", file->path.data());
if (file->fp) if (file->fp)
{ {
fclose(file->fp); fclose(file->fp);
file->fp = nullptr;
} }
if (file->fp_tag) if (file->fp_tag)
{ {
fclose(file->fp_tag); fclose(file->fp_tag);
file->fp_tag = nullptr;
} }
if (file->fp_tmp) if (file->fp_tmp)
{ {
fclose(file->fp_tmp); fclose(file->fp_tmp);
file->fp_tmp = nullptr;
} }
if (file->fp_tag_tmp) if (file->fp_tag_tmp)
{ {
fclose(file->fp_tag_tmp); fclose(file->fp_tag_tmp);
file->fp_tag_tmp = nullptr;
} }
file->fp = file->fp_tag = file->fp_tmp = file->fp_tag_tmp = nullptr;
} }
/* open file (path=filepath[::T[::+<off>][::x<speed>]][::S=swapintv]) --------*/ /* open file (path=filepath[::T[::+<off>][::x<speed>]][::S=swapintv]) --------*/
file_t *openfile(const char *path, int mode, char *msg) file_t *openfile(std::string const &path, int mode, char *msg)
{ {
file_t *file; tracet(3, "openfile: path=%s mode=%d\n", path.data(), mode);
gtime_t time;
gtime_t time0 = {0, 0.0};
double speed = 0.0;
double start = 0.0;
double swapintv = 0.0;
char *p;
int timetag = 0;
tracet(3, "openfile: path=%s mode=%d\n", path, mode); if ((mode & (STR_MODE_R | STR_MODE_W)) == 0)
if (!(mode & (STR_MODE_R | STR_MODE_W)))
{ {
return nullptr; return nullptr;
} }
// Split the string by regular expression (in this case, the trivial "::" string)
std::regex re("::");
auto first = std::sregex_token_iterator(path.begin(), path.end(), re, -1);
auto last = std::sregex_token_iterator();
std::deque<std::string> tokens(first, last);
auto file = std::make_unique<file_t>();
file->mode = mode;
file->path = tokens.front(); // first token is the path
tokens.pop_front();
/* file options */ /* file options */
for (p = const_cast<char *>(path); (p = strstr(p, "::")); p += 2) while (not tokens.empty())
{ /* file options */
if (*(p + 2) == 'T')
{
timetag = 1;
}
else if (*(p + 2) == '+')
{
sscanf(p + 2, "+%lf", &start);
}
else if (*(p + 2) == 'x')
{
sscanf(p + 2, "x%lf", &speed);
}
else if (*(p + 2) == 'S')
{
sscanf(p + 2, "S=%lf", &swapintv);
}
}
if (start <= 0.0)
{ {
start = 0.0; auto tag = tokens.front();
} tokens.pop_front();
if (swapintv <= 0.0)
{ // edge case that may not be possible, but I don't want to test for right now
swapintv = 0.0; if (tag.empty()) continue; // NOLINT(readability-braces-around-statements)
if (tag == "T")
{
file->timetag = 1;
}
else if (tag[0] == '+')
{
double start = 0.0;
std::istringstream ss(tag);
ss.ignore(1, '+') >> start;
// do we care if there are extra characters?
if (start < 0)
{
start = 0;
}
file->start = start;
}
else if (tag[0] == 'x')
{
double speed = 0.0;
std::istringstream ss(tag);
ss.ignore(1, 'x') >> speed;
// do we care if there are extra characters?
file->speed = speed;
}
else if (tag[0] == 'S')
{
double swapintv = 0.0;
std::istringstream ss(tag);
ss.ignore(1, 'S').ignore(1, '=') >> swapintv;
// do we care if there are extra characters?
if (swapintv < 0) swapintv = 0; // NOLINT(readability-braces-around-statements)
file->swapintv = swapintv;
}
else
{
// unexpected value ... not previously handled
}
} }
if (!(file = static_cast<file_t *>(malloc(sizeof(file_t)))))
{
return nullptr;
}
file->fp = file->fp_tag = file->fp_tmp = file->fp_tag_tmp = nullptr;
if (strlen(path) < MAXSTRPATH)
{
std::strncpy(file->path, path, MAXSTRPATH);
file->path[MAXSTRPATH - 1] = '\0';
}
if ((p = strstr(file->path, "::")))
{
*p = '\0';
}
file->openpath[0] = '\0';
file->mode = mode;
file->timetag = timetag;
file->repmode = 0;
file->offset = 0;
file->time = file->wtime = time0;
file->tick = file->tick_f = file->fpos = 0;
file->start = start;
file->speed = speed;
file->swapintv = swapintv;
initlock(&file->lock); initlock(&file->lock);
time = utc2gpst(timeget()); auto time = utc2gpst(timeget());
/* open new file */ /* open new file */
if (!openfile_(file, time, msg)) if (!openfile_(file.get(), time, msg))
{ {
free(file); file.reset();
return nullptr;
} }
return file; return file.release(); // ownership belongs to the caller now
} }
/* close file ----------------------------------------------------------------*/ /* close file ----------------------------------------------------------------*/
void closefile(file_t *file) void closefile(file_t *file)
{ {
if (!file) if (file)
{ {
return; std::unique_ptr<file_t> fileH(file);
tracet(3, "closefile: fp=%p \n", fileH->fp);
closefile_(fileH.get());
} }
tracet(3, "closefile: fp=%p \n", file->fp);
closefile_(file);
free(file);
} }
/* open new swap file --------------------------------------------------------*/ /* open new swap file --------------------------------------------------------*/
void swapfile(file_t *file, gtime_t time, char *msg) void swapfile(file_t *file, gtime_t time, char *msg)
{ {
char openpath[MAXSTRPATH]; std::string openpath;
tracet(3, "swapfile: fp=%p \n time=%s\n", file->fp, time_str(time, 0)); tracet(3, "swapfile: fp=%p \n time=%s\n", file->fp, time_str(time, 0));
@ -463,9 +472,9 @@ void swapfile(file_t *file, gtime_t time, char *msg)
/* check path of new swap file */ /* check path of new swap file */
reppath(file->path, openpath, time, "", ""); reppath(file->path, openpath, time, "", "");
if (!strcmp(openpath, file->openpath)) if (openpath == file->openpath)
{ {
tracet(2, "swapfile: no need to swap %s\n", openpath); tracet(2, "swapfile: no need to swap %s\n", openpath.data());
return; return;
} }
/* save file pointer to temporary pointer */ /* save file pointer to temporary pointer */
@ -1739,7 +1748,7 @@ ntrip_t *openntrip(const char *path, int type, char *msg)
/* ntrip access via proxy server */ /* ntrip access via proxy server */
if (*proxyaddr) if (*proxyaddr)
{ {
std::string s_aux = "http://" + std::string(tpath); std::string s_aux = "http://"s + std::string(tpath);
int n = s_aux.length(); int n = s_aux.length();
if (n < 256) if (n < 256)
{ {
@ -1924,19 +1933,6 @@ gtime_t nextdltime(const int *topts, int stat)
void *ftpthread(void *arg) void *ftpthread(void *arg)
{ {
auto *ftp = static_cast<ftp_t *>(arg); auto *ftp = static_cast<ftp_t *>(arg);
FILE *fp;
gtime_t time;
char remote[1024];
char local[1024];
char tmpfile[1024];
char errfile[1024];
char *p;
char cmd[2048];
char env[1024] = "";
char opt[1024];
char *proxyopt = const_cast<char *>("");
char *proto;
int ret;
tracet(3, "ftpthread:\n"); tracet(3, "ftpthread:\n");
@ -1948,152 +1944,117 @@ void *ftpthread(void *arg)
return nullptr; return nullptr;
} }
/* replace keyword in file path and local path */ /* replace keyword in file path and local path */
time = timeadd(utc2gpst(timeget()), ftp->topts[0]); auto time = timeadd(utc2gpst(timeget()), ftp->topts[0]);
std::string remote;
reppath(ftp->file, remote, time, "", ""); reppath(ftp->file, remote, time, "", "");
auto remotePath = fs::path(remote);
if ((p = strrchr(remote, '/'))) auto local = fs::path(localdir);
{ local /= remotePath.filename();
p++;
}
else
{
p = remote;
}
std::string s_aux = std::string(localdir) + std::to_string(FILEPATHSEP) + std::string(p);
int n = s_aux.length();
if (n < 1024)
{
for (int i = 0; i < n; i++)
{
local[i] = s_aux[i];
}
}
std::string s_aux2 = std::string(local) + ".err"; auto errfile = fs::path(local);
n = s_aux2.length(); errfile.replace_extension("err");
if (n < 1024)
{
for (int i = 0; i < n; i++)
{
errfile[i] = s_aux2[i];
}
}
/* if local file exist, skip download */ /* if local file exist, skip download */
std::strncpy(tmpfile, local, 1024); auto tmpfile = local;
tmpfile[1023] = '\0'; for (auto ext : {".z", ".gz", ".zip", ".Z", ".GZ", ".ZIP"}) // NOLINT(readability-qualified-auto): auto decoration is less readable
if ((p = strrchr(tmpfile, '.')) &&
(!strcmp(p, ".z") || !strcmp(p, ".gz") || !strcmp(p, ".zip") ||
!strcmp(p, ".Z") || !strcmp(p, ".GZ") || !strcmp(p, ".ZIP")))
{ {
*p = '\0'; if (tmpfile.extension() == ext)
{
tmpfile.replace_extension("");
break;
}
} }
if ((fp = fopen(tmpfile, "rbe"))) if (fs::exists(tmpfile))
{ {
fclose(fp); std::strncpy(ftp->local, tmpfile.c_str(), 1024);
std::strncpy(ftp->local, tmpfile, 1024);
ftp->local[1023] = '\0'; ftp->local[1023] = '\0';
tracet(3, "ftpthread: file exists %s\n", ftp->local); tracet(3, "ftpthread: file exists %s\n", ftp->local);
ftp->state = 2; ftp->state = 2;
return nullptr; return nullptr;
} }
std::string env;
/* proxy settings for wget (ref [2]) */ /* proxy settings for wget (ref [2]) */
auto proxyopt = std::string();
if (*proxyaddr) if (*proxyaddr)
{ {
proto = ftp->proto ? const_cast<char *>("http") : const_cast<char *>("ftp"); auto proto = "ftp"s;
std::snprintf(env, sizeof(env), "set %s_proxy=http://%s & ", proto, proxyaddr); if (ftp->proto) proto = "http"s; // NOLINT(readability-braces-around-statements): adding braces reduces readability
proxyopt = const_cast<char *>("--proxy=on "); env = "set "s + proto + "_proxy=http://"s + std::string(proxyaddr) + " % ";
proxyopt = "--proxy=on ";
} }
/* download command (ref [2]) */ /* download command (ref [2]) */
auto cmd_str = std::string();
if (ftp->proto == 0) if (ftp->proto == 0)
{ /* ftp */ { /* ftp */
s_aux = "--ftp-user=" + std::string(ftp->user) + " --ftp-password=" + std::string(ftp->passwd) + auto opt_str = "--ftp-user="s + std::string(ftp->user) + " --ftp-password="s + std::string(ftp->passwd) +
" --glob=off --passive-ftp " + std::string(proxyopt) + "s-t 1 -T " + std::to_string(FTP_TIMEOUT) + " --glob=off --passive-ftp "s + proxyopt + "s-t 1 -T "s + std::to_string(FTP_TIMEOUT) +
" -O \"" + std::string(local) + "\""; R"( -O ")" + local.native() + R"(")"s;
int k = s_aux.length();
if (k < 1024)
{
for (int i = 0; i < k; i++)
{
opt[i] = s_aux[i];
}
}
s_aux2 = std::string(env) + std::string(FTP_CMD) + " " + std::string(opt) + " " + // TODO: this uses shell syntax; consider escaping paths
"\"ftp://" + std::string(ftp->addr) + "/" + std::string(remote) + "\" 2> \"" + std::string(errfile) + "\"\n"; cmd_str = env + std::string(FTP_CMD) + " "s + opt_str + " "s +
k = s_aux2.length(); R"("ftp://)"s + std::string(ftp->addr) + "/"s + remotePath.native() + R"(" 2> ")"s + errfile.native() + "\"\n"s;
for (int i = 0; (i < k) && (i < 1024); i++)
{
cmd[i] = s_aux2[i];
}
} }
else else
{ /* http */ { /* http */
s_aux = std::string(proxyopt) + " -t 1 -T " + std::to_string(FTP_TIMEOUT) + " -O \"" + std::string(local) + "\""; auto opt_str = proxyopt + " -t 1 -T "s + std::to_string(FTP_TIMEOUT) + " -O \""s + local.native() + "\""s;
int l = s_aux.length();
for (int i = 0; (i < l) && (i < 1024); i++)
{
opt[i] = s_aux[i];
}
s_aux2 = std::string(env) + std::string(FTP_CMD) + " " + std::string(opt) + " " + cmd_str = env + std::string(FTP_CMD) + " "s + opt_str + " "s +
"\"http://" + std::string(ftp->addr) + "/" + std::string(remote) + "\" 2> \"" + std::string(errfile) + "\"\n"; R"("http://)"s + std::string(ftp->addr) + "/"s + remotePath.native() + R"(" 2> ")"s + errfile.native() + "\"\n";
l = s_aux2.length();
for (int i = 0; (i < l) && (i < 1024); i++)
{
cmd[i] = s_aux2[i];
}
} }
/* execute download command */ /* execute download command */
if ((ret = execcmd(cmd))) errorlib::error_code ec; // prevent exceptions
auto ret = execcmd(cmd_str.c_str());
if ((ret != 0))
{ {
if (remove(local) != 0) if (fs::remove(local, ec) == false)
{ {
trace(1, "Error removing file"); trace(1, "Error removing file %s", local.c_str());
} }
tracet(1, "execcmd error: cmd=%s ret=%d\n", cmd, ret); tracet(1, "execcmd error: cmd=%s ret=%d\n", cmd_str.data(), ret);
ftp->error = ret; ftp->error = ret;
ftp->state = 3; ftp->state = 3;
return nullptr; return nullptr;
} }
if (remove(errfile) != 0) if (fs::remove(errfile, ec) == false)
{ {
trace(1, "Error removing file"); trace(1, "Error removing file %s", errfile.c_str());
} }
/* uncompress downloaded file */ /* uncompress downloaded file */
if ((p = strrchr(local, '.')) && for (auto ext : {".z", ".gz", ".zip", ".Z", ".GZ", ".ZIP"}) // NOLINT(readability-qualified-auto): auto decoration is less readable
(!strcmp(p, ".z") || !strcmp(p, ".gz") || !strcmp(p, ".zip") ||
!strcmp(p, ".Z") || !strcmp(p, ".GZ") || !strcmp(p, ".ZIP")))
{ {
if (rtk_uncompress(local, tmpfile)) if (local.extension() == ext)
{ {
if (remove(local) != 0) char tmpfile_arg[1024];
ret = rtk_uncompress(local.c_str(), tmpfile_arg);
if (ret != 0) // success
{ {
trace(1, "Error removing file"); if (fs::remove(local, ec) == false)
{
trace(1, "Error removing file %s", local.c_str());
}
local = tmpfile_arg;
} }
if (strlen(tmpfile) < 1024) else
{ {
std::strncpy(local, tmpfile, 1024); tracet(1, "file uncompact error: %s\n", local.c_str());
local[1023] = '\0'; ftp->error = 12;
ftp->state = 3;
return nullptr;
} }
} break;
else
{
tracet(1, "file uncompact error: %s\n", local);
ftp->error = 12;
ftp->state = 3;
return nullptr;
} }
} }
if (strlen(local) < 1024) std::strncpy(ftp->local, local.c_str(), 1024);
{ ftp->local[1023] = '\0';
std::strncpy(ftp->local, local, 1024);
ftp->local[1023] = '\0';
}
ftp->state = 2; /* ftp completed */ ftp->state = 2; /* ftp completed */
tracet(3, "ftpthread: complete cmd=%s\n", cmd); tracet(3, "ftpthread: complete cmd=%s\n", cmd_str.data());
return nullptr; return nullptr;
} }
@ -2115,7 +2076,7 @@ ftp_t *openftp(const char *path, int type, char *msg)
ftp->state = 0; ftp->state = 0;
ftp->proto = type; ftp->proto = type;
ftp->error = 0; ftp->error = 0;
ftp->thread = 0; // NOLINT ftp->thread = pthread_t();
ftp->local[0] = '\0'; ftp->local[0] = '\0';
/* decode ftp path */ /* decode ftp path */

View File

@ -1,7 +1,7 @@
# GNSS-SDR is a Global Navigation Satellite System software-defined receiver. # GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
# This file is part of GNSS-SDR. # This file is part of GNSS-SDR.
# #
# SPDX-FileCopyrightText: 2010-2020 C. Fernandez-Prades cfernandez(at)cttc.es # SPDX-FileCopyrightText: 2010-2022 C. Fernandez-Prades cfernandez(at)cttc.es
# SPDX-License-Identifier: BSD-3-Clause # SPDX-License-Identifier: BSD-3-Clause
@ -90,6 +90,11 @@ if(ENABLE_UHD)
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} uhd_signal_source.h) set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} uhd_signal_source.h)
endif() endif()
if(ENABLE_ZMQ)
list(APPEND OPT_DRIVER_SOURCES zmq_signal_source.cc)
list(APPEND OPT_DRIVER_HEADERS zmq_signal_source.h)
endif()
set(SIGNAL_SOURCE_ADAPTER_SOURCES set(SIGNAL_SOURCE_ADAPTER_SOURCES
signal_source_base.cc signal_source_base.cc
@ -200,6 +205,13 @@ if(ENABLE_UHD)
) )
endif() endif()
if(ENABLE_ZMQ)
target_link_libraries(signal_source_adapters
PUBLIC
Gnuradio::zeromq
)
endif()
if(ENABLE_OSMOSDR AND GROSMOSDR_FOUND) if(ENABLE_OSMOSDR AND GROSMOSDR_FOUND)
target_link_libraries(signal_source_adapters target_link_libraries(signal_source_adapters
PUBLIC PUBLIC

View File

@ -9,7 +9,7 @@
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR. * This file is part of GNSS-SDR.
* *
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors) * Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
* *
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
@ -37,6 +37,12 @@ size_t SignalSourceBase::getRfChannels() const
return rfChannels_; return rfChannels_;
} }
gr::basic_block_sptr SignalSourceBase::get_left_block()
{
LOG(WARNING) << "Trying to get signal source left block.";
return {};
}
SignalSourceBase::SignalSourceBase(ConfigurationInterface const* configuration, std::string role, std::string impl) SignalSourceBase::SignalSourceBase(ConfigurationInterface const* configuration, std::string role, std::string impl)
: role_(std::move(role)), implementation_(std::move(impl)) : role_(std::move(role)), implementation_(std::move(impl))
{ {
@ -44,3 +50,52 @@ SignalSourceBase::SignalSourceBase(ConfigurationInterface const* configuration,
// depending on the order of initialization, assign rfChannels_ in the body // depending on the order of initialization, assign rfChannels_ in the body
rfChannels_ = configuration->property(role_ + ".RF_channels"s, uint64_t(1U)); rfChannels_ = configuration->property(role_ + ".RF_channels"s, uint64_t(1U));
} }
size_t SignalSourceBase::decode_item_type(std::string const& item_type, bool* is_interleaved, bool throw_on_error)
{
size_t item_size = 0;
// The default is for samples not to be interleaved
if (is_interleaved) *is_interleaved = false; // NOLINT
if (item_type == "gr_complex"s)
{
item_size = sizeof(gr_complex);
}
else if (item_type == "float"s)
{
item_size = sizeof(float);
}
else if (item_type == "short"s)
{
item_size = sizeof(int16_t);
}
else if (item_type == "ishort"s)
{
item_size = sizeof(int16_t);
if (is_interleaved) *is_interleaved = true; // NOLINT
}
else if (item_type == "byte"s)
{
item_size = sizeof(int8_t);
}
else if (item_type == "ibyte"s)
{
item_size = sizeof(int8_t);
if (is_interleaved) *is_interleaved = true; // NOLINT
}
else
{
if (throw_on_error)
{
throw std::invalid_argument(item_type + " is not a recognized item type"s);
}
else
{
LOG(WARNING) << item_type
<< " unrecognized item type. Using gr_complex.";
item_size = sizeof(gr_complex);
}
}
return item_size;
}

View File

@ -9,7 +9,7 @@
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR. * This file is part of GNSS-SDR.
* *
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors) * Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
* *
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
@ -32,11 +32,21 @@ public:
std::string implementation() final; std::string implementation() final;
size_t getRfChannels() const override; size_t getRfChannels() const override;
gr::basic_block_sptr get_left_block() override; // non-sensical; implement once
protected: protected:
//! Constructor //! Constructor
SignalSourceBase(ConfigurationInterface const* configuration, std::string role, std::string impl); SignalSourceBase(ConfigurationInterface const* configuration, std::string role, std::string impl);
//! utility for decoding passed ".item_type" values
//! @param[in] item_type - user provided string, should be one of the known types
//! @param[out] is_interleaved - if non-null, the pointed to memory is updated with
//! whether the data is interleaved I/Q (e.g., ishort)
//! @param[in] throw_on_error - if true, throw an exception if the string does not
//! represent a known type
//! @return the size in bytes of the passed type
size_t decode_item_type(std::string const& item_type, bool* is_interleaved = nullptr, bool throw_on_error = false);
private: private:
std::string const role_; std::string const role_;
std::string const implementation_; std::string const implementation_;

View File

@ -0,0 +1,82 @@
/*!
* \file zmq_signal_source.cc
* \brief Signal source which reads from ZeroMQ.
* \author Jim Melton, 2022. jim.melton(at)sncorp.com
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#include "zmq_signal_source.h"
#include "configuration_interface.h"
#include "gnss_sdr_string_literals.h"
#include <glog/logging.h>
#include <vector>
using namespace std::string_literals;
ZmqSignalSource::ZmqSignalSource(const ConfigurationInterface* configuration,
const std::string& role,
unsigned int /* in_stream [[maybe_unused]] */,
unsigned int /* out_stream [[maybe_unused]] */,
Concurrent_Queue<pmt::pmt_t>* /* queue [[maybe_unused]] */)
: SignalSourceBase(configuration, role, "ZMQ_Signal_Source"s),
d_item_size(decode_item_type(configuration->property(role + ".item_type"s, "gr_complex"s), nullptr, true)),
d_dump_filename(configuration->property(role + ".dump_filename"s, "data/zmq_dump.dat"s)),
d_dump(configuration->property(role + ".dump"s, false))
{
auto vlen = configuration->property(role + ".vlen"s, 1);
auto pass_tags = configuration->property(role + ".pass_tags"s, false);
auto timeout_ms = configuration->property(role + ".timeout_ms"s, 100);
auto hwm = configuration->property(role + ".hwm"s, -1);
auto property = role + ".endpoint"s;
auto endpoint = configuration->property(property, ""s);
std::vector<char> address(endpoint.c_str(), endpoint.c_str() + endpoint.size() + 1);
if (!endpoint.empty())
{
LOG(INFO) << "Connecting to ZMQ pub at " << endpoint;
d_source_block = gr::zeromq::sub_source::make(d_item_size, vlen, address.data(), timeout_ms, pass_tags, hwm);
}
else
{
std::cerr << "For ZMQ_Signal_Source " << property << " must be defined" << std::endl;
throw std::invalid_argument(property + ": undefined");
}
}
auto ZmqSignalSource::item_size() -> size_t { return d_item_size; }
auto ZmqSignalSource::connect(gr::top_block_sptr top_block) -> void
{
if (d_dump)
{
d_dump_sink = gr::blocks::file_sink::make(item_size(), d_dump_filename.data());
top_block->connect(d_source_block, 0, d_dump_sink, 0);
}
}
auto ZmqSignalSource::disconnect(gr::top_block_sptr top_block) -> void
{
if (d_dump)
{
top_block->disconnect(d_dump_sink);
}
}
auto ZmqSignalSource::get_right_block() -> gr::basic_block_sptr
{
return d_source_block;
}

View File

@ -0,0 +1,78 @@
/*!
* \file zmq_signal_source.h
* \brief Signal source which reads from ZeroMQ.
* \author Jim Melton, 2022. jim.melton(at)sncorp.com
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_ZMQ_SIGNAL_SOURCE_H
#define GNSS_SDR_ZMQ_SIGNAL_SOURCE_H
#include "signal_source_base.h"
//
#include "concurrent_queue.h"
#include <gnuradio/blocks/file_sink.h> // for dump
#include <gnuradio/zeromq/sub_source.h>
#include <pmt/pmt.h>
#include <string>
/** \addtogroup Signal_Source
* \{ */
/** \addtogroup Signal_Source_adapters
* \{ */
//! This class supports the following properties:
//!
//! .endpoint - the ZMQ endpoint to be connected to
//! .vlen - vector length of the input items (default 1, one item)
//! this must match the size of the publisher!
//! .pass_tags - boolean flag if tags should be propagated (default false)
//! .timeout_ms - receive timeout, in milliseconds (default 100)
//! .hwm - ZMQ high water mark (default -1, ZMQ default)
//!
//! .item_type - data type of the samples (default "gr_complex")
//!
//! (probably should be abstracted to the base class)
//!
//! .dump - whether to archive input data
//! .dump_filename - if dumping, path to file for output
//!
class ZmqSignalSource : public SignalSourceBase
{
public:
ZmqSignalSource(const ConfigurationInterface* configuration,
const std::string& role,
unsigned int in_stream,
unsigned int out_stream,
Concurrent_Queue<pmt::pmt_t>* queue);
~ZmqSignalSource() = default;
size_t item_size() override;
auto connect(gr::top_block_sptr top_block) -> void override;
auto disconnect(gr::top_block_sptr top_block) -> void override;
auto get_right_block() -> gr::basic_block_sptr override;
private:
gr::zeromq::sub_source::sptr d_source_block;
gr::blocks::file_sink::sptr d_dump_sink;
size_t d_item_size;
std::string d_dump_filename;
bool d_dump;
};
/** \} */
/** \} */
#endif

View File

@ -1,7 +1,7 @@
# GNSS-SDR is a Global Navigation Satellite System software-defined receiver. # GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
# This file is part of GNSS-SDR. # This file is part of GNSS-SDR.
# #
# SPDX-FileCopyrightText: 2010-2020 C. Fernandez-Prades cfernandez(at)cttc.es # SPDX-FileCopyrightText: 2010-2022 C. Fernandez-Prades cfernandez(at)cttc.es
# SPDX-License-Identifier: BSD-3-Clause # SPDX-License-Identifier: BSD-3-Clause
@ -112,6 +112,10 @@ if(ENABLE_ARRAY)
target_compile_definitions(core_receiver PRIVATE -DRAW_ARRAY_DRIVER=1) target_compile_definitions(core_receiver PRIVATE -DRAW_ARRAY_DRIVER=1)
endif() endif()
if(ENABLE_ZMQ)
target_compile_definitions(core_receiver PRIVATE -DZEROMQ_DRIVER=1)
endif()
if(ENABLE_FLEXIBAND) if(ENABLE_FLEXIBAND)
target_compile_definitions(core_receiver PRIVATE -DFLEXIBAND_DRIVER=1) target_compile_definitions(core_receiver PRIVATE -DFLEXIBAND_DRIVER=1)
endif() endif()

View File

@ -16,7 +16,7 @@
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR. * This file is part of GNSS-SDR.
* *
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors) * Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
* *
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
@ -173,6 +173,10 @@
#include "flexiband_signal_source.h" #include "flexiband_signal_source.h"
#endif #endif
#if ZEROMQ_DRIVER
#include "zmq_signal_source.h"
#endif
#if CUDA_GPU_ACCEL #if CUDA_GPU_ACCEL
#include "gps_l1_ca_dll_pll_tracking_gpu.h" #include "gps_l1_ca_dll_pll_tracking_gpu.h"
#endif #endif
@ -813,6 +817,16 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
} }
#endif #endif
#if ZEROMQ_DRIVER
else if (implementation == "ZMQ_Signal_Source")
{
std::unique_ptr<GNSSBlockInterface> block_ = std::make_unique<ZmqSignalSource>(configuration, role, in_streams,
out_streams, queue);
block = std::move(block_);
}
#endif
// DATA TYPE ADAPTER ----------------------------------------------------------- // DATA TYPE ADAPTER -----------------------------------------------------------
else if (implementation == "Byte_To_Short") else if (implementation == "Byte_To_Short")
{ {

View File

@ -13,10 +13,10 @@ if("${ARMADILLO_VERSION_STRING}" VERSION_GREATER "9.800" OR (NOT ARMADILLO_FOUND
if(NOT GNSSTK_FOUND OR ENABLE_OWN_GNSSTK) if(NOT GNSSTK_FOUND OR ENABLE_OWN_GNSSTK)
include(GNUInstallDirs) include(GNUInstallDirs)
if(GNSSTK_USES_GPSTK_NAMESPACE) if(GNSSTK_USES_GPSTK_NAMESPACE)
set(GNSSTK_LIBRARY ${GNSSSDR_BINARY_DIR}/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/install/lib/${CMAKE_FIND_LIBRARY_PREFIXES}gpstk${CMAKE_STATIC_LIBRARY_SUFFIX}) set(GNSSTK_LIBRARY ${GNSSSDR_BINARY_DIR}/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/install/${CMAKE_INSTALL_LIBDIR}/${CMAKE_FIND_LIBRARY_PREFIXES}gpstk${CMAKE_STATIC_LIBRARY_SUFFIX})
set(GNSSTK_INCLUDE_DIR ${GNSSSDR_BINARY_DIR}/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/install/include) set(GNSSTK_INCLUDE_DIR ${GNSSSDR_BINARY_DIR}/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/install/include)
else() else()
set(GNSSTK_LIBRARY ${GNSSSDR_BINARY_DIR}/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/install/lib/${CMAKE_FIND_LIBRARY_PREFIXES}gnsstk${CMAKE_STATIC_LIBRARY_SUFFIX}) set(GNSSTK_LIBRARY ${GNSSSDR_BINARY_DIR}/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/install/${CMAKE_INSTALL_LIBDIR}/${CMAKE_FIND_LIBRARY_PREFIXES}gnsstk${CMAKE_STATIC_LIBRARY_SUFFIX})
set(GNSSTK_INCLUDE_DIR ${GNSSSDR_BINARY_DIR}/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/install/include) set(GNSSTK_INCLUDE_DIR ${GNSSSDR_BINARY_DIR}/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/install/include)
endif() endif()
endif() endif()