class GoToStaticBall(Action): ''' Move defender to the ball when static ''' preconditions = [(lambda w, r: abs( utils.defender_get_rotation_to_catch_point( Vector(r.x, r.y, r.angle, 0), Vector(w.ball.x, w.ball.y, 0, 0), r. catch_distance)[0]) < ROTATION_THRESHOLD, "Defender is facing ball"), (lambda w, r: r.catcher == 'OPEN', "Grabbers are open."), (lambda w, r: utils.ball_is_static(w), "Ball is static.")] def perform(self, comms): # reset dynamic threshold # TODO: has to be restarted everywhere! global ROTATION_THRESHOLD ROTATION_THRESHOLD = 0.1 dx = self.world.ball.x - self.robot.x dy = self.world.ball.y - self.robot.y displacement = math.hypot(dx, dy) if displacement == 0: alpha = 0 else: # TODO: has to handle this edge case better try: alpha = math.degrees( math.asin(self.robot.catch_distance / float(displacement))) except ValueError as er: print(er) x = self.world.ball.x y = self.world.ball.y angle = utils.get_rotation_to_point(self.robot.vector, Vector(x, y, 0, 0)) logging.info("Wants to close-rotate by: " + str(angle)) comms.turn(angle) return 1 # TODO: NO FIXED DELAY beta = 90 - alpha if math.sin(math.radians(alpha)) == 0: distance_to_move = 15 # something is obviously wrong so we have to move a bit else: distance_to_move = math.sin( math.radians(beta)) * self.robot.catch_distance / math.sin( math.radians(alpha)) # Find the movement side angle, side = utils.defender_get_rotation_to_catch_point( Vector(self.robot.x, self.robot.y, self.robot.angle, 0), Vector(self.world.ball.x, self.world.ball.y, 0, 0), self.robot.catch_distance) if side == "left": distance_to_move = -distance_to_move logging.info("Wants to move by: " + str(distance_to_move)) comms.move(distance_to_move) return utils.defender_move_delay(distance_to_move)
class AlignForGrab(Action): preconditions = [(lambda w, r: r.catcher == 'OPEN', "Grabbers are open."), (lambda w, r: abs((r.angle - w.ball.angle + pi / 2) % pi - pi / 2) < 0.6, "Ball vector and robot vector within 35 degrees."), (lambda w, r: not utils.ball_is_static(w), "The ball is moving")] def perform(self, comms): dist = utils.defender_get_alignment_offset(self.robot, self.world.ball, self.world.ball.angle) logging.info("Aligning with ball. (Move %f right)", dist) if abs(dist) > MOVEMENT_THRESHOLD: comms.move(dist) return utils.defender_move_delay(dist)
class GoToGrabStaticBall(Action): preconditions = [(lambda w, r: utils.ball_is_static(w), "Ball is static"), (lambda w, r: is_robot_facing_position(w, r, w.ball.vector), "Attacker is facing ball"), (lambda w, r: r.catcher == 'OPEN', "Attacker's grabbers are open")] def perform(self, comms): d = None dx = self.world.ball.x - self.robot.x dy = self.world.ball.y - self.robot.y d = math.sqrt(dx**2 + dy**2) comms.move(d - GRAB_DISTANCE)
def get_goal(self, world, robot): ''' Selects a goal for robot ''' if robot.penalty: return None elif self.current_task == 'game' and world.game_state is not None: utils.defender_rotation_to_defend_point(robot, world.ball, world.our_goal.vector, defender.GOAL_RADIUS, world.our_side) if robot.has_ball(world.ball): info("Defender goal choice: Pass the ball") return defender.Pass(world, robot) elif utils.dist(world.our_goal, world.ball) < defender.GOAL_RADIUS: return None elif not utils.ball_heading_to_our_goal(world) and utils.defender_should_grab_ball(world): info("Defender goal choice: Retrieve the ball") return defender.GetBall(world, robot) else: info("Defender goal choice: Do the wiggle dance!") return defender.Defend(world, robot) elif self.current_task == 'oldgame' and world.game_state is not None: if robot.has_ball(world.ball): info("Defender goal choice: kick the ball") return defender.Pass(world, robot) elif utils.ball_heading_to_our_goal(world) and world.in_our_half(world.ball): info("Defender goal choice: Intercept") return defender.ReactiveGrabGoal(world, robot) elif utils.ball_is_static(world) and world.in_our_half(world.ball): ourdist = math.hypot(world.ball.x - robot.x, world.ball.y - robot.y) oppdists = [math.hypot(world.ball.x - r.x, world.ball.y - r.y) for r in world.their_robots if not r.is_missing()] if (len(oppdists) == 0 or ourdist < min(oppdists)) and world.game_state == 'normal-play': info("Defender goal choice: Retrieve ball") return defender.GetBall(world, robot) else: info("Defender goal choice: Block") return defender.Block(world, robot) else: info("Defender goal choice: Return to defence area") return defender.ReturnToDefenceArea(world, robot) elif self.current_task == 'move-grab': return defender.GetBall(world, robot) elif self.current_task == 'defend': return defender.Defend(world, robot) elif self.current_task == 'reactive-grab': return defender.ReactiveGrabGoal(world, robot) elif self.current_task == 'm1': return defender.ReceivingPass(world, robot) elif self.current_task == 'm2': return defender.ReceiveAndPass(world, robot) elif self.current_task == 'm31': return defender.InterceptPass(world, robot) elif self.current_task == 'm32': return defender.InterceptGoal(world, robot)
def perform(self, comms): d = None if utils.ball_is_static(self.world): dx = self.world.ball.x - self.robot.x dy = self.world.ball.y - self.robot.y d = math.sqrt(dx**2 + dy**2) else: # TODO Find ball path dx = self.world.ball.x - self.robot.x dy = self.world.ball.y - self.robot.y d = math.sqrt(dx**2 + dy**2) # TODO grabbing area size grabber_size = 50 comms.move(d - grabber_size)
class WaitForBallToCome(Action): ''' Defender just waits for the ball to approach it ''' # FIXME: ball_can_reach_robot doesn't do anything. # FIXME: robot_can_reach_ball doesn't do anything. preconditions = [(lambda w, r: abs(utils.get_rotation_to_point(r.vector, w.ball.vector)) < ROTATION_BALL_THRESHOLD, "Defender is facing ball"), (lambda w, r: utils.ball_can_reach_robot(w.ball, r), "The ball can reach the robot"), (lambda w, r: utils.robot_can_reach_ball(w.ball, r), "Defender can reach the ball"), (lambda w, r: r.catcher == 'OPEN', "Grabbers are open."), (lambda w, r: not utils.ball_is_static(w), "The ball is moving.")] def perform(self, comms): pass
class RotateAndAlignForGrab(Action): preconditions = [(lambda w, r: r.catcher == 'OPEN', "Grabbers are open."), (lambda w, r: abs((r.angle - w.ball.angle + pi / 2) % pi - pi / 2) >= 0.6, "Ball vector and robot vector not within 35 degrees."), (lambda w, r: not utils.ball_is_static(w), "The ball is moving")] def perform(self, comms): target_rotation = (self.world.ball.angle - self.robot.angle + pi / 2) % pi - pi / 2 dist = utils.defender_get_alignment_offset(self.robot, self.world.ball, self.world.ball.angle, target_rotation) logging.info("Aligning with ball. (Rotate %f degrees, move %f right)", math.degrees(target_rotation), dist) if abs(dist) > MOVEMENT_THRESHOLD: comms.turn_then_move(target_rotation, dist) return utils.defender_turn_delay(target_rotation) + utils.defender_move_delay(dist) else: comms.turn(target_rotation) return utils.defender_turn_delay(target_rotation)
class FollowBall(Action): ''' Be in the trajectory of moving ball as long as it's predicted that the ball reaches the robot ''' # Different precondition: Face counter to ball trajectory instead of facing # the ball (allows intercepting as well as possible. preconditions = [(lambda w, r: r.catcher == 'OPEN', "Grabbers are open."), (lambda w, r: not utils.ball_is_static(w), "The ball is moving.")] def perform(self, comms): turn_angle = (self.world.ball.angle - self.robot.angle) % (2 * pi) - pi dist = math.hypot(self.robot.x - self.world.ball.x, self.robot.y - self.world.ball.y) tri_angle = utils.get_rotation_to_point(self.world.ball.vector, self.robot) dist *= math.cos(tri_angle) if abs(turn_angle) < ROTATION_BALL_THRESHOLD: logging.info("Adjusting to ball position by distance: " + str(dist)) comms.move(dist) else: logging.info("Adjusting angle by %f, distance by %f." % (turn_angle, dist)) comms.turn_then_move(turn_angle, dist) return 2