def step(self, packet: GameTickPacket, drone: Drone, index: int): self.finished = (100 + self.big_radius - self.time_since_start * self.speed) <= 0 # Get centre of small circle. direction_angle = (math.pi / 4) + ((math.pi / 2) * (index // 16)) centre = vec3(dot(rotation(direction_angle), vec2(1, 0))) # Crossing action. centre *= (self.big_radius - self.time_since_start * self.speed) centre[2] = self.height # Angle for the small circle. angle = (2 * math.pi / 16) * (index % 16) angle += (2 * math.pi / 4) * (index // 16 - 1) angle += self.time_since_start * self.spin target = vec3(dot(rotation(angle), vec2(self.small_radius, 0))) target += centre # Different heights. target[2] += (index // 16 - 2) * self.height_diff # Hover controls. drone.hover.up = normalize(drone.position - centre) drone.hover.target = target drone.hover.step(self.dt) drone.controls = drone.hover.controls
def step(self, packet: GameTickPacket, drone: Drone, index: int): # Get centre of small circle. direction_angle = (math.pi / 4) + ((math.pi / 2) * (index // 16)) centre = vec3(dot(rotation(direction_angle), vec2( 1, 0))) * self.big_radius centre[2] = self.height # Angle for the small circle. # Wraps nicely around the small circle. t = self.time_since_start + 2.5 if t > 2 * math.pi: t = 2 * math.pi angle = (t / 16) * (index % 16 - 8) angle += (2 * math.pi / 4) * (index // 16) + (math.pi / 4) target = vec3(dot(rotation(angle), vec2(self.small_radius, 0))) target += centre # Hover controls. drone.hover.up = normalize(drone.position - centre) drone.hover.target = target drone.hover.step(self.dt) drone.controls = drone.hover.controls # If any bot got lost, now they have a chance to recover. if drone.on_ground: drone.controls.jump = True else: drone.controls.jump = False
def step(self, dt): car = self.car target = ground(self.target) car_speed = norm(car.velocity) time_left = (ground_distance(car, target) - self.finish_distance) / max(car_speed + 500, 1400) forward_speed = dot(car.forward(), car.velocity) if self.driving and car.on_ground: self.action.target_pos = target self._time_on_ground += dt # check if it's a good idea to dodge, wavedash or halfflip if (self._time_on_ground > 0.2 and car.position[2] < 200 and angle_to(car, target, forward_speed < 0) < 0.1): # if going forward, use a dodge or a wavedash if forward_speed > 0: use_boost_instead = self.waste_boost and car.boost > 20 if car_speed > 1200 and not use_boost_instead: if time_left > self.DODGE_DURATION: dodge = Dodge(car) dodge.duration = 0.05 dodge.direction = vec2(direction(car, target)) self.action = dodge self.driving = False elif time_left > self.WAVEDASH_DURATION: wavedash = Wavedash(car) wavedash.direction = vec2(direction(car, target)) self.action = wavedash self.driving = False # if going backwards, use a halfflip elif time_left > self.HALFFLIP_DURATION and car_speed > 800: self.action = HalfFlip(car, self.waste_boost and time_left > 3) self.driving = False self.action.step(dt) self.controls = self.action.controls # make sure we're not boosting airborne if self.driving and not car.on_ground: self.controls.boost = False # make sure we're not stuck turtling if not car.on_ground: self.controls.throttle = 1 if self.action.finished and not self.driving: self.driving = True self._time_on_ground = 0 self.action = self.drive self.drive.backwards = False if ground_distance(car, target) < self.finish_distance and self.driving: self.finished = True
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_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 predict_car_drive(self, index, time_limit=2.0, dt=1 / 60) -> List[vec3]: """Simple prediction of a driving car assuming no acceleration.""" car = self.cars[index] time_steps = int(time_limit / dt) speed = norm(car.velocity) ang_vel_z = car.angular_velocity[2] # predict circular path if ang_vel_z != 0 and car.on_ground: radius = speed / ang_vel_z centre = car.position - cross(normalize(xy(car.velocity)), vec3(0, 0, 1)) * radius centre_to_car = vec2(car.position - centre) return [ vec3(dot(rotation(ang_vel_z * dt * i), centre_to_car)) + centre for i in range(time_steps) ] # predict straight path return [ car.position + car.velocity * dt * i for i in range(time_steps) ]
def step(self, packet: GameTickPacket, drone: Drone, index: int): if drone.position[2] < 25: drone.since_jumped = 0.0 # Go forward drone.controls.throttle = 1.0 if abs( drone.velocity[1]) < 500 else 0.01 # If near half-line if abs(drone.position[1]) < 200: drone.controls.jump = True else: drone.since_jumped += self.dt height = 50 + drone.since_jumped * 150 angle = 1.0 + drone.since_jumped * 1.2 if index % 2 == 0: angle += math.pi rot = rotation(angle) v = vec3(dot(rot, vec2(1, 0))) drone.hover.target = v * self.radius drone.hover.target[2] = height drone.hover.up = normalize(drone.position) drone.hover.step(self.dt) drone.controls = drone.hover.controls
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 set_drone_states(self, drones: List[Drone]): for i, drone in enumerate(drones): angle = (2 * math.pi / 64) * i drone.position = vec3(dot(rotation(angle), vec2(self.radius, 0))) drone.position[2] = self.height drone.velocity = vec3(0, 0, 0) drone.orientation = euler_to_rotation( vec3(math.pi / 2, angle, math.pi)) drone.angular_velocity = vec3(0, 0, 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)
def step(self, packet: GameTickPacket, drone: Drone, index: int): # Calculate shift direction. direction_angle = (math.pi / 4) + ((math.pi / 2) * (index // 16)) direction = vec3(dot(rotation(direction_angle), vec2(1, 0))) # Shift in one direction. angle = (2 * math.pi / 64) * index target = vec3(dot(rotation(angle), vec2(self.start_radius, 0))) target += direction * (self.end_radius - self.start_radius) * ( self.time_since_start / self.duration) target[2] = self.height target = (target + drone.position) / 2 # Hover controls. drone.hover.up = normalize(drone.position) drone.hover.target = target drone.hover.step(self.dt) drone.controls = drone.hover.controls
def step(self, packet: GameTickPacket, drone: Drone, index: int): radius = 1050 + 150 * self.time_since_start angle = math.pi + self.time_since_start * (math.pi / 5) angle += (2 * math.pi / 64) * index target = vec3(dot(rotation(angle), vec2(radius, 0))) target[2] = self.height drone.hover.up = normalize(-1 * xy(drone.position)) drone.hover.target = target drone.hover.step(self.dt) drone.controls = drone.hover.controls
def step(self, packet: GameTickPacket, drone: Drone, index: int): if drone.start_pos is None: drone.start_pos = drone.position # spin = (index % 16 - 8) * 0.01 # Unwind helix. # rotation = axis_to_rotation(vec3(0, 0, spin)) # position_on_circle = normalize(xy(drone.position)) * self.start_radius # drone.hover.target = dot(rotation, position_on_circle) # drone.hover.target[2] = drone.start_pos[2] # drone.hover.step(self.dt) # drone.controls = drone.hover.controls current_radius = norm(vec2(drone.position)) desired_angle = (2 * math.pi / 64) * index current_angle = math.atan2(drone.position[1], drone.position[0]) if current_angle < 0.0: current_angle += 2 * math.pi # only positive angles # Expand radius. if current_radius < self.radius - 150: direction_angle = (math.pi / 4) + ((math.pi / 2) * (index // 16)) direction = vec3(dot(rotation(direction_angle), vec2(1, 0))) target = drone.position + direction * 200 target[2] = drone.start_pos[2] # Get to correct angle. elif abs(desired_angle - current_angle) > 0.05: target = vec3(dot(rotation(desired_angle), vec2(self.radius, 0))) target[2] = drone.start_pos[2] # Get to correct height. else: target = vec3(dot(rotation(desired_angle), vec2(self.radius, 0))) target[2] = self.height drone.hover.up = normalize(drone.position) drone.hover.target = target drone.hover.step(self.dt) drone.controls = drone.hover.controls
def step(self, packet: GameTickPacket, drones: List[Drone]): s = int(math.sqrt(len(drones))) # Side length for i, drone in enumerate(drones): # Get grid pos. x = (i // s) - (s - 1) / 2 y = (i % s) - (s - 1) / 2 # Get height from func. z = 800 + self.func(x, y) # 800 is base height drone.hover.target = vec3(x * self.spacing, y * self.spacing, z) rot = rotation(self.rotation_speed * self.time_since_start * 2) drone.hover.up = vec3(dot(rot, vec2(1, 0))) drone.hover.step(self.dt) drone.controls = drone.hover.controls
def can_dodge(agent, target): """Returns whether its wise to dodge""" bot_to_target = target - agent.info.my_car.location local_bot_to_target = dot(bot_to_target, agent.info.my_car.rotation) angle_front_to_target = math.atan2(local_bot_to_target[1], local_bot_to_target[0]) distance_bot_to_target = norm(vec2(bot_to_target)) good_angle = math.radians(-10) < angle_front_to_target < math.radians(10) on_ground = agent.info.my_car.on_ground and agent.info.my_car.location[ 2] < 100 going_fast = velocity_2d(agent.info.my_car.velocity) > 1250 target_not_in_goal = not agent.my_goal.inside(target) return (good_angle and distance_bot_to_target > 2000 and on_ground and going_fast and target_not_in_goal)
def __init__(self, car: Car, use_boost=False): self.car = car self.use_boost = use_boost self.controls = Input() self.dodge = Dodge(car) self.dodge.duration = 0.12 self.dodge.direction = vec2(car.forward() * (-1)) self.s = 0.95 * sgn( dot(self.car.angular_velocity, self.car.up()) + 0.01) self.timer = 0.0 self.finished = False
def set_drone_states(self, drones: List[Drone]): for i, drone in enumerate(drones): angle = math.pi / 2 rot = rotation(angle) v = vec3(dot(rot, vec2(1, 0))) v[2] = 0.25 if i % 2 == 0: drone.position = self.center + vec3( math.floor(i / 2) * 250, math.floor(i / 2) * -250, 1750) else: drone.position = self.center + vec3( (1 + math.floor(i / 2)) * -250, (1 + math.floor(i / 2)) * -250, 1750) print(i, drone.position)
def step(self, packet: GameTickPacket, drone: Drone, index: int): angle = (2 * math.pi / 64) * index target = vec3(dot(rotation(angle), vec2(self.radius, 0))) target[2] = self.height # Hover controls drone.hover.target = target drone.hover.up = normalize(drone.position) drone.hover.step(self.dt) drone.controls = drone.hover.controls # If any bot got lost, now they have a chance to recover. if drone.on_ground: drone.controls.jump = True else: drone.controls.jump = False
def step(self, packet: GameTickPacket, drones: List[Drone]): for drone in drones: drone.hover.up = normalize(drone.position) for i, layer in enumerate(self.layers): if drone.id in layer: # Calculate radius if self.time_since_start < self.radius_shrink_start: radius = 2000 elif self.time_since_start < self.radius_shrink_start + self.radius_shrink_duration: diff = 2000 - self.radii[i] radius = 2000 - diff * ( (self.time_since_start - self.radius_shrink_start) / self.radius_shrink_duration) else: radius = self.radii[i] # Calculate xy position if self.time_since_start > self.recirculation_start: a = layer.index(drone.id) angle = a * math.pi * 2 / len(layer) rot = rotation(angle) pos_xy = vec3(dot(rot, vec2(1, 0))) else: pos_xy = xy(drone.position) # Combine xy and radius drone.hover.target = normalize(pos_xy) * radius # Get height if self.time_since_start < self.separation_duration: diff = 1000 - self.heights[i] height = 1000 - diff * (self.time_since_start / self.separation_duration) else: height = self.heights[i] drone.hover.target[2] = height break drone.hover.step(self.dt) drone.controls = drone.hover.controls
c.time = 0.0 c.location = vec3(1509.38, -686.19, 17.01) c.velocity = vec3(-183.501, 1398., 8.321) c.angular_velocity = vec3(0, 0, 0) c.rotation = mat3(-0.130158, -0.991493, -0.00117062, 0.991447, -0.130163, 0.00948812, -0.00955977, 0.0000743404, 0.999954) c.dodge_rotation = mat2(-0.130163, -0.991493, 0.991493, -0.130163) c.on_ground = True c.jumped = False c.double_jumped = False c.jump_timer = -1.0 c.dodge_timer = -1.0 dodge = Dodge(c) dodge.direction = vec2(-230.03, 463.42) dodge.duration = 0.1333 dodge.delay = 0.35 f = open("dodge_simulation.csv", "w") for i in range(300): dodge.step(0.008333) print(c.time, dodge.controls.jump, dodge.controls.pitch, dodge.controls.yaw) c.step(dodge.controls, 0.008333) f.write( f"{c.time}, {c.location[0]}, {c.location[1]}, {c.location[2]}, " f"{c.velocity[0]}, {c.velocity[1]}, {c.velocity[2]}, " f"{c.angular_velocity[0]}, {c.angular_velocity[1]}, {c.angular_velocity[2]}\n" )
def velocity_2d(velocity): """Returns the total 2d velocity given a velocity vector""" return norm(vec2(velocity))
def step(self, packet: GameTickPacket, drone: Drone, index: int): if drone.start_pos is None: drone.start_pos = drone.position drone.sort_phase = 1 # Finish if all have been sorted. if index == 0: # Initially set finished to True. self.finished = True if drone.sort_phase != 3: # Will be set to False if any is not in phase 3. self.finished = False # It's my time! if self.time_since_start > 0.5 + index * self.delay: desired_angle = (2 * math.pi / 64) * index # current_radius = norm(vec2(drone.position)) current_angle = math.atan2(drone.position[1], drone.position[0]) if current_angle < 0.0: current_angle += 2 * math.pi # only positive angles # Rotate to correct angle. if drone.sort_phase == 1: # if index in range(64)[::8]: print(index, current_angle, desired_angle) if abs(current_angle - desired_angle) < 0.1: drone.sort_phase = 2 target = dot(rotation(current_angle + 0.4), vec2(self.radius - 400, 0)) target = vec3(target) target[2] = self.height + (180 * index // 16) # Height and final corrections. elif drone.sort_phase == 2: target = vec3( dot(rotation(desired_angle), vec2(self.radius, 0))) target[2] = self.height if norm(drone.position - target) < 200: drone.sort_phase = 3 target[2] = (4 * drone.position[2] + self.height) / 5 elif drone.sort_phase == 3: target = vec3( dot(rotation(desired_angle), vec2(self.radius, 0))) target[2] = self.height else: # Stay in place. target = drone.start_pos # Hover controls drone.hover.target = target drone.hover.up = normalize(drone.position) drone.hover.step(self.dt) drone.controls = drone.hover.controls # If any bot got lost, now they have a chance to recover. if drone.on_ground: drone.controls.jump = True else: drone.controls.jump = False
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
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 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
def step(self, packet: GameTickPacket, drone: Drone, index: int): if drone.since_jumped is None: # Control throttle start and jump. if self.time_since_start > self.delay * (index % 16): # Speed controller. drone.controls.throttle = 1.0 if max(abs( drone.velocity[0]), abs(drone.velocity[1])) < 500 else 0.03 # If near half-line if norm(vec3(0, 0, 0) - drone.position) < 700: drone.since_jumped = 0.0 drone.controls.jump = True # Create helix after jump. else: # Increment timer. drone.since_jumped += self.dt # HEIGHT if drone.since_jumped < 11: height = 150 + drone.since_jumped * 150 # speed of rise elif drone.since_jumped < 20: height = 1800 - (drone.since_jumped - 11) * 150 else: height = 450 + (drone.since_jumped - 16) * 30 height = min(height, 600) # RADIUS if drone.since_jumped < 11: radius = 500 elif drone.since_jumped < 15: radius = 500 - (drone.since_jumped - 10) * 50 elif drone.since_jumped < 17: radius = 300 elif drone.since_jumped < 20: radius = 300 + (drone.since_jumped - 17) * 100 else: radius = 400 + drone.since_jumped**3 / 10 radius = min(radius, 2000) # ANGLE if drone.since_jumped < 11: angle = drone.since_jumped * 0.4 # rotation speed elif drone.since_jumped < 20: angle = (11 * 0.4) + (drone.since_jumped - 11) * 0.6 else: angle = (11 * 0.4) + (9 * 0.6) + (drone.since_jumped - 20) * 0.3 # Offset angle. angle += (index // 16) * (math.pi / 2) # Set hover target and controller. rot = rotation(angle) v = vec3(dot(rot, vec2(1, 0))) drone.hover.target = v * radius drone.hover.target[2] = height drone.hover.up = normalize(drone.position) drone.hover.step(self.dt) drone.controls = drone.hover.controls if drone.since_jumped < 0.05: drone.controls.jump = True drone.controls.boost = False
def distance_2d(vec_a, vec_b): """returns 2d distance between two vectors""" return norm(vec2(vec_a - vec_b))