1 /*
2 * Copyright (C) 2019 Alberto Irurueta Carro (alberto@irurueta.com)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package com.irurueta.navigation.gnss;
17
18 import com.irurueta.algebra.Matrix;
19
20 import java.io.Serializable;
21 import java.util.Objects;
22
23 /**
24 * Kalman filter state for filtered GNSS estimation.
25 */
26 public class GNSSKalmanState implements Serializable, Cloneable {
27
28 /**
29 * Contains estimation of ECEF position and velocity, and estimated clock
30 * offset and drift.
31 */
32 private GNSSEstimation estimation;
33
34 /**
35 * Kalman filter error covariance matrix.
36 */
37 private Matrix covariance;
38
39 /**
40 * Constructor.
41 */
42 public GNSSKalmanState() {
43 }
44
45 /**
46 * Constructor.
47 *
48 * @param estimation GNSS estimation containing ECEF position, velocity and clock
49 * offset and drift.
50 * @param covariance Kalman filter error covariance matrix. Must be 8x8.
51 * @throws IllegalArgumentException if provided covariance matrix is not 8x8.
52 */
53 public GNSSKalmanState(final GNSSEstimation estimation, final Matrix covariance) {
54 setEstimation(estimation);
55 setCovariance(covariance);
56 }
57
58 /**
59 * Copy constructor.
60 *
61 * @param input input instance to copy data from.
62 */
63 public GNSSKalmanState(final GNSSKalmanState input) {
64 copyFrom(input);
65 }
66
67 /**
68 * Gets estimation of ECEF position and velocity, and estimated clock offset
69 * and drift.
70 * If GNSS estimation data is not available, this method makes no action.
71 *
72 * @param result instance where result data will be copied to.
73 * @return true if result data has been copied, false otherwise.
74 */
75 public boolean getEstimation(final GNSSEstimation result) {
76 if (estimation != null) {
77 estimation.copyTo(result);
78 return true;
79 } else {
80 return false;
81 }
82 }
83
84 /**
85 * Gets estimation of ECEF position and velocity, and estimated clock offset
86 * and drift.
87 *
88 * @return GNSS estimation.
89 */
90 public GNSSEstimation getEstimation() {
91 return estimation;
92 }
93
94 /**
95 * Sets estimation of ECEF position and velocity, and estimated clock offset
96 * and drift.
97 *
98 * @param estimation GNSS estimation to be set.
99 */
100 public void setEstimation(final GNSSEstimation estimation) {
101 this.estimation = estimation;
102 }
103
104 /**
105 * Gets Kalman filter error covariance matrix.
106 *
107 * @param result instance where result data will be copied to.
108 * @return true if result data has been copied, false otherwise.
109 */
110 public boolean getCovariance(final Matrix result) {
111 if (covariance != null) {
112 covariance.copyTo(result);
113 return true;
114 } else {
115 return false;
116 }
117 }
118
119 /**
120 * Gets Kalman filter error covariance matrix.
121 *
122 * @return Kalman filter error covariance matrix.
123 */
124 public Matrix getCovariance() {
125 return covariance;
126 }
127
128 /**
129 * Sets Kalman filter error covariance matrix.
130 *
131 * @param covariance Kalman filter error covariance matrix to be set.
132 * @throws IllegalArgumentException if provided covariance matrix is not 8x8.
133 */
134 public void setCovariance(final Matrix covariance) {
135 if (covariance.getRows() != GNSSEstimation.NUM_PARAMETERS
136 || covariance.getColumns() != GNSSEstimation.NUM_PARAMETERS) {
137 throw new IllegalArgumentException();
138 }
139
140 this.covariance = covariance;
141 }
142
143 /**
144 * Copies this instance data into provided instance.
145 *
146 * @param output destination instance where data will be copied to.
147 */
148 public void copyTo(final GNSSKalmanState output) {
149 output.copyFrom(this);
150 }
151
152 /**
153 * Copies data of provided instance into this instance.
154 *
155 * @param input instance to copy data from.
156 */
157 public void copyFrom(final GNSSKalmanState input) {
158 // copy estimation
159 if (input.estimation == null) {
160 estimation = null;
161 } else {
162 if (estimation == null) {
163 estimation = new GNSSEstimation();
164 }
165 estimation.copyFrom(input.estimation);
166 }
167
168 // copy covariance
169 if (input.covariance == null) {
170 covariance = null;
171 } else {
172 if (covariance == null) {
173 covariance = new Matrix(input.covariance);
174 } else {
175 covariance.copyFrom(input.covariance);
176 }
177 }
178 }
179
180 /**
181 * Computes and returns hash code for this instance. Hash codes are almost unique
182 * values that are useful for fast classification and storage of objects in collections.
183 *
184 * @return Hash code.
185 */
186 @Override
187 public int hashCode() {
188 return Objects.hash(estimation, covariance);
189 }
190
191 /**
192 * Checks if provided object is a GNSSKalmanState having exactly the same
193 * contents as this instance.
194 *
195 * @param obj Object to be compared.
196 * @return true if both objects are considered to be equal, false otherwise.
197 */
198 @Override
199 public boolean equals(final Object obj) {
200 if (this == obj) {
201 return true;
202 }
203 if (obj == null || getClass() != obj.getClass()) {
204 return false;
205 }
206 final var other = (GNSSKalmanState) obj;
207 return equals(other);
208 }
209
210 /**
211 * Checks if provided instance has exactly the same contents as this instance.
212 *
213 * @param other instance to be compared.
214 * @return true if both instances are considered to be equal, false otherwise.
215 */
216 public boolean equals(final GNSSKalmanState other) {
217 return equals(other, 0.0);
218 }
219
220 /**
221 * Checks if provided instance has contents similar to this instance up to provided
222 * threshold value.
223 *
224 * @param other instance to be compared.
225 * @param threshold maximum difference allowed for values.
226 * @return true if both instances are considered to be equal (up to provided threshold),
227 * false otherwise.
228 */
229 public boolean equals(final GNSSKalmanState other, final double threshold) {
230 if (other == null) {
231 return false;
232 }
233
234 return other.estimation != null
235 && other.estimation.equals(estimation, threshold)
236 && other.covariance != null
237 && other.covariance.equals(covariance, threshold);
238 }
239
240 /**
241 * Makes a copy of this instance.
242 *
243 * @return a copy of this instance.
244 * @throws CloneNotSupportedException if clone fails for some reason.
245 */
246 @Override
247 protected Object clone() throws CloneNotSupportedException {
248 final var result = (GNSSKalmanState) super.clone();
249 copyTo(result);
250 return result;
251 }
252 }