예제 #1
0
def player_covered_from_goal(player: Player):
    shooting_angle = angle_between_three_points(GameState().field.their_goal_line.p1,
                                                player.position, GameState().field.their_goal_line.p2)
    vec_player_to_goal = GameState().field.their_goal - player.position

    our_team = [other_player for other_player in GameState().our_team.available_players.values() if other_player is not player]
    enemy_team = [other_player for other_player in GameState().enemy_team.available_players.values()]
    pertinent_collisions = []
    for other_player in our_team + enemy_team:
        if object_pointing_toward_point(player.position,
                                        vec_player_to_goal.angle,
                                        other_player.position,
                                        wrap_to_pi(shooting_angle + 5 * np.pi / 180)):
            pertinent_collisions.append(Obstacle(other_player.position.array, avoid_distance=90))

    if not any(pertinent_collisions):
        return GameState().field.their_goal
    pertinent_collisions_positions = np.array([obs.position for obs in pertinent_collisions])
    pertinent_collisions_avoid_radius = np.array([obs.avoid_distance for obs in pertinent_collisions])
    results = []
    for i in range(0, 15 + 1):  # discretisation de la ligne de but
        goal_point = GameState().field.their_goal_line.p1 + GameState().field.their_goal_line.direction * \
                     (GameState().field.their_goal_line.length * i / 15)
        is_colliding = is_path_colliding(pertinent_collisions, pertinent_collisions_positions,
                                         pertinent_collisions_avoid_radius, player.position.array, goal_point.array)
        results.append((is_colliding, goal_point))
    max_len_seg, indexend = find_max_consecutive_bool(results)

    if max_len_seg == 0 and indexend == 0:
        return None
    return results[int(indexend-1 - np.math.ceil(max_len_seg / 2))][1]
예제 #2
0
def compute_turn_radius(
        p1,
        p2,
        p3,
        speed: float,
        max_deviation: float = 50,
        acc: float = MAX_LINEAR_ACCELERATION) -> Tuple[float, float]:
    """Assume the raw path is p1->p2->p3.
       Deviation is compute from p2 to the circle with a line passing by the center of the circle."""

    radius_at_const_speed = speed**2 / acc
    path_angle = wrap_to_pi((p3 - p2).angle - (p1 - p2).angle)
    const_speed_deviation = deviation(radius_at_const_speed, path_angle)
    if const_speed_deviation < max_deviation:
        speed_deviation = const_speed_deviation
        turn_radius = radius_at_const_speed
    else:
        speed *= 0.95
        radius = speed**2 / acc
        speed_deviation = deviation(radius, path_angle)
        turn_radius = speed_deviation / (1 / sin(path_angle / 2) - 1)
        while speed_deviation > max_deviation:
            speed *= 0.9
            radius = speed**2 / acc
            speed_deviation = deviation(radius, path_angle)
            turn_radius = speed_deviation / (1 / sin(path_angle / 2) - 1)
            if abs(speed) < 0.01:
                speed_deviation = 0
                turn_radius = 0
                break
    return abs(turn_radius), speed_deviation
예제 #3
0
    def execute(self, err: float) -> float:

        current_time = time()

        if not self.last_time:
            self.last_time = current_time
            return err * self.kp

        dt, self.last_time = current_time - self.last_time, current_time

        if self.signed_error and (abs(err) > np.pi):
            d_err = err - self.last_err
            d_err = copysign(d_err, wrap_to_pi(d_err))
        else:
            d_err = err - self.last_err

        self.last_err = err
        self.err_sum += err

        if self.anti_windup:
            self.error_deque.append((err, dt))
            self.anti_windup_time += dt
            while self.anti_windup_time > self.anti_windup_max_time:
                old_err, old_dt = self.error_deque.popleft()
                self.anti_windup_time -= old_dt
                self.err_sum -= old_err

        kd = 0 if abs(err) < self.deadzone else self.kd
        return (err * self.kp) + (self.err_sum * self.ki * dt) + (d_err * kd /
                                                                  dt)
예제 #4
0
def compute_turn_radius(p1, p2, p3, speed: float, max_deviation: float=50, acc: float=MAX_LINEAR_ACCELERATION) -> Tuple[float, float]:
    """Assume the raw path is p1->p2->p3.
       Deviation is compute from p2 to the circle with a line passing by the center of the circle."""

    radius_at_const_speed = speed ** 2 / acc
    path_angle = wrap_to_pi((p3 - p2).angle - (p1 - p2).angle)
    const_speed_deviation = deviation(radius_at_const_speed, path_angle)
    if const_speed_deviation < max_deviation:
        speed_deviation = const_speed_deviation
        turn_radius = radius_at_const_speed
    else:
        speed *= 0.95
        radius = speed ** 2 / acc
        speed_deviation = deviation(radius, path_angle)
        turn_radius = speed_deviation / (1 / sin(path_angle / 2) - 1)
        while speed_deviation > max_deviation:
            speed *= 0.9
            radius = speed ** 2 / acc
            speed_deviation = deviation(radius, path_angle)
            turn_radius = speed_deviation / (1 / sin(path_angle / 2) - 1)
            if abs(speed) < 0.01:
                speed_deviation = 0
                turn_radius = 0
                break
    return abs(turn_radius), speed_deviation
예제 #5
0
    def _change_frame_side(detection_frame: Dict[str, List[Dict[str, Any]]]) -> Dict[str, List[Dict[str, Any]]]:

        for robot_obs in detection_frame.get('robots_blue', []) + detection_frame.get('robots_yellow', []):
            robot_obs['x'] *= -1
            robot_obs['orientation'] = wrap_to_pi(np.pi - robot_obs['orientation'])

        for ball_obs in detection_frame.get('balls', ()):
            ball_obs['x'] *= -1

        return detection_frame
예제 #6
0
 def mirror_x(self):
     return Pose.from_values(-self.x, self.y, geometry.wrap_to_pi(np.pi - self.orientation))
예제 #7
0
 def orientation_error(self) -> Optional[float]:
     if self.target_orientation is not None and self.orientation is not None:
         return wrap_to_pi(self.target_orientation - self.orientation)
예제 #8
0
def test_wrap_to_pi_with_angle_greater_than_pi():
    assert wrap_to_pi(
        AN_ANGLE_GREATER_THAN_PI) == AN_ANGLE_GREATER_THAN_PI - 2 * m.pi
예제 #9
0
def test_wrap_to_pi_with_angle_less_than_pi():
    assert wrap_to_pi(AN_ANGLE_LESS_THAN_PI) == AN_ANGLE_LESS_THAN_PI
예제 #10
0
 def orientation_error(self) -> Optional[float]:
     if self.target_orientation is not None and self.orientation is not None:
         return wrap_to_pi(self.target_orientation - self.orientation)
예제 #11
0
def GoBehind(player: Player, position1: Position, position2: Optional[Position]=None,
             distance_behind: float=250,
             orientation: str= 'front'):
    """
    Action GoBehind: Déplace le robot au point le plus proche sur la droite, derrière un objet dont la position
    est passée en paramètre, de sorte que cet objet se retrouve entre le robot et la seconde position passée
    en paramètre
    Méthodes :
        exec(self): Retourne la pose où se rendre
    Attributs (en plus de ceux de Action):
        player_id : L'identifiant du joueur
        position1 : La position de l'objet derrière lequel le robot doit se placer (exemple: le ballon)
        position2 : La position par rapport à laquelle le robot doit être "derrière" l'objet de la position 1
                    (exemple: le but)
    """
    delta_x = position2.x - position1.x
    delta_y = position2.y - position1.y
    theta = math.atan2(delta_y, delta_x)

    x = position1.x - distance_behind * math.cos(theta)
    y = position1.y - distance_behind * math.sin(theta)

    player_x = player.pose.position.x
    player_y = player.pose.position.y

    norm_player_2_position2 = math.sqrt((player_x - position2.x) ** 2+(player_y - position2.y) ** 2)
    norm_position1_2_position2 = math.sqrt((position1.x - position2.x) ** 2 +
                                           (position1.y - position2.y) ** 2)

    if norm_player_2_position2 < norm_position1_2_position2:
        # on doit contourner l'objectif

        vecteur_position1_2_position2 = np.array([position1.x - position2.x,
                                                  position1.y - position2.y, 0])
        vecteur_vertical = np.array([0, 0, 1])

        vecteur_player_2_position1 = np.array([position1.x - player_x,
                                               position1.y - player_y, 0])

        vecteur_perp = np.cross(vecteur_position1_2_position2, vecteur_vertical)
        vecteur_perp /= np.linalg.norm(vecteur_perp)

        if np.dot(vecteur_perp, vecteur_player_2_position1) > 0:
            vecteur_perp = -vecteur_perp

        position_intermediaire_x = x + vecteur_perp[0] * RAYON_AVOID
        position_intermediaire_y = y + vecteur_perp[1] * RAYON_AVOID
        if math.sqrt((player_x-position_intermediaire_x)**2+(player_y-position_intermediaire_y)**2) < 50:
            position_intermediaire_x += vecteur_perp[0] * RAYON_AVOID * 2
            position_intermediaire_y += vecteur_perp[1] * RAYON_AVOID * 2

        destination_position = Position(position_intermediaire_x, position_intermediaire_y)
    else:
        if math.sqrt((player_x-x)**2+(player_y-y)**2) < 50:
            x -= math.cos(theta) * 2
            y -= math.sin(theta) * 2
        destination_position = Position(x, y)

    # Calcul de l'orientation de la pose de destination
    destination_orientation = 0
    if orientation == 'front':
        destination_orientation = wrap_to_pi((position1 - destination_position).angle)
    elif orientation == 'back':
        destination_orientation = wrap_to_pi((position1 - destination_position).angle + np.pi)

    destination_pose = Pose(destination_position, destination_orientation)
    return MoveTo(destination_pose)
예제 #12
0
def test_wrap_to_pi_with_angle_greater_than_pi():
    assert wrap_to_pi(AN_ANGLE_GREATER_THAN_PI) == AN_ANGLE_GREATER_THAN_PI - 2*m.pi
예제 #13
0
def test_wrap_to_pi_with_angle_less_than_pi():
    assert wrap_to_pi(AN_ANGLE_LESS_THAN_PI) == AN_ANGLE_LESS_THAN_PI