def _get_sensor_array_template(self): """create the template for the sensor array """ logg = getMyLogger(f"c.{__class__.__name__}._get_sensor_array_template") logg.debug(f"Start _get_sensor_array_template") # create a grid # self.viewfield_size = 101 self.viewfield_size = 301 self.viewfield_step = 10 # self.viewfield_step = 25 # self.viewfield_step = 33 sat = [] for i in range(0, self.viewfield_size, self.viewfield_step): for j in range(0, self.viewfield_size, self.viewfield_step): sat.append((i, j)) sat = np.array(sat).transpose() logg.debug(f"shape sensor_array_template {sat.shape}") # rotate the array so that is a diamond rot_mat = compute_rot_matrix(-45) sat = np.matmul(rot_mat, sat) # logg.debug(f"sat {sat}") logg.debug(f"shape sensor_array_template {sat.shape}") return sat
def _draw_sensor_array(self, obs=None): """draw the sensor_array on a Surface """ logg = getMyLogger(f"c.{__class__.__name__}._draw_sensor_array") logg.debug(f"Start _draw_sensor_array") # create the new surface for the sensor_array self.sa_surf = pygame.Surface(self.field_size) # self.sa_surf = self.sa_surf.convert() black = (0, 0, 0) self.sa_surf.fill(black) # black colors will not be blit self.sa_surf.set_colorkey(black) the_color = (0, 255, 0, 128) the_second_color = (0, 0, 255, 128) color = the_color the_size = 3 for i, s_pos in enumerate(self.curr_sa): if not obs is None: if obs[i] == 1: color = the_second_color else: color = the_color pygame.draw.circle(self.sa_surf, color, s_pos, the_size)
def _compute_reward(self): """ """ logg = getMyLogger(f"c.{__class__.__name__}._compute_reward") logg.debug(f"Start _compute_reward") # compute collision car/road hits = spritecollide(self.racer_car, self.racer_map, dokill=False) logg.debug(f"hitting {hits}") hit_directions = [] hit_sid = [] for segment in hits: logg.debug(f"hit segment with id {segment.sid}") hit_directions.append(self.racer_map.seg_info[segment.sid][0]) hit_sid.append(segment.sid) # out of the map if len(hit_directions) == 0: return 0, True # too many hits, your road is weird, cap them at 2 segments elif len(hit_directions) > 2: logg.warn(f"Too many segments hit") hit_directions = hit_directions[:2] hit_sid = hit_sid[:2] # now hit_directions is either 1 or 2 elements long if len(hit_directions) == 1: mean_direction = hit_directions[0] else: # 135 90 45 140 95 50 130 85 40 # 180 0 185 5 175 -5 # 225 270 315 230 275 320 220 265 310 # 270, 0 have mean 315 = (270+0+360)/2 # 270, 180 have mean 225 = (270+180)/2 # 0, 90 have mean 45 = (0+90)/2 if abs(hit_directions[0] - hit_directions[1]) > 180: mean_direction = (sum(hit_directions) + 360) / 2 if mean_direction >= 360: mean_direction -= 360 else: mean_direction = sum(hit_directions) / 2 logg.debug(f"mean_direction {mean_direction}") error = self.racer_car.direction - mean_direction logg.debug(f"direction-mean {error}") # error %= 360 if error < 0: error += 360 logg.debug(f"modulus {error}") if error > 180: error = 360 - error logg.debug( f"current direction {self.racer_car.direction} has error of {error:.4f}" ) reward = 90 - error # MAYBE a sigmoid-like shape return reward, False
def run_racer_new(args): """ """ logg = getMyLogger(f"c.{__name__}.run_racer_new") logg.debug(f"Start run_racer_new") template_images = args.template_images fps = args.fps # clock for interactive play clock = pygame.time.Clock() field_wid = 900 field_hei = 900 racer_env = RacerEnv(field_wid, field_hei, template_images) # Main Loop going = True while going: clock.tick(fps) logg.debug(f" New frame") # Handle Input Events # https://stackoverflow.com/a/22099654 for event in pygame.event.get(): logg.debug(f"Handling event {event}") if event.type == pygame.QUIT: going = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: going = False logg.debug(f"Done handling") keys = pygame.key.get_pressed() if keys[pygame.K_d]: racer_env.step("right") elif keys[pygame.K_a]: racer_env.step("left") elif keys[pygame.K_w]: racer_env.step("up") elif keys[pygame.K_x]: racer_env.step("down") elif keys[pygame.K_q]: racer_env.step("upleft") elif keys[pygame.K_e]: racer_env.step("upright") elif keys[pygame.K_z]: racer_env.step("downleft") elif keys[pygame.K_c]: racer_env.step("downright") else: racer_env.step("nop")
def rotate_image(self, direction): """Rotate the image segment """ logg = getMyLogger(f"c.{__name__}.__init__", "INFO") # self.image = rotate(self.orig_image, 360 - direction) self.image = rotate(self.orig_image, direction) self.rect = self.image.get_rect(center=(self.cx, self.cy)) logg.debug( f"lefttop {self.rect.topleft} rightbottom {self.rect.bottomright}") logg.debug(f"width {self.rect.width} height {self.rect.height}")
def __init__(self, field_wid, field_hei, template_images): logg = getMyLogger(f"c.{__class__.__name__}.__init__") logg.debug(f"Start init") self.template_images = template_images self.field_wid = field_wid self.field_hei = field_hei self.field_size = (self.field_wid, self.field_hei) self.sidebar_wid = 300 self.sidebar_hei = self.field_hei self.sidebar_size = (self.sidebar_wid, self.sidebar_hei) self.total_wid = self.sidebar_wid + self.field_wid self.total_hei = self.field_hei self.total_size = (self.total_wid, self.total_hei) pygame.init() self.screen = pygame.display.set_mode(self.total_size) pygame.display.set_caption("Racer") # Create The playing field self.field = pygame.Surface(self.field_size) # convert() changes the pixel format # https://www.pygame.org/docs/ref/surface.html#pygame.Surface.convert self.field = self.field.convert() # self.field.fill((250, 250, 250)) self.field.fill((0, 0, 0)) # draw the field on the screen self.screen.blit(self.field, (0, 0)) # Put Text On The field, Centered if not pygame.font: logg.critical("You need fonts to put text on the screen") # create a new Font object (from a file if you want) self.main_font = pygame.font.Font(None, 36) self.setup_sidebar() self.racer_car = RacerCar(self.template_images, 100, 100) self.racer_map = RacerMap(self.template_images, self.field_wid, self.field_hei) # draw map on the field, it is static, so there is no need to redraw it every time self.racer_map.draw(self.field) self.allsprites = pygame.sprite.RenderPlain((self.racer_car))
def _precompute_map(self): """turn the map into a np array """ logg = getMyLogger(f"c.{__name__}._precompute_map", "DEBUG") logg.debug(f"Start _precompute_map") self.raw_map = np.zeros((self.field_wid, self.field_hei), dtype=np.uint8) for i in self.segments: rect = self.segments[i].rect logg.debug(f"rect {rect}") logg.debug( f" left {rect.left} right {rect.right} top {rect.top} bottom {rect.bottom} " ) self.raw_map[rect.left:rect.right, rect.top:rect.bottom] = 1
def _create_car_sensors(self): """create the array of sensors, and rotate it for all possible directions """ logg = getMyLogger(f"c.{__class__.__name__}._create_car_sensors") logg.debug(f"Start _create_car_sensors") sensor_array_template = self._get_sensor_array_template() # return sensor_array_template self.all_sensor_array = {} for dire in range(0, 360, self.dir_step): rot_mat = compute_rot_matrix(360-dire) rotated_sa = np.matmul(rot_mat, sensor_array_template) # self.all_sensor_array[dire] = rotated_sa.transpose() int_sa = np.array(rotated_sa, dtype=np.int16) self.all_sensor_array[dire] = int_sa.transpose()
def __init__(self, out_file_road, direction, cx, cy, sid): logg = getMyLogger(f"c.{__name__}.__init__", "INFO") logg.debug(f"Start init") super().__init__() self.out_file_road = out_file_road self.orig_image, self.rect = load_image(self.out_file_road) self.direction = direction self.cx = cx self.cy = cy # save a segment id self.sid = sid self.rotate_image(self.direction)
def get_screen(self): """a square with the car in the corner, looking to the diagonal """ logg = getMyLogger(f"c.{__class__.__name__}.get_screen") logg.debug(f"Start get_screen") self.viewfield_size = 100 pos_car = self.racer_car.pos_x, self.racer_car.pos_y vf_cos = cos( radians(360 - self.racer_car.direction - 45)) * self.viewfield_size vf_sin = sin( radians(360 - self.racer_car.direction - 45)) * self.viewfield_size # positions of the corners of the viewfield pos_left = int(pos_car[0] + vf_cos), int(pos_car[1] + vf_sin) pos_right = int(pos_car[0] - vf_sin), int(pos_car[1] + vf_cos) pos_front = int(pos_car[0] + vf_cos - vf_sin), int(pos_car[1] + vf_cos + vf_sin)
def _update_display(self): """draw everything """ logg = getMyLogger(f"c.{__class__.__name__}._update_display") logg.debug(f"Start _update_display") # Draw Everything again, every frame # the field already has the road drawn self.screen.blit(self.field, (0, 0)) # draw all moving sprites (the car) on the screen self.allsprites.draw(self.screen) # if you draw on the field you can easily leave a track # allsprites.draw(field) # draw the sensor surface self.screen.blit(self.sa_surf, (0, 0)) # update the display pygame.display.flip()
def _create_road_segment(self): """Create the bmp for a road segment """ logg = getMyLogger(f"c.{__name__}._create_road_segment") self.size = 350, 150 # img1 = Image.new("RGBA", self.size, "grey") img1 = Image.new("RGBA", self.size, (128, 128, 128, 128)) draw = ImageDraw.Draw(img1) line_wid = 2 mid_hei = self.size[1] // 2 draw.rectangle( ((0, mid_hei - line_wid), (self.size[0], mid_hei + line_wid)), fill="lightgrey", ) draw.rectangle( ((self.size[0] - line_wid * 2, 0), (self.size[0], self.size[1])), fill="lightgrey", ) img1.save(self.out_file_road, "bmp")
def step(self, action): """Perform the action left-rigth: change steering up-down: accelerate/brake combination of the above do nothing ---------- This method steps the game forward one step Parameters ---------- action : str MAYBE should be int anyway Returns ------- ob, reward, episode_over, info : tuple ob (object) : an environment-specific object representing the state of the environment. reward (float) : amount of reward achieved by the previous action. episode_over (bool) : whether it's time to reset the environment again. info (dict) : diagnostic information useful for debugging. """ logg = getMyLogger(f"c.{__class__.__name__}.step") logg.debug(f"Start step {action}") self.racer_car.step(action) reward, done = self._compute_reward() # view = self.get_sensors() view = self._get_sensor_array() self._update_display()
def __init__(self, template_images, field_wid, field_hei): logg = getMyLogger(f"c.{__name__}.__init__", "INFO") logg.debug(f"Start init") super().__init__() self.field_wid = field_wid self.field_hei = field_hei self.template_images = template_images name_road_image = "road.bmp" self.out_file_road = self.template_images.format(name_road_image) self._create_road_segment() # self.orig_image, self.rect = load_image(self.out_file_road) # direction, centerx, centery self.seg_info = [ [0, 200, 100], [270, 450, 200], [0, 550, 450], [270, 800, 550], [180, 700, 800], [180, 350, 800], [90, 100, 700], [90, 100, 350], ] self.segments = {} self.num_segments = len(self.seg_info) # create the various segments for i in range(self.num_segments): # self.seg_img[i], self.seg_rect[i] = Segment(self.out_file_road) direction, cx, cy = self.seg_info[i] self.segments[i] = Segment(self.out_file_road, direction, cx, cy, i) self.add(self.segments[i]) self._precompute_map()
def _get_sensor_array(self): """get the sa for the current direction and collide it with the road """ logg = getMyLogger(f"c.{__class__.__name__}._get_sensor_array") logg.debug(f"Start _get_sensor_array") # get the current sensor_array to use self.curr_sa = self.racer_car.get_current_sensor_array() logg.debug(f"shape curr_sa {self.curr_sa.shape}") obs = [] for s_pos in self.curr_sa: # logg.debug(f"s_pos {s_pos}") if (s_pos[0] < 0 or s_pos[0] >= self.field_wid or s_pos[1] < 0 or s_pos[1] >= self.field_hei): obs.append(0) else: obs.append(self.racer_map.raw_map[s_pos[0], s_pos[1]]) # logg.debug(f"obs {obs}") # draw the array on the sa_surf self._draw_sensor_array(obs) return obs
# Licensed under the terms of the BSD 3-Clause. import json import gtk import shutil import sys import os import urllib2 import uuid from mainwindow import MainWindow import tray import utils from utils import getMyLogger logger = getMyLogger("webapp") def loadClass(confList, default): if confList is None: return default try: modName, clsName = confList return getattr(__import__(modName), clsName) except: logger.error("Cannot load specified module or class") raise class WebApp():