source: ntrip/trunk/BNC/src/RTRover/bncrtrover.cpp@ 4788

Last change on this file since 4788 was 4788, checked in by mervart, 12 years ago
File size: 13.5 KB
Line 
1
2#include <iostream>
3#include <iomanip>
4#include <string.h>
5
6#include "bncrtrover.h"
7#include "bncapp.h"
8#include "bncsettings.h"
9#include "bnctime.h"
10
11#include "rtrover_interface.h"
12
13using namespace std;
14
15// Constructor
16////////////////////////////////////////////////////////////////////////////
17t_bncRtrover::t_bncRtrover() : QThread(0) {
18}
19
20// Destructor
21////////////////////////////////////////////////////////////////////////////
22t_bncRtrover::~t_bncRtrover() {
23 rtrover_destroy();
24}
25
26// Run (virtual)
27////////////////////////////////////////////////////////////////////////////
28void t_bncRtrover::run() {
29 bncSettings settings;
30
31 // User Options
32 // ------------
33 _mode = settings.value("rtroverMode").toByteArray();
34 _roverMount = settings.value("rtroverRoverMount").toByteArray();
35 _baseMount = settings.value("rtroverBaseMount").toByteArray();
36 _corrMount = settings.value("rtroverCorrMount").toByteArray();
37 _outputFile.setFileName(settings.value("rtroverOutput").toString());
38 _outputFile.open(QIODevice::WriteOnly | QIODevice::Text);
39
40 // Define Input Options
41 // --------------------
42 rtrover_opt opt;
43 rtrover_initOptions(&opt);
44
45 opt._roverName = strdup(_roverMount.data());
46 opt._baseName = strdup(_baseMount.data());
47 opt._xyzAprRover[0] = settings.value("rtroverRoverRefCrdX").toDouble();
48 opt._xyzAprRover[1] = settings.value("rtroverRoverRefCrdY").toDouble();
49 opt._xyzAprRover[2] = settings.value("rtroverRoverRefCrdZ").toDouble();
50 opt._xyzAprBase[0] = settings.value("rtroverBaseRefCrdX").toDouble();
51 opt._xyzAprBase[1] = settings.value("rtroverBaseRefCrdY").toDouble();
52 opt._xyzAprBase[2] = settings.value("rtroverBaseRefCrdZ").toDouble();
53
54 rtrover_setOptions(&opt);
55
56 free(opt._roverName);
57 free(opt._baseName);
58
59 // Connect to BNC Signals
60 // ----------------------
61 connect(((bncApp*)qApp), SIGNAL(newCorrections(QList<QString>)),
62 this, SLOT(slotNewCorrections(QList<QString>)));
63
64 connect(((bncApp*)qApp), SIGNAL(newEphGPS(gpsephemeris)),
65 this, SLOT(slotNewEphGPS(gpsephemeris)));
66
67 connect(((bncApp*)qApp), SIGNAL(newEphGlonass(glonassephemeris)),
68 this, SLOT(slotNewEphGlonass(glonassephemeris)));
69
70 connect(((bncApp*)qApp), SIGNAL(newEphGalileo(galileoephemeris)),
71 this, SLOT(slotNewEphGalileo(galileoephemeris)));
72
73 // Start processing loop
74 // ---------------------
75 QThread::exec();
76}
77
78//
79////////////////////////////////////////////////////////////////////////////
80void t_bncRtrover::slotNewEphGPS(gpsephemeris gpseph) {
81 QMutexLocker locker(&_mutex);
82
83 bncTime toc(gpseph.GPSweek, gpseph.TOC);
84 bncTime toe(gpseph.GPSweek, gpseph.TOE);
85
86 rtrover_ephGPS eph;
87 eph._satellite._system = 'G';
88 eph._satellite._number = gpseph.satellite;
89 eph._TOC._mjd = toc.mjd();
90 eph._TOC._sec = toc.daysec();
91 eph._TOE._mjd = toe.mjd();
92 eph._TOE._sec = toe.daysec();
93 eph._IODE = gpseph.IODE;
94 eph._IODC = gpseph.IODC;
95 eph._clock_bias = gpseph.clock_bias;
96 eph._clock_drift = gpseph.clock_drift;
97 eph._clock_driftrate = gpseph.clock_driftrate;
98 eph._Crs = gpseph.Crs;
99 eph._Delta_n = gpseph.Delta_n;
100 eph._M0 = gpseph.M0;
101 eph._Cuc = gpseph.Cuc;
102 eph._e = gpseph.e;
103 eph._Cus = gpseph.Cus;
104 eph._sqrt_A = gpseph.sqrt_A;
105 eph._Cic = gpseph.Cic;
106 eph._OMEGA0 = gpseph.OMEGA0;
107 eph._Cis = gpseph.Cis;
108 eph._i0 = gpseph.i0;
109 eph._Crc = gpseph.Crc;
110 eph._omega = gpseph.omega;
111 eph._OMEGADOT = gpseph.OMEGADOT;
112 eph._IDOT = gpseph.IDOT;
113 eph._TGD = gpseph.TGD;
114 eph._health = gpseph.SVhealth;
115
116 rtrover_putGPSEphemeris(&eph);
117}
118
119//
120////////////////////////////////////////////////////////////////////////////
121void t_bncRtrover::slotNewEphGlonass(glonassephemeris gloeph) {
122 QMutexLocker locker(&_mutex);
123
124 int wwUTC = gloeph.GPSWeek;
125 int towUTC = gloeph.GPSTOW;
126 updatetime(&wwUTC, &towUTC, gloeph.tb*1000, 1); // Moscow -> UTC
127 bncTime tUTC(wwUTC,towUTC);
128
129 int wwGPS = gloeph.GPSWeek;
130 int towGPS = gloeph.GPSTOW;
131 updatetime(&wwGPS, &towGPS, gloeph.tb*1000, 0); // Moscow -> GPS
132 bncTime tGPS(wwGPS,towGPS);
133
134 rtrover_ephGlo eph;
135 eph._satellite._system = 'R';
136 eph._satellite._number = gloeph.almanac_number;
137 eph._timeUTC._mjd = tUTC.mjd();
138 eph._timeUTC._sec = tUTC.daysec();
139 eph._gps_utc = int(tGPS-tUTC);
140 eph._E = gloeph.E;
141 eph._tau = gloeph.tau;
142 eph._gamma = gloeph.gamma;
143 eph._x_pos = gloeph.x_pos;
144 eph._x_velocity = gloeph.x_velocity;
145 eph._x_acceleration = gloeph.x_acceleration;
146 eph._y_pos = gloeph.y_pos;
147 eph._y_velocity = gloeph.y_velocity;
148 eph._y_acceleration = gloeph.y_acceleration;
149 eph._z_pos = gloeph.z_pos;
150 eph._z_velocity = gloeph.z_velocity;
151 eph._z_acceleration = gloeph.z_acceleration;
152 eph._health = 0; // TODO ?
153 eph._frequency_number = gloeph.frequency_number;
154
155 rtrover_putGloEphemeris(&eph);
156}
157
158//
159////////////////////////////////////////////////////////////////////////////
160void t_bncRtrover::slotNewEphGalileo(galileoephemeris /* galeph */) {
161 // not yet implemented
162}
163
164//
165////////////////////////////////////////////////////////////////////////////
166void t_bncRtrover::slotNewCorrections(QList<QString> corrList) {
167 QMutexLocker locker(&_mutex);
168
169 if (corrList.size() == 0) {
170 return;
171 }
172
173 int numOrbCorr = 0;
174 int numClkCorr = 0;
175 int numBiases = 0;
176
177 rtrover_orbCorr orbCorr[corrList.size()];
178 rtrover_clkCorr clkCorr[corrList.size()];
179 rtrover_codeBiases biases[corrList.size()];
180
181 QListIterator<QString> it(corrList);
182 while (it.hasNext()) {
183 QString line = it.next();
184
185 // Check the Mountpoint
186 // --------------------
187 QStringList hlp = line.split(" ");
188 if (hlp.size() > 0) {
189 QString mountpoint = hlp[hlp.size()-1];
190 if (mountpoint != _corrMount) {
191 continue;
192 }
193 }
194
195 // Orbit and clock corrections
196 // ---------------------------
197 t_corr corr;
198 if (corr.readLine(line) == success) {
199
200 if (corr.messageType == COTYPE_GPSCOMBINED ||
201 corr.messageType == COTYPE_GLONASSCOMBINED ||
202 corr.messageType == COTYPE_GPSORBIT ||
203 corr.messageType == COTYPE_GLONASSORBIT ) {
204 ++numOrbCorr;
205 rtrover_orbCorr& orbC = orbCorr[numOrbCorr-1];
206 orbC._satellite._system = corr.prn.toAscii()[0];
207 orbC._satellite._number = corr.prn.mid(1).toInt();
208 orbC._iod = corr.iod;
209 orbC._time._mjd = corr.tRao.mjd();
210 orbC._time._sec = corr.tRao.daysec();
211 for (int ii = 0; ii < 3; ii++) {
212 orbC._rao[ii] = corr.rao[ii];
213 orbC._dotRao[ii] = corr.dotRao[ii];
214 orbC._dotDotRao[ii] = corr.dotDotRao[ii];
215 }
216 }
217
218 if (corr.messageType == COTYPE_GPSCOMBINED ||
219 corr.messageType == COTYPE_GLONASSCOMBINED ||
220 corr.messageType == COTYPE_GPSCLOCK ||
221 corr.messageType == COTYPE_GLONASSCLOCK ) {
222 ++numClkCorr;
223 rtrover_clkCorr& clkC = clkCorr[numClkCorr-1];
224 clkC._satellite._system = corr.prn.toAscii()[0];
225 clkC._satellite._number = corr.prn.mid(1).toInt();
226 clkC._iod = corr.iod;
227 clkC._time._mjd = corr.tClk.mjd();
228 clkC._time._sec = corr.tClk.daysec();
229 clkC._dClk = corr.dClk;
230 clkC._dotDClk = corr.dotDClk;
231 clkC._dotDotDClk = corr.dotDotDClk;
232 }
233 }
234
235 // Code Biases
236 // -----------
237 t_bias bias;
238 if (bias.readLine(line) == success) {
239 ++numBiases;
240 rtrover_codeBiases& codeBiases = biases[numBiases-1];
241 codeBiases._biases = new rtrover_bias[bias._value.size()];
242 int iBias = -1;
243 QMapIterator<QByteArray, double> it(bias._value);
244 while (it.hasNext()) {
245 it.next();
246 ++iBias;
247 rtrover_bias& singleBias = codeBiases._biases[iBias];
248 singleBias._rnxType[0] = it.key()[0];
249 singleBias._rnxType[1] = it.key()[1];
250 singleBias._value = it.value();
251 }
252 }
253 }
254
255 // Pass Corrections and Biases to client library
256 // ---------------------------------------------
257 if (numOrbCorr > 0) {
258 rtrover_putOrbCorrections(numOrbCorr, orbCorr);
259 }
260 if (numClkCorr > 0) {
261 rtrover_putClkCorrections(numClkCorr, clkCorr);
262 }
263 if (numBiases > 0) {
264 rtrover_putBiases(numBiases, biases);
265 }
266
267 // Clean the memory
268 // ----------------
269 for (int ii = 0; ii < numBiases; ii++) {
270 delete [] biases[ii]._biases;
271 }
272}
273
274// Auxiliary function - copy observation data
275////////////////////////////////////////////////////////////////////////////
276void copyObs(const t_obs& obsBnc, rtrover_satObs& satObs) {
277
278 bncTime obsTime(obsBnc.GPSWeek, obsBnc.GPSWeeks);
279 satObs._satellite._system = obsBnc.satSys;
280 satObs._satellite._number = obsBnc.satNum;
281 satObs._time._mjd = obsTime.mjd();
282 satObs._time._sec = obsTime.daysec();
283 satObs._slotNumber = obsBnc.slotNum;
284
285 QMap<QByteArray, rtrover_obs> allObs;
286 for (int iEntry = 0; iEntry < GNSSENTRY_NUMBER; ++iEntry) {
287 if (obsBnc._measdata[iEntry] != 0.0) {
288 QByteArray rnxStr = obsBnc.rnxStr(iEntry).toAscii();
289 if (rnxStr.length() == 3) {
290 QByteArray codeType = rnxStr.mid(1);
291
292 bool existed = allObs.contains(codeType);
293 rtrover_obs& currObs = allObs[codeType];
294 if (!existed) {
295 rtrover_initObs(&currObs);
296 currObs._rnxType[0] = codeType[0];
297 currObs._rnxType[1] = codeType[1];
298 }
299
300 if (rnxStr[0] == 'C') {
301 currObs._code = obsBnc._measdata[iEntry];
302 currObs._codeValid = true;
303 }
304 else if (rnxStr[0] == 'L') {
305 currObs._phase = obsBnc._measdata[iEntry];
306 currObs._phaseValid = true;
307 if (codeType[0] == '1') {
308 currObs._slip = obsBnc.slipL1;
309 currObs._slipCounter = obsBnc.slip_cnt_L1;
310 }
311 else if (codeType[0] == '2') {
312 currObs._slip = obsBnc.slipL2;
313 currObs._slipCounter = obsBnc.slip_cnt_L2;
314 }
315 else if (codeType[0] == '5') {
316 currObs._slip = obsBnc.slipL5;
317 currObs._slipCounter = obsBnc.slip_cnt_L5;
318 }
319 }
320 else if (rnxStr[0] == 'D') {
321 currObs._doppler = obsBnc._measdata[iEntry];
322 currObs._dopplerValid = true;
323 }
324 else if (rnxStr[0] == 'S') {
325 currObs._snr = obsBnc._measdata[iEntry];
326 currObs._snrValid = true;
327 }
328 }
329 }
330 }
331 satObs._numObs = allObs.size();
332 satObs._obs = new rtrover_obs[satObs._numObs];
333 int iObs = -1;
334 QMapIterator<QByteArray, rtrover_obs> it(allObs);
335 while (it.hasNext()) {
336 it.next();
337 ++iObs;
338 satObs._obs[iObs] = it.value();
339 }
340}
341
342//
343////////////////////////////////////////////////////////////////////////////
344void t_bncRtrover::slotNewObs(QByteArray staID, bool /* firstObs */, t_obs obsIn) {
345 QMutexLocker locker(&_mutex);
346
347 if (staID != _roverMount && staID != _baseMount) {
348 return;
349 }
350
351 bncTime obsTime(obsIn.GPSWeek, obsIn.GPSWeeks);
352
353 // Find corresponding epoch or create a new one
354 // --------------------------------------------
355 t_epoData* epoData = 0;
356 for (unsigned ii = 0; ii < _epochs.size(); ii++) {
357 if (_epochs[ii]->_time == obsTime) {
358 epoData = _epochs[ii];
359 break;
360 }
361 }
362 if (epoData == 0) {
363 if (_epochs.size() == 0 || _epochs.back()->_time < obsTime) {
364 epoData = new t_epoData();
365 epoData->_time = obsTime;
366 _epochs.push_back(epoData);
367 }
368 else {
369 return;
370 }
371 }
372
373 // Store observation into epoch class
374 // ----------------------------------
375 if (staID == _roverMount) {
376 epoData->_obsRover.push_back(obsIn);
377 }
378 else if (staID == _baseMount) {
379 epoData->_obsBase.push_back(obsIn);
380 }
381
382 // Wait for observations
383 // ---------------------
384 const double WAITTIME = 5.0;
385 double dt = 0.0;
386 if (_epochs.size() > 1) {
387 dt = _epochs.back()->_time - _epochs.front()->_time;
388 }
389 if (dt < WAITTIME) {
390 return;
391 }
392
393 // Copy observations into rtrover_satObs structures
394 // ------------------------------------------------
395 t_epoData* frontEpoData = _epochs.front();
396 _epochs.erase(_epochs.begin());
397
398 int numSatRover = frontEpoData->_obsRover.size();
399 rtrover_satObs satObsRover[numSatRover];
400 for (int ii = 0; ii < numSatRover; ii++) {
401 const t_obs& obsBnc = frontEpoData->_obsRover[ii];
402 rtrover_satObs& satObs = satObsRover[ii];
403 copyObs(obsBnc, satObs);
404 }
405
406 int numSatBase = frontEpoData->_obsBase.size();
407 rtrover_satObs satObsBase[numSatBase];
408 for (int ii = 0; ii < numSatBase; ii++) {
409 const t_obs& obsBnc = frontEpoData->_obsBase[ii];
410 rtrover_satObs& satObs = satObsBase[ii];
411 copyObs(obsBnc, satObs);
412 }
413
414 delete frontEpoData;
415
416 // Process single epoch
417 // --------------------
418 rtrover_output output;
419 rtrover_processEpoch(numSatRover, satObsRover, numSatBase, satObsBase, &output);
420
421 // Write output
422 // ---------------------
423 _outputFile.write(output._log);
424 _outputFile.flush();
425
426 // Free memory
427 // -----------
428 rtrover_freeOutput(&output);
429 for (int ii = 0; ii < numSatRover; ii++) {
430 rtrover_satObs& satObs = satObsRover[ii];
431 delete [] satObs._obs;
432 }
433 for (int ii = 0; ii < numSatBase; ii++) {
434 rtrover_satObs& satObs = satObsBase[ii];
435 delete [] satObs._obs;
436 }
437}
Note: See TracBrowser for help on using the repository browser.