123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- # pip3 install --user http://bit.ly/csc161graphics
- from graphics import *
- import time
- import numpy as np
- import math
- from map import *
- import random
- import colorsys
- from robot import VirtualRobot, LejosRobot
- # ------------------------------------------------------------------------
- class Particle:
- def __init__(self, worldmap):
- self.weight = 1
- self.x = np.random.rand()*worldmap.width
- self.y = np.random.rand()*worldmap.height
- self.heading = math.pi*2*np.random.rand()
- self.worldmap = worldmap
- def move(self, rot, distance):
- if np.random.rand() < 0.98:
- self.translate(distance)
- self.rotate(rot)
- else:
- self.x = np.random.rand()*self.worldmap.width
- self.y = np.random.rand()*self.worldmap.height
- self.heading = math.pi*2*np.random.rand()
- def translate(self, distance):
- distance = float(distance) + random.gauss(0.0, 0.4*distance)
- self.x = self.x + (math.cos(self.heading) * distance)
- self.y = self.y + (math.sin(self.heading) * distance)
- def rotate(self, radians):
- self.heading += float(radians) + random.gauss(0.0, 0.1*radians+0.02)
- self.heading %= 2 * math.pi
- def read(self):
- return self.worldmap.white(self.x, self.y)
- def __repr__(self):
- return "(%f, %f)" % (self.x, self.y)
- def compute_mean_point(particles):
- m_x, m_y, m_count = 0, 0, 0
- for p in particles:
- m_count += p.weight
- m_x += p.x * p.weight
- m_y += p.y * p.weight
- if m_count == 0:
- return -1, -1
- m_x /= m_count
- m_y /= m_count
- return m_x, m_y
- def low_variance_sampler (particles, worldmap):
- weights = []
- # normalize
- for p in particles:
- weights.append(p.weight)
- weights = weights / np.sum(weights)
- # print(np.sum(weights))
- new_particles = []
- M = len(particles)
- r = np.random.uniform(0, 1.0/M)
- c = weights[0]
- i = 0
- for m in range (0, M):
- # try:
- u = r + m * 1.0/M
- while u > c:
- i = i + 1
- c = c + weights[i]
- p = Particle(worldmap)
- p.x = particles[i].x
- p.y = particles[i].y
- p.heading = particles[i].heading
- new_particles.append(p)
- # except IndexError:
- # new_particles.append(Particle(worldmap))
- return new_particles
- def particle_filter(particles, read, move, rot, worldmap):
- new_particles = []
- M = len(particles)
- for p in particles:
- p.move(rot, move)
- # w = p(z|x) probabilidade de ter lido uma cor estadando em x
- if worldmap.inside(p.x, p.y):
- if p.read() == read:
- p.weight = 0.80
- else:
- p.weight = 0.20
- # p_d = p.read_sensor(world)
- # p.w = w_gauss(r_d, p_d)
- else:
- ptmp = Particle(worldmap)
- p.x = ptmp.x
- p.y = ptmp.y
- p.heading = ptmp.heading
- p.weight = 1.e-300
- # print(particles)
- return low_variance_sampler(particles, worldmap)
-
- # ------------------------------------------------------------------------
- def colorFix(floatcolor):
- r = int(floatcolor*240)
- if r < 0:
- r = 0
- elif r > 255:
- r = 255
- return r
- def main():
- width = 3370.39
- height = 2383.94
- zoom = 2.5
- worldmap = Map(width, height, "../3.txt")
- robot = LejosRobot('00:16:53:18:2E:17')
- PARTICLE_COUNT = 2000
- particles = []
- win = GraphWin('Particle', width/zoom, height/zoom, autoflush=False)
- win.setBackground('black')
- # create particles
- for i in range(0, PARTICLE_COUNT):
- particles.append(Particle(worldmap))
- while True:
- worldmap.draw(win, zoom)
- rot = 0
- move = 50
- ## ---------- Estima posicao ----------
- m_x, m_y = compute_mean_point(particles)
- # Realiza o movimento do robo
- # nesse exemplo estamos utilizando uma tecnica muito ruim.
- # Ela esta baseada na posicao real, deveria ser na estimativa
- if robot.x < width*0.1 or width*0.9 < robot.x:
- rot = np.random.uniform(math.pi/2,math.pi/2)
- robot.rotate(rot)
- if robot.y < height*0.1 or height*0.9 < robot.y:
- rot = np.random.uniform(math.pi/2,math.pi/2)
- robot.rotate(rot)
- robot.move(move)
- # Realiza a leitura de um sensor
- read = robot.read()
- # sabendo o movemento e a leitura, dedistribui as particulas
- particles = particle_filter(particles, read, move, rot, worldmap)
- # exibe as particulas na tela
- for p in particles:
- pt = Point(p.x/zoom, p.y/zoom)
- h = p.heading/(math.pi*2)
- rgb = colorsys.hsv_to_rgb(h, 0.8, 0.8)
- rgb = color_rgb(colorFix(rgb[0]), colorFix(rgb[1]), colorFix(rgb[2]))
- cir = Circle(pt, 10/zoom)
- cir.setWidth(0)
- cir.setFill(rgb)
- cir.draw(win)
- # exibe a posicao estimada na tela
- pt = Point(m_x/zoom, m_y/zoom)
- cir = Circle(pt, 30/zoom)
- cir.setFill('red')
- cir.draw(win)
- # mostra a posicao real
- if type(robot) is VirtualRobot:
- h = robot.heading/(math.pi*2)
- rgb = colorsys.hsv_to_rgb(h, 0.8, 0.8)
- rgb = color_rgb(colorFix(rgb[0]), colorFix(rgb[1]), colorFix(rgb[2]))
- pt = Point(robot.x/zoom, robot.y/zoom)
- cir = Circle(pt, 30/zoom)
- cir.setFill(rgb)
- cir.draw(win)
- win.update()
- win.delete('all')
- main()
|