def execute_kick(self): super().execute_running() kicker = self.subbehavior_with_name('kicker') center1 = self.subbehavior_with_name('center1') center2 = self.subbehavior_with_name('center2') # see if we have a direct shot on their goal win_eval = robocup.WindowEvaluator(main.context()) win_eval.enable_chip = kicker.robot != None and kicker.robot.has_chipper( ) win_eval.min_chip_range = OurGoalKick.MinChipRange win_eval.max_chip_range = OurGoalKick.MaxChipRange windows, best = win_eval.eval_pt_to_seg( main.ball().pos, constants.Field.TheirGoalSegment) # note: the min length value is tunable if best != None and best.segment.length() > 0.3: # we DO have a shot on the goal, take it! kicker.target = constants.Field.TheirGoalSegment # FIXME: make the other robots get out of the shot path center1.target = robocup.Point(0.0, 1.5) center2.target = robocup.Point(1.0, 1.5) else: # no open shot, shoot it in-between the two centers center_x = constants.Field.Width * 0.15 center_y = constants.Field.Length * 0.6 center1.target = robocup.Point(-center_x, center_y) center2.target = robocup.Point(center_x, center_y) kicker.target = robocup.Segment(center1.target, center2.target)
def __init__(self, side=Side.center): super().__init__(continuous=True) self._block_robot = None self._area = None self._side = side self._opponent_avoid_threshold = 2.0 self._defend_goal_radius = 0.9 self._win_eval = robocup.WindowEvaluator(main.context()) self._area = robocup.Rect( robocup.Point(-constants.Field.Width / 2.0, constants.Field.Length), robocup.Point(constants.Field.Width / 2.0, 0)) if self._side is Defender.Side.right: self._area.get_pt(0).x = 0 if self._side is Defender.Side.left: self._area.get_pt(1).x = 0 self.add_state(Defender.State.marking, behavior.Behavior.State.running) self.add_state(Defender.State.area_marking, behavior.Behavior.State.running) self.add_transition(behavior.Behavior.State.start, Defender.State.marking, lambda: True, "immediately") self.add_transition( Defender.State.marking, Defender.State.area_marking, lambda: not self._area.contains_point(main.ball().pos) and self. block_robot is None, "if ball not in area and no robot to block") self.add_transition( Defender.State.area_marking, Defender.State.marking, lambda: self._area.contains_point(main.ball( ).pos) or self.find_robot_to_block() is not None, "if ball or opponent enters my area")
def eval_pass(from_point, to_point, excluded_robots=[]): # we make a pass triangle with the far corner at the ball and the opposing side touching the receiver's mouth # the side along the receiver's mouth is the 'receive_seg' # we then use the window evaluator on this scenario to see if the pass is open pass_angle = math.pi / 32.0 pass_dist = to_point.dist_to(from_point) pass_dir = to_point - from_point pass_perp = pass_dir.perp_ccw() receive_seg_half_len = math.tan(pass_angle) * pass_dist receive_seg = robocup.Segment(to_point + pass_perp * receive_seg_half_len, to_point + pass_perp * -receive_seg_half_len) win_eval = robocup.WindowEvaluator(main.context()) for r in excluded_robots: win_eval.add_excluded_robot(r) windows, best = win_eval.eval_pt_to_seg(from_point, receive_seg) # this is our estimate of the likelihood of the pass succeeding # value can range from zero to one # we square the ratio of best to total to make it weigh more - we could raise it to higher power if we wanted if best != None: return 0.8 * (best.segment.length() / receive_seg.length())**2 else: # the pass is completely blocked return 0
def setupStates(self): self.gameState = main.game_state() self.systemState = main.system_state() self.context = main.context() for g in self.systemState.our_robots: self.robotList.append(g) for g in self.systemState.their_robots: self.robotList.append(g) self.updateRobotList()
def on_enter_passing(self): #capture = self.subbehavior_with_name('capture') #passRobot1 = self.subbehavior_with_name('moveA') #passRobot2 = self.subbehavior_with_name('moveB') #to_exclude = [capture.robot, passRobot1.robot, passRobot2.robot] # Do shot evaluation here win_eval = robocup.WindowEvaluator(main.context()) for r in self.to_exclude: win_eval.add_excluded_robot(r) _, rob_1_best_shot = win_eval.eval_pt_to_opp_goal(self.passRobot1.pos) _, rob_1_best_pass = win_eval.eval_pt_to_pt(self.captureRobot.pos, self.passRobot1.pos, 0.3) rob_1_chance = 0 if (rob_1_best_shot and rob_1_best_pass): rob_1_chance = rob_1_best_pass.shot_success * rob_1_best_shot.shot_success _, rob_2_best_shot = win_eval.eval_pt_to_opp_goal(self.passRobot2.pos) _, rob_2_best_pass = win_eval.eval_pt_to_pt(self.captureRobot.pos, self.passRobot2.pos, 0.3) rob_2_chance = 0 if (rob_2_best_shot and rob_2_best_pass): rob_2_chance = rob_2_best_pass.shot_success * rob_2_best_shot.shot_success _, direct_shot = win_eval.eval_pt_to_opp_goal(self.captureRobot.pos) direct_success = 0 if direct_shot: if (self.captureRobot.pos.y < 4): direct_success = direct_shot.shot_success * 0.7 else: direct_success = direct_shot.shot_success if (direct_shot and direct_success > rob_1_chance and direct_success > rob_2_chance): self.kick_directly = True return if rob_1_chance > rob_2_chance: self.add_subbehavior( tactics.coordinated_pass.CoordinatedPass(self.passRobot1.pos), 'pass') else: self.add_subbehavior( tactics.coordinated_pass.CoordinatedPass(self.passRobot2.pos), 'pass')
def eval_best_receive_point(kick_point, evaluation_zone=None, ignore_robots=[]): win_eval = robocup.WindowEvaluator(main.context()) for r in ignore_robots: win_eval.add_excluded_robot(r) targetSeg = constants.Field.TheirGoalSegment # Autogenerate kick point if evaluation_zone is None: evaluation_zone = generate_default_rectangle(kick_point) segments = get_segments_from_rect(evaluation_zone) if segments is None or len(segments) == 0: # We can't do anything. return None, None, None bestChance = None for segment in segments: main.debug_drawer().draw_line(segment, constants.Colors.Blue, "Candidate Lines") _, best = win_eval.eval_pt_to_seg(kick_point, segment) if best is None: continue currentChance = best.shot_success # TODO dont only aim for center of goal. Waiting on window_evaluator returning a probability. receivePt = best.segment.center() _, best = win_eval.eval_pt_to_seg(receivePt, targetSeg) if best is None: continue currentChance = currentChance * best.shot_success if bestChance is None or currentChance > bestChance: bestChance = currentChance targetPoint = best.segment.center() bestpt = receivePt if bestpt is None: return None, None, None return bestpt, targetPoint, bestChance
def execute_shooting(self): kicker = skills.line_kick.LineKick() #skills.pivot_kick.PivotKick() #aim for goal segmant win_eval = robocup.WindowEvaluator(main.context()) for g in main.our_robots(): win_eval.add_excluded_robot(g) windows, window = win_eval.eval_pt_to_opp_goal(main.ball().pos) if (window != None): kicker.target = window.segment.center() else: kicker.target = constants.Field.TheirGoalSegment kicker.aim_params['desperate_timeout'] = 8 if (not self.has_subbehavior_with_name('kicker') or self.subbehavior_with_name('kicker').is_done_running()): self.remove_all_subbehaviors() self.add_subbehavior(kicker, 'kicker', required=False, priority=5)
def __init__(self, defender_priorities=[20, 19]): super().__init__(continuous=True) # we could make the DefenseOld tactic have more or less defenders, but right now we only support two if len(defender_priorities) != 2: raise RuntimeError( "defender_priorities should have a length of two") self.add_state(DefenseOld.State.defending, behavior.Behavior.State.running) self.add_state(DefenseOld.State.clearing, behavior.Behavior.State.running) self.add_transition(behavior.Behavior.State.start, DefenseOld.State.defending, lambda: True, "immediately") self.add_transition(DefenseOld.State.defending, DefenseOld.State.clearing, lambda: self.should_clear_ball(), "when it is safe to clear the ball") self.add_transition(DefenseOld.State.clearing, DefenseOld.State.defending, lambda: not self.should_clear_ball(), "done clearing") goalie = submissive_goalie.SubmissiveGoalie() goalie.shell_id = main.root_play().goalie_id self.add_subbehavior(goalie, "goalie", required=False) # add defenders at the specified priority levels for num, priority in enumerate(defender_priorities): defender = submissive_defender.SubmissiveDefender() self.add_subbehavior(defender, 'defender' + str(num + 1), required=False, priority=priority) self.debug = True self.win_eval = robocup.WindowEvaluator(main.context())
def recalculate_aim_target_point(self): if self.robot != None: # find the point we want to aim at if isinstance(self.target, robocup.Point): self._aim_target_point = self.target elif isinstance(self.target, robocup.Segment): if self.use_windowing: win_eval = robocup.WindowEvaluator(main.context()) for key, value in self.win_eval_params.items(): setattr(win_eval, key, value) win_eval.chip_enabled = self.robot.has_chipper( ) and self.use_chipper windows, best = win_eval.eval_pt_to_seg( main.ball().pos, self.target) if best != None: self._aim_target_point = best.segment.center() else: self._aim_target_point = self.target.center() else: self._aim_target_point = self.target.center() else: raise AssertionError("Expected Point or Segment, found: " + str(self.target))
def execute_block(self): opposing_kicker = evaluation.ball.opponent_with_ball() if opposing_kicker is not None: winEval = robocup.WindowEvaluator(main.context()) winEval.excluded_robots = [self.robot] best = winEval.eval_pt_to_our_goal(main.ball().pos)[1] if best is not None: shot_line = robocup.Line(opposing_kicker.pos, main.ball().pos) block_line = robocup.Line( robocup.Point( best.segment.get_pt(0).x - constants.Robot.Radius, constants.Robot.Radius), robocup.Point( best.segment.get_pt(1).x + constants.Robot.Radius, constants.Robot.Radius)) main.debug_drawer().draw_line(block_line, (255, 0, 0), "Debug") dest = block_line.line_intersection(shot_line) dest.x = min(Goalie.MaxX, dest.x) dest.x = max(-Goalie.MaxX, dest.x) self.robot.move_to(dest) return self.robot.move_to( robocup.Point(0, constants.Robot.Radius + Goalie.OFFSET))
def find_gap(target_pos=constants.Field.TheirGoalSegment.center(), max_shooting_angle=60, robot_offset=8, dist_from_point=.75): if (not main.ball().valid): return target_pos # Find the hole in the defenders to kick at # The limit is 20 cm so any point past it should be defenders right there win_eval = robocup.WindowEvaluator(main.context()) # 500 cm min circle distance plus the robot width test_distance = dist_from_point + constants.Robot.Radius # +- max offset to dodge ball max_angle = max_shooting_angle * constants.DegreesToRadians # How much left and right of a robot to give # Dont make this too big or it will always go far to the right or left of the robots robot_angle_offset = robot_offset * constants.DegreesToRadians zero_point = robocup.Point(0, 0) # Limit the angle so as we get closer, we dont miss the goal completely as much goal_vector = target_pos - main.ball().pos max_length_vector = robocup.Point(constants.Field.Length, constants.Field.Width) goal_limit = (goal_vector.mag() / max_length_vector.mag()) * max_angle # Limit on one side so we dont directly kick out of bounds # Add in the angle from the sideline to the target field_limit = (1 - abs(main.ball().pos.x) / (constants.Field.Width / 2)) * max_angle field_limit = field_limit + goal_vector.angle_between(robocup.Point(0, 1)) # Limit the angle based on the opponent robots to try and always minimize the left_robot_limit = 0 right_robot_limit = 0 for robot in main.their_robots(): ball_to_bot = robot.pos - main.ball().pos # Add an extra radius as wiggle room # kick eval already deals with the wiggle room so it isn't needed there if (ball_to_bot.mag() <= test_distance + constants.Robot.Radius): angle = goal_vector.angle_between(ball_to_bot) # Try and rotate onto the goal vector # if we actually do, then the robot is to the right of the ball vector ball_to_bot.rotate(zero_point, angle) if (ball_to_bot.angle_between(goal_vector) < 0.01): right_robot_limit = max(right_robot_limit, angle + robot_angle_offset) else: left_robot_limit = max(left_robot_limit, angle + robot_angle_offset) else: win_eval.add_excluded_robot(robot) # Angle limit on each side of the bot->goal vector left_angle = max_angle right_angle = max_angle # Make sure we limit the correct side due to the field if main.ball().pos.x < 0: left_angle = min(left_angle, field_limit) else: right_angle = min(right_angle, field_limit) # Limit due to goal left_angle = min(left_angle, goal_limit) right_angle = min(right_angle, goal_limit) # Limit to just over the robots if (left_robot_limit is not 0): left_angle = min(left_angle, left_robot_limit) if (right_robot_limit is not 0): right_angle = min(right_angle, right_robot_limit) # Get the angle that we need to rotate the target angle behind the defenders # since kick eval doesn't support a nonsymmetric angle around a target rotate_target_angle = (left_angle + -right_angle) / 2 target_width = (left_angle + right_angle) target_point = goal_vector.normalized() * test_distance target_point.rotate(zero_point, rotate_target_angle) windows, window = win_eval.eval_pt_to_pt(main.ball().pos, target_point + main.ball().pos, target_width) # Test draw points target_point.rotate(zero_point, target_width / 2) p1 = target_point + main.ball().pos target_point.rotate(zero_point, -target_width) p2 = target_point + main.ball().pos p3 = main.ball().pos main.debug_drawer().draw_polygon([p1, p2, p3], (0, 0, 255), "Free Kick search zone") is_opponent_blocking = False for robot in main.their_robots(): if (goal_vector.dist_to(robot.pos) < constants.Robot.Radius and (main.ball().pos - robot.pos).mag() < test_distance): is_opponent_blocking = True # Vector from ball position to the goal ideal_shot = (target_pos - main.ball().pos).normalized() # If on our side of the field and there are enemy robots around us, # prioritize passing forward vs passing towards their goal # Would have to change this if we are not aiming for their goal if main.ball().pos.y < constants.Field.Length / 2 and len(windows) > 1: ideal_shot = robocup.Point(0, 1) main.debug_drawer().draw_line(robocup.Line(main.ball().pos, target_pos), (0, 255, 0), "Target Point") # Weights for determining best shot k1 = 1.5 # Weight of closeness to ideal shot k2 = 1 # Weight of shot chance # Iterate through all possible windows to find the best possible shot if windows: best_shot = window.segment.center() best_weight = 0 for wind in windows: pos_to_wind = (wind.segment.center() - main.ball().pos).normalized() dot_prod = pos_to_wind.dot(ideal_shot) weight = k1 * dot_prod + k2 * wind.shot_success if weight > best_weight: best_weight = weight best_shot = wind.segment.center() main.debug_drawer().draw_line(robocup.Line(main.ball().pos, best_shot), (255, 255, 0), "Target Shot") best_shot = robocup.Point(0, 1) + main.ball().pos return best_shot else: return constants.Field.TheirGoalSegment.center()
def execute_running(self): win_eval = robocup.WindowEvaluator(main.context()) win_eval.debug = True windows, best = win_eval.eval_pt_to_our_goal(main.ball().pos)