source: ntrip/trunk/BNC/bncmodel.cpp@ 2079

Last change on this file since 2079 was 2079, checked in by mervart, 14 years ago

* empty log message *

File size: 9.0 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: bncParam, bncModel
30 *
31 * Purpose: Model for PPP
32 *
33 * Author: L. Mervart
34 *
35 * Created: 01-Dec-2009
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <iomanip>
42#include <cmath>
43#include <newmatio.h>
44
45#include "bncmodel.h"
46#include "bncpppclient.h"
47#include "bancroft.h"
48#include "bncutils.h"
49#include "bncsettings.h"
50
51using namespace std;
52
53const unsigned MINOBS = 4;
54const double MINELE = 10.0 * M_PI / 180.0;
55const double sig_crd_0 = 100.0;
56const double sig_crd_p = 100.0;
57const double sig_clk_0 = 1000.0;
58
59// Constructor
60////////////////////////////////////////////////////////////////////////////
61bncParam::bncParam(bncParam::parType typeIn, int indexIn) {
62 type = typeIn;
63 index = indexIn;
64 x0 = 0.0;
65 xx = 0.0;
66}
67
68// Destructor
69////////////////////////////////////////////////////////////////////////////
70bncParam::~bncParam() {
71}
72
73// Partial
74////////////////////////////////////////////////////////////////////////////
75double bncParam::partialP3(t_satData* satData) {
76 if (type == CRD_X) {
77 return (x0 - satData->xx(1)) / satData->rho;
78 }
79 else if (type == CRD_Y) {
80 return (x0 - satData->xx(2)) / satData->rho;
81 }
82 else if (type == CRD_Z) {
83 return (x0 - satData->xx(3)) / satData->rho;
84 }
85 else if (type == RECCLK) {
86 return 1.0;
87 }
88 return 0.0;
89}
90
91// Constructor
92////////////////////////////////////////////////////////////////////////////
93bncModel::bncModel() {
94 _xcBanc.ReSize(4); _xcBanc = 0.0;
95 _params.push_back(new bncParam(bncParam::CRD_X, 1));
96 _params.push_back(new bncParam(bncParam::CRD_Y, 2));
97 _params.push_back(new bncParam(bncParam::CRD_Z, 3));
98 _params.push_back(new bncParam(bncParam::RECCLK, 4));
99 _ellBanc.ReSize(3);
100
101 unsigned nPar = _params.size();
102 _QQ.ReSize(nPar);
103 _QQ = 0.0;
104
105 _QQ(1,1) = sig_crd_0 * sig_crd_0;
106 _QQ(2,2) = sig_crd_0 * sig_crd_0;
107 _QQ(3,3) = sig_crd_0 * sig_crd_0;
108 _QQ(4,4) = sig_clk_0 * sig_clk_0;
109
110 _xx.ReSize(nPar);
111 _xx = 0.0;
112
113 _static = false;
114
115 bncSettings settings;
116 if ( Qt::CheckState(settings.value("pppStatic").toInt()) == Qt::Checked) {
117 _static = true;
118 }
119}
120
121// Destructor
122////////////////////////////////////////////////////////////////////////////
123bncModel::~bncModel() {
124}
125
126// Bancroft Solution
127////////////////////////////////////////////////////////////////////////////
128t_irc bncModel::cmpBancroft(t_epoData* epoData) {
129
130 if (epoData->size() < MINOBS) {
131 return failure;
132 }
133
134 Matrix BB(epoData->size(), 4);
135
136 QMapIterator<QString, t_satData*> it(epoData->satData);
137 int iObs = 0;
138 while (it.hasNext()) {
139 ++iObs;
140 it.next();
141 QString prn = it.key();
142 t_satData* satData = it.value();
143 BB(iObs, 1) = satData->xx(1);
144 BB(iObs, 2) = satData->xx(2);
145 BB(iObs, 3) = satData->xx(3);
146 BB(iObs, 4) = satData->P3 + satData->clk;
147 }
148
149 bancroft(BB, _xcBanc);
150
151 // Ellipsoidal Coordinates
152 // ------------------------
153 xyz2ell(_xcBanc.data(), _ellBanc.data());
154
155 // Compute Satellite Elevations
156 // ----------------------------
157 QMutableMapIterator<QString, t_satData*> it2(epoData->satData);
158 while (it2.hasNext()) {
159 it2.next();
160 QString prn = it2.key();
161 t_satData* satData = it2.value();
162
163 ColumnVector dx = satData->xx - _xcBanc.Rows(1,3);
164 double rho = dx.norm_Frobenius();
165
166 double neu[3];
167 xyz2neu(_ellBanc.data(), dx.data(), neu);
168
169 satData->eleSat = acos( sqrt(neu[0]*neu[0] + neu[1]*neu[1]) / rho );
170 if (neu[2] < 0) {
171 satData->eleSat *= -1.0;
172 }
173 satData->azSat = atan2(neu[1], neu[0]);
174
175 if (satData->eleSat < MINELE) {
176 delete satData;
177 it2.remove();
178 }
179 }
180
181 return success;
182}
183
184// Computed Value
185////////////////////////////////////////////////////////////////////////////
186double bncModel::cmpValueP3(t_satData* satData) {
187
188 ColumnVector xRec(3);
189 xRec(1) = x();
190 xRec(2) = y();
191 xRec(3) = z();
192
193 double rho0 = (satData->xx - xRec).norm_Frobenius();
194 double dPhi = t_CST::omega * rho0 / t_CST::c;
195
196 xRec(1) = x() * cos(dPhi) - y() * sin(dPhi);
197 xRec(2) = y() * cos(dPhi) + x() * sin(dPhi);
198 xRec(3) = z();
199
200 satData->rho = (satData->xx - xRec).norm_Frobenius();
201
202 double tropDelay = delay_saast(satData->eleSat);
203
204 return satData->rho + clk() - satData->clk + tropDelay;
205}
206
207// Tropospheric Model (Saastamoinen)
208////////////////////////////////////////////////////////////////////////////
209double bncModel::delay_saast(double Ele) {
210
211 double height = _ellBanc(3);
212
213 double pp = 1013.25 * pow(1.0 - 2.26e-5 * height, 5.225);
214 double TT = 18.0 - height * 0.0065 + 273.15;
215 double hh = 50.0 * exp(-6.396e-4 * height);
216 double ee = hh / 100.0 * exp(-37.2465 + 0.213166*TT - 0.000256908*TT*TT);
217
218 double h_km = height / 1000.0;
219
220 if (h_km < 0.0) h_km = 0.0;
221 if (h_km > 5.0) h_km = 5.0;
222 int ii = int(h_km + 1);
223 double href = ii - 1;
224
225 double bCor[6];
226 bCor[0] = 1.156;
227 bCor[1] = 1.006;
228 bCor[2] = 0.874;
229 bCor[3] = 0.757;
230 bCor[4] = 0.654;
231 bCor[5] = 0.563;
232
233 double BB = bCor[ii-1] + (bCor[ii]-bCor[ii-1]) * (h_km - href);
234
235 double zen = M_PI/2.0 - Ele;
236
237 return (0.002277/cos(zen)) * (pp + ((1255.0/TT)+0.05)*ee - BB*(tan(zen)*tan(zen)));
238}
239
240// Prediction Step of the Filter
241////////////////////////////////////////////////////////////////////////////
242void bncModel::predict() {
243
244 // Coordinates
245 // -----------
246 if (_static) {
247 if (x() == 0.0 && y() == 0.0 && z() == 0.0) {
248 _params[0]->x0 = _xcBanc(1);
249 _params[1]->x0 = _xcBanc(2);
250 _params[2]->x0 = _xcBanc(3);
251 }
252 else {
253 _params[0]->x0 += _params[0]->xx;
254 _params[1]->x0 += _params[1]->xx;
255 _params[2]->x0 += _params[2]->xx;
256 }
257 }
258 else {
259 _params[0]->x0 = _xcBanc(1);
260 _params[1]->x0 = _xcBanc(2);
261 _params[2]->x0 = _xcBanc(3);
262
263 _QQ(1,1) += sig_crd_p * sig_crd_p;
264 _QQ(2,2) += sig_crd_p * sig_crd_p;
265 _QQ(3,3) += sig_crd_p * sig_crd_p;
266 }
267
268 // Receiver Clocks
269 // ---------------
270 _params[3]->x0 = _xcBanc(4);
271 for (int iPar = 1; iPar <= _params.size(); iPar++) {
272 _QQ(iPar, 4) = 0.0;
273 }
274 _QQ(4,4) = sig_clk_0 * sig_clk_0;
275
276 // Nullify the Solution Vector
277 // ---------------------------
278 for (int iPar = 1; iPar <= _params.size(); iPar++) {
279 _params[iPar-1]->xx = 0.0;
280 }
281 _xx = 0.0;
282}
283
284// Update Step of the Filter (currently just a single-epoch solution)
285////////////////////////////////////////////////////////////////////////////
286t_irc bncModel::update(t_epoData* epoData) {
287
288 if (epoData->size() < MINOBS) {
289 return failure;
290 }
291
292 predict();
293
294 unsigned nPar = _params.size();
295 unsigned nObs = epoData->size();
296
297 // Create First-Design Matrix
298 // --------------------------
299 Matrix AA(nObs, nPar); // first design matrix
300 ColumnVector ll(nObs); // tems observed-computed
301
302 unsigned iObs = 0;
303 QMapIterator<QString, t_satData*> itObs(epoData->satData);
304 while (itObs.hasNext()) {
305 ++iObs;
306 itObs.next();
307 QString prn = itObs.key();
308 t_satData* satData = itObs.value();
309 ll(iObs) = satData->P3 - cmpValueP3(satData);
310
311 for (int iPar = 1; iPar <= _params.size(); iPar++) {
312 AA(iObs, iPar) = _params[iPar-1]->partialP3(satData);
313 }
314 }
315
316 // Compute Kalman Update
317 // ---------------------
318 if (false) {
319 IdentityMatrix PP(nObs);
320 SymmetricMatrix HH; HH << PP + AA * _QQ * AA.t();
321 SymmetricMatrix Hi = HH.i();
322 Matrix KK = _QQ * AA.t() * Hi;
323 ColumnVector v1 = ll - AA * _xx;
324 _xx = _xx + KK * v1;
325 IdentityMatrix Id(nPar);
326 _QQ << (Id - KK * AA) * _QQ;
327 }
328 else {
329 IdentityMatrix PP(nObs);
330 Matrix ATP = AA.t() * PP;
331 SymmetricMatrix NN = _QQ.i();
332 ColumnVector bb = NN * _xx + ATP * ll;
333 NN << NN + ATP * AA;
334 _QQ = NN.i();
335 _xx = _QQ * bb;
336 }
337
338 // Set Solution Vector
339 // -------------------
340 QVectorIterator<bncParam*> itPar(_params);
341 while (itPar.hasNext()) {
342 bncParam* par = itPar.next();
343 par->xx = _xx(par->index);
344 }
345
346 return success;
347}
Note: See TracBrowser for help on using the repository browser.