예제 #1
0
    def _calc_projectile_path_avoidance(self):

        rocket_location = self.history.rocket.location
        turret_location = self.parameters.turret.location

        projectile_path_avoidance = []
        for projectile in self.history.active_projectiles:
            gradient = math.tan(projectile.firing_angle)
            y_intercept = turret_location.y - gradient * turret_location.x
            y_value = gradient * rocket_location.x + y_intercept
            avoidance_angle = normalise_angle(
                projectile.firing_angle +
                (1 if rocket_location.y > y_value else -1) * math.pi / 2)
            min_dist_rocket2path = self.calc_minimum_distance_from_location2line(
                rocket_location, gradient, y_intercept)
            projectile_location = self.helpers.calc_projectile_location(
                projectile)
            dist_rockt2projectile = rocket_location.distance2(
                projectile_location)
            try:
                avoidance_strength = 1 / (
                    min_dist_rocket2path *
                    (dist_rockt2projectile -
                     self.parameters.rocket.target_radius))
            except ZeroDivisionError:
                avoidance_strength = float("inf")
            projectile_path_avoidance.append(
                PolarCoordinate(avoidance_strength,
                                avoidance_angle).pol2cart())

        return (average(projectile_path_avoidance)
                if projectile_path_avoidance else Coordinate(0.0, 0.0))
예제 #2
0
    def _calc_single_obstacle_shadow_attraction(
            self, obstacle: Coordinate) -> Coordinate:

        # TODO: Make this more efficient by storing it between cycles
        # TODO: Deal with perfectly vertical gradients
        angle_turret2obstacle = (obstacle.location -
                                 self.parameters.turret.location).angle

        edge_gradients = self.calc_shadow_edge_gradients(obstacle)
        shadow_attractions = []
        rocket_location = self.history.rocket.location
        for gradient in edge_gradients:
            y_intercept = Line.calculate_y_intercept(
                gradient, self.parameters.turret.location)
            shadow_edge_line = Line(gradient, y_intercept)
            closest_point = shadow_edge_line.closest_point_on_line(
                rocket_location)
            strength = 1 / rocket_location.distance2(closest_point)
            angle_turret2closest_point = (
                closest_point - self.parameters.turret.location).angle
            if normalise_angle(angle_turret2closest_point -
                               angle_turret2obstacle) > 0:
                rotation = -1
            else:
                rotation = 1
            direction_angle = angle_turret2closest_point + rotation * math.pi / 2
            shadow_attractions.append(
                PolarCoordinate(strength, direction_angle).pol2cart())

        return sum(shadow_attractions)
예제 #3
0
    def will_projectile_hit_rocket_before_obstacle(self):

        projectile_location = self.parameters.turret.location
        projectile_speed = self.parameters.turret.projectile_speed
        projectile_angle = self.history.turret.angle
        projectile_velocity = PolarCoordinate(projectile_speed,
                                              projectile_angle).pol2cart()

        rocket_location = self.history.rocket.location
        rocket_velocity = self.physics.calc_rocket_velocity()

        projectile2rocket = RelativeObjects(projectile_location,
                                            rocket_location,
                                            projectile_velocity,
                                            rocket_velocity)

        rocket_output = projectile2rocket.time_objects_first_within_distance(
            self.parameters.rocket.target_radius)
        if rocket_output is None:
            return False  # Doesn't hit rocket at all
        time_rocket_intercept, _ = rocket_output

        for obstacle in self.parameters.environment.obstacles:
            projectile2obstacle = RelativeObjects(projectile_location,
                                                  obstacle.location,
                                                  projectile_velocity)
            obstacle_output = projectile2obstacle.time_objects_first_within_distance(
                obstacle.radius)
            if obstacle_output is None:
                continue
            time_obstacle_intercept, _ = obstacle_output
            if time_obstacle_intercept < time_rocket_intercept:
                return False

        return True
예제 #4
0
    def will_projectile_hit_rocket_within_bounds(self):

        safety_buffer = 2.0

        projectile_location = self.parameters.turret.location
        projectile_speed = self.parameters.turret.projectile_speed
        projectile_angle = self.history.turret.angle
        projectile_velocity = PolarCoordinate(projectile_speed,
                                              projectile_angle).pol2cart()

        rocket_location = self.history.rocket.location
        rocket_velocity = self.physics.calc_rocket_velocity()

        projectile2rocket = RelativeObjects(projectile_location,
                                            rocket_location,
                                            projectile_velocity,
                                            rocket_velocity)

        (
            min_dist,
            _,
            (projectile_location_min_dist, rocket_location_min_dist),
        ) = projectile2rocket.minimum_distance_between_objects()

        return (
            min_dist <= self.parameters.rocket.target_radius / safety_buffer
            and self.helpers.is_within_bounds(projectile_location_min_dist)
            and self.helpers.is_within_bounds(rocket_location_min_dist))
