def should_defending(self): ball = self.info.ball car = self.info.my_car our_goal = self.info.my_goal.center car_to_ball = ball.pos - car.pos in_front_of_ball = distance_2d(ball.pos, our_goal) < distance_2d( car.pos, our_goal) backline_intersect = line_backline_intersect( self.info.my_goal.center[1], vec2(car.pos), vec2(car_to_ball)) return in_front_of_ball and abs(backline_intersect) < 2000
def closest_to_the_ball(self): dist_to_ball = math.inf for i in range(len(self.teammates)): teammate_car = self.info.cars[self.teammates[i]] if distance_2d(teammate_car.position, get_intersect(self, teammate_car)) < dist_to_ball: dist_to_ball = distance_2d(teammate_car.position, get_intersect(self, teammate_car)) return distance_2d(self.info.my_car.position, get_intersect(self, self.info.my_car)) <= dist_to_ball
def should_defending(self): return False # Don't. """Method which returns a boolean regarding whether we should defend or not""" ball = self.info.ball car = self.info.my_car our_goal = self.my_goal.center car_to_ball = ball.location - car.location in_front_of_ball = distance_2d(ball.location, our_goal) < distance_2d( car.location, our_goal) backline_intersect = line_backline_intersect(self.my_goal.center[1], vec2(car.location), vec2(car_to_ball)) return (in_front_of_ball and abs(backline_intersect) < 2000) or self.conceding
def defending(agent): """"Method that gives output for the defending strategy""" target = defending_target(agent) agent.drive.target = target distance = distance_2d(agent.info.my_car.position, target) vf = velocity_forward(agent.info.my_car) dodge_overshoot = distance < (abs(vf) + 500) * 1.5 agent.drive.speed = get_speed(agent, target) agent.drive.step(agent.info.time_delta) agent.controls = agent.drive.controls t = time.time() can_dodge, simulated_duration, simulated_target = agent.simulate() # print(time.time() - t) if can_dodge: agent.dodge = Dodge(agent.info.my_car) agent.turn = AerialTurn(agent.info.my_car) agent.dodge.duration = simulated_duration - 0.1 agent.dodge.target = simulated_target agent.dodge.preorientation = look_at(simulated_target, vec3(0, 0, 1)) agent.timer = 0 agent.step = Step.Dodge if not agent.should_defend(): agent.step = Step.Shooting elif vf < -900 and (not dodge_overshoot or distance < 600): agent.step = Step.HalfFlip agent.halfflip = HalfFlip(agent.info.my_car) elif not dodge_overshoot and agent.info.my_car.position[2] < 80 and \ (agent.drive.speed > abs(vf) + 300 and 1200 < abs(vf) < 2000 and agent.info.my_car.boost <= 25): # Dodge towards the target for speed agent.step = Step.Dodge agent.dodge = Dodge(agent.info.my_car) agent.dodge.duration = 0.1 agent.dodge.target = target
def get_output(self, packet: GameTickPacket) -> SimpleControllerState: """The main method which receives the packets and outputs the controls""" self.time = packet.game_info.seconds_elapsed self.info.read_game_information(packet, self.get_rigid_body_tick(), self.get_field_info()) update_boostpads(self, packet) self.predict() # self.handle_match_comms() self.prev_kickoff = self.kickoff self.kickoff = packet.game_info.is_kickoff_pause and distance_2d( self.info.ball.location, vec3(0, 0, 0)) < 100 self.defending = self.should_defending() if self.kickoff and not self.prev_kickoff: # if not self.close_to_kickoff_spawn(): # return init_kickoff(self) self.prev_kickoff = True self.drive.kickoff = True elif self.kickoff or self.step is Step.Dodge_2: kick_off(self) self.drive.kickoff = True else: self.drive.kickoff = False self.get_controls() self.render_string(self.step.name) # Make sure there is no variance in kickoff setups if not packet.game_info.is_round_active: self.controls.steer = 0 return self.controls
def defending(agent): """"Method that gives output for the defending strategy""" target = defending_target(agent) agent.drive.target = target distance = distance_2d(agent.info.my_car.location, target) vf = velocity_forward(agent.info.my_car) dodge_overshoot = distance < (abs(vf) + 500) * 1.5 agent.drive.speed = get_speed(agent, target) agent.drive.step(agent.info.time_delta) agent.controls = agent.drive.controls if can_dodge(agent, target): agent.step = Step.Dodge agent.dodge = Dodge(agent.info.my_car) agent.dodge.duration = 0.1 agent.dodge.target = target if not agent.defending: agent.step = (Step.Catching if agent.ball_bouncing else Step.Shooting) elif vf < -900 and (not dodge_overshoot or distance < 600): agent.step = Step.HalfFlip agent.halfflip = HalfFlip(agent.info.my_car) elif not dodge_overshoot and agent.info.my_car.location[2] < 80 and\ (agent.drive.speed > abs(vf) + 300 and 1200 < abs(vf) < 2000 and agent.info.my_car.boost <= 25): # Dodge towards the target for speed agent.step = Step.Dodge agent.dodge = Dodge(agent.info.my_car) agent.dodge.duration = 0.1 agent.dodge.target = target
def shooting(agent): """"Method that gives the output for the shooting strategy""" ball = agent.info.ball car = agent.info.my_car target = shooting_target(agent) agent.drive.target = target distance = distance_2d(car.position, target) vf = velocity_forward(car) dodge_overshoot = distance < (abs(vf) + 500) * 1.5 agent.drive.speed = get_speed(agent, target) agent.drive.step(agent.info.time_delta) agent.controls = agent.drive.controls if agent.defending: agent.step = Step.Defending elif should_dodge(agent): agent.step = Step.Dodge agent.dodge = Dodge(car) agent.dodge.duration = 0.1 agent.dodge.target = ball.position elif agent.ball_bouncing and not (abs(ball.velocity[2]) < 100 and sign(agent.team) * ball.velocity[1] < 0) and get_bounce(agent) is not None: agent.step = Step.Catching agent.drive.target = ball.position agent.drive.speed = 1399 elif vf < -900 and (not dodge_overshoot or distance < 600): agent.step = Step.HalfFlip agent.halfflip = HalfFlip(car) elif not dodge_overshoot and car.position[2] < 80 and \ (agent.drive.speed > abs(vf) + 300 and 1200 < abs(vf) < 2000 and car.boost <= 25): # Dodge towards the target for speed agent.step = Step.Dodge agent.dodge = Dodge(car) agent.dodge.duration = 0.1 agent.dodge.target = target
def shooting_target(agent): """"Method that gives the target for the shooting strategy""" ball = agent.info.ball car = agent.info.my_car car_to_ball = ball.location - car.location backline_intersect = line_backline_intersect(agent.their_goal.center[1], vec2(car.location), vec2(car_to_ball)) if abs(backline_intersect) < 700: goal_to_ball = normalize(car.location - ball.location) error = 0 else: # Right of the ball if -500 > backline_intersect: target = agent.their_goal.corners[3] + vec3(400, 0, 0) # Left of the ball elif backline_intersect > 500: target = agent.their_goal.corners[2] - vec3(400, 0, 0) goal_to_ball = normalize(ball.location - target) # Subtract the goal to car vector difference = goal_to_ball - normalize(car.location - target) error = cap(abs(difference[0]) + abs(difference[1]), 0, 5) goal_to_ball_2d = vec2(goal_to_ball[0], goal_to_ball[1]) test_vector_2d = dot(rotation(0.5 * math.pi), goal_to_ball_2d) test_vector = vec3(test_vector_2d[0], test_vector_2d[1], 0) distance = cap( (40 + distance_2d(ball.location, car.location) * (error**2)) / 1.8, 0, 4000) location = ball.location + vec3( (goal_to_ball[0] * distance), goal_to_ball[1] * distance, 0) # this adjusts the target based on the ball velocity perpendicular # to the direction we're trying to hit it multiplier = cap(distance_2d(car.location, location) / 1500, 0, 2) distance_modifier = cap( dot(test_vector, ball.velocity) * multiplier, -1000, 1000) location += vec3(test_vector[0] * distance_modifier, test_vector[1] * distance_modifier, 0) # another target adjustment that applies if the ball is close to the wall extra = 3850 - abs(location[0]) if extra < 0: location[0] = cap(location[0], -3850, 3850) location[1] = location[1] + (-sign(agent.team) * cap(extra, -800, 800)) return location
def shooting_target(agent): ball = agent.info.ball car = agent.info.my_car car_to_ball = ball.pos - car.pos backline_intersect = line_backline_intersect( agent.info.their_goal.center[1], vec2(car.pos), vec2(car_to_ball)) if -500 < backline_intersect < 500: goal_to_ball = normalize(car.pos - ball.pos) error = cap(distance_2d(ball.pos, car.pos) / 1000, 0, 1) else: # Right of the ball if -500 > backline_intersect: target = agent.info.their_goal.corners[3] + vec3(400, 0, 0) # Left of the ball elif 500 < backline_intersect: target = agent.info.their_goal.corners[2] - vec3(400, 0, 0) goal_to_ball = normalize(ball.pos - target) goal_to_car = normalize(car.pos - target) difference = goal_to_ball - goal_to_car error = cap(abs(difference[0]) + abs(difference[1]), 1, 10) goal_to_ball_2d = vec2(goal_to_ball[0], goal_to_ball[1]) test_vector_2d = dot(rotation(0.5 * math.pi), goal_to_ball_2d) test_vector = vec3(test_vector_2d[0], test_vector_2d[1], 0) distance = cap((40 + distance_2d(ball.pos, car.pos) * (error**2)) / 1.8, 0, 4000) location = ball.pos + vec3( (goal_to_ball[0] * distance), goal_to_ball[1] * distance, 0) # this adjusts the target based on the ball velocity perpendicular to the direction we're trying to hit it multiplier = cap(distance_2d(car.pos, location) / 1500, 0, 2) distance_modifier = cap( dot(test_vector, ball.vel) * multiplier, -1000, 1000) modified_vector = vec3(test_vector[0] * distance_modifier, test_vector[1] * distance_modifier, 0) location += modified_vector # another target adjustment that applies if the ball is close to the wall extra = 3850 - abs(location[0]) if extra < 0: location[0] = cap(location[0], -3850, 3850) location[1] = location[1] + (-sign(agent.team) * cap(extra, -800, 800)) return location
def should_dodge(agent): """"Method that checks if we should dodge""" car = agent.info.my_car their_goal = agent.their_goal close_to_goal = distance_2d(car.position, their_goal.center) < 4000 aiming_for_goal = abs(line_backline_intersect( their_goal.center[1], vec2(car.position), vec2(car.forward()))) < 850 bot_to_target = agent.info.ball.position - car.position local_bot_to_target = dot(bot_to_target, agent.info.my_car.orientation) angle_front_to_target = math.atan2(local_bot_to_target[1], local_bot_to_target[0]) close_to_ball = norm(vec2(bot_to_target)) < 750 good_angle = abs(angle_front_to_target) < math.radians(15) return close_to_ball and close_to_goal and aiming_for_goal and good_angle
def should_dodge(agent): car = agent.info.my_car their_goal = agent.info.their_goal close_to_goal = distance_2d(car.pos, their_goal.center) < 4000 aiming_for_goal = abs( line_backline_intersect(their_goal.center[1], vec2(car.pos), vec2(car.forward()))) < 850 bot_to_target = agent.info.ball.pos - car.pos local_bot_to_target = dot(bot_to_target, agent.info.my_car.theta) angle_front_to_target = math.atan2(local_bot_to_target[1], local_bot_to_target[0]) close_to_ball = norm(vec2(bot_to_target)) < 850 good_angle = math.radians(-10) < angle_front_to_target < math.radians(10) return close_to_ball and close_to_goal and aiming_for_goal and good_angle
def close_to_kickoff_spawn(self): blue_one = distance_2d(self.info.my_car.position, vec3( -2048, -2560, 18)) < 10 blue_two = distance_2d(self.info.my_car.position, vec3( 2048, -2560, 18)) < 10 blue_three = distance_2d(self.info.my_car.position, vec3(-256, -3840, 18)) < 10 blue_four = distance_2d(self.info.my_car.position, vec3( 256, -3840, 18)) < 10 blue_five = distance_2d(self.info.my_car.position, vec3(0, -4608, 18)) < 10 blue = blue_one or blue_two or blue_three or blue_four or blue_five orange_one = distance_2d(self.info.my_car.position, vec3(-2048, 2560, 18)) < 10 orange_two = distance_2d(self.info.my_car.position, vec3( 2048, 2560, 18)) < 10 orange_three = distance_2d(self.info.my_car.position, vec3(-256, 3840, 18)) < 10 orange_four = distance_2d(self.info.my_car.position, vec3( 256, 3840, 18)) < 10 orange_five = distance_2d(self.info.my_car.position, vec3(0, 4608, 18)) < 10 orange = orange_one or orange_two or orange_three or orange_four or orange_five return orange or blue
def get_output(self, packet: GameTickPacket) -> SimpleControllerState: """The main method which receives the packets and outputs the controls""" self.info.read_game_information(packet, self.get_field_info()) self.in_front_off_ball = in_front_off_ball(self.info.my_car.position, self.info.ball.position, self.my_goal.center) update_boostpads(self, packet) self.closest_to_ball = self.closest_to_the_ball() self.predict() self.time += self.info.time_delta if self.time > 5 and self.set_state: ball_state = BallState(Physics(location=Vector3(0, 5250, 250))) game_state = GameState(ball=ball_state) self.set_state = False self.set_game_state(game_state) dtype = [('physics', [('location', '<f4', 3), ('rotation', [('pitch', '<f4'), ('yaw', '<f4'), ('roll', '<f4')]), ('velocity', '<f4', 3), ('angular_velocity', '<f4', 3)]), ('game_seconds', '<f4')] self.ball_prediction_np = np.ctypeslib.as_array( self.get_ball_prediction_struct().slices).view( dtype)[:self.get_ball_prediction_struct().num_slices] self.teammates = [] for i in range(self.info.num_cars): if self.info.cars[i].team == self.team and i != self.index: self.teammates.append(i) self.time = packet.game_info.seconds_elapsed # self.handle_match_comms() self.prev_kickoff = self.kickoff self.kickoff = packet.game_info.is_kickoff_pause and distance_2d( self.info.ball.position, vec3(0, 0, 0)) < 100 if self.kickoff and not self.prev_kickoff: # if not self.close_to_kickoff_spawn(): # return if len(self.teammates) > 0: if self.closest_to_ball: init_kickoff(self) self.has_to_go = True else: self.drive.target = get_closest_big_pad(self).location self.drive.speed = 1399 else: init_kickoff(self) self.has_to_go = True if (self.kickoff or self.step == "Dodge2") and self.has_to_go: kick_off(self) elif self.kickoff and not self.has_to_go: self.drive.step(self.info.time_delta) self.controls = self.drive.controls else: if self.has_to_go: self.has_to_go = False self.get_controls() self.render_string(self.step.name) # Make sure there is no variance in kickoff setups if not packet.game_info.is_round_active: self.controls.steer = 0 return self.controls
def kick_off(agent): ball = agent.info.ball car = agent.info.my_car t = distance_2d(ball.position, car.position) / 2200 batmobile_resting = 18.65 robbies_constant = (ball.position - vec3(0, 0, 92.75 - batmobile_resting) - car.position - car.velocity * t) * 2 * t**-2 robbies_boost_constant = dot(normalize(xy( car.forward())), normalize( xy(robbies_constant))) > (0.3 if car.on_ground else 0.1) """"Module that performs the kickoffs""" if agent.kickoffStart == "Diagonal": if agent.step is Step.Drive: agent.drive.step(agent.info.time_delta) agent.controls = agent.drive.controls if agent.drive.finished: ball_location = ball.position + vec3( 0, -sign(agent.team) * 500, 0) target = car.position + 250 * normalize(ball_location - car.position) agent.drive = Drive(car) agent.drive.target = target agent.drive.speed = 2400 agent.step = Step.Drive_1 if agent.step is Step.Drive_1: agent.drive.step(agent.info.time_delta) agent.controls = agent.drive.controls if agent.drive.finished: target = vec3( dot( rotation( math.radians(-sign(agent.info.team) * sign(car.position[0]) * 60)), vec2(car.forward())) * 10000) preorientation = dot( axis_to_rotation( vec3( 0, 0, math.radians(-sign(agent.info.team) * -sign(car.position[0]) * 30))), car.orientation) setup_first_dodge(agent, 0.05, 0.3, target, preorientation) elif agent.step is Step.Dodge_1: agent.timer += agent.info.time_delta if agent.timer > 0.8: lerp_var = lerp( normalize(robbies_constant), normalize(ball.position - vec3(0, 0, 92.75 - batmobile_resting) - car.position), 0.8) agent.turn.target = look_at(lerp_var, vec3(0, 0, 1)) agent.turn.step(agent.info.time_delta) agent.controls = agent.turn.controls if car.on_ground: agent.time = 0 agent.set_state = True agent.step = Step.Shooting else: agent.dodge.step(agent.info.time_delta) agent.controls = agent.dodge.controls agent.controls.boost = robbies_boost_constant elif agent.kickoffStart == "Center": if agent.step is Step.Drive: agent.drive.step(agent.info.time_delta) agent.controls = agent.drive.controls if agent.drive.finished: target = vec3( dot(rotation(math.radians(-65)), vec2(car.forward())) * 10000) preorientation = dot( axis_to_rotation(vec3(0, 0, math.radians(45))), car.orientation) setup_first_dodge(agent, 0.05, 0.4, target, preorientation) elif agent.step is Step.Dodge_1: agent.timer += agent.info.time_delta if agent.timer > 0.8: agent.turn.target = look_at(xy(ball.position - car.position), vec3(0, 0, 1)) agent.turn.step(agent.info.time_delta) agent.controls = agent.turn.controls set_steer(agent) else: agent.dodge.step(agent.info.time_delta) agent.controls = agent.dodge.controls agent.controls.boost = robbies_boost_constant elif agent.step is Step.Steer: agent.drive.step(agent.info.time_delta) agent.controls = agent.drive.controls if distance_2d(car.position, ball.position) < 800: agent.step = Step.Dodge_2 agent.dodge = Dodge(car) agent.dodge.duration = 0.075 agent.dodge.target = ball.position elif agent.step is Step.Dodge_2: agent.dodge.step(agent.info.time_delta) agent.controls = agent.dodge.controls if agent.dodge.finished and car.on_ground: agent.time = 0 agent.set_state = True agent.step = Step.Shooting elif agent.kickoffStart == "offCenter": if agent.step is Step.Drive: agent.drive.step(agent.info.time_delta) agent.controls = agent.drive.controls if distance_2d(car.position, agent.drive.target) < 650: target = vec3( dot( rotation( math.radians(-sign(agent.info.team) * -sign(car.position[0]) * 100)), vec2(car.forward())) * 10000) preorientation = dot( axis_to_rotation( vec3( 0, 0, math.radians(-sign(agent.info.team) * sign(car.position[0]) * 30))), car.orientation) print("PYTHON: ", agent.info.my_car.position) print( "PYTHON: ", math.radians(-sign(agent.info.team) * -sign(car.position[0]) * 100)) setup_first_dodge(agent, 0.05, 0.4, target, preorientation) elif agent.step is Step.Dodge_1: agent.timer += agent.info.time_delta if agent.timer > 0.8: lerp_var = lerp( normalize(robbies_constant), normalize(ball.position - vec3(0, 0, 92.75 - batmobile_resting) - car.position), 0.25) agent.turn.target = look_at(lerp_var, vec3(0, 0, 1)) agent.turn.step(agent.info.time_delta) agent.controls = agent.turn.controls set_steer(agent) else: agent.dodge.step(agent.info.time_delta) agent.controls = agent.dodge.controls agent.controls.boost = robbies_boost_constant elif agent.step is Step.Steer: agent.drive.step(agent.info.time_delta) agent.controls = agent.drive.controls if distance_2d(ball.position, car.position) < 800: agent.step = Step.Dodge_2 agent.dodge = Dodge(car) agent.dodge.duration = 0.075 agent.dodge.target = ball.position elif agent.step is Step.Dodge_2: agent.dodge.step(agent.info.time_delta) agent.controls = agent.dodge.controls if agent.dodge.finished and car.on_ground: agent.time = 0 agent.set_state = True agent.step = Step.Shooting
def kick_off(agent): if agent.kickoffStart == "Diagonal_Scrub": if agent.step == "Drive": agent.drive.step(agent.FPS) agent.controls = agent.drive.controls if agent.drive.finished: agent.step = "Dodge1" # target = agent.info.ball.pos target = normalize(z0(agent.info.my_car.forward())) * 1000 agent.dodge = AirDodge(agent.info.my_car, 0.075, target) elif agent.step == "Dodge1": agent.dodge.step(agent.FPS) agent.controls = agent.dodge.controls if agent.dodge.finished: agent.step = "Steer" target = agent.info.ball.pos agent.drive = Drive(agent.info.my_car, target, 1399) elif agent.step == "Steer": agent.drive.step(agent.FPS) agent.controls = agent.drive.controls if agent.info.my_car.on_ground: agent.drive.target_speed = 2400 if distance_2d(agent.info.ball.pos, agent.info.my_car.pos) < 750: agent.step = "Dodge2" agent.dodge = AirDodge(agent.info.my_car, 0.075, agent.info.ball.pos) elif agent.step == "Dodge2": agent.dodge.step(agent.FPS) agent.controls = agent.dodge.controls if agent.dodge.finished and agent.info.my_car.on_ground: agent.step = "Catching" elif agent.kickoffStart == "Diagonal": if agent.step == "Drive": agent.drive.step(agent.FPS) agent.controls = agent.drive.controls if distance_2d(agent.info.ball.pos, agent.info.my_car.pos) < 850: agent.step = "Dodge" agent.dodge = AirDodge(agent.info.my_car, 0.075, agent.info.ball.pos) elif agent.step == "Dodge": agent.dodge.step(agent.FPS) agent.controls = agent.dodge.controls if agent.dodge.finished and agent.info.my_car.on_ground: agent.step = "Catching" elif agent.kickoffStart == "Center": if agent.step == "Drive": agent.drive.step(agent.FPS) agent.controls = agent.drive.controls if agent.drive.finished: agent.step = "Dodge1" agent.dodge = AirDodge(agent.info.my_car, 0.075, agent.info.ball.pos) elif agent.step == "Dodge1": agent.dodge.step(agent.FPS) agent.controls = agent.dodge.controls agent.controls.boost = 0 if agent.dodge.finished and agent.info.my_car.on_ground: agent.step = "Steer" target = agent.info.ball.pos + sign(agent.team) * vec3( 0, 850, 0) agent.drive = Drive(agent.info.my_car, target, 2400) elif agent.step == "Steer": agent.drive.step(agent.FPS) agent.controls = agent.drive.controls if agent.drive.finished: agent.step = "Dodge2" agent.dodge = AirDodge(agent.info.my_car, 0.075, agent.info.ball.pos) elif agent.step == "Dodge2": agent.dodge.step(agent.FPS) agent.controls = agent.dodge.controls if agent.dodge.finished and agent.info.my_car.on_ground: agent.step = "Catching" elif agent.kickoffStart == "offCenter": if agent.step == "Drive": agent.drive.step(agent.FPS) agent.controls = agent.drive.controls if agent.info.my_car.boost < 15 or agent.drive.finished: agent.step = "Dodge1" agent.dodge = AirDodge(agent.info.my_car, 0.075, agent.info.ball.pos) elif agent.step == "Dodge1": agent.dodge.step(agent.FPS) agent.controls = agent.dodge.controls agent.controls.boost = 0 if agent.dodge.finished and agent.info.my_car.on_ground: agent.step = "Steer" target = agent.info.ball.pos agent.drive = Drive(agent.info.my_car, target, 2400) elif agent.step == "Steer": agent.drive.step(agent.FPS) agent.controls = agent.drive.controls if distance_2d(agent.info.ball.pos, agent.info.my_car.pos) < 850: agent.step = "Dodge2" agent.dodge = AirDodge(agent.info.my_car, 0.075, agent.info.ball.pos) elif agent.step == "Dodge2": agent.dodge.step(agent.FPS) agent.controls = agent.dodge.controls if agent.dodge.finished and agent.info.my_car.on_ground: agent.step = "Catching"
def get_controls(self): if self.step == "Steer" or self.step == "Dodge2": self.step = "Catching" if self.step == "Catching": target = get_bounce(self) if target is None: self.step = "Defending" else: self.catching.target_pos = target[0] self.catching.target_speed = (distance_2d( self.info.my_car.pos, target[0]) + 50) / target[1] self.catching.step(self.FPS) self.controls = self.catching.controls ball = self.info.ball car = self.info.my_car if distance_2d(ball.pos, car.pos) < 150 and 65 < abs(ball.pos[2] - car.pos[2]) < 127: self.step = "Dribbling" self.dribble = Dribbling(self.info.my_car, self.info.ball, self.info.their_goal) if self.defending: self.step = "Defending" if not self.info.my_car.on_ground: self.step = "Recovery" ball = self.info.ball if abs(ball.vel[2]) < 100 and sign( self.team) * ball.vel[1] < 0 and sign( self.team) * ball.pos[1] < 0: self.step = "Shooting" elif self.step == "Dribbling": self.dribble.step(self.FPS) self.controls = self.dribble.controls ball = self.info.ball car = self.info.my_car bot_to_opponent = self.info.opponents[0].pos - self.info.my_car.pos local_bot_to_target = dot(bot_to_opponent, self.info.my_car.theta) angle_front_to_target = math.atan2(local_bot_to_target[1], local_bot_to_target[0]) opponent_is_near = norm(vec2(bot_to_opponent)) < 2000 opponent_is_in_the_way = math.radians( -10) < angle_front_to_target < math.radians(10) if not (distance_2d(ball.pos, car.pos) < 150 and 65 < abs(ball.pos[2] - car.pos[2]) < 127): self.step = "Catching" if self.defending: self.step = "Defending" if opponent_is_near and opponent_is_in_the_way: self.step = "Dodge" self.dodge = AirDodge(self.info.my_car, 0.25, self.info.their_goal.center) if not self.info.my_car.on_ground: self.step = "Recovery" elif self.step == "Defending": defending(self) elif self.step == "Dodge": self.dodge.step(self.FPS) self.controls = self.dodge.controls self.controls.boost = 0 if self.dodge.finished and self.info.my_car.on_ground: self.step = "Catching" elif self.step == "Recovery": self.recovery.step(self.FPS) self.controls = self.recovery.controls if self.info.my_car.on_ground: self.step = "Catching" elif self.step == "Shooting": shooting(self)
def get_controls(self): """Decides what strategy to uses and gives corresponding output""" self.drive.power_turn = False if self.step is Step.Steer or self.step is Step.Drive: self.step = Step.Catching if self.step is Step.Catching: # Enable power turning for catching, since we don't halfflip self.drive.power_turn = True target = get_bounce(self) if target is None: self.step = Step.Shooting else: self.catching.target = target[0] self.catching.speed = (distance_2d(self.info.my_car.location, target[0]) + 50) / target[1] self.catching.step(self.info.time_delta) self.controls = self.catching.controls ball = self.info.ball car = self.info.my_car if distance_2d(ball.location, car.location) < 150 and 65 < abs( ball.location[2] - car.location[2]) < 127: self.step = Step.Dribbling self.dribble = Dribbling(self.info.my_car, self.info.ball, self.their_goal) if self.defending: self.step = Step.Defending ball = self.info.ball if abs(ball.velocity[2]) < 100 and sign(self.team) * ball.velocity[1] < 0 and sign(self.team) * \ ball.location[1] < 0: self.step = Step.Shooting elif self.step is Step.Dribbling: self.dribble.step() self.controls = self.dribble.controls ball = self.info.ball car = self.info.my_car bot_to_opponent = self.info.cars[ 1 - self.index].location - self.info.my_car.location local_bot_to_target = dot(bot_to_opponent, self.info.my_car.rotation) angle_front_to_target = math.atan2(local_bot_to_target[1], local_bot_to_target[0]) opponent_is_near = norm(vec2(bot_to_opponent)) < 2000 opponent_is_in_the_way = math.radians( -10) < angle_front_to_target < math.radians(10) if not (distance_2d(ball.location, car.location) < 150 and 65 < abs(ball.location[2] - car.location[2]) < 127): self.step = Step.Catching if self.defending: self.step = Step.Defending if opponent_is_near and opponent_is_in_the_way: self.step = Step.Dodge self.dodge = Dodge(self.info.my_car) self.dodge.duration = 0.25 self.dodge.target = self.their_goal.center elif self.step is Step.Defending: defending(self) elif self.step in [ Step.Dodge, Step.Dodge_1, Step.Dodge_2, Step.HalfFlip ]: halfflipping = self.step is Step.HalfFlip if halfflipping: self.halfflip.step(self.info.time_delta) else: self.dodge.step(self.info.time_delta) if self.halfflip.finished if halfflipping else self.dodge.finished: self.step = Step.Catching else: self.controls = (self.halfflip.controls if halfflipping else self.dodge.controls) elif self.step is Step.Shooting: shooting(self)
def step(self): """"Gives output for the dribbling strategy""" # direction of ball relative to center of car (where should we aim) # direction of ball relative to yaw of car (where should we aim verse where we are aiming) local_bot_to_ball = dot(self.ball.position - self.car.position, self.car.orientation) angle_front_to_ball = math.atan2(local_bot_to_ball[1], local_bot_to_ball[0]) # distance between bot and ball distance = distance_2d(self.car.position, self.ball.position) # direction of ball velocity relative to yaw of car (which way the ball is moving verse which way we are moving) if velocity_2d(self.ball.velocity) < 1e-10: angle_car_forward_to_ball_velocity = 0 else: angle_car_forward_to_ball_velocity = angle_between( z_0(self.car.forward()), z_0(self.ball.velocity)) # magnitude of ball_bot_angle (squared) ball_bot_diff = (self.ball.velocity[0]**2 + self.ball.velocity[1]**2) - (self.car.velocity[0]**2 + self.car.velocity[1]**2) # p is the distance between ball and car # i is the magnitude of the ball's velocity (squared) the i term would normally # be the integral of p over time, but the ball's velocity is essentially that number # d is the relative speed between ball and car # note that bouncing a ball is distinctly different than balancing something that doesnt bounce # p_s is the x component of the distance to the ball # d_s is the one frame change of p_s, that's why p_s has to be global # we modify distance and ball_bot_diff so that only the component along the car's path is counted # if the ball is too far to the left, we don't want the bot to think it has to drive forward # to catch it distance_y = math.fabs(distance * math.cos(angle_front_to_ball)) distance_x = math.fabs(distance * math.sin(angle_front_to_ball)) # ball moving forward WRT car yaw? forward = False if math.fabs(angle_car_forward_to_ball_velocity) < math.radians(90): forward = True # first we give the distance values signs if forward: d = ball_bot_diff i = (self.ball.velocity[0]**2 + self.ball.velocity[1]**2) else: d = -ball_bot_diff i = -(self.ball.velocity[0]**2 + self.ball.velocity[1]**2) if math.fabs(math.degrees(angle_front_to_ball)) < 90: p = distance_y else: p = -1 * distance_y # this is the PID correction. all of the callibration goes on right here # there is literature about how to set the variables but it doesn't work quite the same # because the car is only touching the ball (and interacting with the system) on bounces # we run the PID formula through tanh to give a value between -1 and 1 for steering input # if the ball is lower we have no velocity bias bias_v = 600000 # 600000 # just the basic PID if the ball is too low if self.ball.position[2] < 120: correction = np.tanh((20 * p + .0015 * i + .006 * d) / 500) # if the ball is on top of the car we use our bias (the bias is in velocity units squared) else: correction = np.tanh( (20 * p + .0015 * (i - bias_v) + .006 * d) / 500) # makes sure we don't get value over .99 so we dont exceed maximum thrust self.controls.throttle = correction * .99 # anything over .9 is boost if correction > .99: self.controls.boost = True else: self.controls.boost = False # this is the PID steering section # p_s is the x component of the distance to the ball (relative to the cars direction) # d_s is the on frame change in p_s # we use absolute value and then set the sign later d_s = math.fabs(self.p_s) - math.fabs(distance_x) self.p_s = math.fabs(distance_x) # give the values the correct sign if angle_front_to_ball < 0: self.p_s = -self.p_s d_s = -d_s # d_s is actually -d_s ...whoops d_s = -d_s max_bias = 35 backline_intersect = line_backline_intersect(self.goal.center[1], vec2(self.car.position), vec2(self.car.forward())) if abs(backline_intersect) < 1000 or self.ball.position[2] > 200: bias = 0 # Right of the ball elif -850 > backline_intersect: bias = max_bias # Left of the ball elif 850 < backline_intersect: bias = -max_bias # the correction settings can be altered to change performance correction = np.tanh((100 * (self.p_s + bias) + 1500 * d_s) / 8000) # apply the correction self.controls.steer = correction