Advertisement
Guest User

Untitled

a guest
Apr 5th, 2015
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.20 KB | None | 0 0
  1. import math
  2. import numpy as np
  3. from Pose import Pose
  4. from Point import Point
  5.  
  6. np.set_printoptions(precision=3)
  7. np.set_printoptions(suppress=True)
  8. np.set_printoptions(linewidth=100)
  9.  
  10. def matmult(*x):
  11.   return reduce(np.dot, x)
  12.  
  13. def wrap_radians(angle):
  14.  return float(((angle + np.pi) % (2*np.pi)) - np.pi)
  15.  
  16. class EKF(object):
  17.  
  18.     def __init__(self, controlSigma, controlTurnSigma, sensorDistSigma):
  19.         self.controlSigma = controlSigma
  20.         self.controlTurnSigma = controlTurnSigma
  21.         self.sensorDistSigma = sensorDistSigma
  22.         self.sensorAngleSigma = np.pi/360
  23.  
  24.         self.X = np.zeros([3,1])
  25.         self.P = np.eye(3,3)
  26.  
  27.         self.JG = np.eye(3,3)
  28.         self.JXR = np.eye(2,3)
  29.         self.JZ = np.zeros([2,2])
  30.  
  31.         self.landmarkCount = 0
  32.  
  33.         self.lastControl = Pose()
  34.  
  35.     def motionModel(self, control):
  36.         deltaControl = control - self.lastControl
  37.  
  38.         if deltaControl.x == 0 and deltaControl.y == 0 and deltaControl.r == 0:
  39.             self.JG = np.eye(3,3)
  40.             return 0
  41.  
  42.         rot1 = wrap_radians(math.atan2(control.y - self.lastControl.y, control.x - self.lastControl.x) - self.lastControl.r)
  43.         trans = math.sqrt(((self.lastControl.x - control.x)**2) + ((self.lastControl.y - control.y)**2))
  44.         rot2 = wrap_radians(control.r - self.lastControl.r - rot1)
  45.  
  46.         drot1 = ((self.controlTurnSigma*(rot1**2)) + (self.controlSigma*(trans**2)))
  47.         dtrans = ((self.controlTurnSigma*(rot1**2)) + (self.controlTurnSigma*(rot2**2)) + (self.controlSigma*(trans**2)))
  48.         drot2 = ((self.controlTurnSigma*(rot2**2)) + (self.controlSigma*(trans**2)))
  49.  
  50.         rot1N = wrap_radians(rot1 - (drot1 * np.random.normal()))
  51.         transN = trans - (dtrans * np.random.normal())
  52.         rot2N = wrap_radians(rot2 - (drot2 * np.random.normal()))
  53.  
  54.         self.X[0] += transN * math.cos(self.X[2] + rot1N)
  55.         self.X[1] += transN * math.sin(self.X[2] + rot1N)
  56.         self.X[2] += rot1N + rot2N
  57.  
  58.         self.X[2] = wrap_radians(self.X[2])
  59.  
  60.         self.JG[0][2] = -trans * math.sin(self.lastControl.r + rot1)
  61.         self.JG[1][2] = trans * math.cos(self.lastControl.r + rot1)
  62.  
  63.         V = np.array([[-trans * math.sin(self.X[2] + rot1), math.cos(self.X[2] + rot1), 0],
  64.                       [trans * math.cos(self.X[2] + rot1), math.sin(self.X[2] + rot1), 0],
  65.                       [1, 0, 1]])
  66.  
  67.         M = np.diag([drot1, dtrans, drot2])
  68.  
  69.         self.lastControl = control
  70.  
  71.         return matmult(V, M, V.T)
  72.  
  73.     def sensorModel(self, landmark):
  74.         q = math.pow(landmark.x - self.X[0], 2) + math.pow(landmark.y - self.X[1], 2)
  75.  
  76.         dist = math.sqrt(q)
  77.         angle = math.atan2(landmark.y - self.X[1], landmark.x - self.X[0]) - self.X[2]
  78.  
  79.         dist += self.sensorDistSigma * np.random.normal()
  80.         angle += self.sensorAngleSigma * np.random.normal()
  81.  
  82.         return Point(dist, angle), q
  83.  
  84.     def inverseSensorModel(self, landmark):
  85.         x = self.X[0] + landmark.dist * math.cos(self.X[2] + math.radians(landmark.angle))
  86.         y = self.X[1] + landmark.dist * math.sin(self.X[2] + math.radians(landmark.angle))
  87.  
  88.         landmark.pos = Point(x,y)
  89.  
  90.     def predict(self, poseEstimate):
  91.         Q = self.motionModel(poseEstimate)
  92.  
  93.         self.getRR()[:] = matmult(self.JG, self.getRR(), self.JG.T) + Q
  94.         if self.landmarkCount > 0:
  95.             self.getRM()[:] = matmult(self.JG, self.getRM())
  96.             self.getMR()[:] = self.getRM().T
  97.  
  98.     def correct(self, reobservedLandmarks):
  99.         for landmark in reobservedLandmarks:
  100.             inv, JH = self.getH(landmark)
  101.  
  102.             if inv == None:
  103.                 continue
  104.  
  105.             V = np.identity(2)
  106.             R = np.array([[landmark.dist*self.sensorDistSigma, 0],[0, self.sensorAngleSigma]])
  107.  
  108.             Z = matmult(JH, self.P, JH.T) + matmult(V, R, V.T)
  109.             K = matmult(self.P, JH.T, np.linalg.inv(Z))
  110.  
  111.             print 'INV:', inv
  112.             print 'Kalman Gain * Inv'
  113.             print matmult(K, inv)
  114.  
  115.             self.X = self.X - matmult(K, inv)
  116.             self.X[2] = wrap_radians(self.X[2])
  117.  
  118.             self.P = matmult((np.eye(self.X.shape[0]) - matmult(K, JH)), self.P)
  119.             # self.P = self.P - matmult(K, matmult(self.P, JH.T).T)
  120.            
  121.             print 'Updating LANDMARK: ',landmark.id
  122.             print self.P
  123.  
  124.         for lm in reobservedLandmarks:
  125.             lm.pos = self.getLandmark(lm.id)
  126.  
  127.             eigenvals, eigenvects = np.linalg.eig(self.getLM(lm.id))
  128.  
  129.             if eigenvals[0] > 0 and eigenvals[1] > 0:
  130.                 lm.error = Point(math.sqrt(eigenvals[0]), math.sqrt(eigenvals[1]))
  131.             elif eigenvals[0] < 0 or eigenvals[1] < 0:
  132.                 print 'NEG'
  133.  
  134.     def grow(self, newLandmarks):
  135.         for landmark in newLandmarks:
  136.             self.addLandmark(landmark)
  137.  
  138.             la = math.radians(landmark.angle)
  139.  
  140.             self.JXR[0][2] = -landmark.dist * math.sin(la + self.X[2])
  141.             self.JXR[1][2] = landmark.dist * math.cos(la + self.X[2])
  142.  
  143.             self.JZ[0][0] = math.cos(la + self.X[2])
  144.             self.JZ[0][1] = -landmark.dist * math.sin(la + self.X[2])
  145.             self.JZ[1][0] = math.sin(la + self.X[2])
  146.             self.JZ[1][1] = landmark.dist * math.cos(la + self.X[2])
  147.  
  148.             R = np.array([[landmark.dist*self.sensorDistSigma, 0],[0, self.sensorAngleSigma]])
  149.  
  150.             self.getLM(landmark.id)[:] = matmult(self.JXR, self.getRR(), self.JXR.T) + matmult(self.JZ, R, self.JZ.T)
  151.  
  152.             self.P[3+(self.landmarkCount*2)-2:, 0:-2] = matmult(self.JXR, self.P[0:3, 0:3+(self.landmarkCount*2)-2])
  153.             self.P[0:-2, 3+(self.landmarkCount*2)-2:] = matmult(self.JXR, self.P[0:3, 0:3+(self.landmarkCount*2)-2]).T
  154.  
  155.             print 'Adding LANDMARK: ', landmark.id
  156.             print self.P
  157.  
  158.     def getH(self, landmark):
  159.         storedLandmark = self.getLandmark(landmark.id)
  160.  
  161.         z = Point(landmark.dist, math.radians(landmark.angle))
  162.         h, q = self.sensorModel(storedLandmark)
  163.  
  164.         if q <= 0:
  165.             return None, None
  166.  
  167.         z.y = wrap_radians(z.y)
  168.         h.y = wrap_radians(h.y)
  169.  
  170.         inv = np.array([[z.x-h.x], [wrap_radians(z.y-h.y)]])
  171.  
  172.         JH = np.zeros([2, 3 + (self.landmarkCount*2)])
  173.         JH[1][2] = -q
  174.  
  175.         JH[0][0] = self.X[0] - storedLandmark.x / math.sqrt(q)
  176.         JH[0][1] = self.X[1] - storedLandmark.y / math.sqrt(q)
  177.         JH[1][0] = storedLandmark.y - self.X[1] / q
  178.         JH[1][1] = storedLandmark.x - self.X[0] / q
  179.  
  180.         JH[0][3+(landmark.id*2)] = -JH[0][0]
  181.         JH[0][4+(landmark.id*2)] = -JH[0][1]
  182.         JH[1][3+(landmark.id*2)] = -JH[1][0]
  183.         JH[1][4+(landmark.id*2)] = -JH[1][1]
  184.  
  185.         return inv, JH
  186.  
  187.     def addLandmark(self, landmark):
  188.         self.inverseSensorModel(landmark)
  189.  
  190.         self.X = np.vstack((self.X, landmark.pos.x))
  191.         self.X = np.vstack((self.X, landmark.pos.y))
  192.  
  193.         self.P = np.hstack((self.P, np.zeros((len(self.P), 2))))
  194.         self.P = np.vstack((self.P, np.zeros((2, len(self.P[0])))))
  195.  
  196.         self.getLM(self.landmarkCount)[:] = np.array([[0, 0],
  197.                                                       [0, 0]])
  198.         landmark.id = self.landmarkCount
  199.         self.landmarkCount += 1
  200.  
  201.     def getLandmark(self, lmID):
  202.         return Point(self.X[3+(lmID*2)], self.X[4+(lmID*2)])
  203.  
  204.     def getRR(self):
  205.         return self.P[0:3, 0:3]
  206.  
  207.     def getRM(self):
  208.         return self.P[0:3, 3:3+(self.landmarkCount*2)]
  209.  
  210.     def getMR(self):
  211.         return self.P[3:3+(self.landmarkCount*2), 0:3]
  212.  
  213.     def getMM(self):
  214.         return self.P[3:3+(self.landmarkCount*2), 3:3+(self.landmarkCount*2)]
  215.  
  216.     def getLM(self, lmID):
  217.         return self.P[3+(lmID*2):5+(lmID*2), 3+(lmID*2):5+(lmID*2)]
  218.  
  219.     def getRM_LM(self, lmID):
  220.         return self.P[0:3, 3+(lmID*2):5+(lmID*2)]
  221.  
  222.     def getMR_LM(self, lmID):
  223.         return self.P[3+(lmID*2):5+(lmID*2), 0:3]
  224.  
  225.     def getPose(self):
  226.         return Pose(self.X[0], self.X[1], self.X[2])
  227.  
  228.     def getPoseError(self):
  229.         eigenvals, eigenvects = np.linalg.eig(self.getRR()[0:2,0:2])
  230.         if eigenvals[0] > 0 and eigenvals[1] > 0:
  231.             return Point(math.sqrt(eigenvals[0]), math.sqrt(eigenvals[1]))
  232.         else:
  233.             return Point(1,1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement