예제 #1
0
 def test_find_mean_angle_wrap_around_2(self):
     angles = [354, 5]
     mean_angle = geometry.find_mean_angle(angles, 11)
     expected_mean = 359.5
     self.assertAlmostEqual(mean_angle, expected_mean, 1)
예제 #2
0
 def test_find_mean_angle_big_difference(self):
     angles = [161.59438184601854, 246.7735850288153]
     mean_angle = geometry.find_mean_angle(angles, 179)
     self.assertAlmostEqual(mean_angle, 204.2, 1)
예제 #3
0
 def test_find_mean_angle(self):
     angles = [299.19, 305.42]
     mean_angle = geometry.find_mean_angle(angles, 8)
     expected_mean = (299.19 + 305.42) / 2
     self.assertAlmostEqual(mean_angle, expected_mean, 1)
예제 #4
0
    def approximate_position_direction_speed(
            self, minimum_data_points_used) -> (Coordinate, int, int):
        if self.projection is not None:
            return self.projection

        if len(self.position_history.list) <= 1:
            return None, None, None  # No information can be deduced about movement of ball
        history = self.position_history.list

        time_1 = history[0][1]
        time_2 = history[1][1]
        c1: Coordinate = history[0][0]
        c2: Coordinate = history[1][0]
        first_coord = c1
        last_coord = c2

        if time_1 == time_2 or c1.euclidean_distance_from(
                c2) < 0.1 or c1.euclidean_distance_from(c2) > 4.2:
            return c1, 0, 0

        final_speed = (c1.euclidean_distance_from(c2) /
                       (time_1 - time_2)) * BALL_DECAY
        final_direction = degrees(calculate_full_origin_angle_radians(c1, c2))
        angles = [final_direction]  # Used for calculating 'average' angle

        max_deviation = 50  # angle deviation
        max_speed_deviation = 0.8
        age = time_1 - time_2
        max_age = 20

        def allowed_angle_deviation(index):
            return 90 if index == 0 else max_deviation

        previous_dist = final_speed
        data_points_used = 2
        for i, pos_and_time in enumerate(islice(history, 2, len(history))):
            c1 = c2
            c2 = pos_and_time[0]
            time_1 = time_2
            time_2 = pos_and_time[1]
            age += time_1 - time_2

            dist = c1.euclidean_distance_from(c2)
            if time_1 == time_2 or dist <= 0.05 or (
                    dist < 0.3 and previous_dist < 0.3) or dist > 4.2:
                break
            previous_dist = dist

            # calculate angle from point observed 2 ticks prior
            direction = degrees(
                calculate_full_origin_angle_radians(history[i][0], c2))
            direction_similar = is_angle_in_range(
                direction,
                (final_direction - allowed_angle_deviation(i)) % 360,
                (final_direction + allowed_angle_deviation(i)) % 360)

            speed = (dist / (time_1 - time_2)) * pow(BALL_DECAY, age)
            speed_similar = (final_speed - max_speed_deviation) <= speed <= (
                final_speed + max_speed_deviation)

            if direction_similar and speed_similar and age < max_age:
                data_points_used += 1
                last_coord = c2
                angles.append(
                    degrees(
                        calculate_full_origin_angle_radians(first_coord, c2)))
                final_speed = (final_speed * age + speed) / (
                    age + 1)  # calculate average with new value
                final_direction = find_mean_angle(angles, 179)
            else:
                debug_msg(
                    "Previous points did not match. Speed : " + str(speed) +
                    "vs." + str(final_speed) + "| Direction :" +
                    str(direction) + "vs." + str(final_direction) + "| age: " +
                    str(age) + str(c1) + str(c2), "POSITIONAL")
                break  # This vector did not fit projection, so no more history is used in the projection

        if data_points_used < minimum_data_points_used:
            return None, None, None

        debug_msg(
            "Prediction based on {0} of these data points: {1}".format(
                data_points_used, self.position_history), "INTERCEPTION")

        direction = degrees(
            calculate_full_origin_angle_radians(first_coord, last_coord))
        self.projection = self.position_history.list[0][
            0], direction, final_speed
        return self.position_history.list[0][0], direction, final_speed