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 }