예제 #1
0
    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))
예제 #2
0
 def step(self, packet: GameTickPacket, drone: Drone, index: int):
     up = normalize(drone.position)
     drone.aerial_turn.target = look_at(vec3(0, 0, 1), up)
     drone.aerial_turn.step(self.dt)
     drone.controls = drone.aerial_turn.controls
     drone.controls.boost = angle_between(vec3(0, 0, 1), drone.forward()) < 0.5
     drone.controls.jump = True
예제 #3
0
    def __init__(self, car: Car, ball_predictions, predicate: callable = None):
        self.ball: Ball = None
        self.is_viable = True

        #find the first reachable ball slice that also meets the predicate
        test_car = Car(car)
        test_aerial = Aerial(car)
        
        for ball in ball_predictions:
            test_aerial.target = ball.position
            test_aerial.arrival_time = ball.time

            # fake our car state :D
            dir_to_target = ground_direction(test_car.position, test_aerial.target)
            test_car.velocity = dir_to_target * max(norm(test_car.velocity), 1200)
            test_car.orientation = look_at(dir_to_target, vec3(0,0,1))

            if test_aerial.is_viable() and (predicate is None or predicate(car, ball)):
                self.ball = ball
                break

        #if no slice is found, use the last one
        if self.ball is None:
            self.ball = ball_predictions[-1]
            self.is_viable = False

        self.time = self.ball.time
        self.ground_pos = ground(self.ball.position)
        self.position = self.ball.position
예제 #4
0
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
예제 #5
0
    def __init__(self, name, team, index):
        self.name = name

        self.index = index

        self.policy = Policy(hidden_size, hidden_size_2).to(device)

        self.policy.load_state_dict(model)
        self.simulation = Simulation(self.policy)
        self.controls = SimpleControllerState()
        self.finished = False

        self.FPS = 120

        self.lastTime = 0
        self.realLastTime = 0
        self.currentTick = 0
        self.skippedTicks = 0
        self.doneTicks = 0
        self.ticksNowPassed = 0

        self.lastDodgeTick = -math.inf
        self.lastDodgePitch = 0
        self.lastDodgeRoll = 0

        self.lastReset = 0
        self.target = vec3(1, 0, 0)
        self.up = vec3(0, 0, 1)
        self.targetOrientation = look_at(self.target, self.up)
        self.lastDoneTick = 0
        self.totalScore = 0
        self.tests = 0

        self.stage = 0
예제 #6
0
    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))
예제 #7
0
    def tick(self, packet: GameTickPacket) -> bool:
        if self.agent.car.on_ground:
            self.controller.jump = not self.controller.jump
            self.controller.throttle = 1
            return True
        else:
            self.controller.jump = self.agent.car.velocity[2] > 100
            self.controller.boost = dot(self.agent.car.forward(), vec3(
                0, 0, -1)) * dot(self.agent.car.velocity, vec3(0, 0, -1)) < 0
            self.controller.throttle = self.controller.boost and self.agent.car.position[
                2] > 150

        hitbox = self.agent.car.hitbox()
        target = normalize(
            flatten(dot(self.agent.car.orientation, hitbox.half_width)))
        tmp = vec3(-hitbox.half_width[1], 0, 0)
        target = dot(self.agent.car.orientation, tmp) + vec3(
            0, 0, -hitbox.half_width[0])

        # self.agent.draw.vector(self.agent.car.position, target)

        self.agent.reorientML.target_orientation = look_at(
            target,
            self.direction * self.agent.car.left() if
            abs(self.agent.car.velocity[2]) < 20 else self.agent.car.velocity)

        self.agent.reorientML.step(1 / self.agent.FPS)
        self.controller.yaw = self.agent.reorientML.controls.yaw
        self.controller.pitch = self.agent.reorientML.controls.pitch
        self.controller.roll = self.agent.reorientML.controls.roll

        return True
