Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
96129 views
1
# -*- coding: utf-8 -*-
2
"""Copyright 2015 Roger R Labbe Jr.
3
4
FilterPy library.
5
http://github.com/rlabbe/filterpy
6
7
Documentation at:
8
https://filterpy.readthedocs.org
9
10
Supporting book at:
11
https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python
12
13
This is licensed under an MIT license. See the readme.MD file
14
for more information.
15
"""
16
17
from __future__ import (absolute_import, division, print_function,
18
unicode_literals)
19
import numpy as np
20
from math import sqrt
21
22
23
class LeastSquaresFilter(object):
24
"""Implements a Least Squares recursive filter. Formulation is per
25
Zarchan [1]_.
26
27
Filter may be of order 0 to 2. Order 0 assumes the value being tracked is
28
a constant, order 1 assumes that it moves in a line, and order 2 assumes
29
that it is tracking a second order polynomial.
30
31
It is implemented to be directly callable like a function. See examples.
32
33
**Example**::
34
35
from filterpy.leastsq import LeastSquaresFilter
36
37
lsq = LeastSquaresFilter(dt=0.1, order=1, noise_sigma=2.3)
38
39
while True:
40
z = sensor_reading() # get a measurement
41
x = lsq(z) # get the filtered estimate.
42
print('error: {}, velocity error: {}'.format(lsq.error, lsq.derror))
43
44
45
**Member Variables**
46
47
n : int
48
step in the recursion. 0 prior to first call, 1 after the first call,
49
etc.
50
51
K1,K2,K3 : float
52
Gains for the filter. K1 for all orders, K2 for orders 0 and 1, and
53
K3 for order 2
54
55
x, dx, ddx: type(z)
56
estimate(s) of the output. 'd' denotes derivative, so 'dx' is the first
57
derivative of x, 'ddx' is the second derivative.
58
59
60
**References**
61
62
.. [1] Zarchan and Musoff. "Fundamentals of Kalman Filtering: A Practical
63
Approach." Third Edition. AIAA, 2009.
64
65
|
66
|
67
68
**Methods**
69
"""
70
71
72
def __init__(self, dt, order, noise_sigma=0.):
73
""" Least Squares filter of order 0 to 2.
74
75
**Parameters**
76
77
dt : float
78
time step per update
79
80
order : int
81
order of filter 0..2
82
83
noise_sigma : float
84
sigma (std dev) in x. This allows us to calculate the error of
85
the filter, it does not influence the filter output.
86
"""
87
88
assert order >= 0
89
assert order <= 2
90
91
self.dt = dt
92
self.dt2 = dt**2
93
94
self.sigma = noise_sigma
95
self._order = order
96
97
self.reset()
98
99
100
def reset(self):
101
""" reset filter back to state at time of construction"""
102
103
self.n = 0 #nth step in the recursion
104
self.x = np.zeros(self._order+1)
105
self.K = np.zeros(self._order+1)
106
107
108
def update(self, z):
109
self.n += 1
110
n = self.n
111
dt = self.dt
112
dt2 = self.dt2
113
114
if self._order == 0:
115
self.K[0] = 1./n
116
residual = z - self.x
117
self.x += residual * self.K[0]
118
119
elif self._order == 1:
120
self.K[0] = 2*(2*n-1) / (n*(n+1))
121
self.K[1] = 6 / (n*(n+1)*dt)
122
123
self.x[0] += self.x[1]*dt
124
125
residual = z - self.x[0]
126
127
self.x[0] += self.K[0]*residual
128
self.x[1] += self.K[1]*residual
129
130
else:
131
den = n*(n+1)*(n+2)
132
self.K[0] = 3*(3*n**2 - 3*n + 2) / den
133
self.K[1] = 18*(2*n-1) / (den*dt)
134
self.K[2] = 60./ (den*dt2)
135
136
137
self.x[0] += self.x[1]*dt + .5*self.x[2]*dt2
138
self.x[1] += self.x[2]*dt
139
140
residual = z - self.x[0]
141
142
self.x[0] += self.K[0]*residual
143
self.x[1] += self.K[1]*residual
144
self.x[2] += self.K[2]*residual
145
146
return self.x
147
148
149
def errors(self):
150
""" Computes and returns the error and standard deviation of the
151
filter at this time step.
152
153
**Returns**
154
155
error : np.array size 1xorder+1
156
std : np.array size 1xorder+1
157
"""
158
159
n = self.n
160
dt = self.dt
161
order = self._order
162
sigma = self.sigma
163
164
error = np.zeros(order+1)
165
std = np.zeros(order+1)
166
167
168
if n == 0:
169
return (error, std)
170
171
if order == 0:
172
error[0] = sigma/sqrt(n)
173
std[0] = sigma/sqrt(self.n)
174
175
elif order == 1:
176
if n > 1:
177
error[0] = sigma*sqrt(2*(2*n-1)/(n*(n+1)))
178
error[1] = sigma*sqrt(12/(n*(n*n-1)*dt*dt))
179
std[0] = sigma*sqrt((2*(2*n-1)) / (n*(n+1)))
180
std[1] = (sigma/dt) *sqrt(12/(n*(n*n-1)))
181
182
elif order == 2:
183
dt2 = self.dt2
184
185
if n >= 3:
186
error[0] = sigma * sqrt(3*(3*n*n-3*n+2) / (n*(n+1)*(n+2)))
187
error[1] = sigma * sqrt(12*(16*n*n-30*n+11) /
188
(n*(n*n-1)*(n*n-4)*dt2))
189
error[2] = sigma * sqrt(720/(n*(n*n-1)*(n*n-4)*dt2*dt2))
190
191
std[0] = sigma*sqrt((3*(3*n*n - 3*n + 2)) / (n*(n+1)*(n+2)))
192
std[1] = (sigma/dt)*sqrt((12*(16*n*n - 30*n + 11)) /
193
(n*(n*n - 1)*(n*n -4)))
194
std[2] = (sigma/dt2) * sqrt(720 / (n*(n*n-1)*(n*n-4)))
195
196
return error, std
197
198
199
def __repr__(self):
200
return 'LeastSquareFilter x={}'.format(self.x)
201
202
203