ModelSpace
All Classes Namespaces Functions Variables Enumerations Pages
EkfMeasurementUpdate.hpp
1/******************************************************************************
2* Copyright (c) ATTX LLC 2024. All Rights Reserved.
3*
4* This software and associated documentation (the "Software") are the
5* proprietary and confidential information of ATTX, LLC. The Software is
6* furnished under a license agreement between ATTX and the user organization
7* and may be used or copied only in accordance with the terms of the agreement.
8* Refer to 'license/attx_license.adoc' for standard license terms.
9*
10* EXPORT CONTROL NOTICE: THIS SOFTWARE MAY INCLUDE CONTENT CONTROLLED UNDER THE
11* INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) OR THE EXPORT ADMINISTRATION
12* REGULATIONS (EAR99). No part of the Software may be used, reproduced, or
13* transmitted in any form or by any means, for any purpose, without the express
14* written permission of ATTX, LLC.
15******************************************************************************/
16
17#ifndef GNC_NAVIGATION_EKF_EKF_MEASUREMENT_UPDATE_HPP
18#define GNC_NAVIGATION_EKF_EKF_MEASUREMENT_UPDATE_HPP
19
20#include "core/Matrix.hpp"
21#include "core/CartesianVector.hpp"
22#include "core/matrixmath.hpp"
23#include "core/vectormath.hpp"
24#include "utils/Measurements.hpp"
25#include "utils/Integrator.hpp"
26
27namespace clockwerk {
28
29 /**
30 * @brief Generic, templated EKF measurement update class
31 *
32 * This class performs an EKF measurement update using the current
33 * target state, an "observer state" which provides information (i.e.
34 * ground station information), and the associated measurement and
35 * H matrix functions. It requires three templated arguments, which
36 * are as follows:
37 * N - The number of target states estimated in the EKF
38 * M - The number of measurement states provided
39 * O - The number of observer states used to support measurement generation
40 *
41 * Two "functions" which take the form of a Measurements class must
42 * also be set: The function which generates measurements, and the
43 * function which generates the H matrix.
44 *
45 * To run the measurement update, both functions are required. The first
46 * generates measurement residuals, and the second to actuall provide
47 * the state update
48 */
49 template <typename T, unsigned int N, unsigned int M, unsigned int O>
51 public:
52 /// @brief Function to generate residual and H matrix from current state
53 /// @param state The current state of the filter
54 /// @param obs_state An observer state used to generate measurements
55 /// @param measurement The actual measurement derived from sensors
56 /// @param residual Implicit return of the difference measurement - estimated measurement
57 /// @param H Implicit return of the measurement sensitivity matrix for the system
58 /// @return Error code corresponding to success/failure
59 int generateResidualHMatrix(const std::array<T, N> &state, const std::array<T, O> &obs_state,
60 const std::array<T, M> &measurement, CartesianVector<T, M> *residual,
61 Matrix<T, M, N> *H);
62
63 /// @brief Function to perform state measurement update in EKF
64 /// @param residual The difference measurement - estimated measurement
65 /// @param H The measurement sensitivity matrix for the system
66 /// @param state_minus The system state prior to measurement update
67 /// @param cov_minus The system covariance prior to measurement update
68 /// @param meas_cov The covariance of the measurement
69 /// @param state_plus Implicit return of the state of the system after measurement update
70 /// @param cov_plus Implicit return of the covariance of the system after measurement update
71 /// @return Error code corresponding to success/failure
72 int updateState(const CartesianVector<T, M> &residual, const Matrix<T, M, N> &H,
73 const std::array<T, N> &state_minus, const Matrix<T, N, N> &cov_minus,
74 const Matrix<T, M, M> &meas_cov, std::array<T, N> *state_plus,
75 Matrix<T, N, N> *cov_plus);
76
77 /// @brief Function to generate covariance for measurement update evaluation
78 /// @param H The measurement sensitivity matrix for the system
79 /// @param state_cov The covariance in the system state
80 /// @param meas_cov The covariance associated with the measurement
81 /// @param residual_cov Implicit return of the expected covariance of the residual
82 /// @return Error code corresponding to success/failure
83 int calculateMeasurementCovariance(const Matrix<T, M, N> &H, const Matrix<T, N, N> &state_cov,
84 const Matrix<T, M, M> &meas_cov, Matrix<T, M, M> *residual_cov);
85
86 /// Pointer to the measurement class to calculate the estimated measurement given the current
87 /// state of the object. The measurement class should be configured to use size
88 Measurements<T, N, M, O>* measurement_ptr = nullptr;
89
90 /// Pointer to the measurement class to calculate the H matrix from the estimated
91 /// spacecraft state
92 Measurements<T, N, M*N, O>* H_ptr = nullptr;
93 private:
94 // Measurement vector from estimated state for internal use
95 std::array<T, M> _est_meas;
96
97 // H matrix for internal use
98 std::array<T, M*N> _tmp_H_array;
99 Matrix<T, N, M> _H_tspose;
100
101 // K matrix for internal use
102 Matrix<T, M, M> _tmp;
103 Matrix<T, M, M> _tmp_inv;
104 Matrix<T, N, M> _K;
105
106 // Update vector for internal use
107 CartesianVector<T, N> _update;
108
109 // Update matrix for covariance
110 Matrix<T, N, N> _tmp_cov;
111 };
112
113 template<typename T, unsigned int N, unsigned int M, unsigned int O>
114 int EkfMeasurementUpdate<T, N, M, O>::generateResidualHMatrix(const std::array<T, N> &state, const std::array<T, O> &obs_state,
115 const std::array<T, M> &measurement, CartesianVector<T, M> *residual,
116 Matrix<T, M, N> *H) {
117 // Verify that our measurement functions are set
118 if(measurement_ptr == nullptr || H_ptr == nullptr) {
119 return ERROR_NULLPTR;
120 }
121
122 if(residual == nullptr || H == nullptr) {
123 return ERROR_NULLPTR;
124 }
125
126 // Calculate our estimated measurement and our H from our state
127 int err = measurement_ptr->calculateMeasurements(T(), state, obs_state, _est_meas);
128 if(err) {return err;}
129
130 err = H_ptr->calculateMeasurements(T(), state, obs_state, _tmp_H_array);
131
132 if(err) {return err;}
133 H->setFromArray(&_tmp_H_array[0]);
134
135 // Calculate our residual
136 for(unsigned int i = 0; i < M; i++) {
137 (*residual)[i] = measurement[i] - _est_meas[i];
138 }
139
140 return NO_ERROR;
141 }
142
143 template<typename T, unsigned int N, unsigned int M, unsigned int O>
144 int EkfMeasurementUpdate<T, N, M, O>::updateState(const CartesianVector<T, M> &residual, const Matrix<T, M, N> &H,
145 const std::array<T, N> &state_minus, const Matrix<T, N, N> &cov_minus,
146 const Matrix<T, M, M> &meas_cov, std::array<T, N> *state_plus,
147 Matrix<T, N, N> *cov_plus) {
148
149 if(state_plus == nullptr || cov_plus == nullptr) {
150 return ERROR_NULLPTR;
151 }
152
153 // First invert our H matrix
154 H.transpose(_H_tspose);
155
156 // Now do some math to calculate our K matrix
157 _tmp = H*cov_minus*_H_tspose + meas_cov;
158 int err = _tmp.inverse(_tmp_inv); if(err) {return err;}
159 _K = cov_minus*_H_tspose*_tmp_inv;
160
161 // Calculate our update from our innovation
162 _update = _K*residual;
163 for(unsigned int i = 0; i < N; i++) {
164 (*state_plus)[i] = state_minus[i] + _update[i];
165 }
166
167 // Update our covariance
168 _tmp_cov.eye();
169 _tmp_cov = _tmp_cov - _K*H;
170 (*cov_plus) = _tmp_cov*cov_minus*_tmp_cov.transpose();
171
172 return NO_ERROR;
173 }
174
175 template<typename T, unsigned int N, unsigned int M, unsigned int O>
176 int EkfMeasurementUpdate<T, N, M, O>::calculateMeasurementCovariance(const Matrix<T, M, N> &H, const Matrix<T, N, N> &state_cov,
177 const Matrix<T, M, M> &meas_cov, Matrix<T, M, M> *residual_cov) {
178 if(residual_cov == nullptr) {return ERROR_NULLPTR;}
179 H.transpose(_H_tspose);
180 *residual_cov = H*state_cov*_H_tspose + meas_cov;
181 return NO_ERROR;
182 }
183
184}
185
186#endif
Standard vector class derived from Matrix.
Definition CartesianVector.hpp:39
Generic, templated EKF measurement update class.
Definition EkfMeasurementUpdate.hpp:50
int calculateMeasurementCovariance(const Matrix< T, M, N > &H, const Matrix< T, N, N > &state_cov, const Matrix< T, M, M > &meas_cov, Matrix< T, M, M > *residual_cov)
Function to generate covariance for measurement update evaluation.
Definition EkfMeasurementUpdate.hpp:176
int generateResidualHMatrix(const std::array< T, N > &state, const std::array< T, O > &obs_state, const std::array< T, M > &measurement, CartesianVector< T, M > *residual, Matrix< T, M, N > *H)
Function to generate residual and H matrix from current state.
Definition EkfMeasurementUpdate.hpp:114
Measurements< T, N, M, O > * measurement_ptr
Pointer to the measurement class to calculate the estimated measurement given the current state of th...
Definition EkfMeasurementUpdate.hpp:88
Measurements< T, N, M *N, O > * H_ptr
Pointer to the measurement class to calculate the H matrix from the estimated spacecraft state.
Definition EkfMeasurementUpdate.hpp:92
int updateState(const CartesianVector< T, M > &residual, const Matrix< T, M, N > &H, const std::array< T, N > &state_minus, const Matrix< T, N, N > &cov_minus, const Matrix< T, M, M > &meas_cov, std::array< T, N > *state_plus, Matrix< T, N, N > *cov_plus)
Function to perform state measurement update in EKF.
Definition EkfMeasurementUpdate.hpp:144
Matrix math implementation.
Definition Matrix.hpp:54
Definition Measurements.hpp:39
#define NO_ERROR
Definition clockwerkerrors.h:31
#define ERROR_NULLPTR
Definition clockwerkerrors.h:57