예제 #8
0
    def set_drone_states(self, drones: List[Drone]):
        # get the length of the path from start to the dragons's head (first bot)
        head_t = self.time_since_start / self.duration * self.path.length

        for drone in drones:
            # offset the other body parts
            drone_t = head_t - self.distance_between_body_parts * (
                drone.id - drones[0].id)

            # if we're not on the path yet, don't do any state setting
            if drone_t < 0:
                continue

            t = self.path.length - drone_t  # because Curve.point_at's argument means distance to end

            pos = self.path.point_at(t)
            pos_ahead = self.path.point_at(t - 500)
            pos_behind = self.path.point_at(t + 300)

            # figure out the orientation of the body part
            facing_direction = direction(pos_behind, pos)
            target_left = cross(facing_direction, direction(pos, pos_ahead))
            target_up = cross(target_left, facing_direction)
            up = drone.up() + target_up * 0.9 + vec3(0, 0, 0.1)
            target_orientation = look_at(facing_direction, up)

            drone.position = pos_behind
            drone.velocity = facing_direction * (self.path.length /
                                                 self.duration)
            drone.angular_velocity = vec3(
                0, 0, 0
            )  # TODO: setting correct angular velocity could help with replays
            drone.orientation = target_orientation
예제 #9
0
 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
예제 #10
0
 def set_drone_states(self, drones: List[Drone]):
     for i, drone in enumerate(drones):
         angle = i * math.pi * 2 / len(drones)
         rot = rotation(angle)
         v = vec3(dot(rot, vec2(1, 0)))
         drone.position = v * self.radius + self.center
         drone.orientation = look_at(v * -1, vec3(0, 0, 1))
         drone.velocity = vec3(0, 0, 0)
         drone.angular_velocity = vec3(0, 0, 0)
예제 #11
0
    def step(self, dt):
        if self.aerialing:
            self.aerial.target_orientation = look_at(
                direction(self.car, self.target), vec3(0, 0, -1))
            self.aerial.step(dt)
            self.controls = self.aerial.controls
            self.finished = self.aerial.finished

        else:
            super().step(dt)

            # simulate aerial from current state
            simulated_car = self.simulate_flight(self.car)

            # if the car ended up too far, we're too fast and we need to slow down
            if ground_distance(self.car,
                               self.aerial.target) + 100 < ground_distance(
                                   self.car, simulated_car):
                # self.controls.throttle = -1
                pass

            # if it ended up near the target, we could take off
            elif distance(simulated_car,
                          self.aerial.target) < self.MAX_DISTANCE_ERROR:
                if angle_to(self.car, self.aerial.target) < 0.1 or norm(
                        self.car.velocity) < 1000:

                    if self.DELAY_TAKEOFF:
                        # extrapolate current state a small amount of time
                        future_car = Car(self.car)
                        time = 0.2
                        future_car.time += time
                        displacement = future_car.velocity * time if norm(future_car.velocity) > 500\
                            else normalize(future_car.velocity) * 500 * time
                        future_car.position += displacement

                        # simulate aerial fot the extrapolated car again
                        future_simulated_car = self.simulate_flight(
                            future_car, write_to_flight_path=False)

                        # if the aerial is also successful, that means we should continue driving instead of taking off
                        # this makes sure that we go for the most late possible aerials, which are the most effective
                        if distance(
                                future_simulated_car,
                                self.aerial.target) > self.MAX_DISTANCE_ERROR:
                            self.aerialing = True
                        else:
                            self.too_early = True
                    else:
                        self.aerialing = True

            else:
                # self.controls.boost = True
                self.controls.throttle = 1
예제 #12
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
예제 #13
0
    def set_drone_states(self, drones: List[Drone]):
        for i, drone in enumerate(drones):
            shifted_index = i - 15
            sign = 1 if shifted_index >= 0 else -1
            if sign > 0:
                shifted_index = 15 - shifted_index

            drone.position = vec3(shifted_index * 200 + sign * 800,
                                  -600 * sign, 20)
            drone.velocity = vec3(0, 0, 0)
            drone.angular_velocity = vec3(0, 0, 0)
            drone.orientation = look_at(vec3(0, 1, 0) * sign, vec3(0, 0, 1))
예제 #14
0
    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.reorient.target_orientation = look_at(
                    direction(self.car.position, self.info.ball),
                    vec3(0, 0, 1))
                self.reorient.step(dt)
                self.controls = self.reorient.controls
