import math from maneuver_scheduler import ManeuverScheduler from . import MechJebManeuver class ComsatManeuver(MechJebManeuver): def __init__(self, conn, vessel, target_body): super().__init__(conn, vessel) self.target_body = target_body body = self.target_body if body.satellites: lowest_sat = min(body.satellites, key=lambda sat: sat.orbit.periapsis) max_orbit = lowest_sat.orbit.periapsis - lowest_sat.sphere_of_influence else: max_orbit = body.sphere_of_influence self.target_altitude = max_orbit - ((5 / 100) * max_orbit) def start(self): self.plan_next_maneuver() def plan_next_maneuver(self): sc = self.conn.space_center vessel = sc.active_vessel if vessel.orbit.body.name != self.target_body.name: raise NotImplementedError if not math.isclose(vessel.orbit.apoapsis, self.target_altitude, rel_tol=.01): SetOrbitApoapsis(self.conn, vessel, self.target_altitude).prepare_maneuver() elif not math.isclose(vessel.orbit.eccentricity, 0, rel_tol=.01): CircularizeOrbitAndDeliver(self.conn, vessel, self.target_altitude).prepare_maneuver() elif self.vessel.control.current_stage == 0: return True return False class SetOrbitApoapsis(ComsatManeuver): name = "Set target orbit's apoapsis" def prepare_maneuver(self): oa = self.maneuver_planner.operation_apoapsis oa.new_apoapsis = self.target_altitude oa.time_selector.time_reference = self.mech_jeb.TimeReference.periapsis nodes = oa.make_nodes() node = nodes[0] ManeuverScheduler.book_timeslot_for_node(self.vessel, node, self) class CircularizeOrbitAndDeliver(ComsatManeuver): name = "Circularize orbit and deliver comsat" def prepare_maneuver(self): oc = self.maneuver_planner.operation_circularize oc.time_selector.time_reference = self.mech_jeb.TimeReference.apoapsis nodes = oc.make_nodes() node = nodes[0] ManeuverScheduler.book_timeslot_for_node(self.vessel, node, self) def execute(self) -> bool: sc = self.conn.space_center if sc.active_vessel.name != self.vessel.name: sc.active_vessel = self.vessel while self.vessel.control.nodes: self._execute_node() if self.vessel.control.current_stage > 0: self.vessel.control.activate_next_stage() oro = self.maneuver_planner.operation_resonant_orbit oro.resonance_numerator = 2 oro.resonance_denominator = 3 oro.time_selector.lead_time = 10 oro.time_selector.time_reference = self.mech_jeb.TimeReference.x_from_now oro.make_nodes() while self.vessel.control.nodes: self._execute_node() return self.plan_next_maneuver() else: return True