Hier gibt es ein sehr schönes Beispiel für die Implementierung eines sehr einfachen Kalman-Filters: https://www.youtube.com/watch?v=X9cC0o9viTo&index=4&list=PLX2gX-ftPVXU3oUFNATxGXY90AULiqnWT Für den Schätzfehler "Eest" gibt es die Formel 3: Eest=(1-KG)*EestOld Irgendwie scheint mir die Formel aber falsch zu sein. Wenn der alte Schätzfehler gleich Null ist, ist der neue Schätzfehler auch immer Null. Das kann aber wohl kaum sein, denn eine neue Schätzung kann ja fehlerbehaftet sein. Wo liegt das Problem?
Markus schrieb: > Für den Schätzfehler "Eest" gibt es die Formel 3: > Eest=(1-KG)*EestOld > > Irgendwie scheint mir die Formel aber falsch zu sein. Wenn der alte > Schätzfehler gleich Null ist, ist der neue Schätzfehler auch immer Null. > Das kann aber wohl kaum sein, denn eine neue Schätzung kann ja > fehlerbehaftet sein. Wo liegt das Problem? Dann wird der initiale Schätzfehler zum Zeitpunkt t=0 eben nicht bei 0 liegen, gehe ich mal stark von aus. Und der Gain liegt auch nicht bei 100%, also wird der ganze Term niemals 0.
:
Bearbeitet durch User
In seinem Beispiel sind die Fehler Eest & Emea die Kovarianz-Matrizen und nicht etwa Fehler im Sinne "Messung - Schätzung". Üblicherweise wird der Schätzfehler für Eest tatsächlich eher "hoch" initialisiert. Der Filter läuft sich dann ein. Ist er eingelaufen kann man bei LTI Systemen KG übernehmen und muss es nicht mehr berechnen. Das KG ist im Grunde die Fehlerrückführmatrix beim Luenberger-Beobachter, aber nach einem anderen Prinzip berechnet (uU ein optimales Prinzip) . Eest besteht eigentlich aus Eest = Eest_alt + Q Emea ist die Angabe des Messrauschens "R". (Q,R : Konvention gemäß seinem Video 7) Im Falle des skalaren Beispiels vom Video: Der Schätzfehler wäre 0, wenn kein Rauschen (perfekte Messung) und kein Systemrauschen (exaktes Modell, kein Eingang). Dann ergibt sich für KG = 0 und auch der Term [MEA-EST_t-1] wäre immer 0. Wir hätten einen konstanten Wert (für das eingangslose 1D Modell). Nächste Annahme: Sagen wir perfekte Messung, aber ein Eingang, den wir als Noise ansehen. Wir setzen den Schätzfehler auf einen hohen Wert und er läuft sich ein und hat dann eine bestimmte Gewichtung auf die Schätzung: und zwar genau KG=1, dh vertrau der Messung zu 100%. Oder umgekehrt: perfektes Modell, kein Eingang oder aber perfekt bekannter Eingang... kurzum wir wissen alles. Messung ist schlecht => "unendliches" R : dann folgt für KG=(Eest+Q)/(Eest+Q+R)=0 Macht Sinn, da wir der Messung nicht vertrauen. Wir schätzen unser Modell ja besser. LG
Erst mal Danke für eure Antworten. Mark Brandis (markbrandis) >Dann wird der initiale Schätzfehler zum Zeitpunkt t=0 eben nicht bei 0 >liegen, gehe ich mal stark von aus. Das habe ich mir auch gedacht. Wenn man den Schätzfehler am Anfang schon auf 0 setzt, verwandelt sich das ganze sowieso in einen einfachen Tiefpass. Das habe ich in einer Simulation ausprobiert und der Filter war dann erstaunlich langsam. Matthias M (Gast) >In seinem Beispiel sind die Fehler Eest & Emea die Kovarianz-Matrizen >und nicht etwa Fehler im Sinne "Messung - Schätzung". Uihh ... Deine Kommentar ist ganz schön aufwendig, den muss ich erst mal "verdauen". Ich werde noch mal versuchen eine Simulation zu machen.
Die Simulation zeigt eine schlechte Reaktion des Filters auf die Sprungantwort. Ich hätte erwartet, dass "ErrorEstimated" beim Sprung auch größer wird und sich dann der Filter schnell anpassen kann. Statt dessen bleibt aber "ErrorEstimated" immer klein und hat sich nur am Anfang angepasst.
1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
2 | % create a step signal for test |
3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
4 | signalLength = 1000; |
5 | stepHeigth = 1; |
6 | noiseStandadDeviation = 0.1; |
7 | |
8 | n1=signalLength/2; |
9 | n2=signalLength-n1; |
10 | signal=zeros(1,n1); |
11 | signal=[signal ones(1,n2)*stepHeigth]; |
12 | signal=signal+randn(1,signalLength)*noiseStandadDeviation; % add some noise |
13 | |
14 | subplot(2,1,1); |
15 | plot(signal,'g'); |
16 | |
17 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
18 | % kalman filter |
19 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
20 | |
21 | measureError = 0.1; |
22 | % initial values: |
23 | ErrorEstimated = 1; |
24 | ErrorEstimatedOld = ErrorEstimated; |
25 | yOld = 0; |
26 | |
27 | l=length(signal); |
28 | |
29 | for n=1:l, |
30 | |
31 | KalmanGain = ErrorEstimated / ( ErrorEstimated + measureError ); |
32 | y(n) = yOld + KalmanGain * ( signal(n)- yOld ); |
33 | ErrorEstimated = (1-KalmanGain) * ErrorEstimatedOld; |
34 | |
35 | ErrorEstimatedOld = ErrorEstimated; |
36 | yOld = y(n); |
37 | |
38 | ErrorEstimatedStore(n)=ErrorEstimated; |
39 | |
40 | end
|
41 | |
42 | hold on |
43 | plot(y); |
44 | |
45 | title("green: signal blue: filter result"); |
46 | grid on |
47 | |
48 | subplot(2,1,2); |
49 | plot(ErrorEstimatedStore); |
50 | title("ErrorEstimated"); |
51 | grid on |
Hab gerade kein Matlab oä zur Hand zum Testen. Folgende Punkte: Für die Messung verwendest du Sigma = 0.1 Varianz = sigma^2 => measureError = 0.1 * 0.1 Bedenke: Ich schrieb: > Im Falle des skalaren Beispiels vom Video: > Der Schätzfehler wäre 0, wenn kein Rauschen (perfekte Messung) und kein > Systemrauschen (exaktes Modell, kein Eingang). Dann ergibt sich für KG = > 0 und auch der Term [MEA-EST_t-1] wäre immer 0. Wir hätten einen > konstanten Wert (für das eingangslose 1D Modell). Es ist so langsam, da dein "Modell" im Grunde keine Änderung erwartet. Wenn du die Q-Matrix hinzufügst, müsste die Anpassung schneller gehen: ErrorEstimatedOld = ErrorEstimated + Q; Probiere mal ein paar Werte für Q (zB.: 0.2) durch. ErrorEstimated kannst du am Anfang auch ruhig größer setzen. LG
>Hab gerade kein Matlab oä zur Hand zum Testen.
Trotzdem Danke für die Hinweise. Bei mir ist immer Standardmäßig das
freie Octave installiert.
Ich habe es jetzt mal geändert.
Tatsächlich wird bei der Einführung von "Q" das Ganze zu einem
Tiefpassfilter. Bei Q=0.2 ergibt sich fast keine Filterwirkung, deshalb
musste ich es verkleinern.
Man sieht aber wieder, dass sich "ErrorEstimated" und "KalmanGain" nur
am Anfang ändern, danach bleiben sie stabil und es ist tatsächlich ein
einfaches Tiefpassfilter. Das Verhalten ist eigentlich kein Wunder, wenn
man den Code analysiert: Das Signal beeinflußt "ErrorEstimated"
überhaupt nicht.
Eigentlich will ich mit dem Filter ein sich eindimensional bewegendes
Objekt verfolgen. Vielleicht sollte ich die Bewegungsgleichung s=s0+v*t
ins Modell einbauen?
1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
2 | % create a step signal for test |
3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
4 | signalLength = 1000; |
5 | stepHeigth = 1; |
6 | noiseStandadDeviation = 0.1; |
7 | |
8 | n1=signalLength/2; |
9 | n2=signalLength-n1; |
10 | signal=zeros(1,n1); |
11 | signal=[signal ones(1,n2)*stepHeigth]; |
12 | signal=signal+randn(1,signalLength)*noiseStandadDeviation; % add some noise |
13 | |
14 | subplot(3,1,1); |
15 | plot(signal,'g'); |
16 | |
17 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
18 | % kalman filter |
19 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
20 | |
21 | measureError = 0.01; |
22 | Q = 0.00005; |
23 | |
24 | % initial values: |
25 | ErrorEstimated = 1; |
26 | ErrorEstimatedOld = ErrorEstimated; |
27 | yOld = 0; |
28 | |
29 | l=length(signal); |
30 | |
31 | for n=1:l, |
32 | |
33 | KalmanGain = ErrorEstimated / ( ErrorEstimated + measureError ); |
34 | y(n) = yOld + KalmanGain * ( signal(n)- yOld ); |
35 | ErrorEstimated = (1-KalmanGain) * ErrorEstimatedOld; |
36 | |
37 | ErrorEstimatedOld = ErrorEstimated + Q; |
38 | yOld = y(n); |
39 | |
40 | ErrorEstimatedStore(n) = ErrorEstimated; |
41 | KalmanGainStore(n) = KalmanGain; |
42 | end
|
43 | |
44 | hold on |
45 | plot(y); |
46 | |
47 | title("green: signal blue: filter result"); |
48 | grid on |
49 | |
50 | subplot(3,1,2); |
51 | plot(ErrorEstimatedStore,'r'); |
52 | grid on |
53 | title("ErrorEstimated"); |
54 | |
55 | subplot(3,1,3); |
56 | plot(KalmanGainStore); |
57 | title("KalmanGain"); |
58 | grid on |
Markus schrieb: > Man sieht aber wieder, dass sich "ErrorEstimated" und "KalmanGain" nur > am Anfang ändern, danach bleiben sie stabil und es ist tatsächlich ein > einfaches Tiefpassfilter. Ja, ist normal wennn sich das System nicht ändert, dann bleibt KG konstant. Siehe: Matthias M schrieb: > Ist er eingelaufen kann man bei LTI Systemen > KG übernehmen und muss es nicht mehr berechnen. Das KG ist im Grunde die > Fehlerrückführmatrix beim Luenberger-Beobachter, aber nach einem anderen > Prinzip berechnet (uU ein optimales Prinzip) Schau mal da: Beitrag "Re: Sensorfusion mit Kalman" ...das diese Matthiase immer mit Kalman Filter spielen...
Matthias M schrieb: > Ja, ist normal wennn sich das System nicht ändert, dann bleibt KG > konstant. Ja, so funktioniert das beschriebene "einfache Kalman Filter". Dient nur dem "entrauschen". Da gibt es noch x weitere Videos für komplexere Anwendungen ... Nicht nur Matthiase beschäftigen sich damit :-)
Markus schrieb: > Man sieht aber wieder, dass sich "ErrorEstimated" und "KalmanGain" nur > am Anfang ändern, danach bleiben sie stabil und es ist tatsächlich ein > einfaches Tiefpassfilter. Kalman Gain konvergiert schnell, wenn man die Kovarianzmatrix t->∞ berechnet. Das Ausgangsverhalten möge mit einem einfachen Tiefpassfilter ähneln, aber es ist völlig anderes Konstrukt, > Eigentlich will ich mit dem Filter ein sich eindimensional bewegendes > Objekt verfolgen. Vielleicht sollte ich die Bewegungsgleichung s=s0+v*t > ins Modell einbauen? Ohne Modell wird nix mit dem Kalman Filter
Stm Mc (stmfresser) >Kalman Gain konvergiert schnell, wenn man die Kovarianzmatrix t->∞ >berechnet. Das Ausgangsverhalten möge mit einem einfachen Tiefpassfilter >ähneln, aber es ist völlig anderes Konstrukt, Wenn man die Code-Zeile aus meinen Beispielen oben nimmt, welches ich dem Lernvideo nachgebaut habe
1 | y(n) = yOld + KalmanGain * ( signal(n)- yOld ); |
ergibt sich bei KalmanGain=Konstant
1 | y(n) = yOld + k * ( signal(n)- yOld ); |
2 | = yOld + k*signal(n) - k* yOld; |
als Z-transformierte ( falls ich mich nicht verrechnet habe )
1 | Y = Y*z⁻¹ + k * X - k*Y*z⁻¹ |
2 | Y/X= 1/( 1 - (1-k)*z⁻¹) |
was einem 1-poligen LowPass entspricht. Bei deinem Beispiel wäre eine Sprung an der Stelle T=20 und ein anderer Sprung in der Frequenz interessant, um zu sehen, ob Dein Filter wirklich mehr ist als ein ein- oder zwei poliger IIR Filter.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.