예제 #15
0
    def step(self, dt):
        super().step(dt)

        if not self.jump.finished and not self.car.on_ground:
            target_direction = direction(self.car, self.target + vec3(0, 0, 200))
            up = target_direction * (-1)
            up[2] = 1
            up = normalize(up)
            self.reorient.target_orientation = look_at(target_direction, up)
            self.reorient.step(dt)
            self.controls.pitch = self.reorient.controls.pitch
            self.controls.yaw = self.reorient.controls.yaw
            self.controls.roll = self.reorient.controls.roll
예제 #16
0
    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
예제 #17
0
    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
예제 #18
0
    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
예제 #19
0
    def set_drone_states(self, drones: List[Drone]):
        for drone in drones:
            t = self.time_since_start / self.duration * self.curve.length
            t -= self.distance_between_body_parts * (drone.id -
                                                     self.target_indexes[0])
            t = self.curve.length - t

            pos = self.curve.point_at(t)
            pos_ahead = self.curve.point_at(t - 500)
            pos_behind = self.curve.point_at(t + 30)

            facing_direction = direction(pos_behind, pos)
            target_left = cross(facing_direction, direction(pos, pos_ahead))
            target_up = cross(target_left, facing_direction)
            up = drone.up() + target_up * 0.9 + vec3(0, 0, 0.1)
            target_orientation = look_at(facing_direction, up)

            drone.position = pos
            drone.velocity = facing_direction * (self.curve.length /
                                                 self.duration)
            drone.angular_velocity = vec3(0, 0, 0)
            drone.orientation = target_orientation
예제 #20
0
 def set_drone_states(self, drones: List[Drone]):
     drone = drones[1]
     drone.position = vec3(-1500, 500, 800)
     drone.velocity = vec3(0, 0, 0)
     drone.angular_velocity = vec3(0, 0, 0)
     drone.orientation = look_at(vec3(0, 0, 500), vec3(0, 0, 1))
