예제 #1
0
class HalfFlip:
    def __init__(self, car):
        self.timer = 0
        self.car = car
        self.direction = vec3(car.forward() * -1)
        self.target = self.direction * 1000 + self.car.location
        self.aerial_turn = AerialTurn(car)
        self.aerial_turn.target = look_at(self.direction, vec3(0, 0, 1))
        self.controls = SimpleControllerState()
        self.finished = False

    def step(self, dt: float):
        self.controls = SimpleControllerState()

        self.aerial_turn.step(dt)
        aerial_turn_controls = self.aerial_turn.controls

        if self.timer < 0.7:
            self.controls.jump = True
            if 0.075 < self.timer < 0.1:
                self.controls.jump = False
            self.controls.pitch = (-1 if self.timer > 0.425 else 1)
            self.controls.roll = aerial_turn_controls.roll
        else:
            self.controls = aerial_turn_controls
            if (self.car.on_ground and self.timer > 0.25) or self.timer > 1.1:
                self.finished = True

        self.controls.boost = (dot(self.car.forward(), self.direction) > 0.8)

        self.timer += dt
예제 #2
0
class Hover:
    """
    PD controller for hovering in the air
    """
    P = 1.8
    D = 2.5

    def __init__(self, car: Car):
        self.turn = AerialTurn(car)
        self.target: vec3 = None
        self.car: Car = car
        self.up: vec3 = None
        self.controls: Input = Input()

    def step(self, dt):
        delta_target = self.target - self.car.position
        target_direction = normalize(
            vec3((delta_target[0]) * self.P - self.car.velocity[0] * self.D,
                 (delta_target[1]) * self.P - self.car.velocity[1] * self.D,
                 1000))

        self.turn.target = look_at(target_direction, self.up)

        self.turn.step(dt)
        self.controls = self.turn.controls
        self.controls.boost = 0

        # tap boost to keep height
        if (delta_target[2] - self.car.velocity[2] * 0.5) > 0:
            self.controls.boost = 1
예제 #3
0
class AimDodge(Maneuver):
    def __init__(self, car: Car, duration: float, target: vec3):
        super().__init__(car)

        self.dodge = AirDodge(car, duration, target)
        self.turn = AerialTurn(car)
        self.turn.target = look_at(direction(car, target), vec3(0, 0, 1))
        self.jump = self.dodge.jump
        self.target = target

    def step(self, dt):
        self.dodge.step(dt)
        self.controls = self.dodge.controls
        self.finished = self.dodge.finished
        if not self.dodge.jump.finished and not self.car.on_ground:
            target_direction = direction(self.car,
                                         self.target + vec3(0, 0, 100))
            up = target_direction * (-1)
            up[2] = 1
            up = normalize(up)
            self.turn.target = look_at(target_direction, up)
            self.turn.step(dt)
            self.controls.pitch = self.turn.controls.pitch
            self.controls.yaw = self.turn.controls.yaw
            self.controls.roll = self.turn.controls.roll
예제 #4
0
    def rotate(self, car: Car, target: vec3, dt) -> SimpleControllerState:
        # up = vec3(*[self.car.theta[i, 2] for i in range(3)])

        target_rotation = look_at(self.target, vec3(0, 0, 1))
        action = AerialTurn(car)
        action.target = target_rotation

        action.step(dt)
        controls = action.controls

        return controls
