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

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

* empty log message *

File size: 8.1 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
113// Destructor
114////////////////////////////////////////////////////////////////////////////
115bncModel::~bncModel() {
116}
117
118// Bancroft Solution
119////////////////////////////////////////////////////////////////////////////
120t_irc bncModel::cmpBancroft(t_epoData* epoData) {
121
122 if (epoData->size() < MINOBS) {
123 return failure;
124 }
125
126 Matrix BB(epoData->size(), 4);
127
128 QMapIterator<QString, t_satData*> it(epoData->satData);
129 int iObs = 0;
130 while (it.hasNext()) {
131 ++iObs;
132 it.next();
133 QString prn = it.key();
134 t_satData* satData = it.value();
135 BB(iObs, 1) = satData->xx(1);
136 BB(iObs, 2) = satData->xx(2);
137 BB(iObs, 3) = satData->xx(3);
138 BB(iObs, 4) = satData->P3 + satData->clk;
139 }
140
141 bancroft(BB, _xcBanc);
142
143 // Ellipsoidal Coordinates
144 // ------------------------
145 xyz2ell(_xcBanc.data(), _ellBanc.data());
146
147 // Compute Satellite Elevations
148 // ----------------------------
149 QMutableMapIterator<QString, t_satData*> it2(epoData->satData);
150 while (it2.hasNext()) {
151 it2.next();
152 QString prn = it2.key();
153 t_satData* satData = it2.value();
154
155 ColumnVector dx = satData->xx - _xcBanc.Rows(1,3);
156 double rho = dx.norm_Frobenius();
157
158 double neu[3];
159 xyz2neu(_ellBanc.data(), dx.data(), neu);
160
161 satData->eleSat = acos( sqrt(neu[0]*neu[0] + neu[1]*neu[1]) / rho );
162 if (neu[2] < 0) {
163 satData->eleSat *= -1.0;
164 }
165 satData->azSat = atan2(neu[1], neu[0]);
166
167 if (satData->eleSat < MINELE) {
168 delete satData;
169 it2.remove();
170 }
171 }
172
173 return success;
174}
175
176// Computed Value
177////////////////////////////////////////////////////////////////////////////
178double bncModel::cmpValueP3(t_satData* satData) {
179
180 ColumnVector xRec(3);
181 xRec(1) = x();
182 xRec(2) = y();
183 xRec(3) = z();
184
185 double rho0 = (satData->xx - xRec).norm_Frobenius();
186 double dPhi = t_CST::omega * rho0 / t_CST::c;
187
188 xRec(1) = x() * cos(dPhi) - y() * sin(dPhi);
189 xRec(2) = y() * cos(dPhi) + x() * sin(dPhi);
190 xRec(3) = z();
191
192 satData->rho = (satData->xx - xRec).norm_Frobenius();
193
194 double tropDelay = delay_saast(satData->eleSat);
195
196 return satData->rho + clk() - satData->clk + tropDelay;
197}
198
199// Tropospheric Model (Saastamoinen)
200////////////////////////////////////////////////////////////////////////////
201double bncModel::delay_saast(double Ele) {
202
203 double height = _ellBanc(3);
204
205 double pp = 1013.25 * pow(1.0 - 2.26e-5 * height, 5.225);
206 double TT = 18.0 - height * 0.0065 + 273.15;
207 double hh = 50.0 * exp(-6.396e-4 * height);
208 double ee = hh / 100.0 * exp(-37.2465 + 0.213166*TT - 0.000256908*TT*TT);
209
210 double h_km = height / 1000.0;
211
212 if (h_km < 0.0) h_km = 0.0;
213 if (h_km > 5.0) h_km = 5.0;
214 int ii = int(h_km + 1);
215 double href = ii - 1;
216
217 double bCor[6];
218 bCor[0] = 1.156;
219 bCor[1] = 1.006;
220 bCor[2] = 0.874;
221 bCor[3] = 0.757;
222 bCor[4] = 0.654;
223 bCor[5] = 0.563;
224
225 double BB = bCor[ii-1] + (bCor[ii]-bCor[ii-1]) * (h_km - href);
226
227 double zen = M_PI/2.0 - Ele;
228
229 return (0.002277/cos(zen)) * (pp + ((1255.0/TT)+0.05)*ee - BB*(tan(zen)*tan(zen)));
230}
231
232// Prediction Step of the Filter
233////////////////////////////////////////////////////////////////////////////
234void bncModel::predict() {
235
236 _params[0]->x0 = _xcBanc(1);
237 _params[1]->x0 = _xcBanc(2);
238 _params[2]->x0 = _xcBanc(3);
239 _params[3]->x0 = _xcBanc(4);
240
241 _params[0]->xx = 0.0;
242 _params[1]->xx = 0.0;
243 _params[2]->xx = 0.0;
244 _params[3]->xx = 0.0;
245
246 _QQ(1,1) += sig_crd_p * sig_crd_p;
247 _QQ(2,2) += sig_crd_p * sig_crd_p;
248 _QQ(3,3) += sig_crd_p * sig_crd_p;
249
250 for (int iPar = 1; iPar <= _params.size(); iPar++) {
251 _QQ(iPar, 4) = 0.0;
252 }
253 _QQ(4,4) = sig_clk_0 * sig_clk_0;
254
255 _xx = 0.0;
256}
257
258// Update Step of the Filter (currently just a single-epoch solution)
259////////////////////////////////////////////////////////////////////////////
260t_irc bncModel::update(t_epoData* epoData) {
261
262 if (epoData->size() < MINOBS) {
263 return failure;
264 }
265
266 predict();
267
268 unsigned nPar = _params.size();
269 unsigned nObs = epoData->size();
270
271 // Create First-Design Matrix
272 // --------------------------
273 Matrix AA(nObs, nPar); // first design matrix
274 ColumnVector ll(nObs); // tems observed-computed
275
276 unsigned iObs = 0;
277 QMapIterator<QString, t_satData*> itObs(epoData->satData);
278 while (itObs.hasNext()) {
279 ++iObs;
280 itObs.next();
281 QString prn = itObs.key();
282 t_satData* satData = itObs.value();
283 ll(iObs) = satData->P3 - cmpValueP3(satData);
284
285 for (int iPar = 1; iPar <= _params.size(); iPar++) {
286 AA(iObs, iPar) = _params[iPar-1]->partialP3(satData);
287 }
288 }
289
290 // Compute Kalman Update
291 // ---------------------
292 IdentityMatrix PP(nObs);
293 SymmetricMatrix HH; HH << PP + AA * _QQ * AA.t();
294 SymmetricMatrix Hi = HH.i();
295 Matrix KK = _QQ * AA.t() * Hi;
296 ColumnVector v1 = ll - AA * _xx;
297 _xx = _xx + KK * v1;
298 IdentityMatrix Id(nPar);
299 _QQ << (Id - KK * AA) * _QQ;
300
301 // Set Solution Vector
302 // -------------------
303 QVectorIterator<bncParam*> itPar(_params);
304 while (itPar.hasNext()) {
305 bncParam* par = itPar.next();
306 par->xx = _xx(par->index);
307 }
308
309 return success;
310}
Note: See TracBrowser for help on using the repository browser.