source: ntrip/trunk/BNC/src/orbComp/sp3Comp.cpp@ 6346

Last change on this file since 6346 was 6346, checked in by mervart, 9 years ago
File size: 11.8 KB
Line 
1// Part of BNC, a utility for retrieving decoding and
2// converting GNSS data streams from NTRIP broadcasters.
3//
4// Copyright (C) 2007
5// German Federal Agency for Cartography and Geodesy (BKG)
6// http://www.bkg.bund.de
7// Czech Technical University Prague, Department of Geodesy
8// http://www.fsv.cvut.cz
9//
10// Email: euref-ip@bkg.bund.de
11//
12// This program is free software; you can redistribute it and/or
13// modify it under the terms of the GNU General Public License
14// as published by the Free Software Foundation, version 2.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25/* -------------------------------------------------------------------------
26 * BKG NTRIP Client
27 * -------------------------------------------------------------------------
28 *
29 * Class: t_sp3Comp
30 *
31 * Purpose: Compare SP3 Files
32 *
33 * Author: L. Mervart
34 *
35 * Created: 24-Nov-2014
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <iostream>
42#include "sp3Comp.h"
43#include "bnccore.h"
44#include "bncsettings.h"
45#include "bncutils.h"
46
47using namespace std;
48
49// Constructor
50////////////////////////////////////////////////////////////////////////////
51t_sp3Comp::t_sp3Comp(QObject* parent) : QThread(parent) {
52
53 bncSettings settings;
54 _sp3FileNames = settings.value("sp3CompFile").toString().split(',', QString::SkipEmptyParts);
55 for (int ii = 0; ii < _sp3FileNames.size(); ii++) {
56 expandEnvVar(_sp3FileNames[ii]);
57 }
58 _logFileName = settings.value("sp3CompOutLogFile").toString(); expandEnvVar(_logFileName);
59 _logFile = 0;
60 _log = 0;
61}
62
63// Destructor
64////////////////////////////////////////////////////////////////////////////
65t_sp3Comp::~t_sp3Comp() {
66 delete _log;
67 delete _logFile;
68}
69
70//
71////////////////////////////////////////////////////////////////////////////
72void t_sp3Comp::run() {
73
74 // Open Log File
75 // -------------
76 _logFile = new QFile(_logFileName);
77 if (_logFile->open(QIODevice::WriteOnly | QIODevice::Text)) {
78 _log = new QTextStream();
79 _log->setDevice(_logFile);
80 }
81 if (!_log) {
82 emit finished();
83 return;
84 }
85
86 for (int ii = 0; ii < _sp3FileNames.size(); ii++) {
87 *_log << "SP3 File " << ii+1 << ": " << _sp3FileNames[ii] << endl;
88 }
89 if (_sp3FileNames.size() != 2) {
90 *_log << "ERROR: sp3Comp requires two input SP3 files" << endl;
91 emit finished();
92 return;
93 }
94
95
96 // Exit (thread)
97 // -------------
98 if (BNC_CORE->mode() != t_bncCore::interactive) {
99 qApp->exit(0);
100 }
101 else {
102 emit finished();
103 deleteLater();
104 }
105}
106
107// Satellite Index in clkSats set
108////////////////////////////////////////////////////////////////////////////////
109int t_sp3Comp::satIndex(const set<t_prn>& clkSats, const t_prn& prn) const {
110 int ret = 0;
111 for (set<t_prn>::const_iterator it = clkSats.begin(); it != clkSats.end(); it++) {
112 if ( *it == prn) {
113 return ret;
114 }
115 ++ret;
116 }
117 throw "satellite not found " + prn.toString();
118}
119
120// Estimate Clock Offsets
121////////////////////////////////////////////////////////////////////////////////
122void t_sp3Comp::processClocks(const set<t_prn>& clkSats, vector<t_epoch*>& epochs,
123 map<string, t_stat>& stat) const {
124
125 if (clkSats.size() == 0) {
126 return;
127 }
128
129 int nPar = epochs.size() + clkSats.size();
130 SymmetricMatrix NN(nPar); NN = 0.0;
131 ColumnVector bb(nPar); bb = 0.0;
132
133 // Create Matrix A'A and vector b
134 // ------------------------------
135 for (unsigned ie = 0; ie < epochs.size(); ie++) {
136 const map<t_prn, double>& dc = epochs[ie]->_dc;
137 Matrix AA(dc.size(), nPar); AA = 0.0;
138 ColumnVector ll(dc.size()); ll = 0.0;
139 map<t_prn, double>::const_iterator it; int ii;
140 for (it = dc.begin(), ii = 0; it != dc.end(); it++, ii++) {
141 const t_prn& prn = it->first;
142 int index = epochs.size() + satIndex(clkSats, prn);
143 AA[ii][ie] = 1.0; // epoch-specfic offset (common for all satellites)
144 AA[ii][index] = 1.0; // satellite-specific offset (common for all epochs)
145 ll[ii] = it->second;
146 }
147 SymmetricMatrix dN; dN << AA.t() * AA;
148 NN += dN;
149 bb += AA.t() * ll;
150 }
151
152 // Regularize NN
153 // -------------
154 RowVector HH(nPar);
155 HH.columns(1, epochs.size()) = 0.0;
156 HH.columns(epochs.size()+1, nPar) = 1.0;
157 SymmetricMatrix dN; dN << HH.t() * HH;
158 NN += dN;
159
160 // Estimate Parameters
161 // -------------------
162 ColumnVector xx = NN.i() * bb;
163
164 // Compute clock residuals
165 // -----------------------
166 for (unsigned ie = 0; ie < epochs.size(); ie++) {
167 map<t_prn, double>& dc = epochs[ie]->_dc;
168 for (map<t_prn, double>::iterator it = dc.begin(); it != dc.end(); it++) {
169 const t_prn& prn = it->first;
170 int index = epochs.size() + satIndex(clkSats, prn);
171 dc[prn] = it->second - xx[ie] - xx[index];
172 stat[prn.toString()]._offset = xx[index];
173 }
174 }
175}
176
177//// Program
178//////////////////////////////////////////////////////////////////////////////////
179//int main(int argc, char* argv[]) {
180//
181// t_sysout* sysout = new t_sysout("", 0, false);
182// rtnet_core_log = sysout->getSysoutCore();
183//
184// // Parse Input Options
185// // -------------------
186// map<string, string> OPT;
187// parseCmdLine(argc, argv, OPT);
188// if (OPT.find("sp3File1") == OPT.end() || OPT.find("sp3File2") == OPT.end()) {
189// cerr << "usage: sp3comp --sp3File1 <fileName> --sp3File2 <fileName> " << endl;
190// return 1;
191// }
192//
193// // Synchronize reading of two sp3 files
194// // ------------------------------------
195// vector<t_prn> prnList;
196// for (unsigned prn = 1; prn <= t_prn::MAXPRN; prn++) {
197// prnList.push_back(t_prn(prn));
198// }
199// t_sp3 in1(prnList); if (in1.assignFile(OPT["sp3File1"].c_str())) return 1;
200// t_sp3 in2(prnList); if (in2.assignFile(OPT["sp3File2"].c_str())) return 1;
201//
202// vector<t_epoch*> epochs;
203// set<t_prn> clkSats;
204// while (true) {
205// in1.readNextEpoch();
206// bncTime tt = in1.etime();
207// if (!tt.valid()) {
208// break;
209// }
210// if (in2.readEpoch(tt) == t_irc::success) {
211// t_epoch* epo = new t_epoch; epo->_tt = tt;
212// bool epochOK = false;
213// for (unsigned iPrn = 1; iPrn <= t_prn::MAXPRN; iPrn++) {
214// t_prn prn(iPrn);
215// ColumnVector xyz1(3), xyz2(3);
216// ColumnVector vel1(3), vel2(3);
217// double clk1, clk2;
218// bool posSet1, posSet2;
219// bool clkSet1, clkSet2;
220// bool velSet1, velSet2;
221// if (in1.position(prn, xyz1[0], xyz1[1], xyz1[2], posSet1, clk1, clkSet1,
222// vel1[0], vel1[1], vel1[2], velSet1) == 0 &&
223// in2.position(prn, xyz2[0], xyz2[1], xyz2[2], posSet2, clk2, clkSet2,
224// vel1[0], vel1[1], vel1[2], velSet1) == 0) {
225// if (posSet1 && posSet2) {
226// epochOK = true;
227// epo->_dr[prn] = xyz1 - xyz2;
228// epo->_xyz[prn] = xyz1;
229// if (clkSet1 && clkSet2) {
230// epo->_dc[prn] = (clk1 - clk2) * t_genConst::c;
231// clkSats.insert(prn);
232// }
233// }
234// }
235// }
236// if (epochOK) {
237// epochs.push_back(epo);
238// }
239// else {
240// delete epo;
241// }
242// }
243// if (in1.finished()) {
244// break;
245// }
246// }
247//
248// // Transform xyz into radial, along-track, and out-of-plane
249// // --------------------------------------------------------
250// for (unsigned ie = 0; ie < epochs.size(); ie++) {
251// t_epoch* epoch = epochs[ie];
252// t_epoch* epoch2 = 0;
253// if (ie == 0 && epochs.size() > 1) {
254// epoch2 = epochs[ie+1];
255// }
256// else {
257// epoch2 = epochs[ie-1];
258// }
259// double dt = epoch->_tt - epoch2->_tt;
260// map<t_prn, ColumnVector>& dr = epoch->_dr;
261// map<t_prn, ColumnVector>& xyz = epoch->_xyz;
262// map<t_prn, ColumnVector>& xyz2 = epoch2->_xyz;
263// for (map<t_prn, ColumnVector>::const_iterator it = dr.begin(); it != dr.end(); it++) {
264// const t_prn& prn = it->first;
265// if (xyz2.find(prn) != xyz2.end()) {
266// const ColumnVector dx = dr[prn];
267// const ColumnVector& x1 = xyz[prn];
268// const ColumnVector& x2 = xyz2[prn];
269// ColumnVector vel = (x1 - x2) / dt;
270// t_astro::XYZ_to_RSW(x1, vel, dx, dr[prn]);
271// }
272// else {
273// cerr << "not found: " << prn << endl;
274// }
275// }
276// }
277//
278// map<string, t_stat> stat;
279//
280// // Estimate Clock Offsets
281// // ----------------------
282// processClocks(clkSats, epochs, stat);
283//
284// // Print Residuals
285// // ---------------
286// const string all = "ZZZ";
287//
288// cout.setf(ios::fixed);
289// cout << "!\n! MJD PRN radial along out clk clkRed iPRN"
290// "\n! ----------------------------------------------------------------\n";
291// for (unsigned ii = 0; ii < epochs.size(); ii++) {
292// const t_epoch* epo = epochs[ii];
293// const map<t_prn, ColumnVector>& dr = epochs[ii]->_dr;
294// const map<t_prn, double>& dc = epochs[ii]->_dc;
295// for (map<t_prn, ColumnVector>::const_iterator it = dr.begin(); it != dr.end(); it++) {
296// const t_prn& prn = it->first;
297// const ColumnVector& rao = it->second;
298// cout << setprecision(6) << epo->_tt.mjddec() << ' ' << prn << ' '
299// << setw(7) << setprecision(4) << rao[0] << ' '
300// << setw(7) << setprecision(4) << rao[1] << ' '
301// << setw(7) << setprecision(4) << rao[2] << " ";
302// stat[prn]._rao += SP(rao, rao); // Schur product
303// stat[prn]._nr += 1;
304// stat[all]._rao += SP(rao, rao);
305// stat[all]._nr += 1;
306// if (dc.find(prn) != dc.end()) {
307// double clkRes = dc.find(prn)->second;
308// double clkResRed = clkRes - it->second[0]; // clock minus radial component
309// cout << setw(7) << setprecision(4) << clkRes << ' '
310// << setw(7) << setprecision(4) << clkResRed;
311// stat[prn]._dc += clkRes * clkRes;
312// stat[prn]._dcRed += clkResRed * clkResRed;
313// stat[prn]._nc += 1;
314// stat[all]._dc += clkRes * clkRes;
315// stat[all]._dcRed += clkResRed * clkResRed;
316// stat[all]._nc += 1;
317// }
318// else {
319// cout << " . . ";
320// }
321// cout << " " << setw(2) << int(prn) << endl;
322// }
323// delete epo;
324// }
325//
326// // Print Summary
327// // -------------
328// cout << "!\n! RMS:\n";
329// for (map<string, t_stat>::iterator it = stat.begin(); it != stat.end(); it++) {
330// const string& prn = it->first;
331// t_stat& stat = it->second;
332// if (stat._nr > 0) {
333// stat._rao[0] = sqrt(stat._rao[0] / stat._nr);
334// stat._rao[1] = sqrt(stat._rao[1] / stat._nr);
335// stat._rao[2] = sqrt(stat._rao[2] / stat._nr);
336// if (prn == all) {
337// cout << "!\n! Total ";
338// }
339// else {
340// cout << "! " << prn << ' ';
341// }
342// cout << setw(7) << setprecision(4) << stat._rao[0] << ' '
343// << setw(7) << setprecision(4) << stat._rao[1] << ' '
344// << setw(7) << setprecision(4) << stat._rao[2] << " ";
345// if (stat._nc > 0) {
346// stat._dc = sqrt(stat._dc / stat._nc);
347// stat._dcRed = sqrt(stat._dcRed / stat._nc);
348// cout << setw(7) << setprecision(4) << stat._dc << ' '
349// << setw(7) << setprecision(4) << stat._dcRed;
350// if (prn != all) {
351// cout << " offset " << setw(7) << setprecision(4) << stat._offset;
352// }
353// }
354// else {
355// cout << " . . ";
356// }
357// cout << endl;
358// }
359// }
360//
361// return 0;
362//}
Note: See TracBrowser for help on using the repository browser.