def moving_ball_dodge_contact(game_info):
    '''
    Returns dodge duration and delay so the car can reach contact_height
    '''

    ball = game_info.ball
    contact_height = ball.pos.z - 20
    hitbox_class = game_info.me.hitbox_class
    car_copy = RLU_Car(game_info.utils_game.my_car)
    turn = RLU_AerialTurn(car_copy)
    turn.target = roll_away_from_target(ball.pos, pi / 4, game_info)
    box = update_hitbox(car_copy, hitbox_class)
    time = 0
    dt = 1 / 60
    ball_contact = has_ball_contact(time, box, ball, game_info.team_sign)
    closest_point = ball_contact[1]

    while closest_point[2] < contact_height and not ball_contact[0]:
        time += dt
        ball = game_info.ball_prediction.state_at_time(game_info.game_time +
                                                       time)

        turn.step(dt)
        contact_height = ball.pos.z - 30
        controls = turn.controls
        if time <= 0.20:
            controls.jump = 1
        controls.boost = 1

        car_copy.step(controls, dt)
        box = update_hitbox(car_copy, hitbox_class)

        ball_contact = has_ball_contact(time, box, ball, game_info.team_sign)
        closest_point = ball_contact[1]
        if time >= 1.45:  #Max dodge time
            return None, None, Simulation()

    if not ball_contact[0]:
        return None, None, Simulation()

    if time < 0.2:
        duration = time
        delay = duration + 2 * dt
    else:
        duration = 0.2
        delay = time

    delay -= 0.05  #Window to dodge just before ball contact

    return duration, delay, Simulation(ball_contact=True,
                                       car=car_copy,
                                       hitbox=box,
                                       time=time)
예제 #6
0
class FastRecovery(Maneuver):
    '''Boost down and try to land on all four wheels'''

    def __init__(self, car: Car):
        super().__init__(car)

        self.landing = False
        self.turn = AerialTurn(self.car)
        self.recovery = Recovery(self.car)

    def step(self, dt):
        self.controls.throttle = 1 # in case we're turtling

        if self.landing:
            self.recovery.step(dt)
            self.controls = self.recovery.controls
        else:
            landing_pos = self.find_landing_pos()
            landing_dir = direction(self.car, landing_pos - vec3(0,0,1000))

            self.turn.target = look_at(landing_dir, vec3(0,0,1))
            self.turn.step(dt)
            self.controls = self.turn.controls

            # boost down
            if angle_between(self.car.forward(), landing_dir) < 0.8:
                self.controls.boost = 1
            else:
                self.controls.boost = 0

            # when nearing landing position, start recovery
            if distance(self.car, landing_pos) < clamp(norm(self.car.velocity), 600, 2300):
                self.landing = True

        self.finished = self.car.on_ground

    def find_landing_pos(self, num_points=200, dt=0.0333) -> vec3:
        '''Simulate car falling until it hits a plane and return it's final position'''
        dummy = Car(self.car)
        for i in range(0, num_points):
            dummy.step(Input(), dt)
            dummy.time += dt
            n = Field.collide(sphere(dummy.position, 40)).direction
            if norm(n) > 0.0 and i > 10:
                return dummy.position
        return self.car.position

    def render(self, draw):
        if self.landing:
            self.recovery.render(draw)
                    
예제 #7
0
class Recovery(Maneuver):
    '''
    Wrapper for RLU recovery (in AerialTurn).
    Not actually used by Botimus, FastRecovery is better.
    '''
    def __init__(self, car: Car):
        super().__init__(car)

        self.turn = AerialTurn(car)
        self.trajectory = []

    def step(self, dt):
        self.find_landing_orientation(200)
        self.turn.step(dt)
        self.controls = self.turn.controls
        self.controls.throttle = 1  # in case we're turtling
        self.finished = self.car.on_ground

    def find_landing_orientation(self, num_points):

        f = vec3(0, 0, 0)
        l = vec3(0, 0, 0)
        u = vec3(0, 0, 0)

        dummy = Car(self.car)
        self.trajectory = [vec3(dummy.position)]
        found = False
        for i in range(0, num_points):
            dummy.step(Input(), 0.01633)
            self.trajectory.append(vec3(dummy.position))
            u = Field.collide(sphere(dummy.position, 40)).direction
            if norm(u) > 0.0 and i > 40:
                f = normalize(dummy.velocity - dot(dummy.velocity, u) * u)
                l = normalize(cross(u, f))
                found = True
                break

        if found:
            self.turn.target = mat3(f[0], l[0], u[0], f[1], l[1], u[1], f[2],
                                    l[2], u[2])
        else:
            self.turn.target = self.car.orientation

    def render(self, draw: DrawingTool):
        draw.color(draw.cyan)
        draw.polyline(self.trajectory)
        draw.color(draw.green)
        draw.vector(self.car.position, facing(self.turn.target) * 200)
        draw.color(draw.red)
        draw.vector(self.car.position, self.car.forward() * 200)
