def actions(self, ship: SpaceShip, input_data: Dict[str, Tuple]) -> None:
        """
        Compute control actions of the ship. Perform all command actions via the ``ship``
        argument. This class acts as an intermediary between the controller and the environment.

        The environment looks for this function when calculating control actions for the Ship sprite.

        :param ship: Object to use when controlling the SpaceShip
        :param input_data: Input data which describes the current state of the environment
        """
        ship.shoot()
    def actions(self, ship: SpaceShip, input_data: Dict[str, Tuple]) -> None:
        """
        Compute control actions of the ship. Perform all command actions via the ``ship``
        argument. This class acts as an intermediary between the controller and the environment.

        The environment looks for this function when calculating control actions for the Ship sprite.

        :param ship: Object to use when controlling the SpaceShip
        :param input_data: Input data which describes the current state of the environment
        """

        #### MAIN ####
        # ship positions
        x, y = ship.position
        sx = x  # [m]
        sy = y  # [m]

        # asteriod positions
        asteriods = []
        for x in input_data['asteroids']:
            asteriods.append([x['position'], x['velocity']])

        circles = []
        ychange = 600
        xchange = 800
        radius = 150
        circles.append([(sx, sy), radius, 1])
        circles.append([(sx + xchange, sy), radius, 0])
        circles.append([(sx, sy + ychange), radius, 0])
        circles.append([(sx + xchange, sy + ychange), radius, 0])
        circles.append([(sx - xchange, sy + ychange), radius, 0])
        circles.append([(sx - xchange, sy), radius, 0])
        circles.append([(sx - xchange, sy - ychange), radius, 0])
        circles.append([(sx, sy - ychange), radius, 0])
        circles.append([(sx + xchange, sy - ychange), radius, 0])

        circles = list(map(lambda a: inRectangle(a), circles))

        avoidanceFisInputs = []
        for c in circles:
            if c[2] == 1:
                for asteriod in asteriods:
                    if distanceFormula(asteriod[0], c[0]) < c[1]:
                        avoidanceFisInputs.append(
                            findFISInputs(c, ship, asteriod))
        #distance, relative heading, closure rate

        num_asteroids = len(input_data['asteroids'])
        X = np.ndarray((num_asteroids, 2))
        for e in range(num_asteroids):
            X[e] = [
                input_data['asteroids'][e]['position'][0],
                input_data['asteroids'][e]['position'][1]
            ]
        try:
            centers = c_means(X, nodes=3)
        except:
            centers = None
        clusterFisInputs = []

        if centers is not None:
            for each_center in centers:
                clusterFisInputs.append(findClusterInputs(ship, each_center))
        # distance, relative heading, closure rate

        turn_rate_each = []
        thrust_each = []
        l_Variables = []
        l_output = []
        for each_asteroid in avoidanceFisInputs:
            ins = [['relative_heading', each_asteroid[1] - 180],
                   ['distance', each_asteroid[0] / radius],
                   ['closure_rate', each_asteroid[2]]]
            lv = self.linguitify(each_asteroid, radius)
            l_Variables.append(lv)
            [turn1, thrust1] = self.A1.compute2Plus(ins,
                                                    ['turn_rate', 'thrust'])
            turn_rate_each.append(turn1)
            thrust_each.append(thrust1)
            l_output = self.linguistify_output(turn_rate_each[0],
                                               thrust_each[0])
        #print(l_Variables)

        #print(l_output)
        for each_cluster in clusterFisInputs:
            ins = [['relative_heading', each_cluster[1] - 180],
                   ['distance', each_cluster[0] / 500],
                   ['closure_rate', each_cluster[2]]]
            [turn2, thrust2] = self.C1.compute2Plus(ins,
                                                    ['turn_rate', 'thrust'])
            turn_rate_each.append(turn2)
            thrust_each.append(thrust2)

        if turn_rate_each:
            ship.turn_rate = sum(turn_rate_each) / len(turn_rate_each)
            thrust = sum(thrust_each) / len(thrust_each)
        else:
            thrust = 0

        if thrust > 0.075:
            ship.thrust = ship.thrust_range[1]
        elif thrust < -0.075:
            ship.thrust = ship.thrust_range[0]
        else:
            ship.thrust = 0

        if abs(ship.velocity[1]) > 1.2 or abs(ship.velocity[0]) > 1.2:
            ship.shoot()
 def actions(self, ship: SpaceShip, input_data: Dict[str, Any]) -> None:
     ship.turn_rate = ship.turn_rate_range[0] * math.cos(
         input_data["frame"] * 10)
 def actions(self, ship: SpaceShip, input_data: Dict[str, Any]) -> None:
     ship.turn_rate = ship.turn_rate_range[0]
