1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
/***********************************************/
/**
* @file instrumentGnssReceiver2TimeSeries.cpp
*
* @brief Convert gnssReceiver file into instrument(MISCVLAUES) file.
*
* @author Torsten Mayer-Guerr
* @date 2020-04-09
*/
/***********************************************/
// Latex documentation
#define DOCSTRING docstring
static const char *docstring = R"(
Convert selected GNSS observations or residuals into a simpler time series format.
The \config{outputfileTimeSeries} is an \file{instrument file}{instrument} (MISCVALUES).
For each epoch the first data column contains the PRN, the second the satellite system,
followed by a column for each GNSS \configClass{type}{gnssType}.
As normally more than one GNSS transmitter is tracked per epoch, the output file
has several lines per observed epoch (epochs with the same time, one for each transmitter).
The second data column of the output contains a number representating the system
\begin{itemize}
\item 71: 'G', GPS
\item 82: 'R', GLONASS
\item 69: 'E', GALILEO
\item 67: 'C', BDS
\item 83: 'S', SBAS
\item 74: 'J', QZSS
\item 73: 'I', IRNSS .
\end{itemize}
A \file{GNSS residual file}{instrument} includes additional information
besides the residuals, which can also be selected with \configClass{type}{gnssType}
\begin{itemize}
\item \verb|A1*|, \verb|E1*|: azimuth and elevation at receiver
\item \verb|A2*|, \verb|E2*|: azimuth and elevation at transmitter
\item \verb|I**|: Estimated slant total electron content (STEC)
\end{itemize}
Furthermore these files may include for each residual \configClass{type}{gnssType}
information about the redundancy and the accuracy relation $\sigma/\sigma_0$
of the estimated $\sigma$ versus the apriori $\sigma_0$ from the least squares adjustment.
The three values (residuals, redundancy, $\sigma/\sigma_0$) are coded with the same type.
To get access to all values the corresponding type must be repeated in \configClass{type}{gnssType}.
Example: Selected GPS phase residuals (\configClass{type}{gnssType}='\verb|L1*G|' and \configClass{type}{gnssType}='\verb|L2*G|').
Plotted with \program{PlotGraph} with two \configClass{layer:linesAndPoints}{plotGraphLayerType}
(\config{valueX}='\verb|data0|', \config{valueY}='\verb|100*data3+data1|' and \config{valueY}='\verb|100*data4+data1|' respectively).
\fig{!hb}{0.8}{instrumentGnssReceiver2TimeSeries}{fig:instrumentGnssReceiver2TimeSeries}{GPS residuals in cm, shifted by PRN}
)";
/***********************************************/
#include "programs/program.h"
#include "files/fileMatrix.h"
#include "files/fileInstrument.h"
/***** CLASS ***********************************/
/** @brief Convert gnssReceiver file into instrument(MISCVLAUES) file.
* @ingroup programsGroup */
class InstrumentGnssReceiver2TimeSeries
{
public:
void run(Config &config, Parallel::CommunicatorPtr comm);
};
GROOPS_REGISTER_PROGRAM(InstrumentGnssReceiver2TimeSeries, SINGLEPROCESS, "Convert gnssReceiver file into instrument(MISCVLAUES) file", Gnss, TimeSeries, Residuals)
/***********************************************/
void InstrumentGnssReceiver2TimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)
{
try
{
FileName fileNameOut;
std::vector<FileName> fileNamesIn;
std::vector<GnssType> types;
readConfig(config, "outputfileTimeSeries", fileNameOut, Config::MUSTSET, "", "Instrument (MISCVALUES): prn, system, values for each type");
readConfig(config, "inputfileGnssReceiver", fileNamesIn, Config::MUSTSET, "", "GNSS receiver observations or residuals");
readConfig(config, "type", types, Config::MUSTSET, "", "");
if(isCreateSchema(config)) return;
// ============================
std::vector<MiscValuesArc> arcList;
for(auto &fileName : fileNamesIn)
{
logStatus<<"read GNSS receiver data <"<<fileName<<">"<<Log::endl;
try
{
InstrumentFile fileReceiver(fileName);
for(UInt arcNo=0; arcNo<fileReceiver.arcCount(); arcNo++)
{
GnssReceiverArc arc = fileReceiver.readArc(arcNo);
MiscValuesArc arcNew;
for(auto &epoch : arc)
{
UInt idObs = 0;
for(GnssType typeSat : epoch.satellite)
{
// find first type for the satellite system
UInt idType = std::distance(epoch.obsType.begin(), std::find(epoch.obsType.begin(), epoch.obsType.end(), typeSat));
MiscValuesEpoch epochNew(2+types.size()); // prn, system, types
epochNew.time = epoch.time;
epochNew.values(0) = static_cast<Double>(typeSat.prn());
if(typeSat == GnssType::GPS) epochNew.values(1) = static_cast<Double>('G');
else if(typeSat == GnssType::GLONASS) epochNew.values(1) = static_cast<Double>('R');
else if(typeSat == GnssType::GALILEO) epochNew.values(1) = static_cast<Double>('E');
else if(typeSat == GnssType::BDS) epochNew.values(1) = static_cast<Double>('C');
else if(typeSat == GnssType::SBAS) epochNew.values(1) = static_cast<Double>('S');
else if(typeSat == GnssType::QZSS) epochNew.values(1) = static_cast<Double>('J');
else if(typeSat == GnssType::IRNSS) epochNew.values(1) = static_cast<Double>('I');
// loop over all obs for this satellite
Bool found = FALSE;
std::vector<GnssType> typesTmp = types;
while((idType<epoch.obsType.size()) && (idObs<epoch.observation.size()) && (epoch.obsType.at(idType) == typeSat))
{
const GnssType type = epoch.obsType.at(idType++) + typeSat;
const Double value = epoch.observation.at(idObs++);
const UInt idx = GnssType::index(typesTmp, type);
if((idx != NULLINDEX) && value)
{
epochNew.values(2+idx) = value;
typesTmp.at(idx) = GnssType(static_cast<UInt64>(-1));
found = TRUE;
}
}
if(found)
arcNew.push_back(epochNew);
} // for(idTrans)
} // for(idEpoch)
if(arcNew.size())
arcList.push_back(arcNew);
} // for(idArc)
}
catch(...)
{
logError<<"error by opening file, continue..."<<Log::endl;
}
} // for(fileName)
// ============================
if(!arcList.size())
logWarning<<"empty arc"<<Log::endl;
logStatus<<"write time series file <"<<fileNameOut<<">"<<Log::endl;
InstrumentFile::write(fileNameOut, arcList);
}
catch(std::exception &e)
{
GROOPS_RETHROW(e)
}
}
/***********************************************/
|