def stationary_ball_dodge_contact(game_info, contact_height):
    '''
    Returns dodge duration and delay so the car can reach contact_height
    '''

    ball = game_info.ball
    hitbox_class = game_info.me.hitbox_class
    car_copy = RLU_Car(game_info.utils_game.my_car)
    turn = RLU_AerialTurn(car_copy)
    turn.target = roll_away_from_target(ball.pos, pi / 4, game_info)
    box = update_hitbox(car_copy, hitbox_class)
    time = 0
    dt = 1 / 60
    ball_contact = has_ball_contact(time, box, ball, game_info.team_sign)
    intended_contact_point = ball_contact[1]

    while intended_contact_point[2] < contact_height and not ball_contact[0]:
        time += dt
        turn.step(dt)
        controls = turn.controls
        if time <= 0.20:
            controls.jump = 1
        controls.boost = 1

        car_copy.step(controls, dt)
        box = update_hitbox(car_copy, hitbox_class)
        ball_contact = has_ball_contact(time, box, ball, game_info.team_sign)
        intended_contact_point = ball_contact[1]
        if time >= 1.45:  #Max dodge time
            return None, None, Simulation()

    if not ball_contact[0]:
        return None, None, Simulation()
    if time < 0.2:
        duration = time
        delay = duration + 2 * dt
    else:
        duration = 0.2
        delay = time

    delay -= 0.05  #How long before we hit the ball is acceptable to dodge

    return duration, delay, Simulation(ball_contact=True,
                                       car=car_copy,
                                       hitbox=box,
                                       time=time)
예제 #9
0
class AirHover(Maneuver):
    '''
    Double jump of the ground and hover in the air at target position.
    Currently useless, but maybe future potential for air-dribbling?
    '''
    P = 1.8
    D = 2.5

    def __init__(self, car: Car, target: vec3):
        super().__init__(car)
        self.turn = AerialTurn(car)
        self.target = target
        self.jump = AirDodge(car, 0.2)

    def step(self, dt):
        if not self.jump.finished:
            self.jump.step(dt)
            self.controls = self.jump.controls
            return

        delta_target = self.target - self.car.position
        target_direction = normalize(
            vec3((delta_target[0]) * self.P - self.car.velocity[0] * self.D,
                 (delta_target[1]) * self.P - self.car.velocity[1] * self.D,
                 1000))

        self.turn.target = look_at(target_direction, self.car.up())

        self.turn.step(dt)
        self.controls = self.turn.controls
        self.controls.boost = 0

        # tap boost to keep height
        if (delta_target[2] - self.car.velocity[2] * 0.5) > 0:
            self.controls.boost = 1

        # boost so we don't fall while relocating
        if dot(self.car.forward(), vec3(0, 0, 1)) < 0.5:
            self.controls.boost = 1
예제 #10
0
class Hover:
    def __init__(self, car: Car, info: Game):
        self.turn = AerialTurn(car)

        self.target = None
        self.car: Car = car
        self.info: Game = info
        self.controls = Input()
        self.jump = False

    def step(self, dt):
        delta_target = self.target - self.car.position

        if norm(delta_target) > 500:
            delta_target = direction(self.car.position, self.target) * 500

        target_direction = delta_target - self.car.velocity + vec3(0, 0, 500)

        self.turn.target = look_at(target_direction, direction(self.car.position, vec3(0, 0, 0)))
        self.turn.step(dt)
        self.controls = self.turn.controls
        self.controls.boost = delta_target[2] - self.car.velocity[2] * 0.5 > 0 and self.car.forward()[2] > 0.2
        self.controls.throttle = not self.car.on_ground
        self.controls.jump = self.car.position[2] < 30 and self.info.time % 1.0 < 0.5