예제 #21
0
    def get_output(self, packet: GameTickPacket) -> SimpleControllerState:
        self.renderer.begin_rendering()

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

        if self.lastReset + 300 < self.currentTick:
            if self.tests > 0:
                score = min(300, self.currentTick - self.lastDoneTick)
                self.totalScore += score
                print(self.tests, score, round(self.totalScore / self.tests,
                                               2))
            self.tests += 1
            self.lastReset = self.currentTick
            self.target = vec3(2 * random() - 1, 2 * random() - 1,
                               2 * random() - 1)
            self.up = orthogonalize(
                vec3(2 * random() - 1, 2 * random() - 1, 2 * random() - 1),
                self.target)
            self.targetOrientation = look_at(self.target, self.up)
            car_state = CarState(
                physics=Physics(location=Vector3(0, 1000, 17),
                                velocity=Vector3(0, 0, 0),
                                rotation=Rotator(0, 0, 0),
                                angular_velocity=Vector3(0, 0, 0)))
            self.set_game_state(GameState(cars={self.index: car_state}))
            self.stage = 0
            self.lastDodgeTick = -math.inf
            # print("TELEPORT TO GROUND")
            return self.controls
        else:
            car_state = CarState(physics=Physics(location=Vector3(0, 0, 400),
                                                 velocity=Vector3(0, 0, 0)))
            self.set_game_state(GameState(cars={self.index: car_state}))

        if self.stage <= 5:
            self.stage += 1
        if self.stage == 6:
            self.dodgeDirection = normalize(vec2(0, 2 * random() - 1))
            self.controls.jump = True  #random() > 0.5
            if self.controls.jump:
                self.lastDodgeTick = self.currentTick

            self.controls.roll, self.controls.pitch, self.controls.yaw = self.dodgeDirection[
                0], self.dodgeDirection[1], 0
            self.stage += 1
            return self.controls
        else:
            self.controls.jump = False

        self.packet = packet
        self.handleTime()

        car = packet.game_cars[self.index]
        position = vec3(car.physics.location.x, car.physics.location.y,
                        car.physics.location.z)

        self.renderer.draw_line_3d(car.physics.location,
                                   position + 300 * normalize(self.target),
                                   self.renderer.yellow())
        self.renderer.draw_line_3d(car.physics.location,
                                   position + 300 * normalize(self.up),
                                   self.renderer.pink())

        carOrientation = rotationToOrientation(car.physics.rotation)
        ang = parseVector(car.physics.angular_velocity)

        if angle_between(carOrientation,
                         self.targetOrientation) > 1 / 180 * math.pi:
            self.lastDoneTick = self.currentTick

        o_rlu = dot(transpose(self.targetOrientation), carOrientation)
        w_rlu = dot(transpose(self.targetOrientation), ang)
        o = torch.tensor([[o_rlu[i, j] for j in range(3)]
                          for i in range(3)])[None, :].float().to(device)
        w = torch.tensor([w_rlu[i]
                          for i in range(3)])[None, :].float().to(device)

        noPitchTime = max(0,
                          (self.lastDodgeTick - self.currentTick) / 120 + .95)
        dodgeTime = max(0, (self.lastDodgeTick - self.currentTick) / 120 + .65)
        if dodgeTime == 0:
            self.dodgeDirection = vec2(0, 0)

        noPitchTime = torch.tensor([noPitchTime]).float().to(device)
        dodgeTime = torch.tensor([dodgeTime]).float().to(device)
        dodgeDirection = torch.tensor([
            self.dodgeDirection[i] for i in range(2)
        ])[None, :].float().to(device)

        # if self.simulation.o is not None and self.simulation.w is not None:
        # 	print("=====================================")
        # 	print("-------------------------------------")
        # 	print(self.simulation.o, o)
        # 	print(self.simulation.w, w)
        # 	print(self.simulation.noPitchTime, noPitchTime)
        # 	print(self.simulation.dodgeTime, dodgeTime)
        # 	print(self.simulation.dodgeDirection, dodgeDirection)
        # 	self.simulation.step(self.ticksNowPassed / 120)
        # 	print(self.simulation.o, o)
        # 	print(self.simulation.w, w)
        # 	print(self.simulation.noPitchTime, noPitchTime)
        # 	print(self.simulation.dodgeTime, dodgeTime)
        # 	print(self.simulation.dodgeDirection, dodgeDirection)

        self.simulation.o = o
        self.simulation.w = w
        self.simulation.noPitchTime = noPitchTime
        self.simulation.dodgeTime = dodgeTime
        self.simulation.dodgeDirection = dodgeDirection

        if True:

            rpy = self.policy(self.simulation.o.permute(0, 2, 1),
                              self.simulation.w_local(),
                              self.simulation.noPitchTime,
                              self.simulation.dodgeTime,
                              self.simulation.dodgeDirection)[0]
            self.controls.roll, self.controls.pitch, self.controls.yaw = rpy

        else:

            self.reorientML.target_orientation = self.targetOrientation
            self.reorientML.step(1 / self.FPS)
            self.controls.roll, self.controls.pitch, self.controls.yaw = self.reorientML.controls.roll, self.reorientML.controls.pitch, self.reorientML.controls.yaw

        if self.simulation.error()[0].item() < 0.01:
            self.frames_done += 1
        else:
            self.frames_done = 0

        if self.frames_done >= 10:
            self.finished = True

        self.renderer.end_rendering()
        return self.controls