Example #5
0
    def actions(self, ship: SpaceShip, input_data: Dict[str, Tuple]) -> None:
        """
        Compute control actions of the ship. Perform all command actions via the ``ship``
        argument. This class acts as an intermediary between the controller and the environment.

        The environment looks for this function when calculating control actions for the Ship sprite.

        :param ship: Object to use when controlling the SpaceShip
        :param input_data: Input data which describes the current state of the environment
        """


        #### MAIN ####
        # ship positions
        x, y = ship.position
        sx = x  # [m]
        sy = y  # [m]

        # asteriod positions
        asteriods = []
        for x in input_data['asteroids']:
            asteriods.append([x['position'], x['velocity']])

        # create bounding radius
        circles = []
        ychange = 600
        xchange = 800
        radius = 150
        circles.append([(sx, sy), radius, 1])
        circles.append([(sx + xchange, sy), radius, 0])
        circles.append([(sx, sy + ychange), radius, 0])
        circles.append([(sx + xchange, sy + ychange), radius, 0])
        circles.append([(sx - xchange, sy + ychange), radius, 0])
        circles.append([(sx - xchange, sy), radius, 0])
        circles.append([(sx - xchange, sy - ychange), radius, 0])
        circles.append([(sx, sy - ychange), radius, 0])
        circles.append([(sx + xchange, sy - ychange), radius, 0])

        circles = list(map(lambda a: inRectangle(a), circles))

        # obtain Inputs for the 150 radius AVOIDANCE FIS
        avoidanceFisInputs = []
        for c in circles:
            if c[2] == 1:
                for asteriod in asteriods:
                    if distanceFormula(asteriod[0], c[0]) < c[1]:
                        avoidanceFisInputs.append(findFISInputs(c, ship, asteriod))

        # Obtain inputs for the CLUSTER FIS
        num_asteroids = len(input_data['asteroids'])
        X = np.ndarray((num_asteroids, 2))
        for e in range(num_asteroids):
            X[e] = [input_data['asteroids'][e]['position'][0], input_data['asteroids'][e]['position'][1]]
        try:
            centers = c_means(X, nodes=3)
        except:
            centers = None
        clusterFisInputs = []

        if centers is not None:
            for each_center in centers:
                clusterFisInputs.append(findClusterInputs(ship, each_center))

        # Compute FIS outputs for the AVOIDANCE FIS
        turn_rate_each = []
        thrust_each = []
        for each_asteroid in avoidanceFisInputs:
            ins = [['relative_heading', each_asteroid[1]-180], ['distance', each_asteroid[0]/radius], ['closure_rate', each_asteroid[2]]]
            [turn1, thrust1] = self.A1.compute2Plus(ins, ['turn_rate', 'thrust'])
            turn_rate_each.append(turn1)
            thrust_each.append(thrust1)

        # Compute FIS outputs for the CLUSTER FIS
        for each_cluster in clusterFisInputs:
            ins = [['relative_heading', each_cluster[1]-180], ['distance', each_cluster[0]/500], ['closure_rate', each_cluster[2]]]
            [turn2, thrust2] = self.C1.compute2Plus(ins, ['turn_rate', 'thrust'])
            turn_rate_each.append(turn2)
            thrust_each.append(thrust2)

        # Determine the turn rate by averaging all crisp outputs
        if turn_rate_each:
            ship.turn_rate = sum(turn_rate_each)/len(turn_rate_each)
            thrust = sum(thrust_each)/len(thrust_each)
        else:
            thrust = 0

        # Determine thrust input
        if thrust > 0.075:
            ship.thrust = ship.thrust_range[1]
        elif thrust < -0.075:
            ship.thrust = ship.thrust_range[0]
        else:
            ship.thrust = 0

        # Determine Shooting Output
        distance_total = 0
        invaders = 0
        avoidanceFisInputs = []
        for c in circles:
            if c[2] == 1:
                for asteriod in asteriods:
                    if distanceFormula(asteriod[0], c[0]) < c[1]:
                        avoidanceFisInputs.append(findFISInputs(c, ship, asteriod))
                        invaders += 1
                        distance_total += distanceFormula(asteriod[0], c[0]) / 150

        shootingFisInputs = [distance_total / len(asteriods), invaders / len(asteriods)]

        shoot = self.S1.compute([['average_distance', shootingFisInputs[0]], ['invaders', shootingFisInputs[1]]], 'shooting')

        print(shoot)

        if shoot < 0.45:
            ship.shoot()
    def actions(self, ship: SpaceShip, input_data: Dict[str, Tuple]) -> None:
        """
        Compute control actions of the ship. Perform all command actions via the ``ship``
        argument. This class acts as an intermediary between the controller and the environment.

        The environment looks for this function when calculating control actions for the Ship sprite.

        :param ship: Object to use when controlling the SpaceShip
        :param input_data: Input data which describes the current state of the environment
        """

        def extract_norms(collision_array):
            collision_norms = []
            collision_array = collision_array.tolist()
            for x, y in zip(*collision_array):
                vnorm = np.linalg.norm([x, y])
                collision_norms.append(vnorm)
            return collision_norms

        def extend_path(asteroid_list, n):
            asteroid_path = []
            for asteroid in asteroid_list:
                x, y = asteroid['position']
                vx, vy = asteroid['velocity']
                xpath = x + np.multiply(np.arange(1, n, 1), vx)
                ypath = y + np.multiply(np.arange(1, n, 1), vy)
                path = np.stack((xpath, ypath))
                asteroid_path.append(path)
            return asteroid_path

        def extend_player_path(player, n):
            x, y = player.center_x, player.center_y
            vx, vy = player.change_x, player.change_y
            xpath = x + np.multiply(np.arange(1, n, 1), vx)
            ypath = y + np.multiply(np.arange(1, n, 1), vy)
            return np.stack((xpath, ypath))

        def get_distance(self, asteroid_list):

            def get_xy_distance(x1, y1, x2, y2):
                distance1 = ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5
                return distance1
            asteroid_array = []
            if not asteroid_list:
                return None
            for asteroid in asteroid_list:
                asteroid_center_x = asteroid['position'][0]
                asteroid_center_y = asteroid['position'][1]
                current_distance = get_xy_distance(asteroid_center_x, asteroid_center_y, ship.center_x, ship.center_y)
                asteroid_array.append(current_distance)
            return asteroid_array


        def get_angle(self, asteroid_list):
            angle_array = []

            if not asteroid_list:
                return None, None

            for asteroid in asteroid_list:
                local_x = ship.center_x - asteroid['position'][0]
                local_y = ship.center_y - asteroid['position'][1]
                phi = math.atan2(local_y, local_x) * 180 / math.pi
                angle = phi + 90 - ship.angle

                while angle > 180 or angle < -180:
                    if angle > 180:
                        angle -= 360
                    elif angle < -180:
                        angle += 360
                angle_array.append(angle)

            return angle_array

        def get_drive_angle(self, goal):
            local_x = ship.center_x - goal[0]
            local_y = ship.center_y - goal[1]
            phi = math.atan2(local_y, local_x) * 180 / math.pi
            angle = phi + 90 - ship.angle
            return angle