예제 #11
0
class CustomDrive:
    def __init__(self, car):
        self.car = car
        self.target = vec3(0, 0, 0)
        self.speed = 2300
        self.controls = SimpleControllerState()
        self.finished = False
        self.rlu_drive = RLUDrive(self.car)
        self.update_rlu_drive()
        self.power_turn = True  # Handbrake while reversing to turn around quickly
        self.aerial_turn = AerialTurn(car)
        self.kickoff = False

    def step(self, dt: float):
        self.speed = abs(self.speed)
        car_to_target = (self.target - self.car.location)
        local_target = dot(car_to_target, self.car.rotation)
        angle = atan2(local_target[1], local_target[0])
        vel = norm(self.car.velocity)
        in_air = (not self.car.on_ground)
        on_wall = (self.car.location[2] > 250 and not in_air)

        reverse = (cos(angle) < 0 and not (on_wall or in_air or self.kickoff))

        get_off_wall = (on_wall and local_target[2] > 450)
        if get_off_wall:
            car_to_target[2] = -self.car.location[2]
            local_target = dot(car_to_target, self.car.rotation)
            angle = atan2(local_target[1], local_target[0])

        max_speed = self.determine_max_speed(local_target)

        self.update_rlu_drive(reverse, max_speed)
        self.rlu_drive.step(dt)
        self.finished = self.rlu_drive.finished

        self.controls = self.rlu_drive.controls
        self.controls.handbrake = False

        if reverse:
            angle = -invert_angle(angle)
            if self.power_turn and not on_wall:
                angle *= -1
                self.controls.handbrake = (vel > 200)
            self.controls.steer = cap(angle * 3, -1, 1)
            self.controls.boost = False
        if not self.controls.handbrake:
            self.controls.handbrake = (abs(angle) > radians(70) and vel > 500
                                       and not on_wall)
        if self.controls.handbrake:
            self.controls.handbrake = (dot(self.car.velocity, car_to_target) >
                                       -150)

        if in_air:
            self.aerial_turn.target = look_at(xy(car_to_target), vec3(0, 0, 1))
            self.aerial_turn.step(dt)
            aerial_turn_controls = self.aerial_turn.controls
            self.controls.pitch = aerial_turn_controls.pitch
            self.controls.yaw = aerial_turn_controls.yaw
            self.controls.roll = aerial_turn_controls.roll
            self.controls.boost = False

    def update_rlu_drive(self, reverse: bool = False, max_speed: float = 2200):
        self.target = self.target
        self.rlu_drive.target = self.target
        self.rlu_drive.speed = cap(self.speed * (-1 if reverse else 1),
                                   -max_speed, max_speed)

    def determine_max_speed(self, local_target):
        low = 100
        high = 2200
        if self.kickoff:
            return high
        for i in range(5):
            mid = (low + high) / 2
            radius = (1 / RLUDrive.max_turning_curvature(mid))
            local_circle = vec3(0, copysign(radius, local_target[1]), 0)
            dist = norm(local_circle - xy(local_target))
            if dist < radius:
                high = mid
            else:
                low = mid
        return high
