def step(self, packet: GameTickPacket, drone: Drone, index: int): drone.hover.up = normalize(drone.position) clockwise_rotation = axis_to_rotation(vec3(0, 0, 0.5)) position_on_circle = normalize(xy(drone.position)) * 2000 drone.hover.target = dot(clockwise_rotation, position_on_circle) drone.hover.target[2] = 1000 drone.hover.step(self.dt) drone.controls = drone.hover.controls
def step(self, packet: GameTickPacket, drone: Drone, index: int): drone.hover.up = normalize(drone.position) rotation = axis_to_rotation(vec3(0, 0, self.spin * (-1)**(index // 16))) position_on_circle = normalize(xy(drone.position)) * ( self.radius + self.radius_increase * self.time_since_start) drone.hover.target = dot(rotation, position_on_circle) drone.hover.target[ 2] = self.height + self.height_increase * self.time_since_start drone.hover.target[2] += (index // 16 - 2) * ( self.height_diff + self.height_diff_increase * self.time_since_start) drone.hover.step(self.dt) drone.controls = drone.hover.controls
def step(self, packet: GameTickPacket, drone: Drone, index: int): for i, layer in enumerate(self.layers): if index in layer: drone.hover.up = normalize(drone.position) clockwise_rotation = axis_to_rotation(vec3(0, 0, 0.3)) position_on_circle = normalize(xy( drone.position)) * self.radii[i] drone.hover.target = dot(clockwise_rotation, position_on_circle) drone.hover.target[2] = self.heights[i] break drone.hover.step(self.dt) drone.controls = drone.hover.controls
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 step(self, packet: GameTickPacket, drone: Drone, index: int): # Just ask me in discord about this. layer = (2 * (index // 16) + (index % 2) - 3.5) / 4 height = self.height + layer * self.radius radius = math.sqrt(1 - layer**2) * self.radius spin = 0 if self.time_since_start < 3.0 else 0.5 drone.hover.up = normalize(drone.position) rotation = axis_to_rotation(vec3(0, 0, spin)) position_on_circle = normalize(xy(drone.position)) * radius drone.hover.target = dot(rotation, position_on_circle) drone.hover.target[2] = height drone.hover.step(self.dt) drone.controls = drone.hover.controls
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 tick(self, packet: GameTickPacket) -> bool: #self.agent.renderer.begin_rendering() kickoff = packet.game_info.is_round_active and packet.game_info.is_kickoff_pause carAccelerations = [] for i in range(packet.num_cars): car = packet.game_cars[i] velocity = vec3(car.physics.velocity.x, car.physics.velocity.y, car.physics.velocity.z) carAccelerations.append((velocity - self.lastVelocities[i]) / self.agent.ticksThisPacket * 120) self.lastVelocities[i] = velocity # car info myCar = packet.game_cars[self.agent.index] carLocation = Vec3(myCar.physics.location) carVelocity = Vec3(myCar.physics.velocity) carSpeed = carVelocity.length() # ball info realBallLocation = ballLocation = Vec3( packet.game_ball.physics.location) ballVelocity = Vec3(packet.game_ball.physics.velocity) if ballLocation.z < 100: self.balanceTime = 0 #return False action_display = f"Air time: {self.balanceTime}" self.balanceTime += 1 # unstuck goal hack if abs(carLocation.y) > 5100: ballLocation.x = 0 # target ball info #targetBallLocation, targetBallVelocity, targetAngle = getTargetBall(self.agent, packet, carLocation) teamDirection = 1 if packet.game_cars[ self.agent.index].team == 0 else -1 sidewaysDiff = abs(carLocation.x) - 893 + 100 isInCorner = sidewaysDiff > 0 if isInCorner: sidewaysDiff = max( 0, sidewaysDiff + 0.4 * (carLocation.y * teamDirection - (5120 - 100))) inTriangleAmount = max(0, min(1, sidewaysDiff / 4500)) scale = 0.55 else: scale = 2 inTriangleAmount = 0 targetBallLocation = Vec3(0, (5120 + 100 - sidewaysDiff * scale) * teamDirection, 0) ## if teammate is closer to the ball, go to defend position. ballToCarAbsoluteLocation = (ballLocation - carLocation).flat() ballToCarDistance = ballToCarAbsoluteLocation.length() futurePositionScoreVector = ballLocation + 1 * ballVelocity - carLocation positionScore = Vec3(futurePositionScoreVector.x, futurePositionScoreVector.y * (1 if futurePositionScoreVector.y * (2*self.agent.team-1) < 0 else 3), 0).length()\ + Vec3(ballToCarAbsoluteLocation.x, ballToCarAbsoluteLocation.y * (1 if ballToCarAbsoluteLocation.y * (2*self.agent.team-1) < 0 else 3), 0).length() beAnnoying = False for carIndex in range(packet.num_cars): car = packet.game_cars[carIndex] if car.team == self.agent.team and carIndex != self.agent.index and not car.is_demolished: OtherCarToBall = ballLocation - Vec3(car.physics.location) OtherFutureCarToBall = ballLocation + 1 * ballVelocity - Vec3( car.physics.location) otherPositionScore = Vec3(OtherCarToBall.x , OtherCarToBall.y * (1 if OtherCarToBall.y * (2*self.agent.team-1) < 0 else 3), 0).length()\ + Vec3(OtherFutureCarToBall.x, OtherFutureCarToBall.y * (1 if OtherFutureCarToBall.y * (2*self.agent.team-1) < 0 else 3), 0).length() # print(f"[{self.agent.index} {round(positionScore)}] {carIndex}: {round(otherPositionScore)}!") if otherPositionScore + math.copysign( 5, carIndex - self.agent.index) < positionScore: # print(f"{self.agent.index} other one is closer!") teamClosestDistance = math.inf enemyClosestDistance = math.inf for carIndex in range(packet.num_cars): car = packet.game_cars[carIndex] distance = ( ballLocation - Vec3(car.physics.location)).flat().length() if car.team == self.agent.team: teamClosestDistance = min(teamClosestDistance, distance) else: enemyClosestDistance = min(enemyClosestDistance, distance) teamHasBallControl = teamClosestDistance - 500 < enemyClosestDistance targetScore = math.inf target = None for carIndex in range(packet.num_cars): car = packet.game_cars[carIndex] # print(f"[{self.agent.index} {self.agent.team}] {carIndex} {car.team}") if car.team != self.agent.team: score = ( ballLocation - Vec3(car.physics.location) ).flat().length() + teamHasBallControl * ( Vec3(0, 5120 * (2 * car.team - 1), 0) - Vec3(car.physics.location)).flat().length() # print(f"[{self.agent.index}] considering car {carIndex}") if score < targetScore: targetScore = score target = car if target != None: beAnnoying = True huntLocation = Vec3(target.physics.location) for _ in range(20): time = min( .6, 900 / max(1, Vec3(target.physics.velocity).length()), (carLocation - huntLocation).length() / max(carSpeed, 1)) huntLocation = Vec3( target.physics.location) + time * Vec3( target.physics.velocity) ballLocation = huntLocation ballVelocity = Vec3(0, 0, 0) #Vec3(target.physics.velocity) ballToCarAbsoluteLocation = (ballLocation - carLocation).flat() ballToCarDistance = ballToCarAbsoluteLocation.length() break ## if convenient, change ball location to nearby boost pad. fieldInfo = self.agent.get_field_info() carFutureLocation = carLocation + 0.2 * carVelocity ballToFutureCarAbsoluteLocation = (ballLocation - carFutureLocation).flat() ballToFutureCarDistance = ballToFutureCarAbsoluteLocation.length() goingForBoost = False if ballToCarDistance > 250 and myCar.boost < 88: convenientBoostPads = [] costs = [] for i in range(fieldInfo.num_boosts): if not packet.game_boosts[i].is_active: continue boostPad = fieldInfo.boost_pads[i] boostLocation = Vec3(boostPad.location) maxOffset = (208 if boostPad.is_full_boost else 144) - 20 orth = (boostLocation - carLocation).orthogonalize(ballToCarAbsoluteLocation) boostLocation -= orth.normalized() * min( orth.length(), maxOffset) carToBoostLength = (boostLocation - carFutureLocation).length() detourLength = (ballLocation - boostLocation).length() + carToBoostLength cost = (detourLength - ballToFutureCarDistance) / ( 1450 if boostPad.is_full_boost else 250) costs.append(cost) if cost < ((100 - myCar.boost) / 100)**1.5: convenientBoostPads.append( (i, carToBoostLength * cost, boostLocation)) #self.agent.renderer.draw_line_3d(boostLocation, boostLocation + Vec3(0, 0, 100), self.agent.renderer.pink()) #print(round(min(costs), 1)) if len(convenientBoostPads) > 0: convenientBoostPads.sort(key=lambda b: b[1], reverse=False) boostPad = fieldInfo.boost_pads[convenientBoostPads[0][0]] boostLocation = convenientBoostPads[0][2] #self.agent.renderer.draw_line_3d(boostLocation, boostLocation + Vec3(0, 0, 400), self.agent.renderer.pink()) ballLocation = boostLocation ballVelocity = Vec3(0, 0, 0) ballToCarAbsoluteLocation = (ballLocation - carLocation).flat() ballToCarDistance = ballToCarAbsoluteLocation.length() goingForBoost = True ## time to next bounce if not goingForBoost: pass ## calculate angles ballDirection = math.atan2(ballVelocity.y, -ballVelocity.x) carDirection = -myCar.physics.rotation.yaw carToBallAngle = math.atan2( ballToCarAbsoluteLocation.y, -ballToCarAbsoluteLocation.x) - carDirection if abs(carToBallAngle) > math.pi: if carToBallAngle > 0: carToBallAngle -= 2 * math.pi else: carToBallAngle += 2 * math.pi ballToTargetAbsoluteLocation = (ballLocation - targetBallLocation).flat() carToTargetAngle = math.atan2( ballToTargetAbsoluteLocation.y, -ballToTargetAbsoluteLocation.x) - carDirection if abs(carToTargetAngle) > math.pi: if carToTargetAngle > 0: carToTargetAngle -= 2 * math.pi else: carToTargetAngle += 2 * math.pi carToTargetAbsoluteLocation = (carLocation - targetBallLocation).flat() ## separate into steering and throttle components ballToCarLocation = ballToCarAbsoluteLocation.rotate_2D(carDirection) ballToTargetLocation = ballToTargetAbsoluteLocation.rotate_2D( carDirection) carToTargetLocation = carToTargetAbsoluteLocation.rotate_2D( carDirection) ballToCarVelocity = (ballVelocity - carVelocity).flat().rotate_2D(carDirection) #carToTargetVelocity = (carVelocity - targetBallVelocity).flat().rotate_2D(carDirection) maxSpeed = max(1410, min(2300, 1410 + (2300 - 1410) / 33 * myCar.boost)) carToMaxSpeed = carVelocity.flat().length() - maxSpeed desiredSpeed = 1200 if ballToTargetLocation.y < 500: self.carToTargetIntegral += ballToTargetLocation else: self.carToTargetIntegral = Vec3() canYeet = myCar.has_wheel_contact \ and (not goingForBoost) \ and ballToCarLocation.length() < 275 \ and ballLocation.z > 100 \ and ballLocation.z < 275 \ and packet.game_info.seconds_elapsed - packet.game_ball.latest_touch.time_seconds < 0.1 teamDirection = 1 if packet.game_cars[ self.agent.index].team == 0 else -1 inCornerDegree = math.atan( (max(abs(carLocation.x), 893) - 893) / max(5120 - carLocation.y * teamDirection, 1)) shouldYeet = ((ballLocation + 1 * ballVelocity).flat() * teamDirection - Vec3(0, 5120+100, 0)).length() < 1500 \ and inCornerDegree < math.pi * 2 / 6 \ and 4200 - abs(ballLocation.y) < 0.7 * abs(ballVelocity.y) #print(f"{canYeet}\t{shouldYeet}\t{round(4200 - abs(ballLocation.y))}\t{round(0.7 * abs(ballVelocity.y))}") #action_display = f"{round((ballLocation.flat() - Vec3(0, 5120+100 * teamDirection, 0)).length())}" carlocs = [] if canYeet and shouldYeet: inComingCar = False for i in range(packet.num_cars): if i == self.agent.index: continue car = packet.game_cars[i] if car.team == myCar.team or car.is_demolished: continue #print(round(0.1 + norm(carAccelerations[i]) / RLUDrive.throttle_accel(Vec3(car.physics.velocity).length()), 2)) for throttle in ( 0, min( 1, 0.1 + norm(carAccelerations[i]) / RLUDrive.throttle_accel( Vec3(car.physics.velocity).length()))): carBoost = car.boost attackerCarLocation = Vec3(car.physics.location) # divide by 120, to go from per second to per frame STEPSIZE = 120 gravity = packet.game_info.world_gravity_z / STEPSIZE**2 attackerCarVelocity = vec3( car.physics.velocity.x, car.physics.velocity.y, car.physics.velocity.z) / STEPSIZE attackerCarAngular = axis_to_rotation( vec3(car.physics.angular_velocity.x, car.physics.angular_velocity.y, car.physics.angular_velocity.z) / STEPSIZE) ballV = ballVelocity / STEPSIZE for j in range(round(STEPSIZE * 0.7)): # simulate 40 ticks forwards attackerCarLocation += Vec3(attackerCarVelocity[0], attackerCarVelocity[1], attackerCarVelocity[2]) if car.has_wheel_contact: attackerCarVelocity = dot(attackerCarAngular, attackerCarVelocity) attackerCarVelocity += vec3(0, 0, gravity) if throttle == 0: attackerCarVelocity -= vec3( math.copysign( min(525 / STEPSIZE, abs(attackerCarVelocity[0])), attackerCarVelocity[0]), 0, 0) else: acceleration = (991.667 * (carBoost > 0) + RLUDrive.throttle_accel( norm(attackerCarVelocity))) attackerCarVelocity += normalize( attackerCarVelocity) * acceleration / STEPSIZE if attackerCarLocation.z < ballLocation.z: attackerCarLocation.z = ballLocation.z carlocs.append(attackerCarLocation) if (attackerCarLocation - ballLocation + j * ballV).flat().length( ) < 750: # longest car has a diagonal of 157uu inComingCar = True break #print(f"{j}\t{ (attackerCarLocation - ballLocation + j * ballV).flat().length()}") if inComingCar: break carBoost -= 1 / 3 / STEPSIZE if inComingCar: self.agent.stateMachine.changeStateMidTick(Yeet) return inComingCar if kickoff and (carLocation - realBallLocation ).length() < 800 and myCar.has_wheel_contact: self.agent.stateMachine.changeStateMidTick(Frontflip) return True ## STEERING steer = 0 steerBias = 0 # ball to car proportional #print(f"{round(min(15, max(-15, 0.02 * ballToCarLocation.y)), 2)}\t{round(0.003 * ballToCarVelocity.y, 2)}") steer += min(15, max(-15, 0.02 * ballToCarLocation.y)) if not goingForBoost: # ball to car derivative steer += 0.005 * ballToCarVelocity.y #print(f"pos: {round(min(15, max(-15, 0.02 * ballToCarLocation.y)), 2)}\tvel: {round(0.009 * ballToCarVelocity.y,2)}") # ball to target proportional targetSteer = ballToTargetLocation.y #action_display = f"{round(carToTargetLocation.x)}" if carToTargetLocation.x > 300: targetSteer = math.copysign(100000, targetSteer) steerBias += 0.005 * targetSteer # ball to target derivative #steerBias += 0.002 * carToTargetVelocity.y # ball to target integral #steerBias += 0.000001 * self.carToTargetIntegral.y #print(f"{round(steerBias, 1)}\t{round(0.008 * carToTargetVelocity.y, 1)}") applySpeedLimit = True if kickoff or beAnnoying: self.steerBiasLimit = 0 if abs(carLocation.x) < 930 and abs( carLocation.y) > 5120 - 550 and ballLocation.z > 500: self.steerBiasLimit = 2.5 applySpeedLimit = False if ballLocation.z > 160 or ballToCarLocation.length() > 800: self.steerBiasLimit = max(0.5, self.steerBiasLimit - 0.1) elif ballLocation.z < 100: self.steerBiasLimit = max(0.5, self.steerBiasLimit - 0.1) else: self.steerBiasLimit = min( 2.5, 1 + 1 * max(0, carSpeed - 600) / 1800, self.steerBiasLimit + 0.065) if applySpeedLimit and ballToCarLocation.length() < 180: self.steerBiasLimit = min( self.steerBiasLimit, 1.3 + (1400 - carVelocity.flat().length()) / 800) steer += min(self.steerBiasLimit, max(-self.steerBiasLimit, steerBias)) action_display = f"SBL {round(self.steerBiasLimit, 1)} SB: {round(min(self.steerBiasLimit, max(-self.steerBiasLimit, steerBias)), 1)}" #action_display = f"{round(ballToTargetLocation.x)}" ## THROTTLE throttle = 0 # ball to car proportional throttle += 0.07 * ballToCarLocation.x # ball to car derivative throttle += 0.015 * ballToCarVelocity.x #print(ballVelocity.length()) if ( ballToCarLocation.length() < 300 and not (abs(ballToCarLocation.y) > 100 and ballVelocity.length() < 500) ) and not beAnnoying: # if the ball is too far from the car, use speed to drive car to ball throttleBias = 0 ## NORMAL TARGET BIAS #ball to target proportional #throttleBias += 0.004 * ballToTargetLocation.x # ball to target derivative if ballLocation.z > 100: #action_display = f"triangle: {round((1 - inTriangleAmount), 1)}\ttargetangle: {round(0.8*math.cos(carToTargetAngle/2), 1)}" carToDesiredSpeed = carVelocity.flat().length( ) - desiredSpeed * max(0.2, (1 - inTriangleAmount)) throttleBias += 0.005 * carToDesiredSpeed # ball to target integral #throttleBias += 0.00001 * self.carToTargetIntegral.x ## STEERING HELP BIAS WHEN FAR AWAY #targetSteeringSpeed = 400 + 3000 * math.pow(math.cos(carToTargetAngle/2), 16) #throttleSteeringBias = max(-1, 3 * (carSpeed - targetSteeringSpeed) / 1400) # alpha = max(0, min(1, (ballToTargetLocation.length() - 1000) / 3000)) # throttleBias = throttleSteeringBias * alpha + throttleBias * (1 - alpha) throttle += min(2, max(-0.9, throttleBias)) #action_display = f"TB: {round(throttleBias, 1)}\tT: {round(throttle, 1)}" else: throttle = 1 - 0.8 * math.cos(carToBallAngle) #print(action_display) if goingForBoost: throttle = max(throttle, 1) ## set controller state self.controller.steer = min(1, max(-1, steer)) self.controller.throttle = min(1, max(-1, throttle)) if myCar.has_wheel_contact and throttle > 1.7 and carLocation.z < 100 and realBallLocation.z < 500: self.controller.boost = carSpeed < 2300 - 991.667 / 120 * ( 1 if self.controller.boost else 10) else: self.controller.boost = False ## test if forward dodge is needed if abs( steer ) < 0.5 and not kickoff and carSpeed > 1400 and carSpeed < 2200 and ( myCar.boost == 0 or carSpeed > 2300 - 20 - 500): try: angleCoeff = carVelocity.normalized().dot( ballVelocity.normalized()) except: angleCoeff = -1 if angleCoeff > 0.95: dist = (realBallLocation - carLocation).length() vel = (carSpeed + 500 - ballVelocity.length()) time = dist / vel ballAfterLocation = realBallLocation + time * ballVelocity isStillInMap = abs( ballAfterLocation.x) < 4096 + 500 and abs( ballAfterLocation.y) < 5120 + 500 if time > 1.5: self.agent.stateMachine.changeStateMidTick(Frontflip) return True # print(self.ballToTargetIntegral) # action_display = f"steer: {round(ballToTargetLocation.y)}" # action_display = f"distance: {round(ballToTargetLocation.x)}" # # Find the direction of our car using the Orientation class #car_orientation = Orientation(myCar.physics.rotation).forward #car_direction = car_orientation.forward # steer_correction_radians = find_correction(car_direction, ballToCarLocation) # turnProportional = max(-1, min(1, steer_correction_radians * 4)) # #action_display = f"turn {round(turn, 2)}" # self.controller.steer = turnProportional # throttleProportional = 10 # speed = Vec3.length(myCar.physics.velocity) # targetSpeed = min(boostSpeed, Vec3.dist(ballLocation, carLocation) * 5 * math.cos(steer_correction_radians)) # self.controller.throttle = max(-1, min(1, (targetSpeed - speed) * 1000)) # self.controller.steer = turnProportional # self.controller.boost = speed < targetSpeed if self.controller.boost or (abs(turnProportional) < 1 and targetSpeed > normalSpeed) else (abs(turnProportional) < 1 and speed < targetSpeed - 400) # targetBallLocation.z = 150 #draw_debug(self.agent, myCar, packet.game_ball, action_display, targetBallLocation, carlocs) return True
def main(self): main_path = BLUE_DRAGON_PATH other_path = PURPLE_DRAGON_PATH selected_point_index = 0 while True: packet = GameTickPacket() self.game_interface.update_live_data_packet(packet) renderer = self.game_interface.renderer renderer.begin_rendering() points = main_path.points selected_point_index = min(selected_point_index, len(points) - 1) # select previous if keyboard.is_pressed("-") and selected_point_index > 0: selected_point_index -= 1 time.sleep(0.1) # select next elif keyboard.is_pressed("+") and selected_point_index < len(points) - 1: selected_point_index += 1 time.sleep(0.1) # move selected elif keyboard.is_pressed("left arrow"): points[selected_point_index][0] -= 10 self.draw_line(renderer, points[selected_point_index], vec3(1, 0, 0)) elif keyboard.is_pressed("right arrow"): points[selected_point_index][0] += 10 self.draw_line(renderer, points[selected_point_index], vec3(1, 0, 0)) elif keyboard.is_pressed("up arrow"): points[selected_point_index][1] += 10 self.draw_line(renderer, points[selected_point_index], vec3(0, 1, 0)) elif keyboard.is_pressed("down arrow"): points[selected_point_index][1] -= 10 self.draw_line(renderer, points[selected_point_index], vec3(0, 1, 0)) elif keyboard.is_pressed("0"): points[selected_point_index][2] -= 10 self.draw_line(renderer, points[selected_point_index], vec3(0, 0, 1)) elif keyboard.is_pressed("1"): points[selected_point_index][2] += 10 self.draw_line(renderer, points[selected_point_index], vec3(0, 0, 1)) # insert new one after selected elif keyboard.is_pressed("*"): if selected_point_index == len(points) - 1: new_point = 2 * points[-1] - points[-2] else: new_point = (points[selected_point_index] + points[selected_point_index + 1]) * 0.5 selected_point_index += 1 points.insert(selected_point_index, new_point) time.sleep(0.2) # delete selected elif keyboard.is_pressed("delete"): del points[selected_point_index] selected_point_index -= 1 time.sleep(0.2) # dump points into file elif keyboard.is_pressed("enter"): with open("points.txt", "w") as file: file.write("\nBLUE DRAGON\n") for point in BLUE_DRAGON_PATH.points: file.write(f'vec3({int(point[0])}, {int(point[1])}, {int(point[2])}),\n') file.write("\nPURPLE DRAGON\n") for point in PURPLE_DRAGON_PATH.points: file.write(f'vec3({int(point[0])}, {int(point[1])}, {int(point[2])}),\n') print("dumped path to points.txt") renderer.clear_all_touched_render_groups() time.sleep(0.2) exit() # switch between paths elif keyboard.is_pressed("9"): main_path, other_path = other_path, main_path time.sleep(0.2) continue # render path path = BezierPath(points) curve = Curve(path.to_points(380)) # t = curve.find_nearest(points[min(selected_point_index, len(points) - 2)]) # rendered_points = [curve.point_at(t + i) for i in range(-5000, 5000, 200)] renderer.draw_polyline_3d(curve.points, renderer.white()) renderer.end_rendering() renderer.begin_rendering("stuff") for i in range(30): pos = curve.point_at((1 - i / 30) * curve.length) renderer.draw_string_3d(pos, 1, 1, str(i), renderer.white()) for i, point in enumerate(points): selected = i == selected_point_index color = renderer.yellow() if selected else renderer.red() size = 6 if selected else 4 renderer.draw_rect_3d(point, size, size, True, color, True) renderer.draw_string_2d(10, 10, 1, 1, str(int(curve.length)), renderer.yellow()) renderer.end_rendering() renderer.begin_rendering("reference") blue = renderer.create_color(255, 150, 180, 255) # render the other path for reference path = BezierPath(other_path.points) curve2 = Curve(path.to_points(380)) # rendered_points = [curve2.point_at(curve2.length - curve.length + t + i) for i in range(-5000, 5000, 200)] renderer.draw_polyline_3d(curve2.points, blue) for i in range(30): pos = curve2.point_at((1 - i / 30) * curve2.length) renderer.draw_string_3d(pos, 1, 1, str(i), renderer.blue()) renderer.draw_string_2d(10, 30, 1, 1, str(int(curve2.length)), renderer.yellow()) renderer.end_rendering() # render the rings of fire orbit for reference renderer.begin_rendering("orbit") points = [dot(axis_to_rotation(vec3(0, 0, i / 30 * pi * 2)), vec3(2200, 0, 1400)) for i in range(30)] renderer.draw_polyline_3d(points, renderer.orange()) renderer.end_rendering() time.sleep(0.02)
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)
def step(self, dt): time_left = self.aerial.arrival_time - self.car.time if self.aerialing: # 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) self.aerial.target_orientation = look_at( direction(self.car, self.info.ball), 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) speed_towards_target = dot( self.car.velocity, ground_direction(self.car, self.aerial.target)) speed_needed = ground_distance(self.car, self.aerial.target) / time_left # too fast, slow down if speed_towards_target > speed_needed and angle_to( self.car, self.aerial.target) < 0.1: self.controls.throttle = -1 # 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 and ground_distance( self.car, self.aerial.target) > 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, 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