diff --git a/car.py b/car.py new file mode 100644 index 0000000..3272945 --- /dev/null +++ b/car.py @@ -0,0 +1,138 @@ +import numpy as np +import pygame + +from brain import Neural_Network +from params import GY, CAR_SIZE, VISION_LENGTH, VISION_SPAN, THROTTLE_POWER, screen +from trigo import angle_to_vector, get_line_feats, segments_intersection, distance + +IMG = pygame.image.load("car20.png")#.convert() + + +class Car(pygame.sprite.Sprite): + def __init__(self): + pygame.sprite.Sprite.__init__(self) + self.top_surface = pygame.Surface((CAR_SIZE, CAR_SIZE)) + self.original_image = IMG + # self.image = pygame.Surface((CAR_SIZE, CAR_SIZE)) + # self.image.fill((0,255,0)) + # self.original_image = self.image + + self.image = self.original_image + + self.rect = self.image.get_rect() + self.rect.center = (75, GY -50) + self.speed = 1 + self.heading = 0 + self.heading_change = 0 + self.vision_length = VISION_LENGTH # line liength + self.vision_span = VISION_SPAN # degrees + self.draw_sensors = True + + # lets add 3 sensors as a start + # 1 straight ahead + # 2 left 15° + # 3 right 15 ° + # we will give each of them a max lenght to + # and we will eventually detect any line crossing the sensor and + # retain the min value as a distance to collision input + self.center_sensor = None + self.left_sensor = None + self.right_sensor = None + self.sensors = [self.left_sensor, self.center_sensor, self.right_sensor] + self.probes = [self.vision_length] *3 + + self.brain = Neural_Network() + + self.update_sensors() + self.probe_brain() + self.run = True + + + def update_sensors(self): + center = self.rect.center + vc = angle_to_vector(self.heading) + self.center_sensor = [center, (int(self.vision_length * vc[0] + center[0]), int(-self.vision_length * vc[1] + center[1]))] + + vl = angle_to_vector(self.heading+self.vision_span) + self.left_sensor = [center, (int(self.vision_length * vl[0] + center[0]), int(-self.vision_length * vl[1] + center[1]))] + + vr = angle_to_vector(self.heading-self.vision_span) + self.right_sensor = [center, (int(self.vision_length * vr[0] + center[0]), int(-self.vision_length * vr[1] + center[1]))] + + + def update_position(self): + vec = angle_to_vector(self.heading) + old_center = self.rect.center + self.rect.center = (self.speed * vec[0] / 2 + old_center[0], -self.speed * vec[1] / 2 + old_center[1]) + self.update_sensors() + + + + def probe_lines_proximity(self, lines): + # print(self.center_sensor, lines[0]) + self.probes = [self.vision_length*2] *3 + for idx,sensor in enumerate([self.left_sensor, self.center_sensor, self.right_sensor]) : + for line in lines : + ip = segments_intersection(sensor, line) + # print(ip) + if ip : + pygame.draw.circle(screen, (125,125,255), ip, 4, 2) + dist = int(distance(ip,self.rect.center)) + self.probes[idx] = min(dist, self.probes[idx]) + if dist < 1.2 * self.speed or self.speed < 0.01 : + self.run = False + print(f'Car {id(self)} crashed') + + # else : + # self.probes[idx] = self.vision_length * 2 + # print(self.probes) + + + def probe_brain(self): + res = self.brain.predict(np.array(self.probes)) + self.heading_change = res[0] * 10 + self.throttle = res[1] * 10 + + + def update(self): + # rotate + old_center = self.rect.center + self.image = pygame.transform.rotate(self.original_image, self.heading) + self.rect = self.image.get_rect() + self.rect.center = old_center + self.update_position() + if self.speed < 0.01 : + self.run = False + print(f'Car {id(self)} crashed') + print( + 'id', id(self), + 'Speed', self.speed, + 'heading', self.heading, + 'throttle', self.throttle, + 'heading change', self.heading_change, + ) + + if self.speed : + self.heading += self.heading_change * 10 / self.speed + self.heading = self.heading % 360 + + self.speed += self.throttle #THROTTLE_POWER + # if self.throttle : + # self.speed += self.throttle #THROTTLE_POWER + # else : + # self.speed -= self.throttle #THROTTLE_POWER + + self.speed = max(0, self.speed) + self.speed = min(self.speed, 7) + + super().update() + + + def show_features(self): + if self.draw_sensors: + pygame.draw.line(screen, (255,0,0), self.center_sensor[0], self.center_sensor[1]) + pygame.draw.line(screen, (0,255,0), self.left_sensor[0], self.left_sensor[1]) + pygame.draw.line(screen, (0,0,255), self.right_sensor[0], self.right_sensor[1]) + pygame.draw.circle(screen, (125,255,125), self.rect.center, 4, 2) + + diff --git a/car20.png b/car20.png new file mode 100644 index 0000000..390690c Binary files /dev/null and b/car20.png differ diff --git a/car25.png b/car25.png deleted file mode 100644 index cc3bae4..0000000 Binary files a/car25.png and /dev/null differ diff --git a/main.py b/main.py index d5a922d..ab10a35 100755 --- a/main.py +++ b/main.py @@ -2,165 +2,22 @@ import math import pygame import random -import numpy as np -from brain import Neural_Network +from car import Car from maps import map1 -from trigo import angle_to_vector, get_line_feats, segments_intersection, distance -from params import FLAGS, GX, GY, CELL_COLOR, CAR_SIZE, VISION_LENGTH, VISION_SPAN, THROTTLE_POWER - - - -pygame.init() -IMG = pygame.image.load("car25.png")#.convert() - - - - - -class Car(pygame.sprite.Sprite): - def __init__(self): - pygame.sprite.Sprite.__init__(self) - self.top_surface = pygame.Surface((CAR_SIZE, CAR_SIZE)) - self.original_image = IMG - # self.image = pygame.Surface((CAR_SIZE, CAR_SIZE)) - # self.image.fill((0,255,0)) - # self.original_image = self.image - - self.image = self.original_image - - self.rect = self.image.get_rect() - self.rect.center = (75, GY -50) - self.speed = 1 - self.heading = 0 - self.heading_change = 0 - self.vision_length = VISION_LENGTH # line liength - self.vision_span = VISION_SPAN # degrees - self.draw_sensors = True - - # lets add 3 sensors as a start - # 1 straight ahead - # 2 left 15° - # 3 right 15 ° - # we will give each of them a max lenght to - # and we will eventually detect any line crossing the sensor and - # retain the min value as a distance to collision input - self.center_sensor = None - self.left_sensor = None - self.right_sensor = None - self.sensors = [self.left_sensor, self.center_sensor, self.right_sensor] - self.probes = [self.vision_length] *3 - - self.brain = Neural_Network() - - self.update_sensors() - self.probe_brain() - self.run = True - - - def update_sensors(self): - center = self.rect.center - vc = angle_to_vector(self.heading) - self.center_sensor = [center, (int(self.vision_length * vc[0] + center[0]), int(-self.vision_length * vc[1] + center[1]))] - - vl = angle_to_vector(self.heading+self.vision_span) - self.left_sensor = [center, (int(self.vision_length * vl[0] + center[0]), int(-self.vision_length * vl[1] + center[1]))] - - vr = angle_to_vector(self.heading-self.vision_span) - self.right_sensor = [center, (int(self.vision_length * vr[0] + center[0]), int(-self.vision_length * vr[1] + center[1]))] - - - def update_position(self): - vec = angle_to_vector(self.heading) - old_center = self.rect.center - self.rect.center = (self.speed * vec[0] + old_center[0], -self.speed * vec[1] + old_center[1]) - self.update_sensors() - - - - def probe_lines_proximity(self, lines): - # print(self.center_sensor, lines[0]) - self.probes = [self.vision_length*2] *3 - for idx,sensor in enumerate([self.left_sensor, self.center_sensor, self.right_sensor]) : - for line in lines : - ip = segments_intersection(sensor, line) - # print(ip) - if ip : - pygame.draw.circle(screen, (125,125,255), ip, 4, 2) - dist = int(distance(ip,self.rect.center)) - self.probes[idx] = min(dist, self.probes[idx]) - if dist < 1.2 * self.speed or self.speed < 0.01 : - self.run = False - print(f'Car {id(self)} crashed') - - # else : - # self.probes[idx] = self.vision_length * 2 - # print(self.probes) - - - def probe_brain(self): - res = self.brain.predict(np.array(self.probes)) - self.heading_change = res[0] * 10 - self.throttle = res[1] * 10 - - - def update(self): - # rotate - old_center = self.rect.center - self.image = pygame.transform.rotate(self.original_image, self.heading) - self.rect = self.image.get_rect() - self.rect.center = old_center - self.update_position() - if self.speed < 0.01 : - self.run = False - print(f'Car {id(self)} crashed') - print( - 'id', id(self), - 'Speed', self.speed, - 'heading', self.heading, - 'throttle', self.throttle, - 'heading change', self.heading_change, - ) - - if self.speed : - self.heading += self.heading_change * 20 / self.speed - self.heading = self.heading % 360 - - self.speed += self.throttle #THROTTLE_POWER - # if self.throttle : - # self.speed += self.throttle #THROTTLE_POWER - # else : - # self.speed -= self.throttle #THROTTLE_POWER - - self.speed = max(0, self.speed) - - super().update() - - - def show_features(self): - if self.draw_sensors: - pygame.draw.line(screen, (255,0,0), self.center_sensor[0], self.center_sensor[1]) - pygame.draw.line(screen, (0,255,0), self.left_sensor[0], self.left_sensor[1]) - pygame.draw.line(screen, (0,0,255), self.right_sensor[0], self.right_sensor[1]) - pygame.draw.circle(screen, (125,255,125), self.rect.center, 4, 2) - - +from params import CELL_COLOR, screen #https://medium.com/intel-student-ambassadors/demystifying-genetic-algorithms-to-enhance-neural-networks-cde902384b6e -screen = pygame.display.set_mode((GX, GY), FLAGS) -screen.set_alpha(None) - map_lines = map1 -# print(lines) all_cars = pygame.sprite.Group() -for x in range(10): +for x in range(100): car = Car() car.heading = x * 30 + 35 all_cars.add(car) @@ -182,9 +39,6 @@ while running_cars : for line in map_lines : pygame.draw.line(screen, (255,255,255), line[0], line[1]) - # point = (int(GX/2), int(GY/2+25)) - # print(distance(point, car2.rect.center)) - # pygame.draw.circle(screen, (125,255,125), point, 4, 2) pygame.display.flip() clock.tick(24) diff --git a/params.py b/params.py index 79dfa8c..0f87ff5 100644 --- a/params.py +++ b/params.py @@ -1,3 +1,4 @@ +import pygame from pygame.locals import HWSURFACE, DOUBLEBUF FLAGS = HWSURFACE | DOUBLEBUF #| FULLSCREEN @@ -5,7 +6,11 @@ FLAGS = HWSURFACE | DOUBLEBUF #| FULLSCREEN GX = 1000 GY = 1000 CELL_COLOR = (80,80,80) -CAR_SIZE=25 +CAR_SIZE=20 VISION_LENGTH = 50 VISION_SPAN = 25 # degrees -THROTTLE_POWER = 3 \ No newline at end of file +THROTTLE_POWER = 3 + +pygame.init() +screen = pygame.display.set_mode((GX, GY), FLAGS) +screen.set_alpha(None)