예제 #12
0
class Recovery(Maneuver):
    """Boost down and try to land smoothly"""
    def __init__(self, car: Car, jump_when_upside_down=True):
        super().__init__(car)

        self.jump_when_upside_down = jump_when_upside_down
        self.landing = False
        self.aerial_turn = AerialTurn(self.car)

        self.trajectory: List[vec3] = []
        self.landing_pos: Optional[vec3] = None

    def interruptible(self) -> bool:
        return False

    def step(self, dt):
        self.simulate_landing()

        self.aerial_turn.step(dt)
        self.controls = self.aerial_turn.controls

        self.controls.boost = angle_between(self.car.forward(), vec3(
            0, 0, -1)) < 1.5 and not self.landing
        self.controls.throttle = 1  # in case we're turtling

        # jump if the car is upside down and has wheel contact
        if (self.jump_when_upside_down and self.car.on_ground
                and dot(self.car.up(), vec3(0, 0, 1)) < -0.95):
            self.controls.jump = True
            self.landing = False

        else:
            self.finished = self.car.on_ground

    def simulate_landing(self):
        pos = vec3(self.car.position)
        vel = vec3(self.car.velocity)
        grav = vec3(0, 0, -650)
        self.trajectory = [vec3(pos)]
        self.landing = False
        collision_normal: Optional[vec3] = None

        dt = 1 / 60
        simulation_duration = 0.8
        for i in range(int(simulation_duration / dt)):
            pos += vel * dt
            vel += grav * dt
            if norm(vel) > 2300: vel = normalize(vel) * 2300
            self.trajectory.append(vec3(pos))

            collision_sphere = sphere(pos, 50)
            collision_ray = Field.collide(collision_sphere)
            collision_normal = collision_ray.direction

            if (norm(collision_normal) > 0.0 or pos[2] < 0) and i > 20:
                self.landing = True
                self.landing_pos = pos
                break

        if self.landing:
            u = collision_normal
            f = normalize(vel - dot(vel, u) * u)
            l = normalize(cross(u, f))
            self.aerial_turn.target = three_vec3_to_mat3(f, l, u)
        else:
            target_direction = normalize(
                normalize(self.car.velocity) - vec3(0, 0, 3))
            self.aerial_turn.target = look_at(target_direction, vec3(0, 0, 1))

    def render(self, draw: DrawingTool):
        if self.landing:
            draw.color(draw.cyan)
            draw.polyline(self.trajectory)

            if self.landing_pos:
                draw.crosshair(self.landing_pos)

        draw.color(draw.green)
        draw.vector(self.car.position, forward(self.aerial_turn.target) * 200)

        draw.color(draw.red)
        draw.vector(self.car.position, self.car.forward() * 200)
예제 #13
0
class Kickoff(Maneuver):
    '''The simplest boost and dodge at the end kickoff.'''
    def __init__(self, car: Car, info: GameInfo):
        super().__init__(car)
        self.info = info

        target_pos = vec3(0, sgn(info.my_goal.center[1]) * 100, 0)
        self.drive = Drive(car, target_pos, 2300)

        self.action: Maneuver = self.drive
        self.phase = 1

    def step(self, dt):
        car = self.car

        if self.phase == 1:
            if norm(car.velocity) > 1300:
                self.phase = 2
                self.action = AirDodge(car, 0.05, car.position + car.velocity)

        if self.phase == 2:
            if car.on_ground and self.action.finished:
                self.action = self.drive
                self.phase = 3

        if self.phase == 3:
            if distance(car, self.info.ball) < norm(car.velocity) * 0.4:

                # detect if an opponent is going for kickoff
                is_opponent_going_for_kickoff = False
                for opponent in self.info.opponents:
                    if distance(self.info.ball, opponent) < 1500:
                        is_opponent_going_for_kickoff = True

                if is_opponent_going_for_kickoff:
                    self.phase = 4
                    self.action = AirDodge(car, 0.05, self.info.ball.position)
                else:
                    self.phase = "anti-fake-kickoff"
                    self.action = self.drive

        if self.phase == 4:
            if self.action.finished:
                self.action = AerialTurn(car)
                self.phase = 5

        if self.phase == 5:
            self.action.target = look_at(self.info.my_goal.center,
                                         vec3(0, 0, 1))
            self.action.controls.throttle = 1
            if car.on_ground:
                self.finished = True
                # self.phase = 6
                # self.action = DodgeShot(car, self.info, self.info.their_goal.center)

        if self.phase == 6:
            self.finished = self.action.finished

        if self.phase == "anti-fake-kickoff":
            self.drive.target_pos = vec3(80, 0, 0)
            self.finished = self.info.ball.position[1] != 0

        self.action.step(dt)
        self.controls = self.action.controls

        # if not self.dodging and :

        #     if is_opponent_going_for_kickoff:
        #         self.action = self.dodge
        #         self.dodging = True
        #     else:
        #         # if not, don't dodge and steer a bit to the side to aim for a top-corner
        #         self.action.target = self.info.ball.position + vec3(100, 0, 0)

        # self.action.step(dt)
        # self.controls = self.action.controls
        # self.finished = self.info.ball.position[0] != 0

    def render(self, draw: DrawingTool):
        if hasattr(self.action, "render"):
            self.action.render(draw)