예제 #22
0
파일: kickoff.py 프로젝트: RLBot/RLBotPack
    def kickoffTick(self, packet: GameTickPacket) -> bool:

        isBallInCenter = packet.game_ball.physics.location.x == 0 and packet.game_ball.physics.location.y == 0

        carToBallDistance = norm(self.agent.car.position -
                                 self.agent.game.ball.position)

        # if at any point something goes wrong and i'll be way too late, cancel the kickoff early.
        if isBallInCenter:
            for car in self.agent.game.cars[:self.agent.game.num_cars]:
                if car.team != self.agent.car.team and norm(
                        car.position - self.agent.game.ball.position
                ) + 200 < carToBallDistance:
                    print("kickoff failed!! big problems..")
                    self.agent.send_quick_chat(QuickChats.CHAT_EVERYONE,
                                               QuickChats.Apologies_Cursing)
                    return False

        speed = norm(self.agent.car.velocity)

        self.controller.throttle = 1
        self.controller.boost = speed < 2300 - 991.666 / 120 * (
            1 if self.controller.boost else 10) and self.agent.car.boost > 0

        if speed < 10:
            self.startTime = self.agent.currentTick
            self.isDiagonalKickoff = abs(self.agent.car.position[0]) >= 1024
            self.isSemiDiagonalKickoff = abs(
                abs(self.agent.car.position[0]) - 256) < 128
            self.isStraightKickoff = not self.isDiagonalKickoff and not self.isSemiDiagonalKickoff
            if self.isSemiDiagonalKickoff:  # force speedflip direction to pick up boost
                self.speedFlipDirection = math.copysign(
                    1,
                    self.agent.car.position[0] * (2 * self.agent.car.team - 1))
                self.speedFlipMaxTurnTicks = 15

            self.riskyStrat = self.full_kickoff_strength

        if self.speedFlipState == 0 and self.isDiagonalKickoff and self.alternateDiagonalKickoff:
            self.alternateDiagonalKickoff = False
            for car in self.agent.game.cars[:self.agent.game.num_cars]:
                if car.team != self.agent.car.team:
                    if norm(car.position - self.agent.game.ball.position
                            ) < carToBallDistance + 150:
                        try:
                            crossWithYAxis = (
                                car.position[1] -
                                self.agent.game.ball.position[1] -
                                (car.position[0] -
                                 self.agent.game.ball.position[0]) /
                                car.velocity[0] * car.velocity[1]) * (
                                    2 * car.team - 1)
                            if crossWithYAxis > 300:
                                self.alternateDiagonalKickoff = True
                                break
                        except ZeroDivisionError:
                            self.alternateDiagonalKickoff = True
                            break

        target = self.agent.game.ball.position

        # LOGIC TO CANCEL THE RISKY STRAT
        if self.riskyStrat:
            if self.isDiagonalKickoff:

                # check if enemy car is also doing a fast strat
                if carToBallDistance < 1500:
                    for car in self.agent.game.cars[:self.agent.game.num_cars]:
                        if car.team != self.agent.car.team:
                            try:
                                enemyTime = norm(car.position -
                                                 self.agent.game.ball.position
                                                 ) / norm(car.velocity)
                                myTime = carToBallDistance / norm(
                                    self.agent.car.velocity)
                                lead = enemyTime - myTime
                                if lead < 0.09:
                                    self.riskyStrat = False
                                    break
                            except ZeroDivisionError:
                                pass
            else:

                for car in self.agent.game.cars[:self.agent.game.num_cars]:
                    if car.team != self.agent.car.team:
                        # if the enemy car jumped, fall back to safe strat immediately
                        if norm(car.position - self.agent.game.ball.position
                                ) < 1500 and car.position[2] > 20:
                            self.riskyStrat = False
                            break

                        lead = norm(
                            car.position -
                            self.agent.game.ball.position) - carToBallDistance

                        # if enemy car is too far, it also has to fall back to safe strat instead of reacting to it
                        if lead < 1500 and (
                                norm(target - self.agent.car.position) < 525
                                and lead > 460):
                            self.riskyStrat = False
                            break

        # LOGIC TO ADJUST THE TARGET TO AIM THE BALL

        if self.riskyStrat:
            if self.isDiagonalKickoff:
                if self.alternateDiagonalKickoff:
                    # aim for the wall to make a pass
                    target += vec3(
                        math.copysign(100, self.agent.car.position[0]), 0, 0)
                else:
                    # aim straight for the goal
                    if carToBallDistance > 1000:
                        target += vec3(0, 190 * (self.agent.car.team * 2 - 1),
                                       0)
                    else:
                        target += vec3(
                            math.copysign(3, self.agent.car.position[0]),
                            140 * (self.agent.car.team * 2 - 1), 0)
            else:
                if self.isSemiDiagonalKickoff:
                    offset = 29
                else:
                    offset = 26
                target += vec3(
                    math.copysign(offset, self.agent.car.position[0]), 0, 0)

        else:
            target += vec3(0, 90 * (self.agent.car.team * 2 - 1), 0)

        # force to pick up boost
        if self.isSemiDiagonalKickoff and abs(
                self.agent.car.position[1]) > 1700:
            self.speedFlipTarget = vec3(0,
                                        1800 * (2 * self.agent.car.team - 1),
                                        70)
        else:
            self.speedFlipTarget = target

        # always drive straight at start
        if speed < 550:
            self.controller.steer = 0
            self.controller.jump = False
            return True

        else:

            carAngle = -atan2(self.agent.car.forward())
            self.controller.steer = min(
                1,
                max(
                    -1, 5 * atan2(
                        rotate2(target - self.agent.car.position, carAngle))))

            if super().tick(packet):
                return True

            else:

                if self.riskyStrat:
                    if self.isDiagonalKickoff:
                        maxJumpDistance = 210
                    elif self.isSemiDiagonalKickoff:
                        maxJumpDistance = 230
                    else:
                        maxJumpDistance = 242
                    self.controller.jump = carToBallDistance < maxJumpDistance

                    return isBallInCenter

                else:
                    self.agent.reorientML.target_orientation = look_at(
                        self.agent.game.ball.position -
                        self.agent.car.position, vec3(0, 0, 1))
                    self.agent.reorientML.step(1 / self.agent.FPS)
                    self.controller.yaw = self.agent.reorientML.controls.yaw
                    self.controller.pitch = self.agent.reorientML.controls.pitch
                    self.controller.roll = self.agent.reorientML.controls.roll

                    if isBallInCenter:
                        if norm(target - self.agent.car.position) < 525:
                            if not self.hasUnJumped:
                                jump = self.agent.game.ball.position[
                                    2] > self.agent.car.position[2]
                                if self.controller.jump and not jump:
                                    self.hasUnJumped = True
                                self.controller.jump = jump
                    else:

                        if speed < 2200:
                            for car in self.agent.game.cars[:self.agent.game.
                                                            num_cars]:
                                if car.team != self.agent.car.team:
                                    if norm(car.position -
                                            self.agent.game.ball.position
                                            ) < 1000:

                                        if not self.hasUnJumped:
                                            self.controller.jump = False
                                            self.hasUnJumped = True
                                        elif self.controller.jump == False:
                                            self.controller.jump = True
                                            self.controller.pitch = -1
                                            self.controller.yaw = 0
                                        else:
                                            return False

                                        break

                        # if no enemies have been found nearby, no need to dodge into the ball again
                        return False

                    return True
