Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
96129 views
1
# -*- coding: utf-8 -*-
2
"""
3
Created on Fri Jul 18 23:23:08 2014
4
5
@author: rlabbe
6
"""
7
8
import book_plots as bp
9
from math import radians, sin, cos, sqrt, exp
10
import numpy.random as random
11
import matplotlib.pyplot as plt
12
import filterpy.kalman as kf
13
import numpy as np
14
15
def ball_kf(x, y, omega, v0, dt, r=0.5, q=0.02):
16
17
g = 9.8 # gravitational constant
18
f1 = kf.KalmanFilter(dim_x=5, dim_z=2)
19
20
ay = .5*dt**2
21
f1.F = np.array ([[1, dt, 0, 0, 0], # x = x0+dx*dt
22
[0, 1, 0, 0, 0], # dx = dx
23
[0, 0, 1, dt, ay], # y = y0 +dy*dt+1/2*g*dt^2
24
[0, 0, 0, 1, dt], # dy = dy0 + ddy*dt
25
[0, 0, 0, 0, 1]]) # ddy = -g.
26
27
f1.H = np.array([
28
[1, 0, 0, 0, 0],
29
[0, 0, 1, 0, 0]])
30
31
f1.R *= r
32
f1.Q *= q
33
34
omega = radians(omega)
35
vx = cos(omega) * v0
36
vy = sin(omega) * v0
37
38
f1.x = np.array([[x,vx,y,vy,-9.8]]).T
39
40
return f1
41
42
43
def plot_radar(xs, track, time):
44
45
plt.figure()
46
bp.plot_track(time, track[:, 0])
47
bp.plot_filter(time, xs[:, 0])
48
plt.legend(loc=4)
49
plt.xlabel('time (sec)')
50
plt.ylabel('position (m)')
51
52
plt.figure()
53
bp.plot_track(time, track[:, 1])
54
bp.plot_filter(time, xs[:, 1])
55
plt.legend(loc=4)
56
plt.xlabel('time (sec)')
57
plt.ylabel('velocity (m/s)')
58
59
plt.figure()
60
bp.plot_track(time, track[:, 2])
61
bp.plot_filter(time, xs[:, 2])
62
plt.ylabel('altitude (m)')
63
plt.legend(loc=4)
64
plt.xlabel('time (sec)')
65
plt.ylim((900, 1600))
66
plt.show()
67
68
def plot_bicycle():
69
plt.clf()
70
plt.axes()
71
ax = plt.gca()
72
#ax.add_patch(plt.Rectangle((10,0), 10, 20, fill=False, ec='k')) #car
73
ax.add_patch(plt.Rectangle((21,1), .75, 2, fill=False, ec='k')) #wheel
74
ax.add_patch(plt.Rectangle((21.33,10), .75, 2, fill=False, ec='k', angle=20)) #wheel
75
ax.add_patch(plt.Rectangle((21.,4.), .75, 2, fill=True, ec='k', angle=5, ls='dashdot', alpha=0.3)) #wheel
76
77
plt.arrow(0, 2, 20.5, 0, fc='k', ec='k', head_width=0.5, head_length=0.5)
78
plt.arrow(0, 2, 20.4, 3, fc='k', ec='k', head_width=0.5, head_length=0.5)
79
plt.arrow(21.375, 2., 0, 8.5, fc='k', ec='k', head_width=0.5, head_length=0.5)
80
plt.arrow(23, 2, 0, 2.5, fc='k', ec='k', head_width=0.5, head_length=0.5)
81
82
#ax.add_patch(plt.Rectangle((10,0), 10, 20, fill=False, ec='k'))
83
plt.text(11, 1.0, "R", fontsize=18)
84
plt.text(8, 2.2, r"$\beta$", fontsize=18)
85
plt.text(20.4, 13.5, r"$\alpha$", fontsize=18)
86
plt.text(21.6, 7, "w (wheelbase)", fontsize=18)
87
plt.text(0, 1, "C", fontsize=18)
88
plt.text(24, 3, "d", fontsize=18)
89
plt.plot([21.375, 21.25], [11, 14], color='k', lw=1)
90
plt.plot([21.375, 20.2], [11, 14], color='k', lw=1)
91
plt.axis('scaled')
92
plt.xlim(0,25)
93
plt.axis('off')
94
plt.show()
95
96
#plot_bicycle()
97
98
class BaseballPath(object):
99
def __init__(self, x0, y0, launch_angle_deg, velocity_ms, noise=(1.0,1.0)):
100
""" Create baseball path object in 2D (y=height above ground)
101
102
x0,y0 initial position
103
launch_angle_deg angle ball is travelling respective to ground plane
104
velocity_ms speeed of ball in meters/second
105
noise amount of noise to add to each reported position in (x,y)
106
"""
107
108
omega = radians(launch_angle_deg)
109
self.v_x = velocity_ms * cos(omega)
110
self.v_y = velocity_ms * sin(omega)
111
112
self.x = x0
113
self.y = y0
114
115
self.noise = noise
116
117
118
def drag_force (self, velocity):
119
""" Returns the force on a baseball due to air drag at
120
the specified velocity. Units are SI
121
"""
122
B_m = 0.0039 + 0.0058 / (1. + exp((velocity-35.)/5.))
123
return B_m * velocity
124
125
126
def update(self, dt, vel_wind=0.):
127
""" compute the ball position based on the specified time step and
128
wind velocity. Returns (x,y) position tuple.
129
"""
130
131
# Euler equations for x and y
132
self.x += self.v_x*dt
133
self.y += self.v_y*dt
134
135
# force due to air drag
136
v_x_wind = self.v_x - vel_wind
137
138
v = sqrt (v_x_wind**2 + self.v_y**2)
139
F = self.drag_force(v)
140
141
# Euler's equations for velocity
142
self.v_x = self.v_x - F*v_x_wind*dt
143
self.v_y = self.v_y - 9.81*dt - F*self.v_y*dt
144
145
return (self.x + random.randn()*self.noise[0],
146
self.y + random.randn()*self.noise[1])
147
148
149
150
def plot_ball():
151
y = 1.
152
x = 0.
153
theta = 35. # launch angle
154
v0 = 50.
155
dt = 1/10. # time step
156
157
ball = BaseballPath(x0=x, y0=y, launch_angle_deg=theta, velocity_ms=v0, noise=[.3,.3])
158
f1 = ball_kf(x,y,theta,v0,dt,r=1.)
159
f2 = ball_kf(x,y,theta,v0,dt,r=10.)
160
t = 0
161
xs = []
162
ys = []
163
xs2 = []
164
ys2 = []
165
166
while f1.x[2,0] > 0:
167
t += dt
168
x,y = ball.update(dt)
169
z = np.mat([[x,y]]).T
170
171
f1.update(z)
172
f2.update(z)
173
xs.append(f1.x[0,0])
174
ys.append(f1.x[2,0])
175
xs2.append(f2.x[0,0])
176
ys2.append(f2.x[2,0])
177
f1.predict()
178
f2.predict()
179
180
p1 = plt.scatter(x, y, color='green', marker='o', s=75, alpha=0.5)
181
182
p2, = plt.plot (xs, ys,lw=2)
183
p3, = plt.plot (xs2, ys2,lw=4, c='r')
184
plt.legend([p1,p2, p3], ['Measurements', 'Kalman filter(R=0.5)', 'Kalman filter(R=10)'])
185
plt.show()
186
187
188
def show_radar_chart():
189
plt.xlim([0.9,2.5])
190
plt.ylim([0.5,2.5])
191
192
plt.scatter ([1,2],[1,2])
193
#plt.scatter ([2],[1],marker='o')
194
ax = plt.axes()
195
196
ax.annotate('', xy=(2,2), xytext=(1,1),
197
arrowprops=dict(arrowstyle='->', ec='r',shrinkA=3, shrinkB=4))
198
199
ax.annotate('', xy=(2,1), xytext=(1,1),
200
arrowprops=dict(arrowstyle='->', ec='b',shrinkA=0, shrinkB=0))
201
202
ax.annotate('', xy=(2,2), xytext=(2,1),
203
arrowprops=dict(arrowstyle='->', ec='b',shrinkA=0, shrinkB=4))
204
205
206
207
ax.annotate('$\Theta$ (', xy=(1.2, 1.1), color='b')
208
ax.annotate('Aircraft', xy=(2.04,2.), color='b')
209
ax.annotate('altitude', xy=(2.04,1.5), color='k')
210
ax.annotate('X', xy=(1.5, .9))
211
ax.annotate('Radar', xy=(.95, 0.9))
212
ax.annotate('Slant\n (r)', xy=(1.5,1.62), color='r')
213
214
plt.title("Radar Tracking")
215
ax.xaxis.set_ticklabels([])
216
ax.yaxis.set_ticklabels([])
217
ax.xaxis.set_ticks([])
218
ax.yaxis.set_ticks([])
219
220
221
plt.show()
222