예제 #14
0
from rlutilities.linear_algebra import vec3, axis_to_rotation, look_at
from rlutilities.mechanics import AerialTurn
from rlutilities.simulation import Car

c = Car()

c.time = 0.0
c.location = vec3(0, 0, 500)
c.velocity = vec3(0, 0, 0)
c.angular_velocity = vec3(0.1, -2.0, 1.2)
c.rotation = axis_to_rotation(vec3(1.7, -0.5, 0.3))
c.on_ground = False

turn = AerialTurn(c)
turn.target = look_at(vec3(1, 0, 0), vec3(0, 0, 1))

turn.step(0.0166)
print(turn.controls.roll)
print(turn.controls.pitch)
print(turn.controls.yaw)

simulation = turn.simulate()
print(simulation.time)
예제 #15
0
class DoubleJumpStrike(Strike):
    def intercept_predicate(self, car, ball):
        return 250 < ball.position[2] < 550

    def __init__(self, car: Car, info: GameInfo, target=None):
        self.drive = Drive(car)
        self.aerial_turn = AerialTurn(car)

        self.jumping = False
        self.time_for_jump = float("inf")
        self.timer = 0.0

        super().__init__(car, info, target)

    def configure(self, intercept: Intercept):
        super().configure(intercept)
        self.drive.target_pos = ground(intercept.position)
        self.time_for_jump = self.double_jump_time_needed(
            intercept.position[2])

    def interruptible(self) -> bool:
        return not self.jumping and super().interruptible()

    def step(self, dt):
        if self.jumping:
            self.controls = Input()
            # first jump for full 0.2 sec
            if self.timer <= 0.2:
                self.controls.jump = True
            # single tick between jumps
            elif self.timer <= 0.2 + dt * JUMP_FALSE_TICKS:
                self.controls.jump = False
            # second jump
            else:
                self.controls.jump = True
                self.jumping = False
            self.timer += dt

        else:
            self.finished = self.intercept.time < self.info.time

            if self.car.on_ground:
                # manage speed before jump
                distance_to_target = ground_distance(self.car.position,
                                                     self.intercept.position)
                if distance_to_target < MIN_DIST_BEFORE_SPEED_CONTROL:
                    target_speed = distance_to_target / self.time_for_jump
                    self.drive.target_speed = -target_speed if self._should_strike_backwards else target_speed
                    self.drive.step(dt)
                    self.controls = self.drive.controls

                else:
                    super().step(dt)

                # decide when to jump
                ground_vel = ground(self.car.velocity)
                direction_to_target = ground_direction(self.car.position,
                                                       self.intercept.position)
                alignment = dot(normalize(ground_vel), direction_to_target)
                # check alignment
                if alignment >= MIN_ALIGNMENT:
                    # check that speed is correct
                    speed_in_direction = dot(ground_vel, direction_to_target)
                    time_to_target = distance_to_target / speed_in_direction
                    if self.time_for_jump - ALLOWED_TIME_ERROR <= time_to_target <= self.time_for_jump + ALLOWED_TIME_ERROR:
                        self.jumping = True

            # after jump (when the car is in the air)
            else:
                # face the ball for some additional height
                self.aerial_turn.target = look_at(
                    direction(self.car.position, self.info.ball),
                    vec3(0, 0, 1))
                self.aerial_turn.step(dt)
                self.controls = self.aerial_turn.controls

    @staticmethod
    def double_jump_time_needed(height):
        """Return the time needed for the double jump to reach a given height"""
        # polynomial approximation
        a = 1.872348977E-8 * height * height * height
        b = -1.126747937E-5 * height * height
        c = 3.560647225E-3 * height
        d = -7.446058499E-3
        return a + b + c + d