예제 #23
0
    def step(self, dt):
        time_left = self.aerial.arrival_time - self.car.time

        if self.aerialing:
            to_ball = direction(self.car, self.info.ball)

            # freestyling
            if self.car.position[2] > 200:
                # if time_left > 0.7:
                #     rotation = axis_to_rotation(self.car.forward() * 0.5)
                #     self.aerial.up = dot(rotation, self.car.up())
                # else:
                self.aerial.up = vec3(0, 0, -1) + xy(to_ball)

            self.aerial.target_orientation = look_at(to_ball,
                                                     vec3(0, 0, -3) + to_ball)
            self.aerial.step(dt)

            self.controls = self.aerial.controls
            self.finished = self.aerial.finished and time_left < -0.3

        else:
            super().step(dt)

            # simulate aerial from current state
            simulated_car = self.simulate_flight(self.car, self.aerial,
                                                 self._flight_path)

            speed_towards_target = dot(
                self.car.velocity,
                ground_direction(self.car, self.aerial.target_position))
            speed_needed = ground_distance(
                self.car, self.aerial.target_position) / time_left

            # too fast, slow down
            if speed_towards_target > speed_needed and angle_to(
                    self.car, self.aerial.target_position) < 0.1:
                self.controls.throttle = -1

            # if it ended up near the target, we could take off
            elif distance(
                    simulated_car,
                    self.aerial.target_position) < self.MAX_DISTANCE_ERROR:
                if angle_to(self.car,
                            self.aerial.target_position) < 0.1 or norm(
                                self.car.velocity) < 1000:

                    if self.DELAY_TAKEOFF and ground_distance(
                            self.car, self.aerial.target_position) > 1000:
                        # extrapolate current state a small amount of time
                        future_car = Car(self.car)
                        time = 0.5
                        future_car.time += time
                        displacement = future_car.velocity * time if norm(future_car.velocity) > 500\
                            else normalize(future_car.velocity) * 500 * time
                        future_car.position += displacement

                        # simulate aerial fot the extrapolated car again
                        future_simulated_car = self.simulate_flight(
                            future_car, self.aerial)

                        # if the aerial is also successful, that means we should continue driving instead of taking off
                        # this makes sure that we go for the most late possible aerials, which are the most effective
                        if distance(future_simulated_car, self.aerial.
                                    target_position) > self.MAX_DISTANCE_ERROR:
                            self.aerialing = True
                        else:
                            self.too_early = True
                    else:
                        self.aerialing = True

            else:
                # self.controls.boost = True
                self.controls.throttle = 1
