AbstractUnscentedTransform.java

  1. /*
  2.  * Licensed to the Hipparchus project under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The Hipparchus project licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      https://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.hipparchus.util;

  18. import org.hipparchus.exception.LocalizedCoreFormats;
  19. import org.hipparchus.exception.MathIllegalArgumentException;
  20. import org.hipparchus.linear.ArrayRealVector;
  21. import org.hipparchus.linear.RealMatrix;
  22. import org.hipparchus.linear.RealVector;
  23. import org.hipparchus.linear.SemiDefinitePositiveCholeskyDecomposition;

  24. /**
  25.  * Base class for unscented transform providers.
  26.  * @since 2.2
  27.  */
  28. public abstract class AbstractUnscentedTransform implements UnscentedTransformProvider {

  29.     /**
  30.      * Constructor.
  31.      * @param stateDim the dimension of the state
  32.      */
  33.     protected AbstractUnscentedTransform(final int stateDim) {
  34.         // Check state dimension
  35.         if (stateDim == 0) {
  36.             // State dimension must be different from 0
  37.             throw new MathIllegalArgumentException(LocalizedCoreFormats.ZERO_STATE_SIZE);
  38.         }
  39.     }

  40.     /**
  41.      * {@inheritDoc}
  42.      * <p>
  43.      * Let n be the state dimension and Si be the ith row of the covariance matrix square root.
  44.      * The returned array is organized as follow. Element 0 contains the process state, also
  45.      * called the mean state. Elements from 1 to n contain the process state + Si. Finally,
  46.      * elements from n + 1 to 2n contain the process state - Si
  47.      */
  48.     @Override
  49.     public RealVector[] unscentedTransform(final RealVector state, final RealMatrix covariance) {

  50.         // State dimensions
  51.         final int n = state.getDimension();

  52.         // Initialize array containing sigma points
  53.         final RealVector[] sigmaPoints = new ArrayRealVector[(2 * n) + 1];
  54.         sigmaPoints[0] = state;

  55.         // Apply multiplication factor to the covariance matrix
  56.         final double     factor = getMultiplicationFactor();
  57.         final RealMatrix temp   = covariance.scalarMultiply(factor);

  58.         // Compute lower triangular matrix of Cholesky decomposition
  59.         // Note: When the estimation error covariance is propagated, it sometimes
  60.         //       cannot maintain the positive semidefiniteness.
  61.         //       To enhance the numerical stability of the unscented transform,
  62.         //       the semidefinite positive Cholesky decomposition is used.
  63.         final RealMatrix L = new SemiDefinitePositiveCholeskyDecomposition(temp).getL();

  64.         // Compute sigma points
  65.         for (int i = 1; i <= n; i++) {
  66.             sigmaPoints[i]     = sigmaPoints[0].add(L.getColumnVector(i - 1));
  67.             sigmaPoints[i + n] = sigmaPoints[0].subtract(L.getColumnVector(i - 1));
  68.         }

  69.         // Return sigma points
  70.         return sigmaPoints;

  71.     }

  72.     /**
  73.      * Get the factor applied to the covariance matrix during the unscented transform.
  74.      * @return the factor applied to the covariance matrix during the unscented transform
  75.      */
  76.     protected abstract double getMultiplicationFactor();

  77. }