예제 #16
0
class Agent(BaseAgent):
    def __init__(self, name, team, index):
        self.game = Game(index, team)
        self.controls = SimpleControllerState()

        self.timer = 0.0
        self.timeout = 3.0
        self.counter = 0

        self.turn = None
        self.dodge = None
        self.name = None
        self.state = State.RESET

    def get_output(self, packet: GameTickPacket) -> SimpleControllerState:
        self.game.read_game_information(packet, self.get_rigid_body_tick(),
                                        self.get_field_info())
        self.controls = SimpleControllerState()

        next_state = self.state

        if self.state == State.RESET:

            self.timer = 0.0

            # put the car in the middle of the field
            car_state = CarState(physics=Physics(
                location=Vector3(-2000, 0, 18),
                velocity=Vector3(0, 0, 0),
                rotation=Rotator(0, 0, 0),
                angular_velocity=Vector3(0, 0, 0)),
                                 jumped=False,
                                 double_jumped=False)

            # put the ball somewhere out of the way
            ball_state = BallState(
                physics=Physics(location=Vector3(0, 5000, 0),
                                velocity=Vector3(0, 0, 0),
                                rotation=Rotator(0, 0, 0),
                                angular_velocity=Vector3(0, 0, 0)))

            self.set_game_state(
                GameState(ball=ball_state, cars={self.game.id: car_state}))

            next_state = State.WAIT

        if self.state == State.WAIT:

            if self.timer > 0.2:
                next_state = State.INITIALIZE

        if self.state == State.INITIALIZE:

            self.dodge = Dodge(self.game.my_car)
            self.turn = AerialTurn(self.game.my_car)

            f = self.game.my_car.forward()
            l = self.game.my_car.left()
            u = self.game.my_car.up()

            # musty flick
            if self.counter % 3 == 0:
                self.name = "Musty Flick"
                self.dodge.duration = 0.2
                self.dodge.delay = 0.8
                self.dodge.direction = vec2(f)
                self.dodge.preorientation = look_at(-0.1 * f - u, -1.0 * u)

            # diagonal forward dodge
            if self.counter % 3 == 1:
                self.name = "Fast Forward Dodge"
                self.dodge.duration = 0.15
                self.dodge.delay = 0.4
                self.dodge.direction = vec2(1.0, 0.0)
                self.dodge.preorientation = dot(
                    axis_to_rotation(vec3(0, 0, 3)), self.game.my_car.rotation)

            # diagonal twist
            if self.counter % 3 == 2:
                self.name = "Air-Roll Dodge hit"
                self.dodge.duration = 0.15
                self.dodge.delay = 0.5
                self.dodge.direction = vec2(f - 0.3 * l)
                self.dodge.preorientation = dot(
                    self.game.my_car.rotation,
                    axis_to_rotation(vec3(-0.8, -0.4, 0)))

            self.counter += 1

            next_state = State.RUNNING

        if self.state == State.RUNNING:

            if self.timer > 1.2:
                self.turn.target = look_at(xy(self.game.my_car.velocity),
                                           vec3(0, 0, 1))
                self.turn.step(self.game.time_delta)
                self.controls = self.turn.controls

            else:
                self.dodge.step(self.game.time_delta)
                self.controls = self.dodge.controls

            if self.timer > self.timeout:
                next_state = State.RESET

        self.game.my_car.last_input.roll = self.controls.roll
        self.game.my_car.last_input.pitch = self.controls.pitch
        self.game.my_car.last_input.yaw = self.controls.yaw

        self.timer += self.game.time_delta
        self.state = next_state

        if self.name:
            self.renderer.begin_rendering()
            self.renderer.draw_string_2d(50, 50, 6, 6, self.name,
                                         self.renderer.red())
            self.renderer.end_rendering()

        return self.controls
