CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download
Project: test
Views: 91872
1
# -*- coding: utf-8 -*-
2
"""
3
Created on Sat Jul 5 16:07:29 2014
4
5
@author: rlabbe
6
"""
7
8
import numpy as np
9
from KalmanFilter import KalmanFilter
10
from math import radians, sin, cos, sqrt, exp
11
import numpy.random as random
12
import matplotlib.markers as markers
13
import matplotlib.pyplot as plt
14
from RungeKutta import *
15
16
17
class BallPath(object):
18
def __init__(self, x0, y0, omega_deg, velocity, g=9.8, noise=[1.0,1.0]):
19
omega = radians(omega_deg)
20
self.vx0 = velocity * cos(omega)
21
self.vy0 = velocity * sin(omega)
22
23
self.x0 = x0
24
self.y0 = y0
25
26
self.g = g
27
self.noise = noise
28
29
def pos_at_t(self, t):
30
""" returns (x,y) tuple of ball position at time t"""
31
x = self.vx0*t + self.x0
32
y = -0.5*self.g*t**2 + self.vy0*t + self.y0
33
34
return (x +random.randn()*self.noise[0], y +random.randn()*self.noise[1])
35
36
37
def ball_kf(x, y, omega, v0, dt, r=0.5, q=0.02):
38
39
g = 9.8 # gravitational constant
40
f1 = KalmanFilter(dim_x=5, dim_z=2)
41
42
ay = .5*dt**2
43
f1.F = np.mat ([[1, dt, 0, 0, 0], # x = x0+dx*dt
44
[0, 1, 0, 0, 0], # dx = dx
45
[0, 0, 1, dt, ay], # y = y0 +dy*dt+1/2*g*dt^2
46
[0, 0, 0, 1, dt], # dy = dy0 + ddy*dt
47
[0, 0, 0, 0, 1]]) # ddy = -g.
48
49
f1.H = np.mat([
50
[1, 0, 0, 0, 0],
51
[0, 0, 1, 0, 0]])
52
53
f1.R *= r
54
f1.Q *= q
55
56
omega = radians(omega)
57
vx = cos(omega) * v0
58
vy = sin(omega) * v0
59
60
f1.x = np.mat([x,vx,y,vy,-9.8]).T
61
62
return f1
63
64
65
66
def ball_kf_noay(x, y, omega, v0, dt, r=0.5, q=0.02):
67
68
g = 9.8 # gravitational constant
69
f1 = KalmanFilter(dim_x=5, dim_z=2)
70
71
ay = .5*dt**2
72
f1.F = np.mat ([[1, dt, 0, 0, 0], # x = x0+dx*dt
73
[0, 1, 0, 0, 0], # dx = dx
74
[0, 0, 1, dt, 0], # y = y0 +dy*dt
75
[0, 0, 0, 1, dt], # dy = dy0 + ddy*dt
76
[0, 0, 0, 0, 1]]) # ddy = -g.
77
78
f1.H = np.mat([
79
[1, 0, 0, 0, 0],
80
[0, 0, 1, 0, 0]])
81
82
f1.R *= r
83
f1.Q *= q
84
85
omega = radians(omega)
86
vx = cos(omega) * v0
87
vy = sin(omega) * v0
88
89
f1.x = np.mat([x,vx,y,vy,-9.8]).T
90
91
return f1
92
93
94
def test_kf():
95
dt = 0.1
96
t = 0
97
f1 = ball_kf (0,1, 35, 50, 0.1)
98
f2 = ball_kf_noay (0,1, 35, 50, 0.1)
99
100
path = BallPath( 0, 1, 35, 50, noise=(0,0))
101
path_rk = BallRungeKutta(0, 1, 50, 35)
102
103
xs = []
104
ys = []
105
while f1.x[2,0]>= 0:
106
t += dt
107
f1.predict()
108
f2.predict()
109
#x,y = path.pos_at_t(t)
110
x,y = path_rk.step(dt)
111
xs.append(x)
112
ys.append(y)
113
114
plt.scatter (f1.x[0,0], f1.x[2,0], color='blue',alpha=0.6)
115
plt.scatter (f2.x[0,0], f2.x[2,0], color='red', alpha=0.6)
116
117
plt.plot(xs, ys, c='g')
118
119
120
class BaseballPath(object):
121
def __init__(self, x0, y0, launch_angle_deg, velocity_ms, noise=(1.0,1.0)):
122
""" Create baseball path object in 2D (y=height above ground)
123
124
x0,y0 initial position
125
launch_angle_deg angle ball is travelling respective to ground plane
126
velocity_ms speeed of ball in meters/second
127
noise amount of noise to add to each reported position in (x,y)
128
"""
129
130
omega = radians(launch_angle_deg)
131
self.v_x = velocity_ms * cos(omega)
132
self.v_y = velocity_ms * sin(omega)
133
134
self.x = x0
135
self.y = y0
136
137
self.noise = noise
138
139
140
def drag_force (self, velocity):
141
""" Returns the force on a baseball due to air drag at
142
the specified velocity. Units are SI
143
"""
144
B_m = 0.0039 + 0.0058 / (1. + exp((velocity-35.)/5.))
145
return B_m * velocity
146
147
148
def update(self, dt, vel_wind=0.):
149
""" compute the ball position based on the specified time step and
150
wind velocity. Returns (x,y) position tuple.
151
"""
152
153
# Euler equations for x and y
154
self.x += self.v_x*dt
155
self.y += self.v_y*dt
156
157
# force due to air drag
158
v_x_wind = self.v_x - vel_wind
159
160
v = sqrt (v_x_wind**2 + self.v_y**2)
161
F = self.drag_force(v)
162
163
# Euler's equations for velocity
164
self.v_x = self.v_x - F*v_x_wind*dt
165
self.v_y = self.v_y - 9.81*dt - F*self.v_y*dt
166
167
return (self.x + random.randn()*self.noise[0],
168
self.y + random.randn()*self.noise[1])
169
170
171
172
def test_baseball_path():
173
ball = BaseballPath (0, 1, 35, 50)
174
while ball.y > 0:
175
ball.update (0.1, 0.)
176
plt.scatter (ball.x, ball.y)
177
178
179
180
def test_ball_path():
181
182
y = 15
183
x = 0
184
omega = 0.
185
noise = [1,1]
186
v0 = 100.
187
ball = BallPath (x0=x, y0=y, omega_deg=omega, velocity=v0, noise=noise)
188
dt = 1
189
190
191
f1 = KalmanFilter(dim_x=6, dim_z=2)
192
dt = 1/30. # time step
193
194
ay = -.5*dt**2
195
196
f1.F = np.mat ([[1, dt, 0, 0, 0, 0], # x=x0+dx*dt
197
[0, 1, dt, 0, 0, 0], # dx = dx
198
[0, 0, 0, 0, 0, 0], # ddx = 0
199
[0, 0, 0, 1, dt, ay], # y = y0 +dy*dt+1/2*g*dt^2
200
[0, 0, 0, 0, 1, dt], # dy = dy0 + ddy*dt
201
[0, 0, 0, 0, 0, 1]]) # ddy = -g
202
203
204
f1.H = np.mat([
205
[1, 0, 0, 0, 0, 0],
206
[0, 0, 0, 1, 0, 0]])
207
208
f1.R = np.eye(2) * 5
209
f1.Q = np.eye(6) * 0.
210
211
omega = radians(omega)
212
vx = cos(omega) * v0
213
vy = sin(omega) * v0
214
215
f1.x = np.mat([x,vx,0,y,vy,-9.8]).T
216
217
f1.P = np.eye(6) * 500.
218
219
z = np.mat([[0,0]]).T
220
count = 0
221
markers.MarkerStyle(fillstyle='none')
222
223
np.set_printoptions(precision=4)
224
while f1.x[3,0] > 0:
225
count += 1
226
#f1.update (z)
227
f1.predict()
228
plt.scatter(f1.x[0,0],f1.x[3,0], color='green')
229
230
231
232
def drag_force (velocity):
233
""" Returns the force on a baseball due to air drag at
234
the specified velocity. Units are SI
235
"""
236
B_m = 0.0039 + 0.0058 / (1. + exp((velocity-35.)/5.))
237
return B_m * velocity
238
239
def update_drag(f, dt):
240
vx = f.x[1,0]
241
vy = f.x[3,0]
242
v = sqrt(vx**2 + vy**2)
243
F = -drag_force(v)
244
print F
245
f.u[0,0] = -drag_force(vx)
246
f.u[1,0] = -drag_force(vy)
247
#f.x[2,0]=F*vx
248
#f.x[5,0]=F*vy
249
250
def test_kf_drag():
251
252
y = 1
253
x = 0
254
omega = 35.
255
noise = [0,0]
256
v0 = 50.
257
ball = BaseballPath (x0=x, y0=y,
258
launch_angle_deg=omega,
259
velocity_ms=v0, noise=noise)
260
#ball = BallPath (x0=x, y0=y, omega_deg=omega, velocity=v0, noise=noise)
261
262
dt = 1
263
264
265
f1 = KalmanFilter(dim_x=6, dim_z=2)
266
dt = 1/30. # time step
267
268
ay = -.5*dt**2
269
ax = .5*dt**2
270
271
f1.F = np.mat ([[1, dt, ax, 0, 0, 0], # x=x0+dx*dt
272
[0, 1, dt, 0, 0, 0], # dx = dx
273
[0, 0, 1, 0, 0, 0], # ddx = 0
274
[0, 0, 0, 1, dt, ay], # y = y0 +dy*dt+1/2*g*dt^2
275
[0, 0, 0, 0, 1, dt], # dy = dy0 + ddy*dt
276
[0, 0, 0, 0, 0, 1]]) # ddy = -g
277
278
# We will inject air drag using Bu
279
f1.B = np.mat([[0., 0., 1., 0., 0., 0.],
280
[0., 0., 0., 0., 0., 1.]]).T
281
282
f1.u = np.mat([[0., 0.]]).T
283
284
f1.H = np.mat([
285
[1, 0, 0, 0, 0, 0],
286
[0, 0, 0, 1, 0, 0]])
287
288
f1.R = np.eye(2) * 5
289
f1.Q = np.eye(6) * 0.
290
291
omega = radians(omega)
292
vx = cos(omega) * v0
293
vy = sin(omega) * v0
294
295
f1.x = np.mat([x,vx,0,y,vy,-9.8]).T
296
297
f1.P = np.eye(6) * 500.
298
299
z = np.mat([[0,0]]).T
300
markers.MarkerStyle(fillstyle='none')
301
302
np.set_printoptions(precision=4)
303
304
t=0
305
while f1.x[3,0] > 0:
306
t+=dt
307
308
#f1.update (z)
309
x,y = ball.update(dt)
310
#x,y = ball.pos_at_t(t)
311
update_drag(f1, dt)
312
f1.predict()
313
print f1.x.T
314
plt.scatter(f1.x[0,0],f1.x[3,0], color='red', alpha=0.5)
315
plt.scatter (x,y)
316
return f1
317
318
if __name__ == '__main__':
319
#test_baseball_path()
320
#test_ball_path()
321
#test_kf()
322
f1 = test_kf_drag()
323
324