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 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 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): # 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 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 )
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): 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