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
def triangle(self, pos: vec3, pointing_dir: vec3, width=50, length=50, up=vec3(0, 0, 1)): left = pos + cross(pointing_dir, up) * width / 2 right = pos - cross(pointing_dir, up) * width / 2 top = pos + pointing_dir * length self.cyclic_polyline([left, right, top])
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 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 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 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
def rotate_by_axis(orientation: Orientation, original: Vec3, target: Vec3, percent=1) -> Rotator: """ Updates the given orientation's original direction to the target direction. original should be `orientation.forward` or `orientation.up` or `orientation.right` """ angle = angle_between(to_rlu_vec(target), to_rlu_vec(original)) * percent rotate_axis = cross(to_rlu_vec(target), to_rlu_vec(original)) ortho = normalize(rotate_axis) * -angle rot_mat_initial: mat3 = orientation.to_rot_mat() rot_mat_adj = axis_to_rotation(ortho) rot_mat = dot(rot_mat_adj, rot_mat_initial) r = rot_mat_to_rot(rot_mat) # printO(orientation) # printO(Orientation(r)) return r
def roll_away_from_target(target, theta, game_info): ''' Returns an orientation mat3 for an air roll shot. Turns directly away from the dodge direction (target) by angle theta Target can either be RLU vec3, or CowBot Vec3. ''' starting_forward = game_info.utils_game.my_car.forward() starting_left = game_info.utils_game.my_car.left() starting_up = game_info.utils_game.my_car.up() starting_orientation = mat3(starting_forward[0], starting_left[0], starting_up[0], starting_forward[1], starting_left[1], starting_up[1], starting_forward[2], starting_left[2], starting_up[2]) if type(target) == vec3: target = vec3_to_Vec3(target, game_info.team_sign) car_to_target = Vec3_to_vec3((target - game_info.me.pos).normalize(), game_info.team_sign) axis = theta * cross(car_to_target, starting_up) return dot(axis_to_rotation(axis), starting_orientation)
def step(self, packet: GameTickPacket, drones: List[Drone]): orbit_t = max(0, self.time_since_start - self.orbit_start_delay) orbit_rotation = self.starting_orbit_rotation + orbit_t * self.orbit_speed direction_from_center = dot( axis_to_rotation(vec3(0, 0, 1) * orbit_rotation), vec3(1, 0, 0)) ring_center = self.orbit_center + direction_from_center * self.orbit_radius ring_facing_direction = cross(direction_from_center, vec3(0, 0, 1)) for drone in drones: i = drone.id - drones[0].id angle = i / len(drones) * pi * 2 pos = ring_center + dot( vec3(0, 0, 1), axis_to_rotation( ring_facing_direction * angle)) * self.ring_radius if pos[2] > self.orbit_center[ 2] + self.ring_radius - self.time_since_start * 200: drone.hover.target = pos drone.hover.up = ring_facing_direction drone.hover.step(self.dt) drone.controls = drone.hover.controls drone.controls.jump = True
def to_Curve(self, team_sign): ''' Converts the path to an RLU Curve object that can be followed ''' control_points = [] #The first arc direction1 = self.start - self.center1 starting_angle = atan2(direction1.y, direction1.x) steps = ceil(30 * (self.phi1 / (2 * pi))) delta = -self.sgn1 * self.phi1 / steps center1 = Vec3_to_vec3(self.center1, team_sign) for i in range(1, steps - 2): angle = starting_angle + delta * i next_point = center1 + abs(self.radius1) * vec3( cos(angle), sin(angle), 0) normal = normalize(next_point - center1) next_control_point = ControlPoint() next_control_point.p = next_point next_control_point.t = cross(normal) next_control_point.n = normal control_points.append(next_control_point) #The line steps = max(10, ceil(self.length_line / 300)) delta = self.length_line / steps tangent = Vec3_to_vec3( (self.transition2 - self.transition1).normalize(), team_sign) normal = cross(tangent) for i in range(0, steps + 1): next_point = Vec3_to_vec3(self.transition1, team_sign) + delta * tangent * i next_control_point = ControlPoint() next_control_point.p = next_point next_control_point.t = tangent next_control_point.n = normal control_points.append(next_control_point) #The second arc direction2 = self.transition2 - self.center2 starting_angle = atan2(direction2.y, direction2.x) steps = ceil(30 * (self.phi2 / (2 * pi))) delta = -self.sgn2 * self.phi2 / steps center2 = Vec3_to_vec3(self.center2, team_sign) for i in range(1, steps + 1): angle = starting_angle + delta * i next_point = center2 + abs(self.radius2) * vec3( cos(angle), sin(angle), 0) normal = normalize(next_point - center2) next_control_point = ControlPoint() next_control_point.p = next_point next_control_point.t = cross(normal) next_control_point.n = normal control_points.append(next_control_point) curve = Curve(control_points) self.RLU_curve = curve self.discretized_path = [ vec3_to_Vec3(point.p, team_sign) for point in control_points ]