예제 #17
0
class Recovery(Maneuver):
    """Boost down and try to land smoothly"""
    def __init__(self, car: Car):
        super().__init__(car)

        self.landing = False
        self.aerial_turn = AerialTurn(self.car)

        self.trajectory: List[vec3] = []
        self.landing_pos: Optional[vec3] = None

    def interruptible(self) -> bool:
        return False

    def step(self, dt):
        self.simulate_landing()

        self.aerial_turn.step(dt)
        self.controls = self.aerial_turn.controls

        self.controls.boost = angle_between(self.car.forward(), vec3(
            0, 0, -1)) < 1.5 and not self.landing
        self.controls.throttle = 1  # in case we're turtling

        self.finished = self.car.on_ground

    def simulate_landing(self):
        dummy = Car(self.car)
        self.trajectory = [vec3(dummy.position)]
        self.landing = False
        collision_normal: Optional[vec3] = None

        dt = 1 / 60
        simulation_duration = 0.8
        for i in range(int(simulation_duration / dt)):
            dummy.step(Input(), dt)
            self.trajectory.append(vec3(dummy.position))

            collision_sphere = sphere(dummy.position, 50)
            collision_ray = Field.collide(collision_sphere)
            collision_normal = collision_ray.direction

            if (norm(collision_normal) > 0.0
                    or dummy.position[2] < 0) and i > 20:
                self.landing = True
                self.landing_pos = dummy.position
                break

        if self.landing:
            u = collision_normal
            f = normalize(dummy.velocity - dot(dummy.velocity, u) * u)
            l = normalize(cross(u, f))
            self.aerial_turn.target = mat3(f[0], l[0], u[0], f[1], l[1], u[1],
                                           f[2], l[2], u[2])
        else:
            target_direction = normalize(
                normalize(self.car.velocity) - vec3(0, 0, 3))
            self.aerial_turn.target = look_at(target_direction, vec3(0, 0, 1))

    def render(self, draw: DrawingTool):
        if self.landing:
            draw.color(draw.cyan)
            draw.polyline(self.trajectory)

            if self.landing_pos:
                draw.crosshair(self.landing_pos)

        draw.color(draw.green)
        draw.vector(self.car.position, forward(self.aerial_turn.target) * 200)

        draw.color(draw.red)
        draw.vector(self.car.position, self.car.forward() * 200)
예제 #18
0
class Agent(BaseAgent):
    def __init__(self, name, team, index):
        self.game = Game(index, team)
        self.controls = SimpleControllerState()

        self.timer = 0.0
        self.action = None
        random.seed(0)

    def get_output(self, packet: GameTickPacket) -> SimpleControllerState:

        self.game.read_game_information(packet, self.get_rigid_body_tick(),
                                        self.get_field_info())

        self.controls = SimpleControllerState()

        if not self.action:
            self.action = AerialTurn(self.game.my_car)
            self.action.eps_phi = 0.01
            self.action.eps_omega = 0.02

        if self.timer == 0.0:

            # randomly generate a proper orthogonal matrix
            self.action.target = axis_to_rotation(
                vec3(random.uniform(-2, 2), random.uniform(-2, 2),
                     random.uniform(-2, 2)))

        f = vec3(self.action.target[0, 0], self.action.target[1, 0],
                 self.action.target[2, 0])
        position = Vector3(0, 0, 1000)
        velocity = Vector3(0, 0, 0)

        car_state = CarState(
            physics=Physics(location=position, velocity=velocity))

        # spawn the ball in front of the desired orientation to visually indicate where we're trying to go
        ball_state = BallState(
            physics=Physics(location=Vector3(500 * f[0], 500 *
                                             f[1], 500 * f[2] + 1000),
                            velocity=Vector3(0, 0, 0),
                            angular_velocity=Vector3(0, 0, 0)))

        self.set_game_state(
            GameState(ball=ball_state, cars={self.game.id: car_state}))

        self.action.step(self.game.time_delta)
        self.controls = self.action.controls

        print(self.action.alpha)

        self.timer += self.game.time_delta
        if self.timer > 2.0:
            self.timer = 0.0

        error = angle_between(self.game.my_car.rotation, self.action.target)

        self.renderer.begin_rendering("path")
        red = self.renderer.create_color(255, 230, 30, 30)
        self.renderer.draw_string_2d(50, 50, 3, 3,
                                     f"error: {error:.4f} radians", red)
        self.renderer.draw_string_2d(50, 100, 3, 3,
                                     f"Roll:   {self.controls.roll:+.2f}", red)
        self.renderer.draw_string_2d(50, 150, 3, 3,
                                     f"Pitch: {self.controls.pitch:+.2f}", red)
        self.renderer.draw_string_2d(50, 200, 3, 3,
                                     f"Yaw:  {self.controls.yaw:+.2f}", red)
        self.renderer.end_rendering()

        return self.controls