WNJfilter.hpp
Go to the documentation of this file.
1 //==============================================================================
2 //
3 // This file is part of GNSSTk, the ARL:UT GNSS Toolkit.
4 //
5 // The GNSSTk is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation; either version 3.0 of the License, or
8 // any later version.
9 //
10 // The GNSSTk is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with GNSSTk; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 // This software was developed by Applied Research Laboratories at the
20 // University of Texas at Austin.
21 // Copyright 2004-2022, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24 
25 //==============================================================================
26 //
27 // This software was developed by Applied Research Laboratories at the
28 // University of Texas at Austin, under contract to an agency or agencies
29 // within the U.S. Department of Defense. The U.S. Government retains all
30 // rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 // Pursuant to DoD Directive 523024
33 //
34 // DISTRIBUTION STATEMENT A: This software has been approved for public
35 // release, distribution is unlimited.
36 //
37 //==============================================================================
38 
40 
41 #ifndef WHITE_NOISE_JERK_KALMAN_FILTER
42 #define WHITE_NOISE_JERK_KALMAN_FILTER
43 
44 // std
45 #include <sstream>
46 #include <string>
47 #include <vector>
48 // gnsstk
49 #include "Exception.hpp"
50 #include "KalmanFilter.hpp"
51 #include "Matrix.hpp"
52 #include "Namelist.hpp"
53 #include "StringUtils.hpp"
54 #include "Vector.hpp"
55 // geomatics
56 #include "logstream.hpp"
57 
58 namespace gnsstk
59 {
60  //---------------------------------------------------------------------------------
61  class WNJfilter : public KalmanFilter
62  {
63  public:
64  // member data is accessible by caller, but must be set before
65  // initializeFilter().
66  bool filterOutput; // output usual KMU,KTU,KSU,etc only if true
67  // initial
68  gnsstk::Vector<double> apState; // apriori state, of length Nstate
69  gnsstk::Vector<double> apNoise; // apriori noise, of length Nstate
70 
71  // TU
72  int count; // index in data,msig of next point for MU
73 
74  // MU - all these parallel, time order, no gaps
75  std::vector<double> ttag; // time since first epoch (not needed by filter)
76  std::vector<double> data; // measurement data(ttag)
77  std::vector<double> msig; // measurement sigma(ttag)
78  std::vector<double> psig; // process noise sigma(ttag)
79  // pointers to output state
80  std::vector<double> *ptrx, *ptrv, *ptra; // position, velocity, accel
81  std::vector<double> *ptrs; // sigma on position
82 
83  // output
84  unsigned int prec, width; // precision and width
85 
86  // member functions
87 
88  // empty c'tor - required but don't use it
90  : filterOutput(true), ptrx(NULL), ptrv(NULL), ptra(NULL), ptrs(NULL),
91  prec(2), width(9)
92  {
93  }
94 
95  // explicit c'tor
96  WNJfilter(int dim) { Reset(dim); }
97 
98  void Reset(int dim)
99  {
100  // dim = NL.size() = Nstate is number of states : X, V, A, J, S, C, P
101  gnsstk::Namelist NL;
102  NL += std::string("X");
103  NL += std::string("V");
104  NL += std::string("A");
105  if (dim > 3)
106  {
107  NL += std::string("J");
108  }
109  if (dim > 4)
110  {
111  NL += std::string("S");
112  }
113  if (dim > 5)
114  {
115  NL += std::string("C");
116  }
117  if (dim > 6)
118  {
119  NL += std::string("P");
120  }
121  apState =
122  gnsstk::Vector<double>(dim, 0.0); // apriori state, of length Nstate
123  apNoise =
124  gnsstk::Vector<double>(dim, 0.0); // apriori noise, of length Nstate
125  ttag.clear();
126  data.clear();
127  msig.clear();
128  psig.clear();
129  if (ptrx)
130  {
131  ptrx->clear();
132  }
133  if (ptrv)
134  {
135  ptrv->clear();
136  }
137  if (ptra)
138  {
139  ptra->clear();
140  }
141  if (ptrs)
142  {
143  ptrs->clear();
144  }
145 
146  KalmanFilter::Reset(NL); // dim's SRIF, sets Nstate=NL.size()
147  }
148 
157  {
158  count = 0; // index into data arrays
159  T0 = ttag[0]; // initial time
160  Nnoise = 1; // number of noises
161 
162  if (apState.size() != Nstate || apNoise.size() != Nstate)
163  {
165  std::string("Must define apState and apNoise, and they ") +
166  std::string("must be of length Nstate = ") +
168  std::string(" before calling initializeFilter"));
169  GNSSTK_THROW(e);
170  }
171 
172  State = apState;
174  for (int i = 0; i < Nstate; i++)
175  Cov(i, i) = apNoise(i) * apNoise(i);
176  LOG(DEBUG) << "defineI state " << State;
177  LOG(DEBUG) << "defineI cov " << Cov;
178 
179  if (filterOutput)
180  {
181  LOG(INFO) << "#K[MTS]U N time X V A "
182  << "sigX sigV sigA data SOLresid (M)PFresid";
183  }
184 
185  return 1; // since Cov is covariance
186  }
187 
191  void defineTimestep(double T, double DT,
193  const gnsstk::Matrix<double>& Cov, bool useFlag)
194  {
195  if (!useFlag)
196  {
197  LOG(INFO) << "Filter is singular in defineT";
198  // gnsstk::Exception e("defineTimestep called with singular filter");
199  // GNSSTK_THROW(e);
200  }
201 
202  LOG(DEBUG) << "defineT with Nstate " << Nstate << " and Nnoise "
203  << Nnoise;
207 
208  // build G and Rw
209  G(Nstate - 1, 0) = 1.0;
210  Rw(0, 0) = 1.0 / psig[count];
211  LOG(DEBUG) << "defineT makes G " << G;
212  LOG(DEBUG) << "defineT makes Rw " << Rw;
213 
214  // build PhiInv, the inverse state transition matrix
215  // 1 -DT DT^2/2 -DT^3/6 DT^4/24 ...
216  // 0 1 -DT DT^2/2 -DT^3/6 ...
217  // 0 0 1 -DT DT^2/2 ...
218  // 0 0 0 1 -DT ...
219  // 0 0 0 0 1 ...
220  // ....
221  ident(PhiInv);
222  for (int i = 0; i < Nstate; i++)
223  { // rows
224  double elem(-DT);
225  for (int j = i + 1; j < Nstate; j++)
226  { // cols
227  PhiInv(i, j) = elem;
228  elem *= -DT / double(j + 1);
229  }
230  }
231  LOG(DEBUG) << "defineT makes PhiInv\n" << PhiInv;
232  }
233 
245  bool useFlag)
246  {
247  if (!useFlag)
248  {
249  LOG(INFO) << "Filter is singular in defineM";
250  // gnsstk::Exception e("defineMeasurement called with singular
251  // filter"); GNSSTK_THROW(e);
252  }
253 
254  // TD make Partials, etc members of KalmanFilter, then don't have to
255  // resize
257  Partials(0, 0) = 1.0;
259  Data(0) = data[count];
261  MCov(0, 0) = msig[count];
262 
263  LOG(DEBUG) << "MU at T " << T << " Data: " << Data;
264  LOG(DEBUG) << "MU at T " << T << " Partials: " << Partials;
265  LOG(DEBUG) << "MU at T " << T << " MCov: " << MCov;
266 
267  // next point
268  count++;
269  if (count == data.size())
270  {
271  count--;
272  T = ttag[count] +
273  nominalDT; // nominalDT is stored in KalmanFilter by FF()
274  return ProcessThenQuit;
275  }
276  T = ttag[count];
277  return Process;
278  }
279 
280  // output at each stage ... the user may override
281  // if singular is true, State and Cov may or may not be good
282  virtual void output(int N)
283  {
284  int i;
285  std::ostringstream oss;
286 
287  if (stage == Unknown)
288  {
289  LOG(ERROR) << "Kalman stage not defined in output().";
290  return;
291  }
292  LOG(DEBUG) << "Enter KalmanFilter::output(" << N << ")";
293 
294  // define the output arrays
295  if (stage == MU)
296  {
297  if (ptrx)
298  {
299  ptrx->push_back(State(0));
300  }
301  if (ptrv)
302  {
303  ptrv->push_back(State(1));
304  }
305  if (ptra)
306  {
307  ptra->push_back(State(2));
308  }
309  if (ptrs)
310  {
311  ptrs->push_back(singular ? 0.0 : ::sqrt(Cov(0, 0)));
312  }
313  }
314  if (stage == SU)
315  { // NB count was decremented just above
316  if (ptrx)
317  {
318  (*ptrx)[count] = State(0);
319  }
320  if (ptrv)
321  {
322  (*ptrv)[count] = State(1);
323  }
324  if (ptra)
325  {
326  (*ptra)[count] = State(2);
327  }
328  if (ptrs)
329  {
330  (*ptrs)[count] = (singular ? 0.0 : ::sqrt(Cov(0, 0)));
331  }
332  }
333 
334  if (!filterOutput)
335  {
336  if (stage == SU)
337  {
338  count--;
339  }
340  return;
341  }
342 
343  // if MU or SU, output the namelist first
344  // TD make verbose
345  // if(stage == Init || stage == MU || stage == SU) {
346  // oss << ((stage==MU || stage==Init) ? "KNL" : "KSL") << KFtag << "
347  // "
348  // << std::fixed << N << " " << std::setprecision(3) << time;
349  // gnsstk::Namelist NL = srif.getNames();
350  // for(i=0; i<NL.size(); i++)
351  // oss << " " << std::setw(9) << NL.getName(i);
352  // for(i=0; i<NL.size(); i++)
353  // oss << " " << std::setw(9) << std::string("sig")+NL.getName(i);
354  // oss << " " << std::setw(9) << std::string("sol.res");
355  // if(stage == MU)
356  // oss << " " << std::setw(9) << std::string("pfit-res");
357 
358  // LOG(INFO) << oss.str();
359  // oss.str("");
360  //}
361 
362  // output a label
363  switch (stage)
364  {
365  case Init:
366  oss << "KIN";
367  break;
368  case IB1:
369  case IB2:
370  case IB3:
371  oss << "KAD";
372  break;
373  case TU:
374  oss << "KTU";
375  break;
376  case MU:
377  oss << "KMU";
378  break;
379  case SU:
380  oss << "KSU";
381  break;
382  default:
383  case Unknown:
384  return;
385  break;
386  }
387  oss << KFtag << " ";
388 
389  // output the time and raw data
390  oss << std::fixed << N << " " << std::setprecision(3) << time;
391 
392  // output the state
393  for (i = 0; i < State.size(); i++)
394  oss << " " << std::fixed << std::setprecision(prec)
395  << std::setw(width) << State(i);
396 
397  // output sqrt of diagonal covariance elements
398  oss << std::scientific << std::setprecision(prec);
399  for (i = 0; i < State.size(); i++)
400  oss << " " << std::setw(width)
401  << (singular ? 0.0 : ::sqrt(Cov(i, i)));
402 
403  // if MU, also output data, sol residual and PF residual
404  if (stage == MU)
405  {
406  oss << std::scientific << std::setprecision(prec) << " "
407  << std::setw(width) << data[count - 1] << " "
408  << std::setw(width) << data[count - 1] - State(0) << " "
409  << std::setw(width) << PFResid(0);
410  }
411  // if SU, also output data, sol residual
412  if (stage == SU)
413  {
414  oss << std::scientific << std::setprecision(prec) << " "
415  << std::setw(width) << data[count] << " " << std::setw(width)
416  << data[count] - State(0);
417  count--;
418  }
419 
420  LOG(INFO) << oss.str();
421  }
422 
423  }; // end class WNJfilter
424 
425  //---------------------------------------------------------------------------------
426  //---------------------------------------------------------------------------------
427 } // namespace gnsstk
428 #endif // WHITE_NOISE_JERK_KALMAN_FILTER
gnsstk::KalmanFilter::singular
bool singular
Definition: KalmanFilter.hpp:182
gnsstk::KalmanFilter::Rw
gnsstk::Matrix< double > Rw
SRIF matrix used internally.
Definition: KalmanFilter.hpp:236
gnsstk::ident
BaseClass & ident(RefMatrixBase< T, BaseClass > &m)
Definition: MatrixBaseOperators.hpp:80
gnsstk::KalmanFilter::PFResid
gnsstk::Vector< double > PFResid
post-fit residuals - valid after MU
Definition: KalmanFilter.hpp:224
gnsstk::KalmanFilter::Process
@ Process
Definition: KalmanFilter.hpp:156
gnsstk::WNJfilter::ptrs
std::vector< double > * ptrs
Definition: WNJfilter.hpp:81
gnsstk::KalmanFilter::State
gnsstk::Vector< double > State
filter state
Definition: KalmanFilter.hpp:220
StringUtils.hpp
gnsstk::KalmanFilter::TU
@ TU
Definition: KalmanFilter.hpp:147
gnsstk::KalmanFilter::Init
@ Init
Definition: KalmanFilter.hpp:143
gnsstk::KalmanFilter::SU
@ SU
Definition: KalmanFilter.hpp:149
logstream.hpp
gnsstk::StringUtils::asString
std::string asString(IonexStoreStrategy e)
Convert a IonexStoreStrategy to a whitespace-free string name.
Definition: IonexStoreStrategy.cpp:46
NULL
#define NULL
Definition: getopt1.c:64
gnsstk::WNJfilter::count
int count
Definition: WNJfilter.hpp:72
gnsstk::KalmanFilter::Partials
gnsstk::Matrix< double > Partials
matrix defined by defineM() and used in MU
Definition: KalmanFilter.hpp:226
gnsstk::KalmanFilter::IB1
@ IB1
Definition: KalmanFilter.hpp:144
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
gnsstk::WNJfilter::prec
unsigned int prec
Definition: WNJfilter.hpp:84
gnsstk::WNJfilter::msig
std::vector< double > msig
Definition: WNJfilter.hpp:77
gnsstk::KalmanFilter::G
gnsstk::Matrix< double > G
SRIF matrix used internally - noise.
Definition: KalmanFilter.hpp:235
gnsstk::KalmanFilter::time
double time
seconds since start
Definition: KalmanFilter.hpp:215
gnsstk::WNJfilter::ptra
std::vector< double > * ptra
Definition: WNJfilter.hpp:80
gnsstk::Exception
Definition: Exception.hpp:151
gnsstk::KalmanFilter::nominalDT
double nominalDT
change in time for one TU seconds
Definition: KalmanFilter.hpp:216
gnsstk::WNJfilter::psig
std::vector< double > psig
Definition: WNJfilter.hpp:78
gnsstk::KalmanFilter::stage
FilterStage stage
current stage of the filter - see enum
Definition: KalmanFilter.hpp:214
gnsstk::WNJfilter::ptrx
std::vector< double > * ptrx
Definition: WNJfilter.hpp:80
gnsstk::Matrix< double >
gnsstk::KalmanFilter::Unknown
@ Unknown
Definition: KalmanFilter.hpp:142
gnsstk::KalmanFilter::Data
gnsstk::Vector< double > Data
vector defined by defineM() and used in MU
Definition: KalmanFilter.hpp:228
gnsstk::WNJfilter::defineTimestep
void defineTimestep(double T, double DT, const gnsstk::Vector< double > &State, const gnsstk::Matrix< double > &Cov, bool useFlag)
Definition: WNJfilter.hpp:191
gnsstk::WNJfilter::WNJfilter
WNJfilter()
Definition: WNJfilter.hpp:89
gnsstk::WNJfilter::filterOutput
bool filterOutput
Definition: WNJfilter.hpp:66
gnsstk::ERROR
@ ERROR
Definition: logstream.hpp:57
gnsstk::KalmanFilter::KalmanReturn
enum gnsstk::KalmanFilter::KalmanMUReturnValuesEnum KalmanReturn
gnsstk::KalmanFilter::MCov
gnsstk::Matrix< double > MCov
measurement covariance (defineM() for MU)
Definition: KalmanFilter.hpp:229
gnsstk::WNJfilter::Reset
void Reset(int dim)
Definition: WNJfilter.hpp:98
gnsstk::WNJfilter::ttag
std::vector< double > ttag
Definition: WNJfilter.hpp:75
gnsstk::KalmanFilter
Definition: KalmanFilter.hpp:136
gnsstk::KalmanFilter::IB3
@ IB3
Definition: KalmanFilter.hpp:146
gnsstk::WNJfilter::defineInitial
int defineInitial(double &T0, gnsstk::Vector< double > &State, gnsstk::Matrix< double > &Cov)
Definition: WNJfilter.hpp:155
gnsstk::WNJfilter::ptrv
std::vector< double > * ptrv
Definition: WNJfilter.hpp:80
gnsstk::Vector< double >
gnsstk::WNJfilter::width
unsigned int width
Definition: WNJfilter.hpp:84
gnsstk::WNJfilter
Definition: WNJfilter.hpp:61
gnsstk::KalmanFilter::Cov
gnsstk::Matrix< double > Cov
filter covariance
Definition: KalmanFilter.hpp:221
gnsstk::KalmanFilter::PhiInv
gnsstk::Matrix< double > PhiInv
SRIF matrix used internally - inv state trans.
Definition: KalmanFilter.hpp:234
LOG
#define LOG(level)
define the macro that is used to write to the log stream
Definition: logstream.hpp:315
gnsstk::KalmanFilter::KFtag
std::string KFtag
optional tag to put in output (2nd field)
Definition: KalmanFilter.hpp:218
gnsstk::Vector::size
size_t size() const
STL size.
Definition: Vector.hpp:207
Exception.hpp
gnsstk::WNJfilter::WNJfilter
WNJfilter(int dim)
Definition: WNJfilter.hpp:96
gnsstk::INFO
@ INFO
Definition: logstream.hpp:57
Namelist.hpp
gnsstk::WNJfilter::apState
gnsstk::Vector< double > apState
Definition: WNJfilter.hpp:68
gnsstk::KalmanFilter::Reset
void Reset(const gnsstk::Namelist &NL)
Definition: KalmanFilter.hpp:354
gnsstk::WNJfilter::output
virtual void output(int N)
Definition: WNJfilter.hpp:282
GNSSTK_THROW
#define GNSSTK_THROW(exc)
Definition: Exception.hpp:366
gnsstk::Namelist
Definition: Namelist.hpp:287
gnsstk::DEBUG
@ DEBUG
Definition: logstream.hpp:57
Matrix.hpp
gnsstk::KalmanFilter::ProcessThenQuit
@ ProcessThenQuit
Definition: KalmanFilter.hpp:157
gnsstk::KalmanFilter::IB2
@ IB2
Definition: KalmanFilter.hpp:145
gnsstk::KalmanFilter::Nstate
int Nstate
number of state elements
Definition: KalmanFilter.hpp:211
gnsstk::WNJfilter::defineMeasurements
KalmanReturn defineMeasurements(double &T, const gnsstk::Vector< double > &X, const gnsstk::Matrix< double > &Cov, bool useFlag)
Definition: WNJfilter.hpp:243
gnsstk::WNJfilter::apNoise
gnsstk::Vector< double > apNoise
Definition: WNJfilter.hpp:69
Vector.hpp
gnsstk::KalmanFilter::Nnoise
int Nnoise
Nnoise is there only for the user.
Definition: KalmanFilter.hpp:212
KalmanFilter.hpp
gnsstk::KalmanFilter::MU
@ MU
Definition: KalmanFilter.hpp:148
gnsstk::WNJfilter::data
std::vector< double > data
Definition: WNJfilter.hpp:76


gnsstk
Author(s):
autogenerated on Wed Oct 25 2023 02:40:42