예제 #5
0
    def _calc_within_buffer_projectile_avoidance(self, safety_factor=2.0):

        rocket_location = self.history.rocket.location
        rocket_velocity = self.physics.calc_rocket_velocity()

        within_buffer_projectile_avoidance = []
        for projectile in self.history.active_projectiles:
            projectile_location = self.helpers.calc_projectile_location(
                projectile)
            projectile_velocity = self.helpers.calc_projectile_velocity(
                projectile)
            rocket2projectile = RelativeObjects(
                rocket_location,
                projectile_location,
                rocket_velocity,
                projectile_velocity,
            )
            (
                min_dist,
                _,
                (rocket_location_min_dist, projectile_location_min_dist),
            ) = rocket2projectile.minimum_distance_between_objects()
            buffer = safety_factor * self.parameters.rocket.target_radius
            if min_dist > buffer:
                continue

            output = rocket2projectile.time_objects_first_within_distance(
                buffer)
            if output:  # Rocket is currently outside buffer
                (
                    time_rocket_enters_projectile_buffer,
                    (rocket_location_enter_buffer,
                     projectile_location_enter_buffer),
                ) = output

                # Check if the collision is out of bounds
                if not self.helpers.is_within_bounds(
                        rocket_location_enter_buffer
                ) or not self.helpers.is_within_bounds(
                        projectile_location_enter_buffer):
                    continue

            current_dist = (
                self.controller_helpers.
                calc_dist_between_rocket_and_projectile(projectile))
            try:
                avoidance_strength = 1 / (
                    min_dist *
                    (current_dist - self.parameters.rocket.target_radius))
            except ZeroDivisionError:
                avoidance_strength = float("inf")
            avoidance_angle = (rocket_location_min_dist -
                               projectile_location_min_dist).angle
            within_buffer_projectile_avoidance.append(
                PolarCoordinate(avoidance_strength,
                                avoidance_angle).pol2cart())

        return (average(within_buffer_projectile_avoidance) if
                within_buffer_projectile_avoidance else Coordinate(0.0, 0.0))
예제 #6
0
    def _plot_engine_thrust(
        self, force, projection_location, relative_engine_angle, engine_plot
    ):

        rocket_angle = self.history.rocket.angle
        projection_angle = normalise_angle(rocket_angle + relative_engine_angle)

        max_main_engine_force = self.parameters.rocket.max_main_engine_force
        rocket_length = self.parameters.rocket.length
        thrust_ratio = force / max_main_engine_force
        edge_length = (
            self.visual.rocket_length_max_thrust_length_ratio
            * rocket_length
            * thrust_ratio
        )

        left_angle = normalise_angle(projection_angle + self.visual.thrust_cone_angle)
        relative_thrust_left_location = PolarCoordinate(
            edge_length, left_angle
        ).pol2cart()
        thrust_left_location = projection_location + relative_thrust_left_location

        right_angle = normalise_angle(projection_angle - self.visual.thrust_cone_angle)
        relative_thrust_right_location = PolarCoordinate(
            edge_length, right_angle
        ).pol2cart()
        thrust_right_location = projection_location + relative_thrust_right_location

        engine_plot.set_data(
            [
                projection_location.x,
                thrust_left_location.x,
                thrust_right_location.x,
                projection_location.x,
            ],
            [
                projection_location.y,
                thrust_left_location.y,
                thrust_right_location.y,
                projection_location.y,
            ],
        )
