Ejemplo n.º 1
0
def main():
    q = collections.deque(maxlen=1)
    back_q = Queue()

    p = threading.Thread(target=childVid.vidCapture, args=(
        q,
        back_q,
    ))
    q.append({'PATH_FILE': 'recs/first.avi'})
    p.start()

    while True:
        if not p.isAlive():
            break
        time.sleep(.01)
        dict = {'STATE': 'ON', 'cur_time': time.perf_counter()}
        q.append(dict)
        try:
            back = back_q.pop()
            print(back)
        except:
            continue
Ejemplo n.º 2
0
class Controller(object):
    def __init__(self):
        motor = get_motor(motor_debug)
        trigger = get_trigger(debug)
        self.motor = motor
        self.video_tracker = None
        print "CONNECTING Motor"
        motor.connect()
        print "CONNECTING Trigger"
        self.trigger = trigger.Trigger()
        print "CONNECTING Joystick"
        self.init_joystick()
        self.manual = False
        self.x = None
        self.y = None
        self.fire_duration = 200
        self.video_tracker = None

    def _unused_init_detect_process(self):
        self.video_in = Queue()
        self.video_out = Queue()
        self.detect_process = DetectProcess(inq=self.video_in, outq=self.video_out)
        self.detect_process.start()

    def on_frame(self, b):
        ret = inp = numpy.fromstring(b.data, dtype=numpy.uint8).reshape(480, 720, 3)
        if not self.video_tracker:
            self.video_tracker = VideoTracker(initial_frame=inp, on_cx_cy=self.on_cx_cy)
        else:
            ret = self.video_tracker.on_frame(inp)
        return gst.Buffer(ret)

    def on_frame_process(self, b):
        ret = inp = numpy.fromstring(b.data, dtype=numpy.uint8).reshape(480, 720, 3)
        print "pushing"
        self.video_in.push("test")
        print "popping"
        ret_unused = self.video_out.pop()
        assert ret_unused == "testout"
        print "popped"
        return gst.Buffer(ret)

    def init_joystick(self):
        self.j = joystick.Joystick()
        self.j.connect("axis", self.on_axis)
        self.j.connect("button", self.on_button)

    def on_axis(self, signal, code, value):
        print "on_axis %s %s" % (code, value)
        # print "on_axis %d, %d" % (code, value)
        if code not in [0, 1, 2]:
            return
        if code == 0:
            self.x = value
            if self.manual:
                self.motor.theta.set(state.x - 127)
        elif code == 1:
            self.y = value
            if self.manual:
                self.motor.pitch.set(state.y - 127)
        else:
            fire_duration = 100 + (float(value) / 255.0) * 900
            print "joy: %d => fire dur %d" % (value, fire_duration)
            self.fire_duration = int(fire_duration)

    def on_button(self, signal, code, value):
        print "on_button: %d, %d" % (code, value)
        if value != 1 or code != 0:
            return
        print " **** FIRE ****"
        self.trigger.fire(self.fire_duration)

    def on_cx_cy(self, cx, cy):
        # print "controller: got (%d, %d)" % (cx, cy)
        cx -= 720 / 2
        cy -= 480 / 2
        for axis, val in [(self.motor.theta, cx), (self.motor.pitch, cy)]:
            if abs(val) > 10:
                print "action %r" % axis
                axis.set(200 if cx > 0 else -200)
