Example #1
0
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)
Example #2
0
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
Example #3
0
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
Example #4
0
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
        )
Example #5
0
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
        )
Example #6
0
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
Example #7
0
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