source: ntrip/trunk/BNC/src/pppMain.cpp@ 11057

Last change on this file since 11057 was 11057, checked in by stuerze, 5 days ago

bug fixes resulting from overall tests

File size: 11.0 KB
Line 
1
2// Part of BNC, a utility for retrieving decoding and
3// converting GNSS data streams from NTRIP broadcasters.
4//
5// Copyright (C) 2007
6// German Federal Agency for Cartography and Geodesy (BKG)
7// http://bkg.bund.de
8// Czech Technical University Prague, Department of Geodesy
9// http://www.fsv.cvut.cz
10//
11// Email: euref-ip@bkg.bund.de
12//
13// This program is free software; you can redistribute it and/or
14// modify it under the terms of the GNU General Public License
15// as published by the Free Software Foundation, version 2.
16//
17// This program is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20// GNU General Public License for more details.
21//
22// You should have received a copy of the GNU General Public License
23// along with this program; if not, write to the Free Software
24// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26/* -------------------------------------------------------------------------
27 * BKG NTRIP Client
28 * -------------------------------------------------------------------------
29 *
30 * Class: t_pppMain
31 *
32 * Purpose: Start of the PPP client(s)
33 *
34 * Author: L. Mervart
35 *
36 * Created: 29-Jul-2014
37 *
38 * Changes:
39 *
40 * -----------------------------------------------------------------------*/
41
42#include <iostream>
43
44#include "pppMain.h"
45#include "pppCrdFile.h"
46#include "bncsettings.h"
47#include "bnccore.h"
48
49using namespace BNC_PPP;
50using namespace std;
51
52// Constructor
53//////////////////////////////////////////////////////////////////////////////
54t_pppMain::t_pppMain() {
55 _running = false;
56}
57
58// Destructor
59//////////////////////////////////////////////////////////////////////////////
60t_pppMain::~t_pppMain() {
61 stop();
62 QListIterator<t_pppOptions*> iOpt(_options);
63 while (iOpt.hasNext()) {
64 delete iOpt.next();
65 }
66}
67
68//
69//////////////////////////////////////////////////////////////////////////////
70void t_pppMain::start() {
71 if (_running) {
72 return;
73 }
74
75 try {
76 readOptions();
77
78 QListIterator<t_pppOptions*> iOpt(_options);
79 while (iOpt.hasNext()) {
80 const t_pppOptions* opt = iOpt.next();
81 t_pppThread* pppThread = new t_pppThread(opt);
82 pppThread->start();
83 // In batch post-processing (--file replay), the data source must not
84 // start before the PPP client is connected, otherwise the data read
85 // in the meantime get lost (a varying amount, depending on thread
86 // scheduling).
87 if (BNC_CORE->mode() == t_bncCore::batchPostProcessing) {
88 pppThread->waitUntilReady();
89 }
90 _pppThreads << pppThread;
91 _running = true;
92 }
93 }
94 catch (t_except exc) {
95 BNC_CORE->slotMessage(QByteArray::fromStdString(exc.what()), true);
96 _running = true;
97 stop();
98 }
99}
100
101//
102//////////////////////////////////////////////////////////////////////////////
103void t_pppMain::stop() {
104
105 if (!_running) {
106 return;
107 }
108
109 if (_realTime) {
110 QListIterator<t_pppThread*> it(_pppThreads);
111 while (it.hasNext()) {
112 t_pppThread* pppThread = it.next();
113 pppThread->exit();
114 if (BNC_CORE->mode() != t_bncCore::interactive) {
115 while(!pppThread->isFinished()) {
116 pppThread->wait();
117 }
118 delete pppThread;
119 }
120 }
121 _pppThreads.clear();
122 }
123
124 _running = false;
125}
126
127//
128//////////////////////////////////////////////////////////////////////////////
129void t_pppMain::readOptions() {
130
131 QListIterator<t_pppOptions*> iOpt(_options);
132 while (iOpt.hasNext()) {
133 delete iOpt.next();
134 }
135 _options.clear();
136
137 bncSettings settings;
138
139 _realTime = false;
140 if (settings.value("PPP/dataSource").toString() == "Real-Time Streams") {
141 _realTime = true;
142 }
143 else if (settings.value("PPP/dataSource").toString() == "RINEX Files") {
144 _realTime = false;
145 }
146 else {
147 return;
148 }
149
150 QListIterator<QString> iSta(settings.value("PPP/staTable").toStringList());
151 while (iSta.hasNext()) {
152 QStringList hlp = iSta.next().split(",");
153
154 if (hlp.size() < 10) {
155 throw t_except("pppMain: wrong option staTable");
156 }
157
158 t_pppOptions* opt = new t_pppOptions();
159
160 if (settings.value("PPP/logMode").toString() == "debug") {
161 opt->_logMode = t_pppOptions::debug;
162 }
163 else if (settings.value("PPP/logMode").toString() == "all") {
164 opt->_logMode = t_pppOptions::all;
165 }
166 else {
167 opt->_logMode = t_pppOptions::normal;
168 }
169
170 opt->_realTime = _realTime;
171 opt->_roverName = hlp[0].toStdString();
172
173 // Numeric Fields: reject malformed entries
174 // ----------------------------------------
175 double num[9];
176 for (int ii = 1; ii <= 8; ii++) {
177 bool ok;
178 num[ii] = hlp[ii].trimmed().toDouble(&ok);
179 if (!ok || num[ii] < 0.0) {
180 std::string msg = "pppMain: wrong option staTable: station "
181 + opt->_roverName + " field " + std::to_string(ii)
182 + " \"" + hlp[ii].toStdString() + "\"";
183 delete opt;
184 throw t_except(msg.c_str());
185 }
186 }
187 bool okPort;
188 int nmeaPort = hlp[9].trimmed().toInt(&okPort);
189 if (!okPort && !hlp[9].trimmed().isEmpty()) {
190 std::string msg = "pppMain: wrong option staTable: station "
191 + opt->_roverName + " NMEA port \""
192 + hlp[9].toStdString() + "\"";
193 delete opt;
194 throw t_except(msg.c_str());
195 }
196
197 opt->_aprSigCrd[0] = num[1]+1e-10;
198 opt->_aprSigCrd[1] = num[2]+1e-10;
199 opt->_aprSigCrd[2] = num[3]+1e-10;
200 opt->_noiseCrd[0] = num[4]+1e-10;
201 opt->_noiseCrd[1] = num[5]+1e-10;
202 opt->_noiseCrd[2] = num[6]+1e-10;
203 opt->_aprSigTrp = num[7];
204 opt->_noiseTrp = num[8];
205 opt->_nmeaPort = nmeaPort;
206
207 string trkStr = hlp[10].trimmed().toStdString();
208 if (trkStr.length() == 0) {
209 trkStr = "G:12&CWPSLX R:12&CP E:1&CBX E:5&QIX C:26&IQX";
210 }
211 opt->setTrkModes(trkStr);
212
213 if (_realTime) {
214 opt->_corrMount.assign(settings.value("PPP/corrMount").toString().toStdString());
215 opt->_isAPC = (opt->_corrMount.substr(0,4)=="SSRA");
216 opt->_biasMount.assign(settings.value("PPP/biasMount").toString().toStdString());
217 opt->_ionoMount.assign(settings.value("PPP/ionoMount").toString().toStdString());
218 }
219 else {
220 opt->_rinexObs.assign(settings.value("PPP/rinexObs").toString().toStdString());
221 opt->_rinexNav.assign(settings.value("PPP/rinexNav").toString().toStdString());
222 opt->_corrFile.assign(settings.value("PPP/corrFile").toString().toStdString());
223 QFileInfo tmp = QFileInfo(QString::fromStdString(opt->_corrFile));
224 opt->_isAPC = (tmp.baseName().mid(0,4)=="SSRA");
225 opt->_biasFile.assign(settings.value("PPP/biasFile").toString().toStdString());
226 opt->_ionoFile.assign(settings.value("PPP/ionoFile").toString().toStdString());
227 }
228
229 opt->_crdFile.assign(settings.value("PPP/crdFile").toString().toStdString());
230 opt->_antexFileName.assign(settings.value("PPP/antexFile").toString().toStdString());
231 opt->_blqFileName.assign(settings.value("PPP/blqFile").toString().toStdString());
232 opt->_sigmaC1 = settings.value("PPP/sigmaC1").toDouble(); if (opt->_sigmaC1 <= 0.0) opt->_sigmaC1 = 1.00;
233 opt->_sigmaL1 = settings.value("PPP/sigmaL1").toDouble(); if (opt->_sigmaL1 <= 0.0) opt->_sigmaL1 = 0.01;
234 opt->_sigmaGIM = settings.value("PPP/sigmaGIM").toDouble();if (opt->_sigmaGIM <= 0.0) opt->_sigmaGIM = 1.00;
235 opt->_corrWaitTime = settings.value("PPP/corrWaitTime").toDouble();
236 if (!_realTime || opt->_corrMount.empty()) {
237 opt->_corrWaitTime = 0;
238 }
239
240 opt->_pseudoObsIono = false;
241 opt->_refSatRequired = false;
242 // Pseudo Observations
243 if (settings.value("PPP/constraints").toString() == "no") {
244 opt->_pseudoObsIono = false;
245 opt->_refSatRequired = false;
246 opt->_ionoModelType = opt->est;
247 }
248 else if (settings.value("PPP/constraints").toString() == "Ionosphere: pseudo-obs") {
249 opt->_pseudoObsIono = true;
250 opt->_refSatRequired = true;
251 opt->_ionoModelType = opt->est;
252 }
253
254 opt->setLCs('G', settings.value("PPP/lcGPS") .toString().trimmed().toStdString());
255 opt->setLCs('R', settings.value("PPP/lcGLONASS").toString().trimmed().toStdString());
256 opt->setLCs('E', settings.value("PPP/lcGalileo").toString().trimmed().toStdString());
257 opt->setLCs('C', settings.value("PPP/lcBDS") .toString().trimmed().toStdString());
258
259 // Information from the coordinate file
260 // ------------------------------------
261 string crdFileName(settings.value("PPP/crdFile").toString().toStdString());
262 if (!crdFileName.empty()) {
263 vector<t_pppCrdFile::t_staInfo> staInfoVec;
264 t_pppCrdFile::readCrdFile(crdFileName, staInfoVec);
265 for (unsigned ii = 0; ii < staInfoVec.size(); ii++) {
266 const t_pppCrdFile::t_staInfo& staInfo = staInfoVec[ii];
267 if (staInfo._name == opt->_roverName) {
268 opt->_xyzAprRover[0] = staInfo._xyz[0];
269 opt->_xyzAprRover[1] = staInfo._xyz[1];
270 opt->_xyzAprRover[2] = staInfo._xyz[2];
271 opt->_neuEccRover[0] = staInfo._neuAnt[0];
272 opt->_neuEccRover[1] = staInfo._neuAnt[1];
273 opt->_neuEccRover[2] = staInfo._neuAnt[2];
274 opt->_velRover[0] = staInfo._velocity[0];
275 opt->_velRover[1] = staInfo._velocity[1];
276 opt->_velRover[2] = staInfo._velocity[2];
277 opt->_refEpochRover = staInfo._epoch;
278 opt->_antNameRover = staInfo._antenna;
279 opt->_recNameRover = staInfo._receiver;
280 break;
281 }
282 }
283 }
284
285 opt->_minObs = settings.value("PPP/minObs").toInt(); if (opt->_minObs < 4) opt->_minObs = 4;
286 opt->_minEle = settings.value("PPP/minEle").toDouble() * M_PI / 180.0;
287 opt->_maxResC1 = settings.value("PPP/maxResC1").toDouble(); if (opt->_maxResC1 <= 0.0) opt->_maxResC1 = 3.0;
288 opt->_maxResL1 = settings.value("PPP/maxResL1").toDouble(); if (opt->_maxResL1 <= 0.0) opt->_maxResL1 = 0.03;
289 opt->_eleWgtCode = (settings.value("PPP/eleWgtCode").toInt() != 0);
290 opt->_eleWgtPhase = (settings.value("PPP/eleWgtPhase").toInt() != 0);
291 opt->_seedingTime = settings.value("PPP/seedingTime").toDouble();
292
293 // Ambiguity Resolution
294 // --------------------
295 if (settings.value("PPP/arGPS").toInt() != 0) {
296 opt->_ar._systems.insert('G');
297 }
298 if (settings.value("PPP/arGalileo").toInt() != 0) {
299 opt->_ar._systems.insert('E');
300 }
301 if (settings.value("PPP/arBDS").toInt() != 0) {
302 opt->_ar._systems.insert('C');
303 }
304 opt->_ar._minEle = opt->_minEle;
305 opt->_ar._minNumEpo = settings.value("PPP/arMinNumEpo").toInt();
306 opt->_ar._minNumSat = settings.value("PPP/arMinNumSat").toInt();
307 opt->_ar._useYaw = (settings.value("PPP/arUseYaw").toInt() != 0);
308 opt->_ar._maxFrac = settings.value("PPP/arMaxFrac").toDouble();
309 opt->_ar._maxSig = settings.value("PPP/arMaxSig").toDouble();
310
311 // Some default values
312 // -------------------
313 opt->_aprSigClk = 1e3;
314 opt->_aprSigAmb = 1e3;
315 opt->_aprSigIon = 1e2;
316 opt->_aprSigCodeBias = 1e1;
317
318 _options << opt;
319 }
320}
321
Note: See TracBrowser for help on using the repository browser.