예제 #7
0
    def _calc_intersecting_projectile_avoidance(self):

        rocket_location = self.history.rocket.location
        rocket_velocity = self.physics.calc_rocket_velocity()

        intersecting_projectile_avoidance = []
        for projectile in self.history.active_projectiles:
            projectile_location = self.helpers.calc_projectile_location(
                projectile)
            projectile_velocity = self.helpers.calc_projectile_velocity(
                projectile)
            rocket2projectile = RelativeObjects(
                rocket_location,
                projectile_location,
                rocket_velocity,
                projectile_velocity,
            )
            (
                min_dist,
                _,
                (rocket_location_min_dist, projectile_location_min_dist),
            ) = rocket2projectile.minimum_distance_between_objects()

            # Check if the projectile will ever get close enough
            threshold = self.parameters.rocket.target_radius
            if min_dist > threshold:
                continue

            (
                time_projectile_hits_rocket,
                (rocket_location_hit, projectile_location_hit),
            ) = rocket2projectile.time_objects_first_within_distance(threshold)

            # Check if the collision is out of bounds
            if not self.helpers.is_within_bounds(
                    rocket_location_hit) or not self.helpers.is_within_bounds(
                        projectile_location_hit):
                continue

            dist2collision = rocket_location.distance2(rocket_location_hit)
            try:
                avoidance_strength = 1 / (min_dist * dist2collision)
            except ZeroDivisionError:
                avoidance_strength = float("inf")
            avoidance_angle = (rocket_location_min_dist -
                               projectile_location_min_dist).angle
            intersecting_projectile_avoidance.append(
                PolarCoordinate(avoidance_strength,
                                avoidance_angle).pol2cart())

        return (average(intersecting_projectile_avoidance)
                if intersecting_projectile_avoidance else Coordinate(0.0, 0.0))
예제 #8
0
    def get_rocket_ends(self):

        rocket_location = self.history.rocket.location
        rocket_angle = self.history.rocket.angle
        rocket_length = self.parameters.rocket.length

        relative_rocket_end = PolarCoordinate(
            rocket_length / 2, rocket_angle
        ).pol2cart()

        rocket_front_location = rocket_location + relative_rocket_end
        rocket_rear_location = rocket_location - relative_rocket_end

        return rocket_front_location, rocket_rear_location
예제 #9
0
    def _calc_projectile_avoidance(self):

        rocket_location = self.history.rocket.location

        projectile_avoidance = []
        for projectile in self.history.active_projectiles:
            delta = rocket_location - self.helpers.calc_projectile_location(
                projectile)
            avoidance_strength = 1 / (delta.magnitude -
                                      self.parameters.rocket.target_radius)
            projectile_avoidance.append(
                PolarCoordinate(avoidance_strength, delta.angle).pol2cart())

        return (average(projectile_avoidance)
                if projectile_avoidance else Coordinate(0.0, 0.0))
예제 #10
0
    def _calc_obstacle_avoidance(self):

        rocket_location = self.history.rocket.location

        obstacle_avoidance = []
        for obstacle in self.parameters.environment.obstacles:
            delta = rocket_location - obstacle.location
            avoidance_strength = 1 / (delta.magnitude - obstacle.radius -
                                      self.parameters.rocket.target_radius)
            obstacle_avoidance.append(
                PolarCoordinate(
                    avoidance_strength,
                    delta.angle,
                ).pol2cart())

        return (average(obstacle_avoidance)
                if obstacle_avoidance else Coordinate(0.0, 0.0))
예제 #11
0
    def plot_turret_barrel(self):

        barrel_length = (
            self.visual.barrel_length_turret_radius_ratio
            * self.parameters.turret.radius
        )

        turret_location = self.parameters.turret.location
        turret_angle = self.history.turret.angle
        relative_barrel_tip_location = PolarCoordinate(
            barrel_length, turret_angle
        ).pol2cart()

        barrel_tip_location = turret_location + relative_barrel_tip_location

        self.turret_barrel.set_data(
            [turret_location.x, barrel_tip_location.x],
            [turret_location.y, barrel_tip_location.y],
        )
예제 #12
0
    def get_engine_bridge_ends(self):

        _, rocket_rear_location = self.get_rocket_ends()

        rocket_length = self.parameters.rocket.length
        engine_bridge_width = (
            self.visual.rocket_length_engine_bridge_width_ratio * rocket_length
        )

        rocket_angle = self.history.rocket.angle

        perpendicular_angle = normalise_angle(rocket_angle + math.pi / 2)
        relative_engine_end = PolarCoordinate(
            engine_bridge_width / 2, perpendicular_angle
        ).pol2cart()

        engine_bridge_left_location = rocket_rear_location + relative_engine_end
        engine_bridge_right_location = rocket_rear_location - relative_engine_end

        return engine_bridge_left_location, engine_bridge_right_location
예제 #13
0
    def _calc_turret_attraction(self):

        min_turret_pull = 0.01
        max_turret_pull = 0.1

        attraction_angle = self.controller_helpers.calc_angle2turret_relative2rocket(
        )

        dist2turret = self.controller_helpers.calc_dist_between_rocket_and_turret(
        )
        turret_radius = self.parameters.turret.radius
        rocket_radius = self.parameters.rocket.target_radius

        attraction_strength = 1 / (dist2turret - rocket_radius - turret_radius)

        clamped_attraction_strength = self.clamp(attraction_strength,
                                                 min_turret_pull,
                                                 max_turret_pull)

        return PolarCoordinate(clamped_attraction_strength,
                               attraction_angle).pol2cart()
