Zunächst einmal versuche ich zum ersten Mal, einen Kalman-Filter zu erstellen.
Ich habe zuvor die folgende Frage gestellt: Herausfiltern von Geräuschen und Abweichungen von Geschwindigkeitswerten auf StackOverflow, die den Hintergrund für diesen Beitrag beschreibt. Dies ist eine typische Stichprobe von Werten, die ich filtern möchte. Sie müssen nicht unbedingt abnehmen, was hier der Fall ist. Die Änderungsrate ist jedoch normalerweise so
X ------- Y
16 --- 233,75
24 --- 234,01
26 --- 234,33
32 --- 234,12
36 --- 233,85
39 --- 233,42
47 --- 233,69
52 --- 233,68
55 --- 233,76
60 --- 232,97
66 --- 233,31
72 --- 233,99
Ich habe meinen Kalman-Filter gemäß diesem Tutorial implementiert: Kalman-Filter für Dummies .
Meine Implementierung sieht so aus (Pseudocode).
//Standard deviation is 0.05. Used in calculation of Kalman gain
void updateAngle(double lastAngle){
if(firsTimeRunning==true)
priorEstimate = 0; //estimate is the old one here
priorErrorVariance = 1.2; //errorCovariance is the old one
else
priorEstimate = estimate; //estimate is the old one here
priorErrorVariance = errorCovariance; //errorCovariance is the old one
rawValue = lastAngle; //lastAngle is the newest Y-value recieved
kalmanGain = priorErrorVariance / (priorErrVariance + 0.05);
estimate = priorEstimate + (kalmanGain * (rawValue - priorEstimate));
errorCovariance = (1 - kalmanGain) * priorErrVariance;
angle = estimate; //angle is the variable I want to update
} //which will be lastAngle next time
Ich beginne mit einer vorherigen Schätzung von 0. Dies scheint gut zu funktionieren. Was ich jedoch bemerke, ist, dass der kalmanGain jedes Mal abnimmt, wenn dieses Update ausgeführt wird, was bedeutet, dass ich meinen neuen Werten weniger vertraue, je länger mein Filter ausgeführt wird (?). Das will ich nicht
Ich ging von einem gleitenden Durchschnitt (einfach und exponentiell gewichtet) zu diesem über. Im Moment kann ich nicht einmal so gute Ergebnisse erzielen.
Meine Frage ist, ob dies die richtige Implementierung ist und ob meine vorherige Fehlervarianz und Standardabweichung gemäß den von mir veröffentlichten Beispielwerten gut aussieht. Meine Parameter werden eigentlich nur zufällig ausgewählt, um zu sehen, ob ich gute Ergebnisse erzielen kann. Ich habe verschiedene Bereiche ausprobiert, aber mit schlechten Ergebnissen. Wenn Sie Vorschläge zu Änderungen haben, die ich vornehmen kann, wäre ich Ihnen sehr dankbar. Es tut mir leid, wenn einige offensichtliche Dinge fehlen. Auch hier zum ersten Mal posten.
Wenn ich es richtig verstanden habe, haben Sie etwas, das sich bewegt, und Sie können die Geschwindigkeit beobachten, und diese Geschwindigkeit ist laut. Bei Ihren Messungen beobachten Sie zwei Arten von Variationen. \
Der Grund, warum Ihre Kalman-Verstärkung auf Null geht, ist, dass Sie implizit angenommen haben, dass die Geschwindigkeit des Objekts konstant ist, und dass Sie nur diese wahre Geschwindigkeit schätzen müssen.
" Hey, ich habe ein Objekt, das sich mit konstanter Geschwindigkeit bewegt, und ich möchte diese konstante Geschwindigkeit schätzen. "
Ihr Modell ist wie folgt: ist die Geschwindigkeit zum Zeitpunkt und ist die entsprechende Messung.xk k yk
Aber Ihr Objekt bewegt sich nicht so. Die Geschwindigkeit ändert sich und Sie wissen nicht, wie und wann sie sich ändern wird.
Was Sie stattdessen zu sagen haben, ist:
" Hey, ich habe ein Objekt, das sich mit einer Geschwindigkeit bewegt, aber ich bin mir nicht sicher, wie es seine Geschwindigkeit ändert. "
Es gibt viele Möglichkeiten, wie Sie dies tun können: Die einfachste Möglichkeit besteht darin, Ihrem Zustand Unsicherheit zu verleihen.
Ihre Kalman-Filtergleichungen sehen folgendermaßen aus:
In Ihrem Fall ist derQo Qs
0.05
Wert die Kovarianz des Beobachtungsrauschens . Um diese Änderung vorzunehmen, müssen Sie lediglich , die Zustandsrausch-Covarinace (die Ungewissheit in Ihrem Zustand), auf einen konstanten Wert setzen.Q sIn Ihrem Code wäre die geringfügige Änderung:
stateVariance = 0.5
errorCovariance = (1 - kalmanGain) * priorErrVariance + stateVariance;
Indem Sie dieQs
stateVariance
oder in Ihren Code einfügen, haben Sie angenommen, dass es Null ist.Dieser
stateVariance
Wert kann beliebig sein. Es basiert auf Ihrem Vertrauen, wie stark sich die Geschwindigkeit tatsächlich ändern wird. Wenn Sie glauben, dass die Geschwindigkeit ziemlich konstant bleibt, stellen Sie diese auf eine kleine Zahl ein.Auf diese Weise geht Ihr Kalman-Gewinn nicht auf Null.
quelle
Sie benötigen ein dynamisches System, um einen Kalman-Filter verwenden zu können.
ich würde vorschlagen
c o v ( w ) = Q z = n ∑ i = 0 a i
Anstatt als Zustände zu verwenden, führen Sie den Koeffizienten ( ) als Zustände einax a
quelle
Ich denke, Sie könnten einige Ideen aus der klassischen Regelungstheorie verwenden, z . B. PID-Regler .
Ihr Signal Y kann der Sollwert des Reglers u (t) sein. Die verfahrenstechnische Anlage ist nur 1 und y (t) wird gefiltert ausgegeben. Alles was Sie tun müssen, ist die Parameter (Melodie) P, I und D einzustellen, um das zu bekommen, was Sie wollen.
Der Ausgang y (t) versucht, dem Eingang u (t) zu "folgen", aber die Parameter steuern, wie diese Verfolgung sein wird.
Die Differenzverstärkung D macht Ihre Reaktion empfindlich gegenüber schnellen Fehleränderungen. In Ihrem Fall denke ich, dass D klein sein sollte. Sie möchten nicht, dass sich y (t) ändert, wenn sich u (t) abrupt ändert.
Die integrale Verstärkung 'I' macht Ihre Antwort empfindlich gegenüber akkumulierten Fehlern. Sie sollten dort einen hohen Wert legen. Wenn u (t) den Pegel ändert und dort bleibt, baut sich der Fehler auf und Sie möchten, dass y (t) dasselbe tut.
Die P-Verstärkung kann eine Feinabstimmung ergeben. Versuchen Sie auf jeden Fall, mit den Parametern zu spielen und zu sehen, was Sie bekommen.
Es gibt zwar komplizierte Abstimmungsmethoden, aber ich glaube nicht, dass Sie sie brauchen werden.
Viel Glück.
quelle
Hier ist eine einfache und übersichtliche Implementierung von Kalman Filter, die den Notationen wie auf der Wikipedia-Seite folgt. https://github.com/zziz/kalman-filter
quelle