View Javadoc
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 }