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

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

* empty log message *

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