예제 #24
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)
예제 #25
0
    def tick(self, packet: GameTickPacket) -> bool:

        if not self.recoveryActive:
            return False

        GRAVITY = vec3(0, 0, packet.game_info.world_gravity_z)
        DOWN = normalize(GRAVITY)

        # TODO: this should be a parameter or something
        boostUsefullnessTreshold = 0.7

        self.controller.jump = False

        if self.ceilingJumpState == 1:
            if self.agent.currentTick - self.ceilingJumpStartTick > 6:
                self.controller.jump = False
                self.ceilingJumpState = 2
            return True
        elif self.ceilingJumpState == 2:
            self.controller.jump = True
            self.ceilingJumpState = 0
            return True

        # If this is true, the car is considered to be recovered.
        if self.agent.car.on_ground and self.agent.currentTick - self.agent.lastJumpTick > 28:
            if self.agent.car.position[2] < 2044 - 17 * 1.5:
                return False
            else:
                # on ceiling, jump down
                if self.ceilingJumpState == 0 and self.agent.car.velocity[
                        2] <= 0:
                    self.controller.jump = True
                    self.controller.yaw = 0
                    self.controller.pitch = 0
                    self.controller.roll = 0
                    self.ceilingJumpStartTick = self.agent.currentTick
                    self.ceilingJumpState = 1

                    return True

        # Find landing point
        landPosition = vec3(0, 0, 0)
        landVelocity = vec3(0, 0, 0)
        landBottomDirection = vec3(0, 0, 0)
        airTime = self.agent.car.nextApproxCollision(landPosition,
                                                     landVelocity,
                                                     landBottomDirection)

        aimToBoost = airTime > boostUsefullnessTreshold and self.agent.car.boost > 0

        # TODO: mix landing velocity and target velocity
        if self.forceLandDirection:
            landVelocity = self.forceLandDirection
        else:
            landVelocity = orthogonalize(landVelocity, landBottomDirection)

        downAngle = dot(landBottomDirection, DOWN)
        nextIsCeiling = downAngle > 0.5
        nextIsGround = downAngle < -0.5
        if nextIsCeiling:
            landVelocity = orthogonalize(self.agent.car.forward(),
                                         landBottomDirection)

        landVelocityUnit = normalize(landVelocity)
        # self.agent.draw.vector(landPosition, landVelocityUnit * 750, self.agent.draw.pink)

        # TODO: this time constraint is just an estimate.. :P
        if not nextIsCeiling\
         and airTime > .65 + math.sqrt(2 * max(0, self.agent.car.position[2] - 17.01) / -packet.game_info.world_gravity_z) \
         and not self.agent.car.double_jumped:
            # dodge to cancel momentum
            atan2(self.agent.car.forward())
            rotate2(landVelocity, atan2(self.agent.car.forward()))
            direction = flatten(
                rotate2(landVelocity, atan2(self.agent.car.forward())))
            direction = direction / max(direction[0], direction[1])

            self.controller.yaw = 0
            self.controller.roll = direction[1]
            self.controller.pitch = direction[0]
            self.controller.throttle = 1
            self.controller.jump = True
            self.controller.boost = False
            # print("DOING AIR DASH")
            return True

        upAngle = dot(self.agent.car.up(), landBottomDirection)
        if aimToBoost and nextIsGround and airTime > 0.15 + 0.2 * (1 + dot(
                self.agent.car.forward(), landVelocityUnit)) + 0.3 * (1 +
                                                                      upAngle):
            self.agent.reorientML.target_orientation = look_at(
                DOWN, landVelocity)
        elif aimToBoost and nextIsCeiling and airTime > 0.3 + 0.35 * (1 +
                                                                      upAngle):
            self.agent.reorientML.target_orientation = look_at(
                DOWN * -1, landVelocity)
        else:
            WAVEDASHANGLE = 30 / 180 * math.pi
            MAXDODGEBEFORELANDTIME = 20.5 / 120
            doWaveDash = False
            if not nextIsCeiling and not self.agent.car.double_jumped and airTime - MAXDODGEBEFORELANDTIME < self.agent.maxDodgeTick:

                waveDashLandVelocity = flatten(landVelocity)
                waveDashLandVelocity += normalize(waveDashLandVelocity) * 500
                if norm(waveDashLandVelocity) > 2300:
                    waveDashLandVelocity *= 2300 / norm(waveDashLandVelocity)
                # TODO: decide if vertical momentum is more important
                if norm(waveDashLandVelocity) > norm(landVelocity) + 100:
                    doWaveDash = True
            if doWaveDash:
                landVelocity = waveDashLandVelocity
                landVelocityUnit = normalize(landVelocity)

                waveDashDirection = landVelocityUnit * math.cos(
                    WAVEDASHANGLE) + landBottomDirection * math.sin(
                        WAVEDASHANGLE)
                self.agent.reorientML.target_orientation = look_at(
                    waveDashDirection, landBottomDirection)

                currentWaveDashAngle = dot(landBottomDirection, normalize(project(\
                 self.agent.car.up(), landBottomDirection)\
                 + project(self.agent.car.up(), landVelocityUnit)\
                ))
                dodgeBeforeLandTime = 6.5 / 120\
                 + 14 / 120 * min(1, (1 - currentWaveDashAngle) / (1 - math.cos(WAVEDASHANGLE)))\
                 - 8 / 120 * (dot(DOWN, self.agent.car.up()) / 2 + 0.5) # TODO: this term should probably depend on speed towards landing surface

                # print(dot(landBottomDirection, self.agent.car.up()) > (1 - 1.5 * (1 - math.cos(WAVEDASHANGLE))), dot(landVelocityUnit, self.agent.car.up()) )
                if airTime < dodgeBeforeLandTime\
                 and currentWaveDashAngle > (1 - 1.5 * (1 - math.cos(WAVEDASHANGLE)))\
                 and dot(landVelocityUnit, self.agent.car.up()) < 0:
                    self.controller.yaw = 0
                    self.controller.roll = 0
                    self.controller.pitch = -1
                    self.controller.throttle = 1
                    self.controller.jump = True
                    # print("DOING WAVEDASH")
                    return True
            else:
                self.agent.reorientML.target_orientation = look_at(
                    landVelocity, landBottomDirection)

        # TODO train my own ML network that 1. prioritizes landing wheels down over in the right direction 2. doesnt care so much about having no angular velocity, instead give it air time

        # TODO do a wavedash

        self.agent.reorientML.step(1 / self.agent.FPS)
        self.controller.yaw = self.agent.reorientML.controls.yaw
        self.controller.pitch = self.agent.reorientML.controls.pitch
        if upAngle < 0 and abs(self.agent.reorientML.controls.roll) < 0.1:
            self.controller.roll = math.copysign(
                1, self.agent.reorientML.controls.roll)
            self.controller.throttle = 1
        else:
            self.controller.roll = self.agent.reorientML.controls.roll
            forwardAngle = dot(self.agent.car.forward(), landBottomDirection)
            if abs(upAngle) > .4 or abs(forwardAngle) > 0.9 or airTime > 0.1:
                self.controller.throttle = math.copysign(1, forwardAngle)
            else:
                self.controller.throttle = 0

        nextTouchDirection = dot(self.agent.car.forward(),
                                 DOWN * -1 if nextIsCeiling else DOWN)
        boostUsefullness = 0 if nextTouchDirection < 0.3 or self.agent.lastDodgeTick + .5 + .65 * 120 > self.agent.currentTick else nextTouchDirection * airTime

        # TODO: decide how urgent the car needs to be somewhere
        # TODO: maybe boost forward a little bit too?
        self.controller.boost = boostUsefullness > boostUsefullnessTreshold
        self.controller.handbrake = nextIsCeiling

        # print(f"YAW  {round(self.controller.yaw, 1)}\tPITCH {round(self.controller.pitch, 1)}\tROLL {round(self.reorientML.controls.roll, 1)}\tTHROTTLE {round(self.controller.throttle, 1)}")

        return True