def return_data(self): # FIXME: need to make sure that data is correct length (sometimes drops the last 0 when input is xxx.x rather # then xxx.xx try: roll = str(round(get_telemetry("roll"), 1)) pitch = str(round(get_telemetry("pitch"), 1)) yaw = str(round(get_telemetry("heading"), 1)) except TelemetryNotAvailable: raise roll = roll.replace(".", "") pitch = pitch.replace(".", "") yaw = yaw.replace(".", "") data = { 1: roll, 2: pitch, 3: yaw, "is_octal": False, "tooltips": [ "Roll (0xxx.x°)", "Pitch (0xxx.x°)", "Yaw (0xxx.x°)", ], } return data
def return_data(self): try: # latitude = str(round(get_telemetry("lat"), 2)).replace(".", "").zfill(5) # longitude = str(round(get_telemetry("long"), 2)).replace(".", "").zfill(5) # altitude = str(round(get_telemetry("altitude") / 1000, 1)).replace(".", "").zfill(5) latitude = str(round(get_telemetry("lat"), 2)) longitude = str(round(get_telemetry("long"), 2)) altitude = str(round(get_telemetry("altitude") / 1000, 1)) except TelemetryNotAvailable: raise # the following fixes a problem that round() will discard a trailing 0 eg 100.10 becomes 100.1 if latitude[-2] == ".": latitude += "0" if longitude[-2] == ".": longitude += "0" latitude = latitude.replace(".", "") longitude = longitude.replace(".", "") altitude = altitude.replace(".", "") data = { 1: latitude, 2: longitude, 3: altitude, "is_octal": False, "tooltips": [ "Latitude (xxx.xx°)", "Longitude (xxx.xx°)", "Altitude", # TODO ], } return data
def return_data(self): try: apoapsis = str(round(get_telemetry("ApA") / 100, 1)) periapsis = str(round(get_telemetry("PeA") / 100, 1)) tff = int(get_telemetry("timeToAp")) except TelemetryNotAvailable: raise apoapsis = apoapsis.replace(".", "") periapsis = periapsis.replace(".", "") tff_minutes, tff_seconds = divmod(tff, 60) tff_hours, tff_minutes = divmod(tff_minutes, 60) tff = str(tff_hours).zfill(1) + str(tff_minutes).zfill(2) + str(tff_seconds).zfill(2) data = { 1: apoapsis, 2: periapsis, 3: tff, "tooltips": [ "Apoapsis Altitude (xxx.xx km)", "Periapsis Altitude (xxx.xx km)", "Time to Apoapsis (hmmss)" ], "is_octal": False, } return data
def update_gyro_angles(self): ''' Gets the latest attitude from KSP and sets those values in IMU :returns: None ''' self.gyro_angles["inner"] = get_telemetry("pitch") self.gyro_angles["middle"] = get_telemetry("heading") self.gyro_angles["outer"] = get_telemetry("roll")
def check_orbital_parameters(): if get_telemetry("eccentricity") > 0.002: return (False, 224) # check if orbit is excessively inclined target_inclination = get_telemetry("target_inclination") vessel_inclination = get_telemetry("inclination") if (vessel_inclination > (target_inclination - 1)) and (vessel_inclination > (target_inclination + 1)): #self.computer.poodoo_abort(225) return (False, 225) else: return True
def __init__(self): self.delta_v_1 = 0.0 self.delta_v_2 = 0.0 self.orbiting_body = get_telemetry("body") self.radius = get_telemetry("body_radius", body_number=config.TELEMACHUS_BODY_IDS[self.orbiting_body]) self.phase_angle_required = 0.0 self.time_of_ignition_first_burn = 0.0 self.target_name = "Mun" self.departure_body = get_telemetry("body") self.departure_altitude = get_telemetry("sma") self.radius = get_telemetry("body_radius", body_number=config.TELEMACHUS_BODY_IDS[self.orbiting_body]) self.destination_altitude = 13500000 + self.radius self.grav_param = get_telemetry("body_gravParameter", body_number=config.TELEMACHUS_BODY_IDS[self.orbiting_body]) self.orbital_period = get_telemetry("period") self.departure_body_period = get_telemetry("body_period", body_number=config.TELEMACHUS_BODY_IDS["Kerbin"]) self.first_burn = None self.second_burn = None self.target_id = config.TELEMACHUS_BODY_IDS[self.target_name] self.time_of_node = 0.0 #self.time_of_second_node = 0.0 self.duration_of_burn = 0
def return_data(self): if not computer.next_burn: computer.program_alarm(115) return False burn = computer.next_burn expected_delta_v_at_cutoff = burn.velocity_at_cutoff actual_delta_v_at_cutoff = get_telemetry("orbitalVelocity") delta_v_error = actual_delta_v_at_cutoff - expected_delta_v_at_cutoff expected_delta_v_at_cutoff = str(int(expected_delta_v_at_cutoff)).replace(".", "") actual_delta_v_at_cutoff = str(int(actual_delta_v_at_cutoff)).replace(".", "") delta_v_error = str(round(delta_v_error, 1)).replace(".", "") data = { 1: expected_delta_v_at_cutoff, 2: actual_delta_v_at_cutoff, 3: delta_v_error, "tooltips": [ "Expected velocity at cutoff (xxxxx m/s)", "Actual velocity at cutoff (xxxxx m/s)", "Velocity error (xxxx.x m/s)" ], "is_octal": False, } return data
def _thrust_monitor(self): # recalculate accumulated delta-v so far self.accumulated_delta_v = self._calculate_accumulated_delta_v() current_velocity = get_telemetry("orbitalVelocity") #print("Accumulated dV: {:.2f}".format(self.accumulated_delta_v)) #print("dV required: {:.2f}".format(self.delta_v_required)) #print("Velocity at start: {:.2f}".format(self.initial_speed)) #print("Current Velocity: {:.2f}".format(current_velocity)) #print("Expected dV at cutoff: {}".format(self.velocity_at_cutoff)) if current_velocity > (self.velocity_at_cutoff - 13.5) and not self._is_thrust_reduced: utils.log("Throttling back to 10%", log_level="DEBUG") telemachus.set_throttle(10) self._is_thrust_reduced = True telemachus.disable_smartass() telemachus.send_command_to_ksp("command=f.sas") if current_velocity > (self.velocity_at_cutoff - 3.5): # the 3.5 a hack otherwise it overshoots, FIXME! telemachus.cut_throttle() utils.log("Closing throttle, burn complete!", log_level="DEBUG") computer.dsky.current_verb.terminate() computer.execute_verb(verb="06", noun="14") computer.main_loop_table.remove(self._thrust_monitor) #computer.burn_complete() self.terminate() computer.go_to_poo()
def return_data(self): try: telemetry = get_telemetry("missionTime") except TelemetryNotAvailable: raise minutes, seconds = divmod(telemetry, 60) hours, minutes = divmod(minutes, 60) days, hours = divmod(hours, 24) days = str(int(days)).zfill(2) hours = str(int(hours)).zfill(2) minutes = str(int(minutes)).zfill(2) seconds = str(round(seconds, 2)).replace(".", "").zfill(4) data = { 1: days + "b" + hours, 2: "bbb" + minutes, 3: "b" + seconds, "tooltips": [ "Mission Elapsed Time (ddbhh)", "Mission Elapsed Time (bbbmm)", "Mission Elapsed Time (bss.ss)", ], "is_octal": False, } return data
def __init__(self): """ Class constructor. :return: None """ super().__init__(description="MOI Burn Calculator", number="31") self.delta_v = Program.computer.moi_burn_delta_v self.time_of_node = get_telemetry("timeOfPeriapsisPassage") self.time_of_ignition = None
def calculate_time_to_ignition(self): """ Calculates the time to ignition in seconds :return: time to ignition in seconds :rtype : float """ current_time = get_telemetry("universalTime") return self.time_of_ignition - current_time
def return_data(self): surface_velocity_x = str(round(get_telemetry("surfaceVelocityx"), 1)).replace(".", "") surface_velocity_y = str(round(get_telemetry("surfaceVelocityy"), 1)).replace(".", "") surface_velocity_z = str(round(get_telemetry("surfaceVelocityz"), 1)).replace(".", "") data = { 1: surface_velocity_x, 2: surface_velocity_y, 3: surface_velocity_z, "tooltips": [ "Surface Velocity X (xxxx.x m/s)", "Surface Velocity Y (xxxx.x m/s)", "Surface Velocity Z (xxxx.x m/s)" ], "is_octal": False, } return data
def check_for_liftoff(self): if get_telemetry("verticalSpeed") > 1: utils.log("Liftoff discrete") Program.computer.remove_from_mainloop(self.check_for_liftoff) # Clear display for register in ["verb", "noun", "program", "data_1", "data_2", "data_3"]: Program.computer.dsky.blank_register(register) # pause for 1 second, then run P11 self.timer.start(1000)
def update_parameters(self): self.delta_v = Program.computer.moi_burn_delta_v self.time_of_node = get_telemetry("timeOfPeriapsisPassage") initial_mass = float(self.computer.noun_data["25"][0] + "." + self.computer.noun_data["25"][1]) thrust = float(self.computer.noun_data["31"][0] + "." + self.computer.noun_data["31"][1]) specific_impulse = float(self.computer.noun_data["38"][0]) self.duration_of_burn = maneuver.calc_burn_duration(initial_mass, thrust, specific_impulse, self.delta_v) self.time_of_ignition = self.time_of_node - (self.duration_of_burn / 2)
def calculate_burn_timings(self): time_to_node = HohmannTransfer.get_time_to_node(self.phase_angle_difference(), self.orbital_period, self.departure_body_period) self.time_of_node = get_telemetry("universalTime") + time_to_node initial_mass = float(computer.noun_data["25"][0] + "." + computer.noun_data["25"][1]) thrust = float(computer.noun_data["31"][0] + "." + computer.noun_data["31"][1]) specific_impulse = float(computer.noun_data["38"][0]) self.duration_of_burn = calc_burn_duration(initial_mass, thrust, specific_impulse, self.delta_v_1) self.time_of_ignition_first_burn = self.time_of_node - (self.duration_of_burn / 2) # TIG
def phase_angle_difference(self): #set_trace() current_phase_angle = get_telemetry("body_phaseAngle", body_number=self.target_id) phase_angle_difference = current_phase_angle - self.phase_angle_required #if phase_angle_difference < 0: #phase_angle_difference = 180 + abs(phase_angle_difference) #utils.log("Adding 180 degrees to phase angle difference") utils.log() utils.log("Current Phase Angle: {} degrees".format(current_phase_angle)) utils.log("Phase Angle Required: {} degrees".format(self.phase_angle_required)) utils.log("Phase Angle Difference: {} degrees".format(phase_angle_difference)) return phase_angle_difference
def return_data(self): surface_velocity = str(round(get_telemetry("relativeVelocity"), 1)) altitude_rate = str(round(get_telemetry("verticalSpeed"), 1)) altitude = str(round(get_telemetry("altitude") / 1000, 1)) surface_velocity = surface_velocity.replace(".", "") altitude_rate = altitude_rate.replace(".", "") altitude = altitude.replace(".", "") data = { 1: surface_velocity, 2: altitude_rate, 3: altitude, "is_octal": False, "tooltips": [ "Inertial Velocity (xxxx.x m/s)", "Altitude Rate (xxxx.x m/s)", "Altitude (xxxx.x km)", ], } return data
def update_parameters(self): # update departure altitide self.departure_altitude = get_telemetry("altitude") self.calculate() self.calculate_burn_timings() self.first_burn.delta_v = self.delta_v_1 self.first_burn.time_of_ignition = self.time_of_ignition_first_burn self.first_burn.time_of_node = self.time_of_node telemachus.update_maneuver_node(ut=self.time_of_node, delta_v=(0.0, 0.0, self.delta_v_1)) if config.current_log_level == "DEBUG": self.print_maneuver_data()
def check_for_liftoff(self): if get_telemetry("verticalSpeed") > 1: utils.log("Liftoff discrete") Program.computer.remove_from_mainloop(self.check_for_liftoff) # Clear display for register in [ "verb", "noun", "program", "data_1", "data_2", "data_3" ]: Program.computer.dsky.blank_register(register) # pause for 1 second, then run P11 self.timer.start(1000)
def _begin_burn(self): self.initial_speed = get_telemetry("orbitalVelocity") self.velocity_at_cutoff = self._calculate_velocity_at_cutoff() # start thrusting # set actual TIG #self.actual_time_of_ignition = get_telemetry("universalTime") #self.time_of_cutoff = self.actual_time_of_ignition + self.burn_duration telemachus.set_throttle(100) computer.main_loop_table.append(self._thrust_monitor)
def update_parameters(self): self.delta_v = Program.computer.moi_burn_delta_v self.time_of_node = get_telemetry("timeOfPeriapsisPassage") initial_mass = float(self.computer.noun_data["25"][0] + "." + self.computer.noun_data["25"][1]) thrust = float(self.computer.noun_data["31"][0] + "." + self.computer.noun_data["31"][1]) specific_impulse = float(self.computer.noun_data["38"][0]) self.duration_of_burn = maneuver.calc_burn_duration( initial_mass, thrust, specific_impulse, self.delta_v) self.time_of_ignition = self.time_of_node - (self.duration_of_burn / 2)
def receive_data(self, data): if data == "01": Verb.computer.accept_uplink() elif data == "02": data = telemachus.get_telemetry("maneuverNodes") data = data[0] for key, value in sorted(data.items()): if key == "orbitPatches": print("-" * 40) print("Orbit patches:") print() for index in range(len(value)): print("Patch {}:".format(index)) for a, b in sorted(value[index].items()): print("{}: {}".format(a, b)) print() #for a, b in data[key].items(): #print("{}: {}".format(a, b)) print("-" * 40) else: print("{}: {}".format(key, value))
def return_data(self): if not computer.next_burn: computer.program_alarm(115) return False burn = computer.next_burn time_to_ignition = utils.seconds_to_time(burn.time_until_ignition) minutes_to_ignition = str(int(time_to_ignition["minutes"])).zfill(2) seconds_to_ignition = str(int(time_to_ignition["seconds"])).zfill(2) velocity = str(int(get_telemetry("orbitalVelocity"))).replace(".", "") accumulated_delta_v = str(int(burn.accumulated_delta_v)).replace(".", "") data = { 1: "-" + minutes_to_ignition + "b" + seconds_to_ignition, 2: velocity, 3: accumulated_delta_v, "is_octal": False, "tooltips": [ "Time From Ignition (mmbss minutes, seconds)", "Orbital Velocity (xxxxx m/s)", "Accumulated Δv (xxxxx m/s)", ], } return data
def calculate_delta_v(departure_altitude, destination_altitude, departure_body="Kerbin"): """ Given a circular orbit at altitude departure_altitude and a target orbit at altitude destination_altitude, return the delta-V budget of the two burns required for a Hohmann transfer. departure_altitude and destination_altitude are in meters above the surface. returns a float of the burn delta-v required, positive means prograde, negative means retrograde :param departure_body: :param departure_altitude: departure orbit altitude :param destination_altitude: destination orbit altitude """ #departure_planet_radius = get_telemetry("body_radius", body_number=TELEMACHUS_BODY_IDS[departure_body]) r1 = departure_altitude r2 = destination_altitude mu = float(get_telemetry("body_gravParameter", body_number=TELEMACHUS_BODY_IDS[departure_body])) sqrt_r1 = math.sqrt(r1) sqrt_r2 = math.sqrt(r2) sqrt_2_sum = math.sqrt(2 / (r1 + r2)) sqrt_mu = math.sqrt(mu) delta_v_1 = sqrt_mu / sqrt_r1 * (sqrt_r2 * sqrt_2_sum - 1) delta_v_2 = sqrt_mu / sqrt_r2 * (1 - sqrt_r1 * sqrt_2_sum) return delta_v_1, delta_v_2
def _calculate_accumulated_delta_v(self): current_speed = get_telemetry("orbitalVelocity") return current_speed - self.initial_speed
def update_parameters(self): try: self.body_id = config.BODIES[self.object_name] except KeyError: self.body_id = None self.type_of_object = "Spacecraft" else: self.type_of_object = "celestial_body" self.orbiting_body_name = get_telemetry("body") self.eccentricity = get_telemetry("eccentricity") self.semi_major_axis = get_telemetry("sma") self.inclination = get_telemetry("inclination") self.longitude_of_ascending_node = get_telemetry("lan") self.argument_of_periapsis = get_telemetry("argumentOfPeriapsis") self.mean_anomaly_at_epoch = get_telemetry("maae") self.true_anomaly = get_telemetry("trueAnomaly") self.apoapsis = get_telemetry("ApA") self.periapsis = get_telemetry("PeA") self.time_to_apoapsis = get_telemetry("timeToAp") self.time_to_periapsis = get_telemetry("timeToPe") self.orbital_period = get_telemetry("period") self.time_of_periapsis_passage = get_telemetry("timeOfPeriapsisPassage") self.time_to_apoapsis_dhms = utils.seconds_to_time(self.time_to_apoapsis) self.time_to_periapsis_dhms = utils.seconds_to_time(self.time_to_periapsis) self.orbital_period_hms = utils.seconds_to_time(self.orbital_period) self.time_of_periapsis_passage_hms = utils.seconds_to_time(self.time_of_periapsis_passage)