Skip to content
This repository was archived by the owner on Aug 26, 2024. It is now read-only.

Commit 1802cdb

Browse files
Implements interface changes for #48
1 parent 2baade1 commit 1802cdb

7 files changed

+38
-22
lines changed

chisquare.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
// of both the NEES and NIS tests.
1414
// Returns NEESmeans, NISmeans and an error if applicable
1515
// TODO: Change order of parameters.
16-
func NewChiSquare(kf KalmanFilter, runs MonteCarloRuns, controls []*mat64.Vector, withNEES, withNIS bool) ([]float64, []float64, error) {
16+
func NewChiSquare(kf LDKF, runs MonteCarloRuns, controls []*mat64.Vector, withNEES, withNIS bool) ([]float64, []float64, error) {
1717
if !withNEES && !withNIS {
1818
return nil, nil, errors.New("Chi Square requires either NEES or NIS or both")
1919
}

hybrid.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,18 @@ func (kf *HybridKF) PreparePNT(Γ *mat64.Dense) {
9090

9191
// Update computes a full time and measurement update.
9292
// Will return an error if the KF is locked (call Prepare to unlock).
93-
func (kf *HybridKF) Update(realObservation, computedObservation *mat64.Vector) (est *HybridKFEstimate, err error) {
93+
func (kf *HybridKF) Update(realObservation, computedObservation *mat64.Vector) (est Estimate, err error) {
9494
return kf.fullUpdate(false, realObservation, computedObservation)
9595
}
9696

9797
// Predict computes only the time update (or prediction).
9898
// Will return an error if the KF is locked (call Prepare to unlock).
99-
func (kf *HybridKF) Predict() (est *HybridKFEstimate, err error) {
99+
func (kf *HybridKF) Predict() (est Estimate, err error) {
100100
return kf.fullUpdate(true, nil, nil)
101101
}
102102

103103
// fullUpdate performs all the steps of an update and allows to stop right after the pure prediction (or time update) step.
104-
func (kf *HybridKF) fullUpdate(purePrediction bool, realObservation, computedObservation *mat64.Vector) (est *HybridKFEstimate, err error) {
104+
func (kf *HybridKF) fullUpdate(purePrediction bool, realObservation, computedObservation *mat64.Vector) (est Estimate, err error) {
105105
if kf.locked {
106106
return nil, errors.New("kf is locked (call Prepare() first)")
107107
}
@@ -135,7 +135,7 @@ func (kf *HybridKF) fullUpdate(purePrediction bool, realObservation, computedObs
135135
return nil, symerr
136136
}
137137
est = &HybridKFEstimate{kf.Φ, kf.Γ, &xBar, mat64.NewVector(kf.measSize, nil), mat64.NewVector(kf.measSize, nil), mat64.NewVector(kf.measSize, nil), PBarSym, PBarSym, mat64.NewDense(1, 1, nil)}
138-
kf.prevEst = *est
138+
kf.prevEst = est.(HybridKFEstimate)
139139
kf.step++
140140
kf.sncEnabled = false
141141
kf.locked = true
@@ -196,7 +196,7 @@ func (kf *HybridKF) fullUpdate(purePrediction bool, realObservation, computedObs
196196
Γ = mat64.DenseCopyOf(kf.Γ)
197197
}
198198
est = &HybridKFEstimate{&Φ, Γ, &xHat, realObservation, &innov, &y, PSym, PBarSym, &K}
199-
kf.prevEst = *est
199+
kf.prevEst = est.(HybridKFEstimate)
200200
kf.step++
201201
kf.sncEnabled = false
202202
kf.locked = true

hybrid_test.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,11 @@ func hybridFullODExample(ekfTrigger int, ekfDisableTime, sncDisableTime float64,
223223
}
224224
// There is no truth measurement here, let's only predict the KF covariance.
225225
kf.Prepare(state.Φ, nil)
226-
est, perr := kf.Predict()
226+
estI, perr := kf.Predict()
227227
if perr != nil {
228228
t.Fatalf("[ERR!] (#%04d)\n%s", measNo, perr)
229229
}
230+
est := estI.(*HybridKFEstimate)
230231
if smoothing {
231232
// Save to history in order to perform smoothing.
232233
estHistory[stateNo-1] = est
@@ -307,11 +308,11 @@ func hybridFullODExample(ekfTrigger int, ekfDisableTime, sncDisableTime float64,
307308
kf.PreparePNT(Γ)
308309
}
309310
}
310-
est, err := kf.Update(measurement.StateVector(), computedObservation.StateVector())
311+
estI, err := kf.Update(measurement.StateVector(), computedObservation.StateVector())
311312
if err != nil {
312313
t.Fatalf("[ERR!] %s", err)
313314
}
314-
315+
est := estI.(*HybridKFEstimate)
315316
if !est.IsWithin2σ() {
316317
t.Logf("[Not within 2-sigma] %s", est)
317318
}

kalman.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package gokalman
22

33
import "github.com/gonum/matrix/mat64"
44

5-
// KalmanFilter defines a general KF.
6-
type KalmanFilter interface {
5+
// LDKF defines a linear dynamics Kalman Filter.
6+
type LDKF interface {
77
Update(measurement, control *mat64.Vector) (Estimate, error)
88
GetNoise() Noise
99
GetStateTransition() mat64.Matrix
@@ -17,6 +17,14 @@ type KalmanFilter interface {
1717
String() string
1818
}
1919

20+
// NLDKF defines a non-linear dynamics Kalman Filter.
21+
// Operates and is architectured slightly differently than LDKF.
22+
type NLDKF interface {
23+
Prepare(Φ, Htilde *mat64.Dense)
24+
Predict() (est Estimate, err error)
25+
Update(realObservation, computedObservation *mat64.Vector) (est Estimate, err error)
26+
}
27+
2028
// Estimate is returned from Update() in any KF.
2129
// This allows to avoid some computations in other filters, e.g. in the Information filter.
2230
type Estimate interface {

kalman_test.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,24 @@ package gokalman
22

33
import "testing"
44

5-
func TestImplementsKF(t *testing.T) {
6-
implements := func(KalmanFilter) {}
5+
func TestImplementsLDKF(t *testing.T) {
6+
implements := func(LDKF) {}
77
implements(new(Vanilla))
88
implements(new(Information))
99
implements(new(SquareRoot))
1010
}
1111

12+
func TestImplementsNLDKF(t *testing.T) {
13+
implements := func(NLDKF) {}
14+
implements(new(SRIF))
15+
implements(new(HybridKF))
16+
}
17+
1218
func TestImplementsEst(t *testing.T) {
1319
implements := func(Estimate) {}
1420
implements(VanillaEstimate{})
1521
implements(InformationEstimate{})
1622
implements(SquareRootEstimate{})
1723
implements(HybridKFEstimate{})
24+
implements(SRIFEstimate{})
1825
}

srif.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,18 @@ func (kf *SRIF) Prepare(Φ, Htilde *mat64.Dense) {
6868

6969
// Update computes a full time and measurement update.
7070
// Will return an error if the KF is locked (call Prepare to unlock).
71-
func (kf *SRIF) Update(realObservation, computedObservation *mat64.Vector) (est *SRIFEstimate, err error) {
71+
func (kf *SRIF) Update(realObservation, computedObservation *mat64.Vector) (est Estimate, err error) {
7272
return kf.fullUpdate(false, realObservation, computedObservation)
7373
}
7474

7575
// Predict computes only the time update (or prediction).
7676
// Will return an error if the KF is locked (call Prepare to unlock).
77-
func (kf *SRIF) Predict() (est *SRIFEstimate, err error) {
77+
func (kf *SRIF) Predict() (est Estimate, err error) {
7878
return kf.fullUpdate(true, nil, nil)
7979
}
8080

8181
// fullUpdate performs all the steps of an update and allows to stop right after the pure prediction (or time update) step.
82-
func (kf *SRIF) fullUpdate(purePrediction bool, realObservation, computedObservation *mat64.Vector) (est *SRIFEstimate, err error) {
82+
func (kf *SRIF) fullUpdate(purePrediction bool, realObservation, computedObservation *mat64.Vector) (est Estimate, err error) {
8383
if kf.locked {
8484
return nil, errors.New("kf is locked (call Prepare() first)")
8585
}
@@ -115,7 +115,7 @@ func (kf *SRIF) fullUpdate(purePrediction bool, realObservation, computedObserva
115115
if purePrediction {
116116
tmpEst := NewSRIFEstimate(kf.Φ, &bBar, mat64.NewVector(kf.measSize, nil), mat64.NewVector(kf.measSize, nil), &RBar, &RBar)
117117
est = &tmpEst
118-
kf.prevEst = *est
118+
kf.prevEst = est.(SRIFEstimate)
119119
kf.step++
120120
kf.locked = true
121121
return
@@ -134,7 +134,7 @@ func (kf *SRIF) fullUpdate(purePrediction bool, realObservation, computedObserva
134134
}
135135
tmpEst := NewSRIFEstimate(kf.Φ, bk, realObservation, &y, Rk, &RBar)
136136
est = &tmpEst
137-
kf.prevEst = *est
137+
kf.prevEst = est.(SRIFEstimate)
138138
kf.step++
139139
kf.locked = true
140140
return
@@ -207,7 +207,7 @@ func (e SRIFEstimate) State() *mat64.Vector {
207207
e.cachedState = mat64.NewVector(rState, nil)
208208
var rInv mat64.Dense
209209
if err := rInv.Inverse(e.R); err != nil {
210-
panic("cannot invert R!")
210+
panic(fmt.Errorf("cannot invert R: %s", err))
211211
}
212212
e.cachedState.MulVec(&rInv, e.sqinfoState)
213213
}

srif_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ func _SRIFFullODExample(smoothing bool, t *testing.T) {
210210
}
211211
if smoothing {
212212
// Save to history in order to perform smoothing.
213-
estHistory[stateNo-1] = est
213+
estHistory[stateNo-1] = est.(*SRIFEstimate)
214214
stateHistory[stateNo-1] = nil
215215
} else {
216216
// Stream to CSV file
@@ -237,11 +237,11 @@ func _SRIFFullODExample(smoothing bool, t *testing.T) {
237237

238238
Htilde := computedObservation.HTilde()
239239
kf.Prepare(state.Φ, Htilde)
240-
est, err := kf.Update(measurement.StateVector(), computedObservation.StateVector())
240+
estI, err := kf.Update(measurement.StateVector(), computedObservation.StateVector())
241241
if err != nil {
242242
t.Fatalf("[ERR!] %s", err)
243243
}
244-
244+
est := estI.(*SRIFEstimate)
245245
if !est.IsWithin2σ() {
246246
t.Fatalf("%s", est)
247247
}

0 commit comments

Comments
 (0)