def __init__(self, logdata=True): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2)) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None # Setup the PyTorch model and load the weights self.model = simpleNetV3() weights = 'simpleNetV3_lr=0.01_epoch_1_all_tracks.csv.pkl' self.model.load_state_dict(torch.load(weights)) # Initialize inputs, counters and history self.input = torch.zeros(D_in) self.crashCounter = 0 self.reverseCounter = 0 self.forwardCounter = 0 self.resetGear = False self.crashed = False self.counter = 0 self.name = '3001' self.history = np.zeros((5, 2), dtype=float) # Initialize SWARM self.pheromones = [] pickle.dump(self.pheromones, open("sent_3001.txt", "wb")) self.straight_begin = 0 self.straight_end = 0 self.list_straight = [] self.list_corner = [] self.received = [] self.list_average_corner = []
def __init__(self, logdata=True): # filenames = ['aalborg.csv', 'alpine-1.csv', 'f-speedway.csv', 'data_track_2.csv'] #filenames = ['aalborg.csv', 'alpine-1.csv', 'f-speedway.csv'] filenames = ['forza_urja.csv', 'newdata5.csv', 'aalborg_urja.csv'] #, 'aalborg_urja.csv', 'aalborg_urja_vx80.csv'] #filenames = ['aalborg_new.csv', 'forza_new.csv'] data, labels = helper_functions.readData(filenames) # self.network = do_the_thing(data, labels) learning_rate = 1e-6 #self.network = Network(data, labels, learning_rate) #self.network.train() #torch.save(self.network, 'current_network.pt') self.network = torch.load('current_network_17_WINEF.pt') self.id = random.uniform(0, 1) fh = open("cooperation" + str(self.id) + ".txt", "w") write(str(self.id) + ": 0.0") fh.close() self.set = False self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2)) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None
def __init__(self, logdata=True, net=None): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2) ) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None self.counter = 0 # import the neural net that drives the car self.model = simpleNetV2() self.weights = 'simpleNetV2_epoch_3_all_tracks.csv.pkl' self.model.load_state_dict(torch.load(self.weights)) self.input = torch.FloatTensor(D_in) self.track_check1 = False self.track_check2 = False # import the neat neural network to handle the gear config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet, neat.DefaultStagnation, 'config-neat') with open('winner-feedforward', 'rb') as f: winner = pickle.load(f) self.net = neat.nn.FeedForwardNetwork.create(winner, config) self.clock = time.time() self.done = False # initialize the fitness with zero self.temp_fitness = 0
def __init__(self, logdata=True): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2)) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None
def __init__(self, logdata=True, models=None, explore=0.9, optimizer=None): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2)) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None # Algorithm variables self.previous_state = None if os.path.isfile("memory.txt") == True: with open("memory.txt", "rb") as fp: self.replay_memory = pickle.load(fp) else: self.replay_memory = [] # Maximum size of the replay memory self.max_RM_size = 100000 self.model, self.target = models self.criterion = torch.nn.MSELoss() self.model_optim = optimizer self.restart = False # Discretize the action space self.action_space = [ 0.9, 0.7, 0.5, 0.4, 0.3, 0.2, 0.1, 0, -0.1, -0.2, -0.3, -0.4, -0.5, -0.7, -0.9 ] self.action = 0 self.reward = 0 # Model that is used for accelerating and braking self.model_acc_brake = simpleNetV2() self.pheromones = [] # self.receiver = Receiver(6001) weights = 'simpleNetV2_epoch_3_all_tracks.csv.pkl' self.model_acc_brake.load_state_dict(torch.load(weights)) self.input = torch.zeros(D_in) # STATS if os.path.isfile("counter.txt") == True: with open("counter.txt", "rb") as fp: self.counter = pickle.load(fp) else: self.counter = 0 self.counter_per_game = 0 self.train_counter = 0 self.average_reward = 0 self.average_loss = 0 # Hyperparameters self.exploration_rate = explore self.batch_size = 128 self.gamma = 0.99
def __init__(self, logdata=True): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2)) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None self.path = [] self.pid_steer = PID(Kp=0.5, Ki=0.0, Kd=1.0, setpoint=0, sample_time=0.02,\ output_limits=(-1.0, 1.0), auto_mode=True, proportional_on_measurement=True)
def __init__(self, logdata=True): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2) ) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None self.model = TwoLayerNet(D_in, hidden_size, hidden_size_2, D_out) self.model.load_state_dict(torch.load('LaurensNet30.pkl'))
def __init__(self, logdata=True): # filenames = ['aalborg.csv', 'alpine-1.csv', 'f-speedway.csv', 'data_track_2.csv'] #filenames = ['aalborg.csv', 'alpine-1.csv', 'f-speedway.csv'] filenames = ['forza_urja.csv'] #filenames = ['aalborg_new.csv', 'forza_new.csv'] data, labels = helper_functions.readData(filenames) # self.network = do_the_thing(data, labels) learning_rate = 1e-6 self.network = Network(data, labels, learning_rate) self.network.train() torch.save(self.network, 'current_network.pt') self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2)) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None
def __init__(self, logdata=True): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2)) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None self.model = simpleNetV2() weights = 'simpleNetV2_epoch_3_all_tracks.csv.pkl' self.model.load_state_dict(torch.load(weights)) self.input = torch.zeros(D_in) self.crashCounter = 0 self.reverseCounter = 0 self.forwardCounter = 0 self.resetGear = False self.crashed = False self.counter = 0 self.name = '3001' # NEAT self.history = np.zeros((5, 2), dtype=float) config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet, neat.DefaultStagnation, 'config-neat') with open('winner-feedforward', 'rb') as f: winner = pickle.load(f) self.net = neat.nn.FeedForwardNetwork.create(winner, config) #SWARM self.pheromones = [] pickle.dump(self.pheromones, open("../sent_3001.txt", "wb")) self.straight_begin = 0 self.straight_end = 0 self.list_straight = [] self.list_corner = [] self.received = [] self.list_average_corcer = []
def __init__(self, log_data=False, net=None): # self.steering_ctrl = CompositeController(ProportionalController(0.4),IntegrationController(0.2, integral_limit=1.5),DerivativeController(2)) # self.acceleration_ctrl = CompositeController( # ProportionalController(3.7), # ) self.steering_ctrl = CompositeController(ProportionalController(0.4), DerivativeController(2)) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if log_data else None self.net = net print("mehmehmeh") self.flag = False
def __init__(self, logdata=True, net=None): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2) ) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None self.eta = 20 self.counter = 0 self.model = simpleNetV2() self.weights = 'simpleNetV2_epoch_3_all_tracks.csv.pkl' self.model.load_state_dict(torch.load(self.weights)) self.input = torch.FloatTensor(D_in) self.track_check1 = False self.track_check2 = False self.action_neat = None self.net = net self.clock = time.time() self.done = False self.temp_fitness = 0
def __init__(self,log_data=False, net=None): # self.steering_ctrl = CompositeController(ProportionalController(0.4),IntegrationController(0.2, integral_limit=1.5),DerivativeController(2)) # self.acceleration_ctrl = CompositeController( # ProportionalController(3.7), # ) # json_file = open('model.json', 'r') # loaded_model_json = json_file.read() # json_file.close() # loaded_model = model_from_json(loaded_model_json) # loaded_model.compile(loss='mean_squared_error', optimizer='rmsprop', metrics=['accuracy']) # # load weights into new model # self.loaded_model=loaded_model.load_weights("model.h5") # print("Loaded model from disk") # self.steering_ctrl = CompositeController( # ProportionalController(0.4), # DerivativeController(1) # ) # self.acceleration_ctrl = CompositeController( # ProportionalController(3.7), # ) self.data_logger = DataLogWriter() if log_data else None self.net=net print("mehmehmeh") self.flag=False
class Driver: """ Driving logic. Implement the driving intelligence in this class by processing the current car state as inputs creating car control commands as a response. The ``drive`` function is called periodically every 20ms and must return a command within 10ms wall time. """ def __init__(self, logdata=True): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2)) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None self.path = [] self.pid_steer = PID(Kp=0.5, Ki=0.0, Kd=1.0, setpoint=0, sample_time=0.02,\ output_limits=(-1.0, 1.0), auto_mode=True, proportional_on_measurement=True) @property def range_finder_angles(self): """Iterable of 19 fixed range finder directions [deg]. The values are used once at startup of the client to set the directions of range finders. During regular execution, a 19-valued vector of track distances in these directions is returned in ``state.State.tracks``. """ return -90, -75, -60, -45, -30, -20, -15, -10, -5, 0, 5, 10, 15, 20, \ 30, 45, 60, 75, 90 def on_shutdown(self): """ Server requested driver shutdown. Optionally implement this event handler to clean up or write data before the application is stopped. """ if self.data_logger: self.data_logger.close() self.data_logger = None def drive(self, carstate: State) -> Command: command = Command() self.steer(carstate, 0.0, command) ACC_LATERAL_MAX = 6400 * 5 #v_x = min(120, math.sqrt(ACC_LATERAL_MAX / abs(command.steering))) v_x = 120 self.accelerate(carstate, v_x, command) if self.data_logger: self.data_logger.log(carstate, command) return command def accelerate(self, carstate, target_speed, command): # compensate engine deceleration, but invisible to controller to # prevent braking: speed_error = 1.0025 * target_speed * MPS_PER_KMH - carstate.speed_x acceleration = self.acceleration_ctrl.control( speed_error, carstate.current_lap_time) # stabilize use of gas and brake: acceleration = math.pow(acceleration, 3) if acceleration > 0: if abs(carstate.distance_from_center) >= 1: # off track, reduced grip: acceleration = min(0.4, acceleration) command.accelerator = min(acceleration, 1) if carstate.rpm > 8000: command.gear = carstate.gear + 1 else: command.brake = min(-acceleration, 1) if carstate.rpm < 2500: command.gear = carstate.gear - 1 if not command.gear: command.gear = carstate.gear or 1 def steer(self, carstate, target_track_pos, command): steering_error = target_track_pos - carstate.distance_from_center control = -self.pid_steer(steering_error) command.steering = self.steering_ctrl.control( control, carstate.current_lap_time) return control
class MyDriver(Driver): def __init__(self, logdata=True): # filenames = ['aalborg.csv', 'alpine-1.csv', 'f-speedway.csv', 'data_track_2.csv'] #filenames = ['aalborg.csv', 'alpine-1.csv', 'f-speedway.csv'] filenames = ['newdata4.csv'] #filenames = ['aalborg_new.csv', 'forza_new.csv'] data, labels = helper_functions.readData(filenames) # self.network = do_the_thing(data, labels) learning_rate = 1e-6 self.network = Network(data, labels, learning_rate) self.network.train() self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2) ) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None def stateToArray(self, carstate): # print([carstate.angle, carstate.current_lap_time, carstate.damage, # carstate.distance_from_start, carstate.distance_raced, # carstate.fuel, carstate.gear, carstate.last_lap_time, # carstate.opponents, carstate.race_position, carstate.rpm, # carstate.speed_x, carstate.speed_y, carstate.speed_z, # carstate.distances_from_edge, carstate.distance_from_center, # carstate.wheel_velocities, carstate.z, # carstate.focused_distances_from_edge]) return np.array([[carstate.speed_x/24, carstate.distance_from_center, carstate.angle] + list(carstate.distances_from_edge)]) # Override the `drive` method to create your own driver def drive(self, carstate: State) -> Command: """ Produces driving command in response to newly received car state. This is a dummy driving routine, very dumb and not really considering a lot of inputs. But it will get the car (if not disturbed by other drivers) successfully driven along the race track. """ command = Command() stateList = self.stateToArray(carstate) # output = self.network.activate(stateList) output = self.network.forward(stateList).data print(output) #self.steer(carstate, output[0, 2], command) command.steering = output[0,0] acceleration = output[0,1]*129 acceleration = math.pow(acceleration, 3) if acceleration > 0: if abs(carstate.distance_from_center) >= 1: # off track, reduced grip: acceleration = min(0.4, acceleration) command.accelerator = min(acceleration, 1) if carstate.rpm > 8000: command.gear = carstate.gear + 1 else: command.brake = min(-acceleration, 1) if carstate.rpm < 2500: command.gear = carstate.gear - 1 if not command.gear: command.gear = carstate.gear or 1 #if output[0,0]>0.5: # ACC_LATERAL_MAX = 6400 * 5 # v_x = min(80, math.sqrt(ACC_LATERAL_MAX / abs(command.steering))) #else: # v_x = 0 #self.accelerate(carstate, 85, command) if self.data_logger: self.data_logger.log(carstate, command) return command
class Driver: """ Driving logic. Implement the driving intelligence in this class by processing the current car state as inputs creating car control commands as a response. The ``drive`` function is called periodically every 20ms and must return a command within 10ms wall time. """ def __init__(self, logdata=True): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2)) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None @property def range_finder_angles(self): """Iterable of 19 fixed range finder directions [deg]. The values are used once at startup of the client to set the directions of range finders. During regular execution, a 19-valued vector of track distances in these directions is returned in ``state.State.tracks``. """ return -90, -75, -60, -45, -30, -20, -15, -10, -5, 0, 5, 10, 15, 20, \ 30, 45, 60, 75, 90 def on_shutdown(self): """ Server requested driver shutdown. Optionally implement this event handler to clean up or write data before the application is stopped. """ if self.data_logger is not None: self.data_logger.close() self.data_logger = None def drive(self, carstate: State) -> Command: """ Produces driving command in response to newly received car state. This is a dummy driving routine, very dumb and not really considering a lot of inputs. But it will get the car (if not disturbed by other drivers) successfully driven along the race track. """ command = Command() self.steer(carstate, 0.0, command) # ACC_LATERAL_MAX = 6400 * 5 # v_x = min(80, math.sqrt(ACC_LATERAL_MAX / abs(command.steering))) v_x = 80 self.accelerate(carstate, v_x, command) if self.data_logger: self.data_logger.log(carstate, command) return command def accelerate(self, carstate, target_speed, command): # compensate engine deceleration, but invisible to controller to # prevent braking: speed_error = 1.0025 * target_speed * 1000 / 3600 - carstate.speed_x acceleration = self.acceleration_ctrl.control( speed_error, carstate.current_lap_time) # stabilize use of gas and brake: acceleration = math.pow(acceleration, 3) if acceleration > 0: if abs(carstate.distance_from_center) >= 1: # off track, reduced grip: acceleration = min(0.4, acceleration) command.accelerator = min(acceleration, 1) if carstate.rpm > 8000: command.gear = carstate.gear + 1 # else: # command.brake = min(-acceleration, 1) if carstate.rpm < 2500: command.gear = carstate.gear - 1 if not command.gear: command.gear = carstate.gear or 1 def steer(self, carstate, target_track_pos, command): steering_error = target_track_pos - carstate.distance_from_center command.steering = self.steering_ctrl.control( steering_error, carstate.current_lap_time)
class MyDriver(Driver): def __init__(self, logdata=True): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2)) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None # Setup the PyTorch model and load the weights self.model = simpleNetV3() weights = 'simpleNetV3_lr=0.01_epoch_1_all_tracks.csv.pkl' self.model.load_state_dict(torch.load(weights)) # Initialize inputs, counters and history self.input = torch.zeros(D_in) self.crashCounter = 0 self.reverseCounter = 0 self.forwardCounter = 0 self.resetGear = False self.crashed = False self.counter = 0 self.name = '3001' self.history = np.zeros((5, 2), dtype=float) # Initialize SWARM self.pheromones = [] pickle.dump(self.pheromones, open("sent_3001.txt", "wb")) self.straight_begin = 0 self.straight_end = 0 self.list_straight = [] self.list_corner = [] self.received = [] self.list_average_corner = [] @property def range_finder_angles(self): """Iterable of 19 fixed range finder directions [deg]. The values are used once at startup of the client to set the directions of range finders. During regular execution, a 19-valued vector of track distances in these directions is returned in ``state.State.tracks``. """ return -90, -75, -60, -45, -30, -20, -15, -10, -5, 0, 5, 10, 15, 20, \ 30, 45, 60, 75, 90 def on_shutdown(self): """ Server requested driver shutdown. Optionally implement this event handler to clean up or write data before the application is stopped. """ if self.data_logger: self.data_logger.close() self.data_logger = None # Create new input for the network with predicted values and carstate def update_state(self, pred, carstate): # Create empty vector state_t_plus = torch.FloatTensor(D_in) # Fill with predicted values and carstate state_t_plus[0] = pred.data[0][0] state_t_plus[1] = pred.data[0][1] state_t_plus[2] = pred.data[0][2] state_t_plus[3] = carstate.speed_x * 3.6 state_t_plus[4] = carstate.distance_from_center state_t_plus[5] = carstate.angle for index, edge in enumerate(carstate.distances_from_edge): state_t_plus[6 + index] = edge return state_t_plus # Update the distance_from_start history def update_history(self, carstate): # Roll the sequence so the last history is now at front self.history = np.roll(self.history, 1) self.history[0][0] = carstate.distance_from_start # Checks if distance_from_start in the last 5 ticks increased less than 0.2 meters, # if so, adds one to the crashCounter. # Once the crashCounter reaches 100, sets crashed to true which starts auto-reset behaviour def detect_crash(self): # Check if not standing still or moving really slowly if (self.history[0][0] - self.history[-1][0] < 0.2): self.crashCounter += 1 else: self.crashCounter = 0 # Activate auto-reset behaviour if self.crashCounter > 100: self.crashed = True self.crashCounter = 0 # Checks whether the car is back on track and has the correct angle. # If after 200 ticks still not back on track, start driving forward def check_back_on_track(self, carstate): if self.reverseCounter < 200: # Check back on track with correct angle, if correct activate forward counter if abs(carstate.distance_from_center) < 0.5 and abs( carstate.angle) < 45: self.crashed = False self.forwardCounter = 250 self.reverseCounter = 0 else: self.reverseCounter += 1 # Reversecounter finished, so start moving in forward direction else: self.crashed = False self.forwardCounter = 250 self.reverseCounter = 0 # Detects sharp corners by checking if the steering angle is more than 0.4 for 25 ticks def check_for_corner(self, steering, distance_from_start): begin_corner = 0 # Check if steering angle is more than 0.4 in either direction if steering > 0.4 or steering < -0.4: self.list_corner.append(distance_from_start) self.list_average_corner.append(steering) else: # Check if steering sharply for more than 25 ticks if len(self.list_corner) > 25: average = np.average(np.asarray(self.list_average_corner)) begin_corner = self.list_corner[0] print(average) self.list_corner = [] return begin_corner # Checks for pheromones placed on track, if 20 meters ahead, start braking def check_for_info(self, received, distance_from_start, carspeed): for info in received: if info[0] == "Corner" and distance_from_start > info[ 1] - 75 and distance_from_start < info[1] - 20: if carspeed * 3.6 < 135: return 135, 0.6, 0, None return 135, 0, 0.6, 0 return None, None, None, None # Returns appropriate commands for the car, depending on the currenst carstate def drive(self, carstate: State) -> Command: command = Command() # If crashed, reverse if self.crashed: self.check_back_on_track(carstate) command.accelerator = 0.5 command.gear = -1 # Only steer if incorrect angle and off track if abs(carstate.angle) > 20 and abs( carstate.distance_from_center) < 1: # If car orientated towards the right if carstate.angle > 0: # Steer to right while reversing command.steering = -1 self.forward_steer_direction = 0.5 # Car orientated towards left else: # Steer to left while reversing command.steering = 1 self.forward_steer_direction = -0.5 self.resetGear = True # If forwardCounter is activated, drive forward, steering in the correct direction elif self.forwardCounter > 0: # Start by braking if self.forwardCounter > 200: command.brake = 1 # Then drive forward steering in the correct direction if carstate.angle > 0: command.steering = 0.5 else: command.steering = -0.5 command.accelerator = 0.5 command.gear = 1 self.forwardCounter -= 1 # Normal behaviour else: # Run input through model to predict next commands out = self.model(Variable(self.input)) self.input = self.update_state(out, carstate) self.update_history(carstate) self.detect_crash() # Create command with predictions command.accelerator = out.data[0][0] command.brake = out.data[0][1] command.steering = out.data[0][2] # Check for corners, if found, place pheromones begin_corner = self.check_for_corner(command.steering, carstate.distance_from_start) if begin_corner > 0: self.pheromones.append(("Corner", begin_corner)) # Save pheromones to file if self.counter % 50 == 0: pickle.dump(self.pheromones, open("sent_3001.txt", "wb")) if os.path.isfile("sent_3001.txt"): self.received = pickle.load(open("sent_3001.txt", "rb")) # Maximum target speed v_x = 500 # Use information from pheromones max_speed, accel, brake, steer = self.check_for_info( self.received, carstate.distance_from_start, carstate.speed_x) if max_speed is not None: v_x = max_speed command.accelerator = accel command.brake = brake if steer == 0: command.steering = steer self.accelerate(carstate, v_x, command) if self.resetGear: self.resetGear = False # Prevent the car from braking when driving slowly, causing it to get stuck when off track if carstate.speed_x * 3.6 < 20: command.brake = 0 self.counter += 1 self.input[2] = command.accelerator return command def get_gear(self, carstate): output = self.net.activate([carstate.rpm / 10000]) # convert the outcome into a command command = Command() if (output[0] < -0.5): gear = carstate.gear - 1 elif (output[0] > 0.5): gear = carstate.gear + 1 else: gear = carstate.gear if gear < 1: gear = 1 if gear > 6: gear = 6 return gear def accelerate(self, carstate, target_speed, command): # compensate engine deceleration, but invisible to controller to # prevent braking: speed_error = 1.0025 * target_speed * MPS_PER_KMH - carstate.speed_x acceleration = self.acceleration_ctrl.control( speed_error, carstate.current_lap_time) # stabilize use of gas and brake: acceleration = math.pow(acceleration, 3) if acceleration > 0: if abs(carstate.distance_from_center) >= 1: # off track, reduced grip: acceleration = min(0.4, acceleration) command.accelerator = min(acceleration, 1) if carstate.rpm > 8000: command.gear = carstate.gear + 1 # else: # command.brake = min(-acceleration, 1) if carstate.rpm < 4000: command.gear = carstate.gear - 1 if not command.gear: command.gear = carstate.gear or 1
class MyDriver(Driver): # Override the `drive` method to create your own driver ... # def drive(self, carstate: State) -> Command: # # Interesting stuff # command = Command(...) # return command def __init__(self, logdata=True): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2)) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None self.model = simpleNetV2() weights = 'simpleNetV2_epoch_3_all_tracks.csv.pkl' self.model.load_state_dict(torch.load(weights)) self.input = torch.zeros(D_in) self.crashCounter = 0 self.reverseCounter = 0 self.forwardCounter = 0 self.resetGear = False self.crashed = False self.counter = 0 self.name = '3001' # NEAT self.history = np.zeros((5, 2), dtype=float) config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet, neat.DefaultStagnation, 'config-neat') with open('winner-feedforward', 'rb') as f: winner = pickle.load(f) self.net = neat.nn.FeedForwardNetwork.create(winner, config) #SWARM self.pheromones = [] pickle.dump(self.pheromones, open("../sent_3001.txt", "wb")) self.straight_begin = 0 self.straight_end = 0 self.list_straight = [] self.list_corner = [] self.received = [] self.list_average_corcer = [] @property def range_finder_angles(self): """Iterable of 19 fixed range finder directions [deg]. The values are used once at startup of the client to set the directions of range finders. During regular execution, a 19-valued vector of track distances in these directions is returned in ``state.State.tracks``. """ return -90, -75, -60, -45, -30, -20, -15, -10, -5, 0, 5, 10, 15, 20, \ 30, 45, 60, 75, 90 def on_shutdown(self): """ Server requested driver shutdown. Optionally implement this event handler to clean up or write data before the application is stopped. """ if self.data_logger: self.data_logger.close() self.data_logger = None def update_history_seq_len(self, output, carstate): # Roll the sequence so the last history is now at front throwaway = self.input_sequence[0] keep = self.input_sequence[1:] self.input_sequence = torch.cat((keep, throwaway.view(1, -1)), 0) #Overwrite old values with new prediction and carstate self.input_sequence[-1][0] = self.pred[0] self.input_sequence[-1][1] = self.pred[1] self.input_sequence[-1][2] = self.pred[2] self.input_sequence[-1][3] = carstate.speed_x * 3.6 self.input_sequence[-1][4] = carstate.distance_from_center self.input_sequence[-1][5] = carstate.angle for index, edge in enumerate(carstate.distances_from_edge): self.input_sequence[-1][6 + index] = edge def make_input(self, carstate, out): inputs = [carstate.rpm / 10000, carstate.speed_x / 100, out[0], out[1]] return inputs def update_state(self, pred, carstate): # # Roll the sequence so the last history is now at front # throwaway = self.input_sequence[0] # print(self.input_sequence.shape) state_t_plus = torch.FloatTensor(D_in) # print(state_t_plus) # sys.exit() #Overwrite old values with new prediction and carstate # print('[BEFORE]') # print(state_t_plus[0][2]) # sys.exit() state_t_plus[0] = pred.data[0] state_t_plus[1] = pred.data[1] state_t_plus[2] = pred.data[2] state_t_plus[3] = carstate.speed_x * 3.6 state_t_plus[4] = carstate.distance_from_center state_t_plus[5] = carstate.angle for index, edge in enumerate(carstate.distances_from_edge): state_t_plus[6 + index] = edge return state_t_plus def update_history(self, carstate): # Roll the sequence so the last history is now at front self.history = np.roll(self.history, 1) self.history[0][0] = carstate.distance_from_start def detect_crash(self): if (self.history[0][0] - self.history[-1][0] < 0.2): self.crashCounter += 1 else: self.crashCounter = 0 if self.crashCounter > 100: self.crashed = True self.crashCounter = 0 def check_back_on_track(self, carstate): if self.reverseCounter < 200: # print(abs(carstate.distance_from_center)) if abs(carstate.distance_from_center) < 0.5 and abs( carstate.angle) < 45: # print(abs(carstate.angle)) # print("-------------Found center!") self.crashed = False self.forwardCounter = 250 self.reverseCounter = 0 else: self.reverseCounter += 1 else: # print("---------------ReverseCounter Finished!") self.crashed = False self.forwardCounter = 250 self.reverseCounter = 0 def check_for_corner(self, steering, distance_from_start): begin_corner = 0 if steering > 0.4 or steering < -0.4: self.list_corner.append(distance_from_start) self.list_average_corcer.append(steering) else: if len(self.list_corner) > 25: average = np.average(np.asarray(self.list_average_corcer)) begin_corner = self.list_corner[0] print(average) self.list_corner = [] return begin_corner def check_for_acceleration(self, steering, distance_from_start): begin_accel = 0 end_accel = 0 if steering > -0.05 and steering < 0.05: self.list_straight.append((steering, distance_from_start)) else: if len(self.list_straight) > 500: begin_accel = self.list_straight[0][1] end_accel = self.list_straight[-1][1] - 100 if begin_accel > end_accel: self.pheromones.append(("Accel", begin_accel, 100000)) self.begin_accel = 0 self.list_straight = [] return begin_accel, end_accel def check_for_info(self, received, distance_from_start, carspeed): for info in received: #if info[0] == "Accel" and distance_from_start > info[1] + 75 and distance_from_start < info[2] - 30: #return 360, 1, 0, None if info[0] == "Corner" and distance_from_start > info[ 1] - 75 and distance_from_start < info[1] - 20: if carspeed * 3.6 < 135: return 135, 0.6, 0, None return 135, 0, 0.6, 0 return None, None, None, None def drive(self, carstate: State) -> Command: command = Command() out = self.model(Variable(self.input)) self.input = self.update_state(out, carstate) # If crashed -> reversing if self.crashed: self.check_back_on_track(carstate) command.accelerator = 0.5 command.gear = -1 # Only steer if incorrect angle and off track if abs(carstate.angle) > 20 and abs( carstate.distance_from_center) < 1: # If car orientated towards the right if carstate.angle > 0: # Steer to right while reversing command.steering = -1 # self.forward_steer_direction = 1 self.forward_steer_direction = 0.5 else: # Steer to left while reversing command.steering = 1 # else: # Steer to right while reversing # command.steering = -1 # self.forward_steer_direction = 1 self.forward_steer_direction = -0.5 # command.steering = 1 # self.forwardCounter -= 1 self.resetGear = True elif self.forwardCounter > 0: # print("Turning to correct direction") if self.forwardCounter > 200: command.brake = 1 # if abs(carstate.angle) > : if carstate.angle > 0: command.steering = 0.5 else: command.steering = -0.5 # command.steering = self.forward_steer_direction command.accelerator = 0.5 command.gear = 1 self.forwardCounter -= 1 # Normal behaviour else: out = self.model(Variable(self.input)) self.input = self.update_state(out, carstate) self.update_history(carstate) self.detect_crash() command.accelerator = out.data[0] command.brake = out.data[1] command.steering = out.data[2] begin_corner = self.check_for_corner(command.steering, carstate.distance_from_start) begin_acceleration, end_acceleration = self.check_for_acceleration( command.steering, carstate.distance_from_start) if begin_corner > 0: self.pheromones.append(("Corner", begin_corner)) if begin_acceleration > 0: self.pheromones.append( ("Accel", begin_acceleration, end_acceleration)) if self.counter % 50 == 0: pickle.dump(self.pheromones, open("../sent_3001.txt", "wb")) if os.path.isfile("../sent_3001.txt"): self.received = pickle.load(open("../sent_3001.txt", "rb")) v_x = 500 max_speed, accel, brake, steer = self.check_for_info( self.received, carstate.distance_from_start, carstate.speed_x) if max_speed is not None: v_x = max_speed command.accelerator = accel command.brake = brake if steer == 0: command.steering = steer #command.gear = self.get_gear(carstate) USE NEAT TO SHIFT GEARS self.accelerate(carstate, v_x, command) if self.resetGear: #command.gear = self.get_gear(carstate) self.resetGear = False if carstate.speed_x * 3.6 < 20: command.brake = 0 self.counter += 1 self.input[2] = command.accelerator return command def get_gear(self, carstate): output = self.net.activate([carstate.rpm / 10000]) # convert the outcome into a command command = Command() if (output[0] < -0.5): gear = carstate.gear - 1 elif (output[0] > 0.5): gear = carstate.gear + 1 else: gear = carstate.gear if gear < 1: gear = 1 if gear > 6: gear = 6 return gear def accelerate(self, carstate, target_speed, command): # compensate engine deceleration, but invisible to controller to # prevent braking: speed_error = 1.0025 * target_speed * MPS_PER_KMH - carstate.speed_x acceleration = self.acceleration_ctrl.control( speed_error, carstate.current_lap_time) # stabilize use of gas and brake: acceleration = math.pow(acceleration, 3) if acceleration > 0: if abs(carstate.distance_from_center) >= 1: # off track, reduced grip: acceleration = min(0.4, acceleration) command.accelerator = min(acceleration, 1) if carstate.rpm > 8000: command.gear = carstate.gear + 1 # else: # command.brake = min(-acceleration, 1) if carstate.rpm < 4000: command.gear = carstate.gear - 1 if not command.gear: command.gear = carstate.gear or 1 def steer(self, carstate, target_track_pos, command): steering_error = target_track_pos - carstate.distance_from_center command.steering = self.steering_ctrl.control( steering_error, carstate.current_lap_time)
class NeatDriver: """ In this current implementation this neatdriver drives on the track by commands from the output of a neural network namely the simpleNetV2_epoch_3_all_tracks.csv.pkl. The command for the gear is predicted by the neural network that is created with the neat- algorithm. The winner genome 'winner-feedforward' is loaded in and controlling the gear. Below this class there is code of how the winner-feedforward is obtained. """ def __init__(self, logdata=True, net=None): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2) ) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None self.counter = 0 # import the neural net that drives the car self.model = simpleNetV2() self.weights = 'simpleNetV2_epoch_3_all_tracks.csv.pkl' self.model.load_state_dict(torch.load(self.weights)) self.input = torch.FloatTensor(D_in) self.track_check1 = False self.track_check2 = False # import the neat neural network to handle the gear config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet, neat.DefaultStagnation, 'config-neat') with open('winner-feedforward', 'rb') as f: winner = pickle.load(f) self.net = neat.nn.FeedForwardNetwork.create(winner, config) self.clock = time.time() self.done = False # initialize the fitness with zero self.temp_fitness = 0 @property def range_finder_angles(self): """Iterable of 19 fixed range finder directions [deg]. The values are used once at startup of the client to set the directions of range finders. During regular execution, a 19-valued vector of track distances in these directions is returned in ``state.State.tracks``. """ return -90, -75, -60, -45, -30, -20, -15, -10, -5, 0, 5, 10, 15, 20, \ 30, 45, 60, 75, 90 def on_shutdown(self): """ Server requested driver shutdown. Optionally implement this event handler to clean up or write data before the application is stopped. """ if self.data_logger: self.data_logger.close() self.data_logger = None def update_state(self, pred, carstate): state_t_plus = torch.FloatTensor(D_in) state_t_plus[0] = pred.data[0] state_t_plus[1] = pred.data[1] state_t_plus[2] = pred.data[2] state_t_plus[3] = carstate.speed_x *3.6 state_t_plus[4] = carstate.distance_from_center state_t_plus[5] = carstate.angle for index, edge in enumerate(carstate.distances_from_edge): state_t_plus[6 + index] = edge return state_t_plus def drive(self, carstate: State) -> Command: """ Produces driving command in response to newly received car state. """ global net # define the output out = self.model(Variable(self.input)) self.input = self.update_state(out, carstate) # code to check wheter the driver is stuck, namely if it is for a long time of track if self.track_check1 == True and self.check_offtrack(carstate) == True: self.track_check2 = True if self.counter % 100 == 0: self.track_check1 = self.check_offtrack(carstate) # this is a previous used fitness function #self.temp_fitness += carstate.speed_x * (np.cos(carstate.angle*(np.pi/180)) - np.absolute(np.sin(carstate.angle * (np.pi/180)))) # calculate the fitness if(carstate.rpm > 8000 or carstate.rpm < 2500): reward = -1 else: reward = 1 self.temp_fitness += reward # calculate the gear with the neat network output = self.net.activate([carstate.rpm/10000]) # convert the outcome into a command command = Command() if(output[0] < -0.5): command.gear = carstate.gear - 1 elif(output[0] > 0.5): command.gear = carstate.gear + 1 else: command.gear = carstate.gear if command.gear < 1: command.gear = 1 if command.gear > 6: command.gear = 6 # Define the command with output of the other neural net command.accelerator = out.data[0] command.brake = out.data[1] command.steering = out.data[2] # update the counter self.counter += 1 # log the command if self.data_logger: self.data_logger.log(carstate, command) # If car has too much damage or max time has exceeded do a restart if carstate.damage >= 9500 or carstate.last_lap_time > 0 or carstate.current_lap_time > 120: global fitness fitness = (self.temp_fitness/self.counter) command.meta = 1 return command def check_offtrack(self, carstate): """ Function that checks whether the car is offtrack param: carstate return: boolean """ counter = 0 for values in carstate.distances_from_edge: if values == -1: counter += 1 if counter == len(carstate.distances_from_edge): return True else: return False
class MyDriver(Driver): def __init__(self, logdata=True): # filenames = ['aalborg.csv', 'alpine-1.csv', 'f-speedway.csv', 'data_track_2.csv'] #filenames = ['aalborg.csv', 'alpine-1.csv', 'f-speedway.csv'] #filenames = ['forza_urja.csv', 'newdata5.csv', 'aalborg_urja.csv'] #, 'aalborg_urja.csv', 'aalborg_urja_vx80.csv'] #filenames = ['aalborg_new.csv', 'forza_new.csv'] #data, labels = helper_functions.readData(filenames) learning_rate = 1e-6 #self.network = Network(data, labels, learning_rate) #self.network.train() #torch.save(self.network, 'current_network_reg.pt') #self.network = torch.load('current_network_17_WINEF.pt') self.network = torch.load('current_network_reg.pt') self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2) ) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None def stateToArray(self, carstate): # print([carstate.angle, carstate.current_lap_time, carstate.damage, # carstate.distance_from_start, carstate.distance_raced, # carstate.fuel, carstate.gear, carstate.last_lap_time, # carstate.opponents, carstate.race_position, carstate.rpm, # carstate.speed_x, carstate.speed_y, carstate.speed_z, # carstate.distances_from_edge, carstate.distance_from_center, # carstate.wheel_velocities, carstate.z, # carstate.focused_distances_from_edge]) edge_lists = [8.4, 9.2, 57, 200, 200, 200, 200, 200, 200, 200, 200] edge_lists += [200, 200, 200, 200, 200, 156, 20, 13] edges = list(carstate.distances_from_edge) normalized_edges = [edges[i]/edge_lists[i] for i in range(len(edge_lists))] return np.array([[carstate.speed_x/22, carstate.distance_from_center/0.99, carstate.angle/28] + normalized_edges]) # Override the `drive` method to create your own driver def drive(self, carstate: State) -> Command: """ Produces driving command in response to newly received car state. This is a dummy driving routine, very dumb and not really considering a lot of inputs. But it will get the car (if not disturbed by other drivers) successfully driven along the race track. """ command = Command() stateList = self.stateToArray(carstate) # output = self.network.activate(stateList) output = self.network.forward(stateList).data print(output) print(carstate.speed_x) print(carstate.distance_from_start) #print(carstate.opponents) #self.steer(carstate, output[0, 2], command) command.steering = output[0,0] #self.accelerate(carstate, 80, command) if carstate.speed_x < 0.1: command.accelerator = abs(output[0,1]) else: command.accelerator = output[0,1] if output[0,1] < 0.0: command.brake = output[0,2] else: command.brake = 0 if command.accelerator > 0: if carstate.rpm > 8000: command.gear = carstate.gear + 1 if command.accelerator < 0: if carstate.rpm < 2500: command.gear = carstate.gear - 1 if not command.gear: command.gear = carstate.gear or 1 #acceleration = output[0,1]*129 #acceleration = math.pow(acceleration, 3) #if acceleration > 0: # if abs(carstate.distance_from_center) >= 1: # off track, reduced grip: # acceleration = min(0.4, acceleration) # command.accelerator = min(acceleration, 1) # if carstate.rpm > 8000: # command.gear = carstate.gear + 1 #else: # command.brake = min(-acceleration, 1) #if carstate.rpm < 2500: # command.gear = carstate.gear - 1 #if not command.gear: # command.gear = carstate.gear or 1 #if output[0,0]>0.5: # ACC_LATERAL_MAX = 6400 * 5 # v_x = min(80, math.sqrt(ACC_LATERAL_MAX / abs(command.steering))) #else: # v_x = 0 #self.accelerate(carstate, 85, command) if self.data_logger: self.data_logger.log(carstate, command) return command
class MyDriver(Driver): # Override the `drive` method to create your own driver ... # def drive(self, carstate: State) -> Command: # # Interesting stuff # command = Command(...) # return command def __init__(self, logdata=True): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2) ) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None self.model = TwoLayerNet(D_in, hidden_size, hidden_size_2, D_out) self.model.load_state_dict(torch.load('LaurensNet30.pkl')) @property def range_finder_angles(self): """Iterable of 19 fixed range finder directions [deg]. The values are used once at startup of the client to set the directions of range finders. During regular execution, a 19-valued vector of track distances in these directions is returned in ``state.State.tracks``. """ return -90, -75, -60, -45, -30, -20, -15, -10, -5, 0, 5, 10, 15, 20, \ 30, 45, 60, 75, 90 def on_shutdown(self): """ Server requested driver shutdown. Optionally implement this event handler to clean up or write data before the application is stopped. """ if self.data_logger: self.data_logger.close() self.data_logger = None def drive(self, carstate: State) -> Command: """ Produces driving command in response to newly received car state. This is a dummy driving routine, very dumb and not really considering a lot of inputs. But it will get the car (if not disturbed by other drivers) successfully driven along the race track. """ global fullData data = np.empty(25) data[3] = carstate.speed_x data[4] = carstate.z data[5] = carstate.angle for index, edge in enumerate(carstate.distances_from_edge): data[3 + index] = edge # data = torch.from_numpy(data.T) # data = data.type(torch.FloatTensor) # data=torch.unsqueeze(data,1) # data = Variable(data) net_input = torch.from_numpy(fullData.flatten()) net_input = Variable(net_input.type(torch.FloatTensor)) # force = np.random.random() < 0.5 # data = torch.transpose(data, 0, 1) predict, hidden_layer = self.model.forward(net_input) command = Command() predict = predict[0].data.numpy() data[0] = predict[0] data[1] = predict[1] data[2] = predict[2] if predict[0] > 0.5: command.accelerator = 1 else: command.accelerator = 0 if predict[1] > 0.5: command.brake = 1 print("BRAKING") else: command.brake = 0 command.steer = predict[2] self.steer(carstate, 0.0, command) # ACC_LATERAL_MAX = 6400 * 5 # v_x = min(80, math.sqrt(ACC_LATERAL_MAX / abs(command.steering))) v_x = 300 self.accelerate(carstate, v_x, command) if self.data_logger: self.data_logger.log(carstate, command) fullData = np.delete(fullData, 0, axis=1) fullData = np.append(fullData, data.reshape((25,1)), axis=1) return command def accelerate(self, carstate, target_speed, command): # compensate engine deceleration, but invisible to controller to # prevent braking: speed_error = 1.0025 * target_speed * MPS_PER_KMH - carstate.speed_x acceleration = self.acceleration_ctrl.control( speed_error, carstate.current_lap_time ) # stabilize use of gas and brake: acceleration = math.pow(acceleration, 3) if acceleration > 0: if abs(carstate.distance_from_center) >= 1: # off track, reduced grip: acceleration = min(0.4, acceleration) command.accelerator = min(acceleration, 1) if carstate.rpm > 8000: command.gear = carstate.gear + 1 # else: # command.brake = min(-acceleration, 1) if carstate.rpm < 2500: command.gear = carstate.gear - 1 if not command.gear: command.gear = carstate.gear or 1 def steer(self, carstate, target_track_pos, command): steering_error = target_track_pos - carstate.distance_from_center command.steering = self.steering_ctrl.control( steering_error, carstate.current_lap_time )
class MyDriver: """ Driving logic. Implement the driving intelligence in this class by processing the current car state as inputs creating car control commands as a response. The ``drive`` function is called periodically every 20ms and must return a command within 10ms wall time. """ def __init__(self, logdata=True, models=None, explore=0.9, optimizer=None): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2)) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None # Algorithm variables self.previous_state = None if os.path.isfile("memory.txt") == True: with open("memory.txt", "rb") as fp: self.replay_memory = pickle.load(fp) else: self.replay_memory = [] # Maximum size of the replay memory self.max_RM_size = 100000 self.model, self.target = models self.criterion = torch.nn.MSELoss() self.model_optim = optimizer self.restart = False # Discretize the action space self.action_space = [ 0.9, 0.7, 0.5, 0.4, 0.3, 0.2, 0.1, 0, -0.1, -0.2, -0.3, -0.4, -0.5, -0.7, -0.9 ] self.action = 0 self.reward = 0 # Model that is used for accelerating and braking self.model_acc_brake = simpleNetV2() self.pheromones = [] # self.receiver = Receiver(6001) weights = 'simpleNetV2_epoch_3_all_tracks.csv.pkl' self.model_acc_brake.load_state_dict(torch.load(weights)) self.input = torch.zeros(D_in) # STATS if os.path.isfile("counter.txt") == True: with open("counter.txt", "rb") as fp: self.counter = pickle.load(fp) else: self.counter = 0 self.counter_per_game = 0 self.train_counter = 0 self.average_reward = 0 self.average_loss = 0 # Hyperparameters self.exploration_rate = explore self.batch_size = 128 self.gamma = 0.99 @property def range_finder_angles(self): """Iterable of 19 fixed range finder directions [deg]. The values are used once at startup of the client to set the directions of range finders. During regular execution, a 19-valued vector of track distances in these directions is returned in ``state.State.tracks``. """ return -90, -75, -60, -45, -30, -20, -15, -10, -5, 0, 5, 10, 15, 20, \ 30, 45, 60, 75, 90 def on_shutdown(self): """ Server requested driver shutdown. Optionally implement this event handler to clean up or write data before the application is stopped. """ if self.data_logger: self.data_logger.close() self.data_logger = None def get_state(self, carstate): state = np.zeros(26) state[0] = carstate.speed_x state[1] = carstate.speed_y state[2] = carstate.speed_z state[3] = carstate.damage state[4] = carstate.distance_from_center state[5] = carstate.angle * (np.pi / 180) state[6] = carstate.z for index, edge in enumerate(carstate.distances_from_edge): state[7 + index] = edge return state def get_action(self, carstate, state): probability = np.random.uniform() if probability < self.exploration_rate: temp_action = self.steer(carstate, 0) action = ( np.absolute(np.asarray(self.action_space) - temp_action) ).argmin() # Pick the action that is closest to mediocre model if np.random.uniform() > 0.75: action = np.random.randint(0, len(self.action_space)) else: state = torch.from_numpy(np.array(state)) action = self.model( Variable(state, volatile=True).type(torch.FloatTensor)).data action = np.argmax(action.numpy()) return action def get_reward(self, carstate): #Reward function that is based on optimizing the speed in the right direction and minimizing the speed is wrong direction return carstate.speed_x * ( np.cos(carstate.angle * (np.pi / 180)) - np.absolute(np.sin(carstate.angle * (np.pi / 180)))) - np.absolute( carstate.distance_from_center) def print_stats(self): print("The average reward is: ", self.average_reward / self.counter) print("The average loss is: ", self.average_loss / self.train_counter) def update_state(self, pred, carstate): # # Roll the sequence so the last history is now at front # throwaway = self.input_sequence[0] # print(self.input_sequence.shape) state_t_plus = torch.FloatTensor(D_in) # print(state_t_plus) # sys.exit() #Overwrite old values with new prediction and carstate # print('[BEFORE]') # print(state_t_plus[0][2]) # sys.exit() state_t_plus[0] = pred.data[0] state_t_plus[1] = pred.data[1] state_t_plus[2] = pred.data[2] state_t_plus[3] = carstate.speed_x * 3.6 state_t_plus[4] = carstate.distance_from_center state_t_plus[5] = carstate.angle for index, edge in enumerate(carstate.distances_from_edge): state_t_plus[6 + index] = edge return state_t_plus def drive(self, carstate: State) -> Command: #Get current state state = self.get_state(carstate) # Get current action action = self.get_action(carstate, state) # Get current reward reward = self.get_reward(carstate) # Keep track of the average reward self.average_reward += reward if self.counter > 0: self.replay_memory.append( (self.previous_state, self.action, reward, state, False)) # Check if replay memory is full while len(self.replay_memory) > self.max_RM_size: del self.replay_memory[np.random.randint( 0, len(self.replay_memory))] command = Command() # Predict brake and accelerate out = self.model_acc_brake(Variable(self.input)) self.input = self.update_state(out, carstate) #Create command command = Command() command.brake = out.data[1] * 0.2 # Maximum speed for training, v_x = 300 self.counter += 1 self.counter_per_game += 1 self.accelerate(carstate, v_x, command) command.steering = self.action_space[action] self.action = action self.previous_state = state if carstate.damage > 0 or carstate.last_lap_time > 0: command.meta = 1 # Add terminal states to the replay memory if carstate.damage > 0: self.replay_memory.append( (self.previous_state, self.action, -100, np.ones( (26, )), True)) else: self.replay_memory.append( (self.previous_state, self.action, 1000, np.ones( (26, )), True)) self.save_variables() print("distance:, ", carstate.distance_from_start) print( "------------------------------------------------------------------------------" ) if self.exploration_rate == 0: print("TEST DRIVE AVERAGE REWARD IS: ", self.average_reward / self.counter_per_game) print("THE DISTANCE DRIVEN BY THE AGENT IS: ", carstate.distance_from_start) print("EPISODE ENDED") print( "------------------------------------------------------------------------------" ) return command def save_variables(self): with open("memory.txt", "wb") as fp: # save the Replay Memory pickle.dump(self.replay_memory, fp) def accelerate(self, carstate, target_speed, command): # compensate engine deceleration, but invisible to controller to # prevent braking: speed_error = 1.0025 * target_speed * MPS_PER_KMH - carstate.speed_x acceleration = self.acceleration_ctrl.control( speed_error, carstate.current_lap_time) # stabilize use of gas and brake: acceleration = math.pow(acceleration, 3) if acceleration > 0: if abs(carstate.distance_from_center) >= 1: # off track, reduced grip: acceleration = min(0.4, acceleration) command.accelerator = min(acceleration, 1) if carstate.rpm > 8000: command.gear = carstate.gear + 1 # else: # command.brake = min(-acceleration, 1) if carstate.rpm < 2500: command.gear = carstate.gear - 1 if not command.gear: command.gear = carstate.gear or 1 if command.gear < 1: command.gear = 1 def steer(self, carstate, target_track_pos): steering_error = target_track_pos - carstate.distance_from_center steering = self.steering_ctrl.control(steering_error, carstate.current_lap_time) return steering
class TestNeatDriver: """ Driving logic. Implement the driving intelligence in this class by processing the current car state as inputs creating car control commands as a response. The ``drive`` function is called periodically every 20ms and must return a command within 10ms wall time. """ def __init__(self, logdata=True, net=None): self.steering_ctrl = CompositeController( ProportionalController(0.4), IntegrationController(0.2, integral_limit=1.5), DerivativeController(2) ) self.acceleration_ctrl = CompositeController( ProportionalController(3.7), ) self.data_logger = DataLogWriter() if logdata else None self.eta = 20 self.counter = 0 self.model = simpleNetV2() self.weights = 'simpleNetV2_epoch_3_all_tracks.csv.pkl' self.model.load_state_dict(torch.load(self.weights)) self.input = torch.FloatTensor(D_in) self.track_check1 = False self.track_check2 = False self.action_neat = None self.net = net self.clock = time.time() self.done = False self.temp_fitness = 0 @property def range_finder_angles(self): """Iterable of 19 fixed range finder directions [deg]. The values are used once at startup of the client to set the directions of range finders. During regular execution, a 19-valued vector of track distances in these directions is returned in ``state.State.tracks``. """ return -90, -75, -60, -45, -30, -20, -15, -10, -5, 0, 5, 10, 15, 20, \ 30, 45, 60, 75, 90 def on_shutdown(self): """ Server requested driver shutdown. Optionally implement this event handler to clean up or write data before the application is stopped. """ if self.data_logger: self.data_logger.close() self.data_logger = None def make_input(self, carstate, out): inputs = [] inputs.extend([carstate.angle, carstate.speed_x]) inputs.extend(out[0], out[1]) return inputs def update_state(self, pred, carstate): # # Roll the sequence so the last history is now at front # throwaway = self.input_sequence[0] # print(self.input_sequence.shape) state_t_plus = torch.FloatTensor(D_in) # print(state_t_plus) # sys.exit() #Overwrite old values with new prediction and carstate # print('[BEFORE]') # print(state_t_plus[0][2]) # sys.exit() state_t_plus[0] = pred.data[0] state_t_plus[1] = pred.data[1] state_t_plus[2] = pred.data[2] state_t_plus[3] = carstate.speed_x *3.6 state_t_plus[4] = carstate.distance_from_center state_t_plus[5] = carstate.angle for index, edge in enumerate(carstate.distances_from_edge): state_t_plus[6 + index] = edge return state_t_plus def drive(self, carstate: State) -> Command: """ Produces driving command in response to newly received car state. This is a dummy driving routine, very dumb and not really considering a lot of inputs. But it will get the car (if not disturbed by other drivers) successfully driven along the race track.""" global net out = self.model(Variable(self.input)) self.input = self.update_state(out, carstate) inputs = self.make_input(carstate, out.data) if self.track_check1 == True and self.check_offtrack(carstate) == True: self.track_check2 = True if self.counter % 100 == 0: self.track_check1 = self.check_offtrack(carstate) self.temp_fitness += carstate.speed_x * (np.cos(carstate.angle*(np.pi/180)) - np.absolute(np.sin(carstate.angle * (np.pi/180)))) self.counter += 1 outputs = net.activate(inputs) command = Command() command.accelerator = outputs[0] command.brake = outputs[1] command.steering = outputs[2] v_x = 350 self.counter += 1 self.accelerate(carstate, v_x, command) if self.data_logger: self.data_logger.log(carstate, command) if carstate.damage >= 9500 or carstate.last_lap_time > 0 or carstate.current_lap_time > 60: positions_won = 10 - carstate.race_position damage = (carstate.damage) / 1000 global fitness fitness = self.eta + (self.temp_fitness/self.counter) + positions_won - damage command.meta = 1 return command def check_offtrack(self, carstate): counter = 0 for values in carstate.distances_from_edge: if values == -1: counter += 1 if counter == len(carstate.distances_from_edge): return True else: return False def accelerate(self, carstate, target_speed, command): # compensate engine deceleration, but invisible to controller to # prevent braking: speed_error = 1.0025 * target_speed * MPS_PER_KMH - carstate.speed_x acceleration = self.acceleration_ctrl.control( speed_error, carstate.current_lap_time ) # stabilize use of gas and brake: acceleration = math.pow(acceleration, 3) if acceleration > 0: if abs(carstate.distance_from_center) >= 1: # off track, reduced grip: acceleration = min(0.4, acceleration) command.accelerator = min(acceleration, 1) if carstate.rpm > 8000: command.gear = carstate.gear + 1 # else: # command.brake = min(-acceleration, 1) if carstate.rpm < 2500: command.gear = carstate.gear - 1 if not command.gear: command.gear = carstate.gear or 1 def steer(self, carstate, target_track_pos, command): steering_error = target_track_pos - carstate.distance_from_center command.steering = self.steering_ctrl.control( steering_error, carstate.current_lap_time )