def test_directional_sensors(): a = Animat() lx, ly = 0.5, 0.5 # obj position o = Obj(lx, ly, 'default') a.add_obj(o) res = np.linspace(0, 1, 50) mesh = np.meshgrid(res, res) def f(coords): a.x = coords[0] a.y = coords[1] a.update_sensors() return a.sensors['default'][Sides.LEFT] zs = np.apply_along_axis(f, 0, mesh) imshow(zs, extent=[0, 1, 0, 1], origin='lower') plot(lx, ly, 'wo', label='object') xlabel('animat position') ylabel('animat position') title('Animat is facing to the right') legend() show()
def test_animat_no_controller(): for n_animats in range(10): duration = 50.0 DT = 0.02 iterations = int(np.round(duration / DT)) animat = Animat() animat.x = np.random.randn() animat.y = np.random.randn() animat.a = np.random.rand() * np.pi * 2.0 obj = Obj(0, 0, 'default') animat.add_obj(obj) for iteration in range(iterations): animat.calculate_derivative() animat.euler_update(DT=DT) left_sensor = animat.sensors['default'][Sides.LEFT] right_sensor = animat.sensors['default'][Sides.RIGHT] # print(f'l:{left_sensor}\t r:{right_sensor}') # animat.lm = 0.4 # animat.rm = 0.5 animat.lm = left_sensor * 5 animat.rm = right_sensor * 5 plot(animat.x_h, animat.y_h, ',') plot(animat.x_h[-1], animat.y_h[-1], 'ko', ms=3) plot(-999, -999, 'k.', label='Aniamt Final Position') plot(0, 0, ',', label='Animat Trajectory') plot(0, 0, 'rx', label='Object Position') xlim(-3, 3) ylim(-3, 3) legend() gca().set_aspect('equal') show()
def simulate_trial(controller, trial_index, generating_animation=False): # seed for environment for this generation np.random.seed(generation_index * 10 + trial_index) current_t = 0.0 score = 0.0 animat = Animat() animat.x = 0.0 animat.y = 0.0 animat.a = 0.0 controller.trial_data = {} foods = [] waters = [] traps = [] n = {ObjTypes.FOOD: 2, ObjTypes.WATER: 2, ObjTypes.TRAP: 2} for obj_type in ObjTypes: for _ in range(n[obj_type]): x, y = random_obj_position(animat) obj = Obj(x, y, obj_type) animat.add_obj(obj) if obj_type == ObjTypes.FOOD: foods.append(obj) if obj_type == ObjTypes.WATER: waters.append(obj) if obj_type == ObjTypes.TRAP: traps.append(obj) food_bat = 1.0 water_bat = 1.0 controller.trial_data['sample_times'] = [] controller.trial_data['water_battery_h'] = [] controller.trial_data['food_battery_h'] = [] controller.trial_data['score_h'] = [] controller.trial_data['eaten_FOOD_positions'] = [] controller.trial_data['eaten_WATER_positions'] = [] controller.trial_data['eaten_TRAP_positions'] = [] controller.trial_data['FOOD_positions'] = [] controller.trial_data['WATER_positions'] = [] controller.trial_data['TRAP_positions'] = [] for iteration in range(N_STEPS): # battery states for plotting controller.trial_data['sample_times'].append(current_t) controller.trial_data['water_battery_h'].append(water_bat) controller.trial_data['food_battery_h'].append(food_bat) controller.trial_data['score_h'].append(score) if generating_animation: # used in animation controller.trial_data['FOOD_positions'].append([(l.x, l.y) for l in foods]) controller.trial_data['WATER_positions'].append([(l.x, l.y) for l in waters]) controller.trial_data['TRAP_positions'].append([(l.x, l.y) for l in traps]) current_t += DT # drain battery states DRAIN_RATE = 0.2 water_bat = water_bat - DT * DRAIN_RATE food_bat = food_bat - DT * DRAIN_RATE # if going faster drains more battery # water_b -= (animat.lm**2) * DT * 0.01 # food_b -= (animat.rm**2) * DT * 0.01 score += (water_bat * food_bat) * DT # pass sensor states to controller for obj_type in ObjTypes: controller.set_sensor_states(obj_type, animat.sensors[obj_type]) # set animat motor states with controller calculations animat.lm, animat.rm = controller.get_motor_output( (food_bat, water_bat)) animat.calculate_derivative() # calculate changes animat.euler_update(DT=DT) # apply changes # check for FOOD collisions for food in animat.objs[ObjTypes.FOOD]: if (animat.x - food.x)**2 + (animat.y - food.y)**2 < Obj.RADIUS**2: food_bat += 20.0 * DT controller.trial_data['eaten_FOOD_positions'].append( (food.x, food.y)) food.x, food.y = random_obj_position(animat) # relocate entity # check for WATER collisions for water in animat.objs[ObjTypes.WATER]: if (animat.x - water.x)**2 + (animat.y - water.y)**2 < Obj.RADIUS**2: water_bat += 20.0 * DT controller.trial_data['eaten_WATER_positions'].append( (water.x, water.y)) water.x, water.y = random_obj_position( animat) # relocate entity # check for TRAP collisions for trap in animat.objs[ObjTypes.TRAP]: if (animat.x - trap.x)**2 + (animat.y - trap.y)**2 < Obj.RADIUS**2: food_bat -= 50.0 * DT water_bat -= 50.0 * DT score = 0.0 controller.trial_data['eaten_TRAP_positions'].append( (trap.x, trap.y)) trap.x, trap.y = random_obj_position(animat) # relocate entity # DEATH -- if either of the batteries reaches 0, the trial is over if food_bat < 0.0 or water_bat < 0.0: food_bat = water_bat = 0.0 break # position of entities still not eaten at end of trial (used for plotting) controller.trial_data['uneaten_FOOD_positions'] = [ (l.x, l.y) for l in animat.objs[ObjTypes.FOOD] ] controller.trial_data['uneaten_WATER_positions'] = [ (l.x, l.y) for l in animat.objs[ObjTypes.WATER] ] controller.trial_data['uneaten_TRAP_positions'] = [ (l.x, l.y) for l in animat.objs[ObjTypes.TRAP] ] controller.trial_data['animat'] = animat if TEST_GA: # simple GA test -- maximise genome score = np.mean(controller.genome) return score