Ejemplo n.º 3
0
class Simulator:
    def __init__(self, num_gens=10, pop_size=30, max_matchups=30, num_parents=4, epsilon=0.1, parallel=False):
        self.engine = Engine()
        self.num_generations = num_gens
        self.population_size = pop_size
        self.max_matchups = max_matchups
        self.num_parents = num_parents
        self.epsilon = epsilon
        self.population = []
        self.matchups = []
        self.parents = []
        self.breed_method = 'randrange'
        self.neural = True
        self.genome_len = 488 if self.neural else 11
        self.gen_num = 0
        self.parallel = parallel
        self.num_matchups = 0
        self.elo_K = 32
        if self.parallel:
            self.manager = Manager()
            self.matchups = Queue()
            self.population = self.manager.list()

    def init_sample(self, genome):
        if self.parallel:
            return self.manager.dict({
                'genome': genome,
                'wins': 0,
                'games': 0,
                'record': 0,
                'elo': 1200
            })
        return {
            'genome': genome,
            'wins': 0,
            'games': 0,
            'record': 0,
            'elo': 1200
        }

    def handle_next_move(self, engine, agent1, agent2):
        move = None
        if engine.player == 1:
            move = agent1.compute_next_move()
        elif engine.player == 2:
            move = agent2.compute_next_move()
        engine.make_move(move)

    def build_random_sample(self):
        genome = []
        for i in range(self.genome_len):
            genome.append((random.randrange(0, 20000) - 10000) / 10000)
        # if self.parallel:
            # return self.manager.Sample(Sample(genome))
        return self.init_sample(genome)

    def build_breeded_sample(self):
        genome = [0 for i in range(self.genome_len)]
        p1 = self.parents.pop(random.randrange(0, len(self.parents)))
        p2 = self.parents[random.randrange(0, len(self.parents))]
        self.parents.append(p1)
        for i in range(self.genome_len):
            mutate = (random.randrange(0, 100) / 100) < self.epsilon
            p1_gene = p1['genome'][i]
            p2_gene = p2['genome'][i]
            if mutate:
                genome[i] = (random.randrange(0, 20000) - 10000) / 10000
            elif self.breed_method == 'randrange':
                try:
                    if p1_gene > p2_gene:
                        gene = (random.randrange(int(p2_gene * 10000 + 10000), int(p1_gene * 10000 + 10000)) - 10000) / 10000
                        genome[i] = gene
                    elif p1_gene < p2_gene:
                        gene = (random.randrange(int(p1_gene * 10000 + 10000), int(p2_gene * 10000 + 10000)) - 10000) / 10000
                        genome[i] = gene
                    elif p1_gene == p2_gene:
                        genome[i] = p1_gene
                except ValueError:
                    genome[i] = p1_gene
                # else:
                #     min_gene = p1_gene - 0.1 * p1_gene
                #     max_gene = p1_gene + 0.1 * p1_gene
                #     gene = random.randrange(int(min_gene * 1000), int(max_gene * 1000)) / 1000
                #     genome.append(gene)
            elif self.breed_method == 'weighted_sum':
                p1_weight = p1.record / (p1.record + p2.record)
                p2_weight = p2.record / (p1.record + p2.record)
                gene = p1_gene * p1_weight + p2_gene * p2_weight
                genome.append(gene)
            elif self.breed_method == 'interpolate':
                if random.randrange(0, 100) / 100 > 0.5:
                    genome.append(p1_gene)
                else:
                    genome.append(p2_gene)
        return self.init_sample(genome)

    def generate_population(self):
        self.population = []
        if self.parallel:
            self.population = Manager().list()
        if len(self.parents) == 0:
            for i in range(self.population_size):
                sample = self.build_random_sample()
                self.population.append(sample)
        else:
            for i in range(self.population_size):
                sample = self.build_breeded_sample()
                self.population.append(sample)

    def select_parents(self):
        self.population = sorted(self.population, key=lambda k: k['elo'], reverse=True)
        self.parents = self.population[:self.num_parents]

    def generate_matchups(self):
        def rotate(n):
            return n[1:] + n[:1]
        pop_size = len(self.population)
        matchups_per_sample = self.max_matchups if self.max_matchups < pop_size else pop_size-1
        matchups = []
        if pop_size % 2 == 0:
            for i in range(matchups_per_sample):
                for j in range(pop_size // 2):
                    if random.randrange(0, 100) / 100 > 0.5:
                        matchups.append((self.population[j], self.population[pop_size-1-j]))
                    else:
                        matchups.append((self.population[pop_size-1-j], self.population[j]))
                constant = self.population[0]
                self.population.pop(0)
                self.population = rotate(self.population)
                self.population = [constant, *self.population]

        else:
            for i in range(matchups_per_sample):
                for j in range(pop_size // 2):
                    matchups.append((self.population[j], self.population[pop_size-2-j]))
                self.population = rotate(self.population)
        self.matchups = matchups

    def generate_matchups_vs_parents(self):
        if len(self.parents) == 0:
            self.generate_matchups()
        else:
            matchups = []
            for i in range(self.population_size):
                for j in range(len(self.parents)):
                    matchups.append((self.parents[j], self.population[i]))
            self.matchups = matchups

    def generate_tournament_mactchups(self):
        matchups = []
        pop_size = len(self.population)
        if len(self.population) % 2 != 0:
            raise Exception(f'Invalid population size {pop_size}, must be 2^x for tournament matchups')
        for i in range(len(self.population)//2):
            if random.randrange(0, 100) / 100 > 0.5:
                matchups.append((self.population[i], self.population[pop_size-1-i]))
            else:
                matchups.append((self.population[pop_size-1-i], self.population[i]))
        self.matchups = matchups

    def play_match(self, matchup, lock=None):
        engine_copy = deepcopy(self.engine)
        if lock is not None:
            lock.acquire()
        p1 = matchup[0]
        p2 = matchup[1]
        if p1['genome'] != self.genome_len or p2['genome'] != self.genome_len:
            pass
        p1_agent = GeneticAlphaBetaAgent(engine_copy, 1, p1['genome'], allowed_depth=4, simulation=True)
        p2_agent = GeneticAlphaBetaAgent(engine_copy, 2, p2['genome'], allowed_depth=4, simulation=True)
        if lock is not None:
            lock.release()
        while engine_copy.game_state is None:
            self.handle_next_move(engine_copy, p1_agent, p2_agent)
        if lock is not None:
            lock.acquire()
        self.update_game_stats(p1, p2, engine_copy.game_state)
        self.update_elo(p1, p2, engine_copy.game_state)
        if lock is not None:
            lock.release()

    def update_game_stats(self, p1, p2, game_state):
        p1['games'] += 1
        p2['games'] += 1
        if game_state == 0:
            p1['wins'] += 0.5
            p2['wins'] += 0.5
        elif game_state == 1:
            p1['wins'] += 1
        else:
            p2['wins'] += 1
        p1['record'] = p1['wins'] / p1['games']
        p2['record'] = p2['wins'] / p2['games']

    def update_elo(self, p1, p2, game_state):
        p1_rating = 10**(p1['elo']/400)
        p2_rating = 10**(p2['elo']/400)
        p1_expected = p1_rating / (p1_rating + p2_rating)
        p2_expected = p2_rating / (p1_rating + p2_rating)
        p1_score = 1 if game_state == 1 else 0.5 if game_state == 0 else 0
        p2_score = 0 if game_state == 1 else 0.5 if game_state == 0 else 1
        p1['elo'] = int(p1['elo'] + self.elo_K * (p1_score - p1_expected))
        p2['elo'] = int(p2['elo'] + self.elo_K * (p2_score - p2_expected))

    def output_parent_genomes(self):
        if len(self.parents) == 0:
            return
        count = 1
        for parent in self.parents:
            print(f'Parent {count:02d}', end=': [ ')
            for gene in parent['genome']:
                print(f'{gene:06.3f}', end=' ]\t' if gene == parent['genome'][-1] else ', ')
            # print(f'Fitness (ELO): {parent["elo"]:04d}')
            print(f'Fitness (Wins): {parent["wins"]:04.1f}')
            count += 1

    def run(self):
        if self.parallel:
            self.run_parallel()
        else:
            for i in range(self.num_generations):
                print(f'\nBEGINNING GENERATION {i}')
                self.generate_population()
                self.generate_matchups()
                while len(self.matchups) != 0:
                    print(f'Simulations left: {len(self.matchups)} of gen. {i}')
                    matchup = self.matchups.pop()
                    self.play_match(matchup)
                self.select_parents()
                self.output_parent_genomes(i)

    def do_work(self, matchup_count, matchup_lock, update_lock):
        while True:
            if self.matchups.qsize() == 0:
                break
            matchup_lock.acquire()
            matchup_count.value += 1
            sys.stdout.write(f'\rSimulation {matchup_count.value:04d}/{self.num_matchups:04d} of Generation {self.gen_num:03d}')
            sys.stdout.flush()
            matchup = self.matchups.get()
            matchup_lock.release()
            self.play_match(matchup, update_lock)

    def save_parents(self):
        if len(self.parents) != 0:
            # print('Saving Genomes of parents')
            genomes = list(map(lambda p: p['genome'], self.parents))
            dir_path = os.path.dirname(os.path.realpath(__file__))
            if not os.path.exists(os.path.join(dir_path, 'scratch')):
                os.mkdir(os.path.join(dir_path, 'scratch'))
            pickle_path = os.path.join(dir_path, 'scratch/genome.p')
            with open(pickle_path, 'wb') as genome_file:
                pickle.dump(genomes, genome_file)

    def init_parents(self):
        if self.gen_num == 1:
            try:
                dir_path = os.path.dirname(os.path.realpath(__file__))
                pickle_path = os.path.join(dir_path, 'scratch/genome.p')
                with open(pickle_path, 'rb') as genome_file:
                    genomes = pickle.load(genome_file)
                for genome in genomes:
                    self.parents.append(self.init_sample(genome))
            except FileNotFoundError:
                self.parents = []

    def run_parallel(self):
        for gen_num in tqdm(range(1, self.num_generations + 1)):
            self.gen_num = gen_num
            time.sleep(1)
            print(f'\nBEGINNING GENERATION {gen_num:03d}')
            self.init_parents()
            self.output_parent_genomes()
            self.generate_population()
            self.generate_matchups()
            self.num_matchups = len(self.matchups)
            matchup_lock = Lock()
            update_lock = Lock()
            temp = self.matchups
            self.matchups = Queue()
            for m in temp:
                self.matchups.put(m)
            processes = []
            for i in range(cpu_count()):
                processes.append(Process(target=self.do_work, args=(matchup_lock, update_lock)))
                processes[i].start()
            for i in range(cpu_count()):
                processes[i].join()
            print('\n')
            self.select_parents()
            self.save_parents()
            clear_screen()

    def run_tournament(self):
        for gen_num in tqdm(range(1, self.num_generations + 1)):
            self.gen_num = gen_num
            time.sleep(1)
            print(f'\nBEGINNING GENERATION {gen_num:03d}')
            self.init_parents()
            # self.output_parent_genomes()
            self.generate_population()
            matchup_count = Value('i', 0)
            while len(self.population) > self.num_parents:
                self.generate_tournament_mactchups()
                self.num_matchups = sum([2**i for i in range(int(math.log2(self.num_parents)), int(math.log2(self.population_size)))])
                matchup_lock = Lock()
                update_lock = Lock()
                temp = self.matchups
                self.matchups = Queue()
                for m in temp:
                    self.matchups.put(m)
                processes = []
                for i in range(cpu_count()):
                    processes.append(Process(target=self.do_work, args=(matchup_count, matchup_lock, update_lock)))
                    processes[i].start()
                for i in range(cpu_count()):
                    processes[i].join()
                self.population = sorted(self.population, key=lambda k: k['wins'], reverse=True)
                self.population = self.population[:len(self.population)//2]
            self.parents = self.population[:self.num_parents]
            self.save_parents()
            clear_screen()