View Javadoc
1   /*
2    * Copyright (C) 2016 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.ar.slam;
17  
18  import com.irurueta.algebra.Matrix;
19  import com.irurueta.algebra.WrongSizeException;
20  import com.irurueta.statistics.InvalidCovarianceMatrixException;
21  import com.irurueta.statistics.MultivariateNormalDist;
22  
23  import java.io.Serializable;
24  
25  /**
26   * Contains control calibration data for a SLAM estimator during
27   * Kalman filtering prediction stage.
28   */
29  public abstract class BaseCalibrationData implements Serializable {
30  
31      /**
32       * Length of control signal.
33       */
34      private final int controlLength;
35  
36      /**
37       * Length of state in SLAM estimator.
38       */
39      private final int stateLength;
40  
41      /**
42       * Control signal mean to correct biases in control signal.
43       */
44      private double[] controlMean;
45  
46      /**
47       * Control signal covariance to take into account for estimation of process
48       * noise during Kalman prediction stage.
49       */
50      private Matrix controlCovariance;
51  
52      /**
53       * Evaluator for distribution propagation.
54       */
55      private transient MultivariateNormalDist.JacobianEvaluator evaluator;
56  
57      /**
58       * Constructor.
59       *
60       * @param controlLength length of control signal.
61       * @param stateLength   length of state in SLAM estimator.
62       * @throws IllegalArgumentException if provided length is not greater than
63       *                                  zero.
64       */
65      protected BaseCalibrationData(final int controlLength, final int stateLength) {
66          if (controlLength < 1 || stateLength < 1) {
67              throw new IllegalArgumentException("length must be greater than zero");
68          }
69  
70          this.controlLength = controlLength;
71          this.stateLength = stateLength;
72      }
73  
74      /**
75       * Gets length of control signal.
76       *
77       * @return length of control signal.
78       */
79      public int getControlLength() {
80          return controlLength;
81      }
82  
83      /**
84       * Gets length of state in SLAM estimator.
85       *
86       * @return length of state in SLAM estimator.
87       */
88      public int getStateLength() {
89          return stateLength;
90      }
91  
92      /**
93       * Gets control signal mean to correct biases in control signal.
94       *
95       * @return control signal mean.
96       */
97      public double[] getControlMean() {
98          return controlMean;
99      }
100 
101     /**
102      * Sets control signal mean to correct biases in control signal.
103      *
104      * @param controlMean control signal mean.
105      * @throws IllegalArgumentException if provided array does not have expected
106      *                                  length.
107      */
108     public void setControlMean(final double[] controlMean) {
109         if (controlMean.length != controlLength) {
110             throw new IllegalArgumentException("wrong mean length");
111         }
112 
113         this.controlMean = controlMean;
114     }
115 
116     /**
117      * Gets control signal covariance to take into account for estimation of
118      * process noise during Kalman prediction stage.
119      *
120      * @return control signal covariance.
121      */
122     public Matrix getControlCovariance() {
123         return controlCovariance;
124     }
125 
126     /**
127      * Sets control signal covariance to take into account for estimation of
128      * process noise during Kalman prediction stage.
129      *
130      * @param controlCovariance control signal covariance.
131      * @throws IllegalArgumentException if provided covariance size is wrong.
132      */
133     public void setControlCovariance(final Matrix controlCovariance) {
134         if (controlCovariance.getRows() != controlLength || controlCovariance.getColumns() != controlLength) {
135             throw new IllegalArgumentException("wrong covariance size");
136         }
137 
138         this.controlCovariance = controlCovariance;
139     }
140 
141     /**
142      * Sets control signal mean and covariance to correct biases in control
143      * signal and to take into account for estimation process noise during
144      * Kalman prediction stage.
145      *
146      * @param controlMean       control signal mean.
147      * @param controlCovariance control signal covariance.
148      * @throws IllegalArgumentException if provided mean or covariance do not
149      *                                  have proper size or length.
150      */
151     public void setControlMeanAndCovariance(final double[] controlMean, final Matrix controlCovariance) {
152         if (controlMean.length != controlLength) {
153             throw new IllegalArgumentException("wrong mean length");
154         }
155         if (controlCovariance.getRows() != controlLength || controlCovariance.getColumns() != controlLength) {
156             throw new IllegalArgumentException("wrong covariance size");
157         }
158 
159         this.controlMean = controlMean;
160         this.controlCovariance = controlCovariance;
161     }
162 
163     /**
164      * Propagates calibrated control signal covariance using current control
165      * jacobian matrix.
166      * The propagated distribution can be used during prediction stage in Kalman
167      * filtering.
168      *
169      * @param controlJacobian current control jacobian matrix.
170      * @return propagated distribution.
171      * @throws InvalidCovarianceMatrixException if estimated covariance is not
172      *                                          valid.
173      * @throws IllegalArgumentException         if provided jacobian has invalid size.
174      */
175     public MultivariateNormalDist propagateWithControlJacobian(final Matrix controlJacobian)
176             throws InvalidCovarianceMatrixException {
177         final var dist = new MultivariateNormalDist();
178         propagateWithControlJacobian(controlJacobian, dist);
179         return dist;
180     }
181 
182     /**
183      * Propagates calibrated control signal covariance using current control
184      * jacobian matrix.
185      * The propagated distribution can be used during prediction stage in Kalman
186      * filtering.
187      *
188      * @param controlJacobian current control jacobian matrix.
189      * @param result          instance where propagated distribution will be stored.
190      * @throws InvalidCovarianceMatrixException if estimated covariance is not
191      *                                          valid.
192      * @throws IllegalArgumentException         if provided jacobian has invalid size.
193      */
194     public void propagateWithControlJacobian(
195             final Matrix controlJacobian, final MultivariateNormalDist result) throws InvalidCovarianceMatrixException {
196         if (controlJacobian.getRows() != stateLength || controlJacobian.getColumns() != controlLength) {
197             throw new IllegalArgumentException("wrong control jacobian size");
198         }
199 
200         if (evaluator == null) {
201             evaluator = new MultivariateNormalDist.JacobianEvaluator() {
202                 @Override
203                 public void evaluate(final double[] x, final double[] y, final Matrix jacobian) {
204                     controlJacobian.copyTo(jacobian);
205                 }
206 
207                 @Override
208                 public int getNumberOfVariables() {
209                     return stateLength;
210                 }
211             };
212         }
213 
214         try {
215             MultivariateNormalDist.propagate(evaluator, controlMean, controlCovariance, result);
216         } catch (final WrongSizeException e) {
217             throw new InvalidCovarianceMatrixException(e);
218         }
219     }
220 }