Skip to content

Commit 2b5ed95

Browse files
authored
Issue 363 - Kalman smoother (#364)
* Linear and extended Kalman smoothers. * Unscented Kalman smoother. * Smoother as Kalman observer. * Check for processing at least one measurement.
1 parent 69427a6 commit 2b5ed95

File tree

11 files changed

+851
-32
lines changed

11 files changed

+851
-32
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) 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 ASF 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+
18+
/*
19+
* This is not the original file distributed by the Apache Software Foundation
20+
* It has been modified by the Hipparchus project
21+
*/
22+
package org.hipparchus.filtering;
23+
24+
import org.hipparchus.exception.Localizable;
25+
26+
import java.util.Locale;
27+
28+
/**
29+
* Enumeration for localized messages formats used in exceptions messages.
30+
* <p>
31+
* The constants in this enumeration represent the available
32+
* formats as localized strings. These formats are intended to be
33+
* localized using simple properties files, using the constant
34+
* name as the key and the property value as the message format.
35+
* The source English format is provided in the constants themselves
36+
* to serve both as a reminder for developers to understand the parameters
37+
* needed by each format, as a basis for translators to create
38+
* localized properties files, and as a default format if some
39+
* translation is missing.
40+
* </p>
41+
*/
42+
public enum LocalizedFilterFormats implements Localizable {
43+
44+
/** PROCESS_AT_LEAST_ONE_MEASUREMENT. */
45+
PROCESS_AT_LEAST_ONE_MEASUREMENT("at least one measurement must be processed before smoothing");
46+
47+
/** Source English format. */
48+
private final String sourceFormat;
49+
50+
/** Simple constructor.
51+
* @param sourceFormat source English format to use when no
52+
* localized version is available
53+
*/
54+
LocalizedFilterFormats(final String sourceFormat) {
55+
this.sourceFormat = sourceFormat;
56+
}
57+
58+
/** {@inheritDoc} */
59+
@Override
60+
public String getSourceString() {
61+
return sourceFormat;
62+
}
63+
64+
/** {@inheritDoc} */
65+
@Override
66+
public String getLocalizedString(final Locale locale) {
67+
return getLocalizedString("assets/" + LocalizedFilterFormats.class.getName().replaceAll("\\.", "/"),
68+
name(), locale);
69+
}
70+
71+
}

hipparchus-filtering/src/main/java/org/hipparchus/filtering/kalman/AbstractKalmanFilter.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,26 @@ public abstract class AbstractKalmanFilter<T extends Measurement> implements Kal
3838
/** Corrected state. */
3939
private ProcessEstimate corrected;
4040

41+
/** Prior corrected covariance. */
42+
private RealMatrix priorCovariance;
43+
44+
/** State transition matrix. */
45+
private RealMatrix stateTransitionMatrix;
46+
47+
/** Observer. */
48+
private KalmanObserver observer;
49+
50+
4151
/** Simple constructor.
4252
* @param decomposer decomposer to use for the correction phase
4353
* @param initialState initial state
4454
*/
4555
protected AbstractKalmanFilter(final MatrixDecomposer decomposer, final ProcessEstimate initialState) {
4656
this.decomposer = decomposer;
4757
this.corrected = initialState;
58+
this.priorCovariance = null;
59+
this.stateTransitionMatrix = null;
60+
this.observer = null;
4861
}
4962

5063
/** Perform prediction step.
@@ -57,6 +70,8 @@ protected void predict(final double time, final RealVector predictedState, final
5770
final RealMatrix predictedCovariance =
5871
stm.multiply(corrected.getCovariance().multiplyTransposed(stm)).add(noise);
5972
predicted = new ProcessEstimate(time, predictedState, predictedCovariance);
73+
stateTransitionMatrix = stm;
74+
priorCovariance = corrected.getCovariance();
6075
corrected = null;
6176
}
6277

@@ -133,6 +148,21 @@ protected void correct(final T measurement, final RealMatrix stm, final RealVect
133148

134149
}
135150

151+
/** Get the observer.
152+
* @return the observer
153+
*/
154+
protected KalmanObserver getObserver() {
155+
return observer;
156+
}
157+
158+
159+
/** {@inheritDoc} */
160+
@Override
161+
public void setObserver(final KalmanObserver kalmanObserver) {
162+
observer = kalmanObserver;
163+
observer.init(this);
164+
}
165+
136166
/** Get the predicted state.
137167
* @return predicted state
138168
*/
@@ -149,4 +179,9 @@ public ProcessEstimate getCorrected() {
149179
return corrected;
150180
}
151181

182+
/** {@inheritDoc} */
183+
@Override
184+
public RealMatrix getStateCrossCovariance() {
185+
return priorCovariance.multiplyTransposed(stateTransitionMatrix);
186+
}
152187
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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.filtering.kalman;
18+
19+
import org.hipparchus.linear.RealMatrix;
20+
21+
public interface KalmanEstimate {
22+
23+
/** Get the current predicted state.
24+
* @return current predicted state
25+
*/
26+
ProcessEstimate getPredicted();
27+
28+
/** Get the current corrected state.
29+
* @return current corrected state
30+
*/
31+
ProcessEstimate getCorrected();
32+
33+
/** Get the cross-covariance between the previous state and the prediction.
34+
* Not required for forward filtering, but required for the smoother.
35+
* @return cross-covariance
36+
*/
37+
RealMatrix getStateCrossCovariance();
38+
39+
}

hipparchus-filtering/src/main/java/org/hipparchus/filtering/kalman/KalmanFilter.java

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
* @param <T> the type of the measurements
2525
* @since 1.3
2626
*/
27-
public interface KalmanFilter<T extends Measurement> {
27+
public interface KalmanFilter<T extends Measurement> extends KalmanEstimate {
2828

2929
/** Perform one estimation step.
3030
* @param measurement single measurement to handle
@@ -34,14 +34,8 @@ public interface KalmanFilter<T extends Measurement> {
3434
ProcessEstimate estimationStep(T measurement)
3535
throws MathRuntimeException;
3636

37-
/** Get the current predicted state.
38-
* @return current predicted state
37+
/** Set the filter observer callback.
38+
* @param observer the observer
3939
*/
40-
ProcessEstimate getPredicted();
41-
42-
/** Get the current corrected state.
43-
* @return current corrected state
44-
*/
45-
ProcessEstimate getCorrected();
46-
40+
void setObserver(KalmanObserver observer);
4741
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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.filtering.kalman;
18+
19+
/** Observer for Kalman filter recursions.
20+
* <p>
21+
* This interface is intended to be implemented by users to monitor
22+
* the progress of the Kalman filter estimator during estimation.
23+
* </p>
24+
*/
25+
public interface KalmanObserver {
26+
27+
/** Callback for initialisation of observer.
28+
* @param estimate estimate calculated by a Kalman filter
29+
*/
30+
default void init(KalmanEstimate estimate) {}
31+
32+
/** Notification callback after each Kalman filter measurement update.
33+
* @param estimate estimate calculated by a Kalman filter
34+
*/
35+
void updatePerformed(KalmanEstimate estimate);
36+
}

0 commit comments

Comments
 (0)