package com.dronecontrol.perceptual.components.filters; import com.google.inject.Inject; import com.dronecontrol.perceptual.data.body.Coordinate; import org.ejml.data.DenseMatrix64F; public class KalmanFilterLinear2D { private static final double speed = 1.0; private static final DenseMatrix64F x = new DenseMatrix64F(new double[][]{{0}, {0}, {0}, {0}}); private static final DenseMatrix64F P = new DenseMatrix64F( new double[][]{{5, 0, 0, 0}, {0, 5, 0, 0}, {0, 0, 5, 0}, {0, 0, 0, 5}}); private static final DenseMatrix64F F = new DenseMatrix64F( new double[][]{{1, 0, speed, 0}, {0, 1, 0, speed}, {0, 0, 1, 0}, {0, 0, 0, 1}}); private static final DenseMatrix64F R = new DenseMatrix64F(new double[][]{{5, 0}, {0, 5}}); private static final DenseMatrix64F H = new DenseMatrix64F(new double[][]{{1, 0, 0, 0}, {0, 1, 0, 0}}); private final KalmanFilter kalmanFilter; private float lastZ = 0; @Inject public KalmanFilterLinear2D(KalmanFilter kalmanFilter) { this.kalmanFilter = kalmanFilter; kalmanFilter.configure(F, H); kalmanFilter.setState(x, P); } public void resetFilter(Coordinate coordinate) { DenseMatrix64F x = new DenseMatrix64F(new double[][]{{coordinate.getX()}, {coordinate.getY()}, {0}, {0}}); kalmanFilter.setState(x, P); } public Coordinate updateAndGetCoordinate(Coordinate coordinate) { if (coordinate == null) { return getCoordinateFromCurrentState(); } DenseMatrix64F z = new DenseMatrix64F(new double[][]{{coordinate.x}, {coordinate.y}}); kalmanFilter.predict(); kalmanFilter.update(z, R); lastZ = coordinate.getZ(); return getCoordinateFromCurrentState(); } private Coordinate getCoordinateFromCurrentState() { DenseMatrix64F newState = kalmanFilter.getState(); return new Coordinate((float) newState.get(0, 0), (float) newState.get(1, 0), lastZ); } }