def test_location(self): loc = Location(10, 20) self.assertEqual('location', loc.isa) self.assertEqual(10, loc.x) self.assertEqual(20, loc.y) loc.move(50, 60) self.assertEqual(50, loc.x) self.assertEqual(60, loc.y) loc2 = Location(30, 40, 'loc') self.assertEqual('loc', loc2.get('isa')) self.assertAlmostEqual(28.28, loc2.distance_to(loc), 2)
class Eyes(Module): def __init__(self, agent): super().__init__('eyes', agent) self.vision = None self.loc = Location(0, 0) self.last_prep_cancel = None self.fixate_fns = [] self.enc_time_f = .001 self.enc_time_exp = .4 self.prep_time = .150 self.exec_time_base = .070 self.exec_time_inc = .002 def set_vision(self, vision): self.vision = vision def add_fixate_fn(self, fn): self.fixate_fns.append(fn) def move_to(self, x, y): self.loc = Location(x, y) def _compute_eccentricity(self, visual): return self.vision.display.pixels_to_degrees( self.loc.distance_to(visual)) def compute_enc_time(self, visual): freq = visual.freq if freq is not None: return (self.enc_time_f * -math.log(freq) * math.exp( self.enc_time_exp * self._compute_eccentricity(visual))) else: return self.vision.default_enc_time def _rand_time(self, time): return max(time + random.gauss(0, time / 3), .001) def prepare(self, visual, enc_start, enc_dur): if self.last_prep_cancel is not None: self.last_prep_cancel.try_cancel() sd = .1 * \ self.vision.display.degrees_to_pixels( self._compute_eccentricity(visual)) new_loc = Location(visual.x + random.gauss(0, sd), visual.y + random.gauss(0, sd)) self.log('prepare {}'.format(new_loc)) duration = self._rand_time(self.prep_time) def fn(): self.move(visual, new_loc, enc_start, enc_dur) self.last_prep_cancel = self.run_thread_can_cancel(fn, duration) def move(self, visual, new_loc, enc_start, enc_dur): self.log('move {}'.format(new_loc)) duration = self._rand_time( self.exec_time_base ) + self.exec_time_inc * self._compute_eccentricity(visual) def fn(): self.log('moved {}'.format(new_loc)) self.loc = new_loc if enc_start + enc_dur > self.time(): completed = (self.time() - enc_start) / enc_dur new_time = self.compute_enc_time(visual) rem_dur = (1 - completed) * new_time if rem_dur > 0: self.vision.start_encode_thread(visual, rem_dur) self.prepare(visual, self.time(), rem_dur) self.vision.display.set_eye(self.loc) for fn in self.fixate_fns: fn(self.loc) self.run_thread(fn, duration)