def __init__(self, car, angle, x, y): # sensor itself self.direction_relative_to_car = angle self.position_relative_to_car = Point(x, y) self.direction = 0 self.position = Point(0, 0) self.sensor_line_id = None # connection to car self.car = car self.car.sensors.append(self)
def update(self): '''Update the car status (brain, sensors, position, speed, direction, ...).''' if self.isalive: self.brain.update() # update speed and direction self.speed = self.speed + self.acceleration self.direction = (self.direction + self.steeringwheel) % 360 # update position relativeposition = Point(0, self.speed).rotate(self.direction) self.position = self.position.move(relativeposition.x, -relativeposition.y) # update sensor for s in self.sensors: s.update() # check position if any([not self.track.intrack(*p) for p in self.points()]): #print("!!!!!!!!!!!!!OUT OF TRACK!!!!!!!!!!!!!") self.isalive = False self.canvas.itemconfig(self.canvas_shape_id, fill="black") elif self.track.ingoal(*self.position): #print("!!!!!!!!!!!!! WON !!!!!!!!!!!!!") self.isalive = False self.canvas.itemconfig(self.canvas_shape_id, fill="blue") self.acceleration = 0 self.steeringwheel = 0
def intersections(self, polynom, frompoint, topoint): '''Return intersections of the line (frompoint,topoint) with the polynom.''' points_of_shape = [Point(x,y) for x,y in [polynom[-1]] + polynom] points = [] for i in range(0,len(points_of_shape)-1): s = Line(frompoint, topoint).intersection(Line(points_of_shape[i], points_of_shape[i+1])) if s is not None: points.append(s) return points
def __init__(self, track, brain, color="red"): self.canvas = track.canvas self.canvas_shape_id = None self.track = track self.position = Point(*track.startpoint) self.direction = track.startdirection self.steeringwheel = 0 # -90 ... left, 0 ... forward, 90 ... right self.acceleration = 0 # -10 ... slow down, 0 ... keep, 10 ... speed up self.speed = 0 self.brain = brain self.color = color self.isalive = True self.sensors = [] self.brain.initialize(self)
def update(self): self.reward = 0 '''Update the car status (brain, sensors, position, speed, direction, ...).''' if self.isalive: self.brain.update() self.totalReward = self.totalReward - 0.1 self.reward -= 0.1 self.speed = self.speed + self.acceleration self.direction = (self.direction + self.steeringwheel) % 360 relativeposition = Point(0, self.speed).rotate(self.direction) self.position = self.position.move(relativeposition.x, -relativeposition.y) for s in self.sensors: s.update() self.distanceToCheckpoint = sqrt( (self.position.x - self.nextMiddlePoint[0]) * (self.position.x - self.nextMiddlePoint[0]) + (self.position.y - self.nextMiddlePoint[1]) * (self.position.y - self.nextMiddlePoint[1])) if self.distanceToCheckpoint < 100 and self.nextMiddlePointIndex < len( self.middlePoints[self.level - 1]): self.nextMiddlePoint = self.middlePoints[self.level - 1][ self.nextMiddlePointIndex] self.nextMiddlePointIndex = self.nextMiddlePointIndex + 1 self.totalReward = self.totalReward + 1 self.reward = self.reward + 1 # check position if any([not self.track.intrack(*p) for p in self.points()]): #print("!!!!!!!!!!!!!OUT OF TRACK!!!!!!!!!!!!!") self.totalReward = self.totalReward - 10 self.reward = self.reward - 10 self.isalive = False self.canvas.itemconfig(self.canvas_shape_id, fill="black") elif self.track.ingoal(*self.position): #print("!!!!!!!!!!!!! WON !!!!!!!!!!!!!") self.totalReward = self.totalReward + 10 self.reward = self.reward + 10 self.isalive = False self.canvas.itemconfig(self.canvas_shape_id, fill="blue") self.acceleration = 0 self.steeringwheel = 0
def measure(self): '''Measure distance to goal.''' x = self.car.position.x y = self.car.position.y min_distance = 9999 min_distance_point_on_midline = None min_distance_line_index = None midline_lines = [ Line(Point(*self.car.track.midline_points[i]), Point(*self.car.track.midline_points[i + 1])) for i in range(0, len(self.car.track.midline_points) - 1) ] for i in range(0, len(midline_lines)): l = Line( Point(x, y), Point(x, y).move(*Vector.from_points( *midline_lines[i]).normal_vector())) s = midline_lines[i].intersection(l, treat_as_line_segments=False) if s is not None and midline_lines[i].inline(s): d = Vector.from_points(Point(x, y), s).length() if min_distance > d: min_distance = d min_distance_point_on_midline = s min_distance_line_index = i # if outside of line use distance to endpoints ad = Vector.from_points(midline_lines[i].a, Point(x, y)).length() bd = Vector.from_points(midline_lines[i].b, Point(x, y)).length() if min_distance > ad: min_distance = ad min_distance_point_on_midline = midline_lines[i].a min_distance_line_index = i if min_distance > bd: min_distance = bd min_distance_point_on_midline = midline_lines[i].b min_distance_line_index = i # sum up distances distance = Vector.from_points( min_distance_point_on_midline, midline_lines[min_distance_line_index].b).length() for i in range(min_distance_line_index + 1, len(midline_lines)): distance = distance + midline_lines[i].length() return distance - 25 # remove length of goal area
def __init__(self, track, brain, level, color="red"): self.canvas = track.canvas self.canvas_shape_id = None self.track = track self.position = Point(*track.startpoint) self.direction = track.startdirection self.steeringwheel = 0 # -90 ... left, 0 ... forward, 90 ... right self.acceleration = 0 # -10 ... slow down, 0 ... keep, 10 ... speed up self.speed = 0 self.brain = brain self.color = color self.isalive = True self.sensors = [] self.brain.initialize(self) self.totalReward = 0.0 self.reward = 0.0 self.level = level self.middlePoints = [ # level 1 [(100, 535), (100, 100), (700, 100), (700, 500), (200, 500)], # level 2 [(72, 503), (82, 98), (662, 86), (653, 237), (368, 233), (358, 336), (643, 343), (636, 464), (203, 488), (205, 191)], # level 3 [(461, 127), (286, 301), (461, 408), (723, 143), (424, 18), (84, 295), (486, 562)], # level 4 [(24, 372), (129, 252), (220, 165), (272, 148), (321, 148), (386, 195), (429, 270), (446, 337), (481, 391), (532, 405), (604, 377), (646, 337), (679, 279), (747, 215)], # Level 5 [(166, 447), (136, 387), (136, 330), (148, 266), (180, 226), (223, 196), (285, 171), (352, 141), (436, 136), (510, 144), (561, 178), (602, 222), (623, 278), (626, 325), (620, 377), (586, 415), (526, 451), (446, 467), (360, 477)], # Level 6 [(152, 448), (144, 295), (166, 177), (236, 125), (342, 97), (505, 89), (629, 97), (704, 193), (700, 337), (692, 420), (629, 500), (548, 549), (415, 550), (296, 551), (253, 485), (252, 414), (268, 338), (296, 250), (370, 217), (428, 202), (520, 202), (577, 220), (605, 269), (587, 341), (548, 398), (486, 421), (384, 405)] ] self.nextMiddlePoint = self.middlePoints[self.level - 1][0] self.nextMiddlePointIndex = 0
def update(self): '''Update the position of the sensor and its measurements.''' # update direction self.direction = self.car.direction + self.direction_relative_to_car # update position relativesensor = self.position_relative_to_car.rotate( self.car.direction) self.position = self.car.position.move(relativesensor.x, -relativesensor.y) # update distance & obstacle relativeray = Point(0, 1000).rotate(self.direction) ray = self.position.move(relativeray.x, -relativeray.y) nearest_point_meassured = self.measure(self.car.track.shapes(), self.position, ray) if nearest_point_meassured is None: self.distance = 1000 self.obstacle = None else: self.obstacle, self.distance = nearest_point_meassured self.is_obstacle_goal = self.car.track.ingoal(*self.obstacle)
def points(self): '''Points of the car shape.''' return [(self.position.x + x, self.position.y - y) for x, y in [Point(x, y).rotate(self.direction) for x, y in self._shape]]
def calculate_points(self,midline_points): '''Calculate the track shape, goal and start point based on the provided midline points.''' inner_lines = [] outer_lines = [] # create inner/outer lines for i in range(0, len(midline_points)-1): a = Point(*midline_points[i]) b = Point(*midline_points[i+1]) v = Vector.from_points(a, b) left_vector = v.normal_vector(direction='left').normalize().multiply(self.track_width) right_vector = v.normal_vector(direction='right').normalize().multiply(self.track_width) outer_line = Line(a.move(left_vector.x, left_vector.y), b.move(left_vector.x, left_vector.y)) inner_line = Line(a.move(right_vector.x, right_vector.y), b.move(right_vector.x, right_vector.y)) inner_lines.append(inner_line) outer_lines.append(outer_line) self.lines = outer_lines + [Line(inner_lines[-1].b, outer_lines[-1].b)] + list(reversed(inner_lines)) + [Line(inner_lines[0].a, outer_lines[0].a)] # intersect lines lines_points = [] for i in range(0, len(self.lines) - 1): l1 = self.lines[i] l2 = self.lines[i+1] s = l1.intersection(l2, treat_as_line_segments=False) lines_points.append(s) # points of track self.points = [self.lines[0].a] + lines_points + [self.lines[-1].b] # start point (25 from start) self.startpoint = Point(*Vector.from_points(Point(*midline_points[0]), Point(*midline_points[1])).normalize().multiply(25)).move(*midline_points[0]) # start direction startvector = Vector.from_points(Point(*midline_points[0]), Point(*midline_points[1])).normalize() self.startdirection = startvector.angle(Vector(0,1)) self.startdirection = -(180-self.startdirection) if startvector.x <= 0 else 180 - self.startdirection # end polynom end_vector = Vector.from_points(Point(*midline_points[-1]), Point(*midline_points[-2])).normalize() end_vector_left = end_vector.normal_vector(direction='left').multiply(self.track_width*0.80) end_vector_right = end_vector.normal_vector(direction='right').multiply(self.track_width*0.80) self.endpoint = Point(*end_vector.multiply(25)).move(*midline_points[-1]) self.endarea_points = [ Point(*midline_points[-1]).move(*end_vector_left).astuple(), self.endpoint.move(*end_vector_left).astuple(), self.endpoint.move(*end_vector_right).astuple(), Point(*midline_points[-1]).move(*end_vector_right).astuple() ]