예제 #14
0
    def _calc_within_buffer_obstacle_avoidance(self, safety_factor=2.0):

        rocket_location = self.history.rocket.location
        rocket_velocity = self.physics.calc_rocket_velocity()

        within_buffer_obstacle_avoidance = []
        for obstacle in self.parameters.environment.obstacles:
            rocket2obstacle = RelativeObjects(rocket_location,
                                              obstacle.location,
                                              rocket_velocity)
            (
                min_dist,
                _,
                (rocket_location_min_dist, _),
            ) = rocket2obstacle.minimum_distance_between_objects()
            buffer = safety_factor * (self.parameters.rocket.target_radius +
                                      obstacle.radius)
            if min_dist > buffer:
                continue  # Rocket doesn't come within buffer

            output = rocket2obstacle.time_objects_first_within_distance(buffer)
            if output:  # Rocket is currently outside buffer
                time_rocket_enter_buffer, (rocket_location_enter_buffer,
                                           _) = output
                if not self.helpers.is_within_bounds(
                        rocket_location_enter_buffer):
                    continue  # Rocket will be out of bounds before it enters buffer

            try:
                avoidance_strength = 1 / min_dist
            except ZeroDivisionError:
                avoidance_strength = float("inf")
            avoidance_angle = (rocket_location_min_dist -
                               obstacle.location).angle
            within_buffer_obstacle_avoidance.append(
                PolarCoordinate(avoidance_strength,
                                avoidance_angle).pol2cart())

        return (average(within_buffer_obstacle_avoidance)
                if within_buffer_obstacle_avoidance else Coordinate(0.0, 0.0))
예제 #15
0
    def _calc_intersecting_obstacle_avoidance(self):

        rocket_location = self.history.rocket.location
        rocket_velocity = self.physics.calc_rocket_velocity()

        intersecting_obstacle_avoidance = []
        for obstacle in self.parameters.environment.obstacles:
            rocket2obstacle = RelativeObjects(rocket_location,
                                              obstacle.location,
                                              rocket_velocity)
            (
                min_dist,
                _,
                (rocket_location_min_dist, _),
            ) = rocket2obstacle.minimum_distance_between_objects()
            threshold = self.parameters.rocket.target_radius + obstacle.radius
            if min_dist <= threshold and self.helpers.is_within_bounds(
                    rocket_location_min_dist):
                _, (
                    rocket_location_thresh_dist,
                    _,
                ) = rocket2obstacle.time_objects_first_within_distance(
                    threshold)
                dist2threshold = rocket_location.distance2(
                    rocket_location_thresh_dist)

                try:
                    avoidance_strength = obstacle.radius / (min_dist *
                                                            dist2threshold)
                except ZeroDivisionError:
                    avoidance_strength = float("inf")
                avoidance_angle = (rocket_location_min_dist -
                                   obstacle.location).angle
                intersecting_obstacle_avoidance.append(
                    PolarCoordinate(avoidance_strength,
                                    avoidance_angle).pol2cart())

        return (average(intersecting_obstacle_avoidance)
                if intersecting_obstacle_avoidance else Coordinate(0.0, 0.0))
예제 #16
0
    def _calc_firing_path_avoidance(self):

        rocket_location = self.history.rocket.location
        turret_location = self.parameters.turret.location

        recharge_factor = self._calc_recharge_factor()
        rotation_factor = self._calc_rotation_factor()

        turret_angle = self.history.turret.angle
        gradient = math.tan(turret_angle)
        y_intercept = turret_location.y - gradient * turret_location.x
        y_value = gradient * rocket_location.x + y_intercept
        avoidance_angle = normalise_angle(
            turret_angle +
            (1 if rocket_location.y > y_value else -1) * math.pi / 2)
        min_dist_rocket2path = self.calc_minimum_distance_from_location2line(
            rocket_location, gradient, y_intercept)
        dist_rockt2projectile = (
            self.controller_helpers.calc_dist_between_rocket_and_turret())
        return PolarCoordinate(
            rotation_factor * recharge_factor /
            (min_dist_rocket2path * dist_rockt2projectile),
            avoidance_angle,
        ).pol2cart()
예제 #17
0
    def calc_projectile_velocity(self, projectile):

        angle = projectile.firing_angle
        velocity = self.parameters.turret.projectile_speed

        return PolarCoordinate(velocity, angle).pol2cart()