Advertisement
Guest User

Untitled

a guest
Oct 30th, 2014
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.39 KB | None | 0 0
  1. '''
  2. Introduction to Uncertainty Quantification: Assignment 1 Question 3
  3. Student ID: 1100121
  4.  
  5. '''
  6.  
  7.  
  8. import numpy as np
  9. from numpy import linalg as LA
  10. import matplotlib.pyplot as plt
  11.  
  12. ############################# QUESTION 3.3
  13.  
  14. Δt = 0.1 #s
  15. N = 1200 #Number of time-steps (so N+1 = 1201 total time points)
  16. g = 9.807 #N/kg
  17. b = 1e-4 #drag parameter
  18.  
  19. # X = [x1,x2,v1,v2] = [position, velocity]
  20. # F: R^4 -> R^4
  21. # [ I | [Δt-(bΔt^2)/2]I ]
  22. # F = [---+-----------------] (in block form)
  23. # [ 0 | [1-bΔt]I ]
  24. # so that X_{k+1} = F.X_k + affine part + noise
  25.  
  26. F = np.array([
  27. [1 , 0. , Δt - b*Δt*Δt/2. , 0. ],
  28. [0. , 1. , 0 , Δt - b*Δt*Δt/2. ],
  29. [0. , 0. , 1.-b*Δt , 0. ],
  30. [0. , 0. , 0. ,1.-b*Δt ]
  31. ])
  32.  
  33. Gu = np.array([ 0,
  34. -g*Δt*Δt/2.,
  35. 0,
  36. -g*Δt]) #control term is a constant vector (as timestep is constant)
  37.  
  38. wind = 5.*np.random.randn(2*(N+2))+10.
  39. # wind at position X_k is wind[k] ~ N(10,5^2), k = 0,...,N+1
  40. # make 2 times as much wind to ensure the projective reaches the ground.
  41.  
  42. def nextIter(X,n):
  43. global Gu,wind
  44. # X_{K} = F.X_{K-1} + Gu + wind_K
  45. # wind only affects velocity horizontally
  46.  
  47. return F.dot(X) + Gu + np.array([0.,0., wind[n] - wind[n-1] ,0.])
  48.  
  49. def trajectory():
  50. global N,wind
  51. initial_condition = np.array([0,0,300. + wind[0],600.])
  52. #initialise array of points
  53. graph = np.array([[0., 0., 0., 0.] for _ in range(N+1)]) #<- MUST NOT initialise
  54. graph[0] = initial_condition # as [0,0,0,0]s
  55.  
  56. for n in range(N):
  57. graph[n+1] = nextIter(graph[n],n+1)
  58. return graph
  59.  
  60. graph = trajectory()
  61. # plt.plot(graph[:,0], graph[:,1],'b')
  62. # plt.show()
  63.  
  64. ############################# QUESTION 3.4
  65.  
  66. #observe at timesteps 400≤t≤600
  67. default_start = 400
  68. default_num_obs = 201 #note |{400,...,600}| = 201
  69. default_end = default_start + default_num_obs -1 #the last time point
  70.  
  71. def polar(x):
  72. # polar:R^4 -> R^2 takes us from cartesian (x1,x2,v1,v2) space to polar (φ,r) space [(m,m,m/s,m/s)->(radians, m)]
  73. # (forgetting velocity components)
  74.  
  75. return np.array([np.arctan2( x[1],30000. - x[0]) ,
  76. np.sqrt((30000. - x[0])**2 + x[1]**2) ])
  77.  
  78. def cartesian(y):
  79. # cartesian:R^2 -> R^2 is the inverse of polar:R^2 -> R^2
  80.  
  81. return np.array([30000. + y[1]*np.cos(np.pi-y[0]) , y[1]*np.sin(np.pi-y[0]) ])
  82.  
  83.  
  84. def dPolar(x):
  85. # give the matrix representing the linear map best approximating polar() at x
  86.  
  87. r = np.sqrt((30000-x[0])**2 + x[1]**2)
  88. return np.array([
  89. [x[1]/r**2 , (30000-x[0])/r**2 , 0 , 0],
  90. [(x[0]-30000)/r , x[1]/r , 0 , 0]
  91. ])
  92.  
  93.  
  94. #sanity check for dPolar():
  95. '''
  96. def dPolarError(x,h):
  97. # given two 2-vectors, returns the size of the error term polar(x+h) - polar(x) - dPolar(x).h ; this should be small for h small
  98. return LA.norm(polar(x[0:2]+h[0:2]) - polar(x[0:2]) - dPolar(x[0:2]).dot([ h[0], h[1], 0, 0]))
  99.  
  100. def dPolarSanityCheck(x, K = 50):
  101. # print a rapidly decreasing sequence to calm my nerves
  102. for n in range(K-30,K):
  103. print(dPolarError(x,x/np.exp(n)))
  104.  
  105. dPolarSanityCheck( np.array([1,1]) )
  106. '''
  107.  
  108. def radians(deg):
  109. #converts degrees to radians
  110. return deg * np.pi / 180.
  111.  
  112. def observations(graph,start = default_start, num_obs = default_num_obs):
  113. # this is the array of observation 2-vectors (in polar coordinates) with noise
  114.  
  115. φ_error = radians(5.)*np.random.randn(num_obs) #N(0,radians(5)^2) noise
  116. r_error = 500.*np.random.randn(num_obs) #N(0,500^2) noise
  117.  
  118. obs = np.array([[0.,0.] for i in range(num_obs)])
  119. for i in range(num_obs):
  120. obs[i] = polar([graph[start+i,0],graph[start+i,1]]) + np.array([φ_error[i],r_error[i]])
  121.  
  122. return obs
  123.  
  124.  
  125. y = observations(graph)
  126.  
  127. # convert back to cartesian coordinates for later use
  128. xhat = np.array([cartesian(pt) for pt in y])
  129.  
  130. (obs_post_x , obs_post_y) = ([30000.], [0.]) #in meters
  131.  
  132. # observations sanity check:
  133. '''
  134. # points should be 'centered on true trajectory'
  135. plt.plot(graph[:,0], graph[:,1],'b', obs_post_x,obs_post_y,'bo', xhat[:,0],xhat[:,1],'rx' )
  136. plt.show()
  137. '''
  138. ############################# QUESTION 3.5
  139.  
  140. # covariance matrix of noise in dynamics(wind) at time k is
  141. Q = np.diag([0.,0.,25.,0.])
  142.  
  143. # covariance matrix of noise in observations at time k is
  144. R = np.diag( [radians(5.)**2 , 500.**2 ] )
  145. # but only its inverse appears in the formula:
  146. #invR = np.diag( [1/radians(5.)**2 , 1/50.**2])
  147.  
  148. #initialise length N+1 (one for each time point) array of covariance matrices
  149. #
  150. # [ C_{0|0} ]
  151. # [ C_{1|1} ]
  152. # C = [ C_{2|2} ] where each C_{k|k} is a 4x4 matrix
  153. # [ ... ]
  154. # [ C_{N|N} ]
  155. # [ C_{N+1|N+1} ]
  156. #
  157. C = np.array(
  158. [
  159. [[0.]*4]*4 # <-- 4x4 zero matrix
  160. ]*(N+1) # <-- N+1 rows
  161. )
  162.  
  163.  
  164. # initialise length N+1 array of 4-vectors, X[k] = X_{k|k}
  165. X = np.array(
  166. [
  167. [0.]*4 # <-- 4-vectors
  168. ]*(N+1) # <-- N+1 rows
  169. )
  170.  
  171.  
  172. #Evolve the system from t = default_start to t = default_end via the Extended Kalman Filter equations
  173.  
  174. ############# INITIALISATION
  175.  
  176. # initial uncertainty = huge; lets just pretend the the noises are independent
  177. C[default_start] = np.eye(4)*100000.
  178.  
  179. # start off with (xhat[0,0], xhat[0,1], something, something) because why not?
  180. X[default_start] = np.array([xhat[0,0], xhat[0,1], 500,500])
  181.  
  182.  
  183. for t in range(default_start,default_end+1):
  184.  
  185. ############ STEP 2: PREDICTION
  186. Xt = F.dot(X[t]) + Gu #X_{t+1|t} in notes
  187. Ct = F.dot(C[t]).dot(F.T) + Q #C_{t+1|t} in notes
  188.  
  189. ############ STEP 3: CORRECTION VIA NEWTON-RAPHSON
  190. Ht = dPolar(Xt)
  191. C[t+1] = LA.inv( LA.inv(Ct) + (Ht.T).dot(LA.inv(R)).dot(Ht) )
  192. X[t+1] = Xt - C[t+1].dot(Ht.T).dot(LA.inv(R)).dot(polar(Xt) - y[t-default_start])
  193.  
  194.  
  195. #plot the predicted data along with the observations and the true values
  196. plt.plot(
  197. graph[:,0], graph[:,1], 'b',
  198. obs_post_x, obs_post_y, 'bo',
  199. xhat[:,0], xhat[:,1], 'gx',
  200. X[default_start:default_end,0], X[default_start:default_end,1], 'r'
  201. )
  202. plt.show()
  203.  
  204.  
  205. C_x_norm = np.array([LA.norm(c[0:2,0:2]) for c in C[default_start:default_end] ])
  206. x_error = np.array([LA.norm(
  207. np.array([graph[t,0] - X[t,0], graph[t,1] - X[t,1]])
  208. ) for t in range(default_start,default_end+1)])
  209.  
  210. plt.plot(np.log(x_error), 'b', np.log(C_x_norm),'ro')
  211. plt.show()
  212.  
  213. #repeat the plots but for velocity now
  214. plt.plot(
  215. graph[:,0], graph[:,2], 'b',
  216. graph[:,0], graph[:,3], 'r',
  217. X[default_start:default_end,0], X[default_start:default_end,2], 'bx',
  218. X[default_start:default_end,0], X[default_start:default_end,3], 'rx'
  219. )
  220. plt.show()
  221.  
  222. C_v_norm = np.array([LA.norm(c[2:4,2:4]) for c in C[default_start:default_end] ])
  223. v_error = np.array([LA.norm(
  224. np.array([graph[t,2] - X[t,2], graph[t,3] - X[t,3]])
  225. ) for t in range(default_start,default_end+1)])
  226.  
  227. plt.plot(np.log(v_error), 'b', np.log(C_v_norm),'ro')
  228. plt.show()
  229.  
  230. C_norm = np.array([LA.norm(c) for c in C[default_start:default_end]])
  231. X_error = np.array([LA.norm(X[t]-graph[t]) for t in range(default_start,default_end-1)])
  232. '''
  233. #total C and X norm plots
  234.  
  235. plt.plot(X_error, 'g', C_norm, 'r')
  236. plt.show()
  237.  
  238. plt.plot(np.log(X_error), 'g', np.log(C_norm), 'r')
  239. plt.show()
  240. '''
  241. ############################# QUESTION 3.6
  242. '''
  243. #run out of observations; continue with prediction steps until you hit the earth
  244.  
  245. #first check if you have hit the earth already
  246. earth_flag = False
  247. impact_timestep = -1
  248. for t in range(default_start, default_end+1):
  249. if X[t,1] < 0:
  250. earth_flag = True
  251. impact_timestep = t
  252. break
  253.  
  254. if earth_flag is False:
  255.  
  256. for t in range(default_end,2*N): #one is unlikely to avoid the earth over 2N steps
  257. X[t+1] = F.dot(X[t]) + Gu
  258. C[t+1] = F.dot(C[t]).dot(F.T) + Q
  259.  
  260. if X[t+1,1] < 0:
  261. earth_flag = True
  262. impact_timestep = (t+1)
  263. break
  264.  
  265. if earth_flag is False:
  266. print('wow.')
  267. else:
  268. plt.plot(
  269. graph[:,0], graph[:,1], 'b',
  270. obs_post_x, obs_post_y, 'bo',
  271. xhat[:,0], xhat[:,1], 'gx',
  272. X[default_start:,0], X[default_start:,1], 'r'
  273. )
  274. plt.show()
  275. '''
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement