def move_ball(self): if self._check_success(): self.next_state = self.wait_for_ball_stop_spinning elif self._has_ball_quit_dribbler(): self._fetch_ball() ball_position = self.game_state.ball_position ball_to_target_dir = normalize(self.target.position - ball_position) self.player_target_position = ROBOT_CENTER_TO_KICKER * ball_to_target_dir + self.target.position return CmdBuilder().addMoveTo( Pose(self.player_target_position, self.steady_orientation), cruise_speed=self.move_ball_cruise_speed, ball_collision=False, enable_pathfinder=False).addForceDribbler().build()
def __init__(self, game_state: GameState, player: Player, target: Pose = Pose(), args: Optional[List[str]] = None, keepout_radius: int = KEEPOUT_DISTANCE_FROM_BALL, forbidden_areas: Optional[List[Area]] = None): super().__init__(game_state, player, target, args, forbidden_areas=forbidden_areas) self.current_state = self.stay_out_of_circle self.next_state = self.stay_out_of_circle self.keepout_radius = keepout_radius
def kick(self): if self.auto_update_target: self._find_best_passing_option() if self.get_alignment_with_ball_and_target() > 45: self.next_state = self.go_behind_ball return self.go_behind_ball() self.next_state = self.validate_kick player_to_target = (self.target.position - self.player.pose.position) position_behind_ball = self.game_state.ball_position + normalize(player_to_target) * ROBOT_CENTER_TO_KICKER required_orientation = (self.target.position - self.game_state.ball_position).angle return CmdBuilder().addMoveTo(Pose(position_behind_ball, required_orientation), ball_collision=False)\ .addKick(self.kick_force)\ .addForceDribbler().build()
def grab_ball(self): if not self.is_ball_going_to_collide(threshold=18): self.next_state = self.go_behind_ball if self._get_distance_from_ball() < HAS_BALL_DISTANCE: self.next_state = self.halt return self.halt() orientation = (self.game_state.ball_position - self.player.position).angle distance_behind = self.get_destination_behind_ball(GRAB_BALL_SPACING) return CmdBuilder().addMoveTo( Pose(distance_behind, orientation), cruise_speed=3, end_speed=0, ball_collision=False).addChargeKicker().build()
def support_other_zone(self): enemy_positions = self.get_enemy_in_zone() if len(enemy_positions) == 0: self.next_state = self.support_other_zone else: self.next_state = self.cover_zone destination = stay_inside_square(self.game_state.ball_position, self.y_top, self.y_bottom, self.x_left, self.x_right) destination = self.game_state.game.field.stay_outside_goal_area( destination, our_goal=True) orientation = (self.game_state.ball_position - destination).angle return MoveTo(Pose(destination, orientation))
def execute(self, robot: Robot, dt): self.dt = dt speed_norm = self.get_next_speed(robot) path_correction = self.following_path_vector(robot) velocity = robot.position_error * speed_norm / robot.position_error.norm + path_correction * speed_norm / self.v_d velocity /= max(1.0, abs(velocity.norm) / speed_norm) cmd_orientation = self.orientation_controller.execute( robot.orientation_error) cmd_orientation /= max(1.0, abs(cmd_orientation) / MAX_ANGULAR_SPEED) self.last_commanded_velocity = velocity return Pose(velocity, cmd_orientation)
def go_behind_ball(self): self.status_flag = Flags.WIP orientation = (self.game_state.ball.position - self.target.position).angle distance_behind = self._get_destination_behind_ball( self.go_behind_distance) if (self.player.pose.position - distance_behind).norm < 200 \ and compare_angle(self.player.pose.orientation, orientation, abs_tol=0.1): self.next_state = self.grab_ball return CmdBuilder().addMoveTo(Pose(distance_behind, orientation), cruise_speed=1, ball_collision=True).build()
def __init__(self, game_state: GameState, player: Player, target: Pose = Pose(), args: List[str] = None): super().__init__(game_state, player, target, args) self.current_state = self.get_behind_ball self.next_state = self.get_behind_ball self.debug_interface = DebugCommandFactory() self.move_action = self._generate_move_to() self.last_ball_position = self.game_state.ball_position self.charge_time = 0 self.last_time = time.time() self.orientation_target = 0 self.target = target
def __init__(self, game_state: GameState): super().__init__(game_state) self.target_position = Position( self.game_state.field.our_goal_area.left - 3 * ROBOT_RADIUS, 0) number_of_player = len(self.game_state.our_team.available_players) role_to_positions = {} for i, role in enumerate(Role.as_list()): position_offset = Position(0, (i - (number_of_player - 1) / 2) * ROBOT_RADIUS * 4) role_to_positions[role] = Pose(self.target_position + position_offset) self.assign_tactics(role_to_positions)
def predict(self, robot_state: RobotState, dt: float): velocity_commands = [Pose() for _ in range(len(self._our_team))] for packet in robot_state.packet: velocity_commands[packet.robot_id] = packet.command for robot in self._our_team: if robot.orientation is not None: velocity = self._put_in_world_referential(robot.orientation, velocity_commands[robot.id]) robot.predict(dt, next_velocity=velocity.to_array()) for robot in self._their_team: robot.predict(dt) for ball in self._balls: ball.predict(dt)
def grab_ball(self): if self.auto_update_target: self._find_best_passing_option() if self.get_alignment_with_ball_and_target() > 45: self.next_state = self.go_behind_ball if self._get_distance_from_ball() < KICK_DISTANCE: self.next_state = self.kick self.kick_last_time = time.time() required_orientation = (self.target.position - self.game_state.ball_position).angle position_behind_ball = self.get_destination_behind_ball(GRAB_BALL_SPACING) return CmdBuilder().addMoveTo(Pose(position_behind_ball, required_orientation), ball_collision=False)\ .addForceDribbler()\ .addKick(self.kick_force)\ .build()
def grab_ball(self): if self.position_ball_at_start is None: self.position_ball_at_start = self.game_state.ball_position.copy() orientation = (self.game_state.ball.position - self.target.position).angle distance_behind = self._get_destination_behind_ball(GRAB_BALL_SPACING) if (self.position_ball_at_start - self.game_state.ball.position).norm > BALL_DISPLACEMENT_TO_DETECT_GRABBING \ and compare_angle(self.player.pose.orientation, orientation, abs_tol=0.3): self.next_state = self.move_ball self.position_ball_at_start = None self.steady_orientation = orientation return CmdBuilder().addMoveTo( Pose(distance_behind, orientation), cruise_speed=0.2, ball_collision=False).addForceDribbler().build()
def push_ball(self): # self.debug.add_log(1, "Grab ball called") # self.debug.add_log(1, "vector player 2 ball : {} mm".format(self.vector_norm)) if (self.last_ball_position - self.player.pose.position).norm < 40: self.next_state = self.halt self.last_time = time.time() elif self._is_player_opposing_ball_and_target(-0.9): self.next_state = self.push_ball else: self.next_state = self.get_behind_ball # self.debug.add_log(1, "orientation go get ball {}".format(self.last_angle)) target = self.target.position player = self.player.pose.position player_to_target = target - player player_to_target = 0.5 * player_to_target / np.linalg.norm( player_to_target) speed_pose = Pose(Position.from_array(player_to_target)) return MoveTo(speed_pose)
def test_initialize_tactic(tactic_class): simulator = PerfectSim(tactic_class) mock_id = 1 mock_pose = Pose(Position(3, 5)) try: simulator.start(mock_id, mock_pose) except AssertionError: pass # This is done to pass snowflake tactic that require additional arguments # TODO: Fix tactics so they pass that test # def test_few_ticks_tactic(tactic_class): # FEW_TICKS = 10 # simulator = PerfectSim(tactic_class) # mock_id = 1 # mock_pose = Pose(Position(3, 5)) # simulator.start(mock_id, mock_pose) # # for _ in range(0, FEW_TICKS): # simulator.tick()
def __init__(self, game_state: GameState, player: Player, target: Pose = Pose(), args: List[str] = None, go_behind_distance=GO_BEHIND_SPACING): super().__init__(game_state, player, target, args, forbidden_areas=[]) self.target = target self.go_behind_distance = go_behind_distance # The simulation dribbler does not back spin as much as in real life self.move_ball_cruise_speed = 0.1 if Config().is_simulation() else 0.3 self._fetch_ball() self.wait_timer = None self.position_ball_at_start = None self.player_target_position = None self.steady_orientation = None
def _check_for_forbidden_area(self, next_ai_command): old_target_position = next_ai_command.target.position target_to_position = Line(self.player.position, next_ai_command.target.position) closest_new_target = None for area in self.forbidden_areas: if old_target_position in area: target_position = self._find_best_next_target( area, old_target_position, self.player.position, target_to_position) new_target = Pose(target_position, next_ai_command.target.orientation) if closest_new_target is None \ or (closest_new_target - self.player.position).norm > (new_target - self.player.position).norm: closest_new_target = new_target if closest_new_target is not None: # This trailing _ is not for protected access, it was add to avoid a name conflict with the function replace return next_ai_command._replace(target=closest_new_target) return next_ai_command
def __init__(self, p_game_state): super().__init__(p_game_state) target = None if self.game_state.last_ref_state is None: self.logger.warning("The AI has not received a referee message and does not know where to place the ball.") else: target = self.game_state.last_ref_state.ball_placement_position if target is None: self.logger.warning("The last ref_state did not contains a ball_placement position\n" "The AI does not know where to place the ball") for r, p in self.assigned_roles.items(): if r == Role.FIRST_ATTACK and target is not None: self.create_node(r, PlaceBall(self.game_state, p, target=Pose(target))) elif r == Role.GOALKEEPER: self.create_node(r, StayAwayFromBall(self.game_state, p, forbidden_areas=[], keepout_radius=2*KEEPOUT_DISTANCE_FROM_BALL)) else: self.create_node(r, StayAwayFromBall(self.game_state, p, keepout_radius=2*KEEPOUT_DISTANCE_FROM_BALL))
def __init__(self, game_state: GameState, player: Player, target: Pose = Pose(), args: Optional[List[str]] = None, robots_in_formation: Optional[List[Player]] = None): super().__init__(game_state, player, args=args) if robots_in_formation is None: self.robots_in_formation = [player] else: self.robots_in_formation = robots_in_formation assert isinstance(self.robots_in_formation[0], Player) self.player_number_in_formation = None self.init_players_in_formation() self.current_state = self.main_state self.next_state = self.main_state self.dist_from_ball = KEEPOUT_DISTANCE_FROM_BALL * 1.1
def go_behind_ball(self): orientation = (self.game_state.ball_position - self.player.position).angle ball_speed = self.game_state.ball.velocity.norm ball_speed_modifier = (ball_speed / 1000 + 1) effective_ball_spacing = GRAB_BALL_SPACING * 3 * ball_speed_modifier distance_behind = self.get_destination_behind_ball( effective_ball_spacing) dist_from_ball = (self.player.position - self.game_state.ball_position).norm if self.is_ball_going_to_collide(threshold=18) \ and compare_angle(self.player.pose.orientation, orientation, abs_tol=max(0.1, 0.1 * dist_from_ball/100)): self.next_state = self.wait_for_ball else: self.next_state = self.go_behind_ball return CmdBuilder().addMoveTo(Pose(distance_behind, orientation), cruise_speed=3, end_speed=0, ball_collision=True)\ .addChargeKicker().build()
def __init__(self, game_state: GameState, player: Player, target: Pose=Pose(), args: List[str]=None, kick_force: KickForce=KickForce.MEDIUM, auto_update_target=False, go_behind_distance=GO_BEHIND_SPACING): super().__init__(game_state, player, target, args) self.current_state = self.kick_charge self.next_state = self.kick_charge self.cmd_last_time = time.time() self.kick_last_time = time.time() self.auto_update_target = auto_update_target self.target_assignation_last_time = 0 self.target = target if self.auto_update_target: self._find_best_passing_option() self.kick_force = kick_force self.go_behind_distance = go_behind_distance self.tries_flag = 0 self.grab_ball_tries = 0 self.points_sequence = []
def main_state(self): target_player = closest_player_to_point(self.game_state.ball_position, our_team=False).player orientation_opponent = np.array([ math.cos(target_player.pose.orientation), math.sin(target_player.pose.orientation) ]) destination_position = target_player.pose.position + self.distance * orientation_opponent ball_to_player = self.game_state.ball_position - self.player.pose.orientation destination_orientation = ball_to_player.angle if self.check_success(): self.status_flag = Flags.SUCCESS else: self.status_flag = Flags.WIP return CmdBuilder().addMoveTo( Pose(destination_position, destination_orientation), cruise_speed=self.cruise_speed, ball_collision=self.ball_collision, end_speed=self.end_speed).addChargeKicker().addForceDribbler( ).build()
def next_position(self): self.target_orientation = (self.target.position - self.game_state.ball_position).angle self.position = ( self.game_state.ball_position - Position.from_angle(self.offset_orientation) * DISTANCE_FROM_BALL) if self.start_time is not None: if time.time() - self.start_time >= self.rotate_time: self.rotation_sign = self._get_direction() if compare_angle(self.target_orientation, (self.game_state.ball_position - self.player.position).angle, VALID_DIFF_ANGLE): self.next_state = self.halt return self._go_to_final_position() elif time.time() - self.iter_time >= self.switch_time: self.iter_time = time.time() self._switch_rotation() if (self.player.pose.position - self.position).norm < VALID_DISTANCE: if self.start_time is None: self.start_time = time.time() self.iter_time = time.time() self.ball_collision = True self.speed = 1 self.offset_orientation += DIFF_ANGLE * self.rotation_sign self.position = (self.game_state.ball_position - Position.from_angle(self.offset_orientation) * DISTANCE_FROM_BALL) if self.start_time is not None: orientation = self.offset_orientation if time.time() - self.start_time < \ self.rotate_time else self.target_orientation else: orientation = self.target_orientation return CmdBuilder().addMoveTo( Pose(self.position, orientation), cruise_speed=self.speed, ball_collision=self.ball_collision).build()
def ProtectGoal(game_state: GameState, player: Player, is_right_goal: bool = True, minimum_distance: float = 150 / 2, maximum_distance: float = None): """ Calcul la pose que doit prendre le gardien en fonction de la position de la balle. :return: Un tuple (Pose, kick) où Pose est la destination du gardien et kick est nul (on ne botte pas) """ goalkeeper_position = player.pose.position ball_position = game_state.ball_position goal_x = game_state.field.our_goal_x goal_position = Position(goal_x, 0) # Calcul des deux positions extremums entre la balle et le centre du but inner_circle_position = stay_inside_circle(ball_position, goal_position, minimum_distance) outer_circle_position = stay_inside_circle(ball_position, goal_position, maximum_distance) destination_position = closest_point_on_segment(goalkeeper_position, inner_circle_position, outer_circle_position) # Vérification que destination_position respecte la distance maximale if maximum_distance is None: destination_position = game_state.game.field.stay_inside_goal_area( destination_position, our_goal=True) else: destination_position = stay_inside_circle(destination_position, goal_position, maximum_distance) # Calcul de l'orientation de la pose de destination destination_orientation = (ball_position - destination_position).angle destination_pose = Pose(destination_position, destination_orientation) return MoveTo(destination_pose)
def __init__(self, game_state: GameState, player: Player, target: Pose=Pose(), args: List[str]=None, kick_force: KickForce=KickForce.HIGH, auto_update_target=False, go_behind_distance=GRAB_BALL_SPACING*3, forbidden_areas=None, can_kick_in_goal=True): super().__init__(game_state, player, target, args=args, forbidden_areas=forbidden_areas) self.current_state = self.initialize self.next_state = self.initialize self.kick_last_time = time.time() self.auto_update_target = auto_update_target self.can_kick_in_goal = can_kick_in_goal self.target_assignation_last_time = 0 self.target = target if self.auto_update_target: self._find_best_passing_option() self.kick_force = kick_force self.go_behind_distance = go_behind_distance self.is_debug = False
def wait_for_ball(self): perp_vec = perpendicular(self.player.position - self.game_state.ball.position) component_lateral = perp_vec * np.dot( perp_vec.array, normalize(self.game_state.ball.velocity).array) small_segment_len = np.sqrt(1 - component_lateral.norm**2) latteral_move = component_lateral / small_segment_len * ( self.player.position - self.game_state.ball.position).norm if self._get_distance_from_ball() < HAS_BALL_DISTANCE: self.next_state = self.halt return self.halt() if not self.is_ball_going_to_collide(threshold=18): self.next_state = self.wait_for_ball return CmdBuilder().build() orientation = (self.game_state.ball_position - self.player.position).angle return CmdBuilder().addMoveTo( Pose(self.player.position + latteral_move.view(Position), orientation), cruise_speed=3, end_speed=0, ball_collision=False).addChargeKicker().build()
def __init__(self, game_state: GameState, player: Player, args: List[str]=None, center_of_zone=Position(0, 0), height_of_zone=800, width_of_zone=800): super().__init__(game_state, player, args=args) self.current_state = self.main_state self.next_state = self.main_state self.center_of_zone = center_of_zone self.height_of_zone = height_of_zone self.width_of_zone = width_of_zone self.bottom_left_corner = Position(self.center_of_zone[0] - self.width_of_zone / 2, self.center_of_zone[1] - self.height_of_zone / 2) self.grid_of_positions = [] discretisation = 100 for i in range(int(self.width_of_zone / discretisation)): for j in range(int(self.height_of_zone / discretisation)): self.grid_of_positions.append(self.bottom_left_corner + Position(discretisation * i, discretisation * j)) self.current_position_index_to_go = random.randint(0, len(self.grid_of_positions) - 1) self.current_position_to_go = self.grid_of_positions[self.current_position_index_to_go] self.current_angle_to_go = 0 #random.randint(0, 100) * np.pi / 100. self.next_pose = Pose(self.current_position_to_go, self.current_angle_to_go)
def __init__(self, game_state: GameState, player: Player, target: Pose=Pose(), args: Optional[List[str]]=None, auto_position=False, robots_in_formation: Optional[List[Player]] = None, forbidden_areas=None): super().__init__(game_state, player, target, args=args, forbidden_areas=forbidden_areas) self.current_state = self.move_to_pass_position self.next_state = self.move_to_pass_position self.target = target self.auto_position = auto_position if robots_in_formation is None: self.robots_in_formation = [player] else: self.robots_in_formation = robots_in_formation self.is_offense = self.is_player_offense(player) self.robots_in_formation = [player for player in self.robots_in_formation if self.is_offense == self.is_player_offense(player)] self.idx_in_formation = self.robots_in_formation.index(player) self.area = None self.last_evaluation = time.time() # Use for debug_cmd self.best_position = self._find_best_player_position() if self.auto_position else self.target
def defense_dumb(self): dest_y = self.game_state.ball.position.y \ * self.game_state.goal_width / 2 / self.game_state.field.top position = self.game_state.field.our_goal - Position( ROBOT_RADIUS + 10, -dest_y) return MoveTo(Pose(position, np.pi))
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)
def pose_error(self) -> Pose: return Pose(self.position_error, self.orientation_error)