particle.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. # pip3 install --user http://bit.ly/csc161graphics
  2. from graphics import *
  3. import time
  4. import numpy as np
  5. import math
  6. from map import *
  7. import random
  8. import colorsys
  9. class VirtualRobot:
  10. def __init__(self, worldmap):
  11. self.x = np.random.rand()*worldmap.width
  12. self.y = np.random.rand()*worldmap.height
  13. self.heading = math.pi*2*np.random.rand()
  14. self.worldmap = worldmap
  15. def move(self, distance):
  16. self.x = self.x + (math.cos(self.heading) * distance)
  17. self.y = self.y + (math.sin(self.heading) * distance)
  18. def rotate(self, radians):
  19. self.heading += float(radians)
  20. self.heading %= 2 * math.pi
  21. def read(self):
  22. return self.worldmap.white(self.x, self.y)
  23. # ------------------------------------------------------------------------
  24. class Particle:
  25. def __init__(self, worldmap):
  26. self.weight = 1
  27. self.x = np.random.rand()*worldmap.width
  28. self.y = np.random.rand()*worldmap.height
  29. self.heading = math.pi*2*np.random.rand()
  30. self.worldmap = worldmap
  31. def move(self, rot, distance):
  32. if np.random.rand() < 0.98:
  33. self.translate(distance)
  34. self.rotate(rot)
  35. else:
  36. self.x = np.random.rand()*self.worldmap.width
  37. self.y = np.random.rand()*self.worldmap.height
  38. self.heading = math.pi*2*np.random.rand()
  39. def translate(self, distance):
  40. distance = float(distance) + random.gauss(0.0, 0.4*distance)
  41. self.x = self.x + (math.cos(self.heading) * distance)
  42. self.y = self.y + (math.sin(self.heading) * distance)
  43. def rotate(self, radians):
  44. self.heading += float(radians) + random.gauss(0.0, 0.1*radians+0.02)
  45. self.heading %= 2 * math.pi
  46. def read(self):
  47. return self.worldmap.white(self.x, self.y)
  48. def __repr__(self):
  49. return "(%f, %f)" % (self.x, self.y)
  50. def compute_mean_point(particles):
  51. m_x, m_y, m_count = 0, 0, 0
  52. for p in particles:
  53. m_count += p.weight
  54. m_x += p.x * p.weight
  55. m_y += p.y * p.weight
  56. if m_count == 0:
  57. return -1, -1
  58. m_x /= m_count
  59. m_y /= m_count
  60. return m_x, m_y
  61. def low_variance_sampler (particles, worldmap):
  62. weights = []
  63. # normalize
  64. for p in particles:
  65. weights.append(p.weight)
  66. weights = weights / np.sum(weights)
  67. # print(np.sum(weights))
  68. new_particles = []
  69. M = len(particles)
  70. r = np.random.uniform(0, 1.0/M)
  71. c = weights[0]
  72. i = 0
  73. for m in range (0, M):
  74. # try:
  75. u = r + m * 1.0/M
  76. while u > c:
  77. i = i + 1
  78. c = c + weights[i]
  79. p = Particle(worldmap)
  80. p.x = particles[i].x
  81. p.y = particles[i].y
  82. p.heading = particles[i].heading
  83. new_particles.append(p)
  84. # except IndexError:
  85. # new_particles.append(Particle(worldmap))
  86. return new_particles
  87. def particle_filter(particles, read, move, rot, worldmap):
  88. new_particles = []
  89. M = len(particles)
  90. for p in particles:
  91. p.move(rot, move)
  92. # w = p(z|x) probabilidade de ter lido uma cor estadando em x
  93. if worldmap.inside(p.x, p.y):
  94. if p.read() == read:
  95. p.weight = 0.80
  96. else:
  97. p.weight = 0.20
  98. # p_d = p.read_sensor(world)
  99. # p.w = w_gauss(r_d, p_d)
  100. else:
  101. ptmp = Particle(worldmap)
  102. p.x = ptmp.x
  103. p.y = ptmp.y
  104. p.heading = ptmp.heading
  105. p.weight = 1.e-300
  106. # print(particles)
  107. return low_variance_sampler(particles, worldmap)
  108. # ------------------------------------------------------------------------
  109. def colorFix(floatcolor):
  110. r = int(floatcolor*240)
  111. if r < 0:
  112. r = 0
  113. elif r > 255:
  114. r = 255
  115. return r
  116. def main():
  117. width = 3370.39
  118. height = 2383.94
  119. zoom = 2.5
  120. worldmap = Map(width, height, "../3.txt")
  121. robot = VirtualRobot(worldmap)
  122. PARTICLE_COUNT = 2000
  123. particles = []
  124. win = GraphWin('Particle', width/zoom, height/zoom, autoflush=False)
  125. win.setBackground('black')
  126. # create particles
  127. for i in range(0, PARTICLE_COUNT):
  128. particles.append(Particle(worldmap))
  129. while True:
  130. worldmap.draw(win, zoom)
  131. rot = 0
  132. move = 50
  133. # # ---------- Try to find current best estimate for display ----------
  134. m_x, m_y = compute_mean_point(particles)
  135. # movimento
  136. if robot.x < width*0.1 or width*0.9 < robot.x:
  137. rot = np.random.uniform(math.pi/2,math.pi/2)
  138. robot.rotate(rot)
  139. if robot.y < height*0.1 or height*0.9 < robot.y:
  140. rot = np.random.uniform(math.pi/2,math.pi/2)
  141. robot.rotate(rot)
  142. robot.move(move)
  143. #leitura
  144. read = robot.read()
  145. particles = particle_filter(particles, read, move, rot, worldmap)
  146. # ---------- display particles ----------
  147. for p in particles:
  148. pt = Point(p.x/zoom, p.y/zoom)
  149. h = p.heading/(math.pi*2)
  150. rgb = colorsys.hsv_to_rgb(h, 0.8, 0.8)
  151. rgb = color_rgb(colorFix(rgb[0]), colorFix(rgb[1]), colorFix(rgb[2]))
  152. cir = Circle(pt, 10/zoom)
  153. cir.setWidth(0)
  154. cir.setFill(rgb)
  155. cir.draw(win)
  156. # ---------- show mean point ----------
  157. pt = Point(m_x/zoom, m_y/zoom)
  158. cir = Circle(pt, 30/zoom)
  159. cir.setFill('red')
  160. cir.draw(win)
  161. # ---------- display robot ----------
  162. h = robot.heading/(math.pi*2)
  163. rgb = colorsys.hsv_to_rgb(h, 0.8, 0.8)
  164. rgb = color_rgb(colorFix(rgb[0]), colorFix(rgb[1]), colorFix(rgb[2]))
  165. pt = Point(robot.x/zoom, robot.y/zoom)
  166. cir = Circle(pt, 30/zoom)
  167. cir.setFill(rgb)
  168. cir.draw(win)
  169. win.update()
  170. win.delete('all')
  171. main()