# Targeting FIS
        aMF1, aMF2, aMF3 = self.MF1
        dMF1, dMF2, dMF3 = self.MF2
        sMF1, sMF2, sMF3 = self.MF4
        Fr1 = self.Fr1

        asteroid_list = input_data['asteroids']
        angle = get_angle(self, asteroid_list)
        distance = get_distance(self, asteroid_list)

        shoot_list = []
        if angle and distance:
            for ang, dist in zip(angle, distance):
                in1 = ang
                in2 = dist

                angleMF1 = aMF1.lshlder(in1)
                angleMF2 = aMF2.triangle(in1)
                angleMF3 = aMF3.rshlder(in1)

                distanceMF1 = dMF1.lshlder(in2)
                distanceMF2 = dMF2.triangle(in2)
                distanceMF3 = dMF3.rshlder(in2)

                F_rules = [Fr1.AND_rule([angleMF1, distanceMF1]), Fr1.AND_rule([angleMF1, distanceMF2]), Fr1.AND_rule([angleMF1, distanceMF3]),
                           Fr1.AND_rule([angleMF2, distanceMF1]), Fr1.AND_rule([angleMF2, distanceMF2]), Fr1.AND_rule([angleMF2, distanceMF3]),
                           Fr1.AND_rule([angleMF3, distanceMF1]), Fr1.AND_rule([angleMF3, distanceMF2]), Fr1.AND_rule([angleMF3, distanceMF3])
                           ]

                F_shoot = []
                F_dont_shoot = []

                fRules = [1, 1, 1, 2, 2, 2, 1, 1, 1]

                for idx, rule in enumerate(fRules):
                    if rule == 2.0:
                        F_shoot.append(F_rules[idx])
                    elif rule == 1.0:
                        F_dont_shoot.append(F_rules[idx])

                F_s = Fr1.OR_rule(F_shoot)
                F_d = Fr1.OR_rule(F_dont_shoot)

                F_mu = [F_d, F_s]
                F_out = Defuzz(F_mu, self.MF3)
                output = F_out.defuzz_out()
                shoot_list.append(output)

            if any(x > 6 for x in shoot_list):
                ship.shoot()

            n = 10
            asteroid_path = extend_path(asteroid_list, n)
            player_path = extend_player_path(ship, n)

            collision_array = [collide - player_path for collide in asteroid_path]
            collision_norms = list(map(extract_norms, collision_array))
            s = collision_norms.index(min(collision_norms, key=min))

# Aiming FIS
            shoot_idx = np.argmin(np.absolute(angle))
            shoot_angle = angle[s]

            steerMF1 = sMF1.lshlder(shoot_angle)
            steerMF2 = sMF2.triangle(shoot_angle)
            steerMF3 = sMF3.rshlder(shoot_angle)

            F_mus = [steerMF1, steerMF2, steerMF3]
            F_out2 = Defuzz(F_mus, self.MF5)
            output2 = F_out2.defuzz_out()
            ship.turn_rate = output2