Exemplo n.º 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
        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
Exemplo n.º 2
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 = 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)
Exemplo n.º 3
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)
Exemplo n.º 4
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
Exemplo n.º 5
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
        )
Exemplo n.º 6
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
        )
Exemplo n.º 7
0
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
Exemplo n.º 8
0
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