import sys import signal from enum import Enum from maneuver_scheduler import ManeuverScheduler from maneuvers.rendezvous import RendezvousManeuver from maneuvers.approach import ApproachManeuver from maneuvers.docking import DockingManeuver from maneuvers.comsat import ComsatManeuver from connector import get_connexion from lib import get_contract, get_vessel, get_rescuee_vessel, get_body class MissionType(Enum): transport = 1 rescue = 2 comsat = 3 class MissionStatus(Enum): Backlog = 1 Assigned = 2 InProgress = 3 Done = 4 class MissionReport: mission_status = None new_vessel_id = None new_missions = [] def __int__(self): pass class Mission: pass class TransportMission(Mission): type = MissionType.transport def __init__(self, kerbal_name, destination): self.kerbal_name = kerbal_name self.destination = destination class RescueMission(Mission): type = MissionType.rescue def __init__(self, contract_title): self.contract_title = contract_title self.contract = get_contract(contract_title) rescuee_first_name = contract_title.split()[1] self.rescuee_vessel = get_rescuee_vessel(rescuee_first_name) self.rescuee_vessel_name = self.rescuee_vessel.name self.rescuee_name = self.rescuee_vessel.crew[0].name def execute(self, mission_control): conn = get_connexion() sc = conn.space_center if sc.active_vessel.name != mission_control.vessel.name: sc.active_vessel = mission_control.vessel if sc.target_vessel is None or sc.target_vessel.name != self.rescuee_vessel.name: sc.target_vessel = self.rescuee_vessel rendezvous_done = RendezvousManeuver(conn, mission_control).execute() if rendezvous_done: reference_frame = sc.ReferenceFrame.create_relative( self.rescuee_vessel.reference_frame, rotation=(1., 0., 0., 0.) ) sc.active_vessel.parts.controlling = mission_control.get_grappling() approach_done = ApproachManeuver(conn, mission_control, reference_frame).start() if approach_done: mission_control.toggle_grappling(True) docking_done = DockingManeuver(conn, mission_control, mission_control.get_grappling(), reference_frame).start() # Find new creat member name # sc.transfer_crew(self.rescuee_name, target_part) # Release Grapple # Destroy Capsule report = MissionReport() report.mission_status = MissionStatus.Done report.new_missions.append( TransportMission(self.rescuee_name, 'kerbin_orbit') ) return report class ComSatNetworkMission: type = MissionType.comsat def __init__(self, body_name): self.body = get_body(body_name) def execute(self, mission_control): conn = get_connexion() sc = conn.space_center if sc.active_vessel.name != mission_control.vessel.name: sc.active_vessel = mission_control.vessel mission_control.toggle_engines(True) comsat_done = ComsatManeuver(conn, mission_control, self.body).execute() if comsat_done: report = MissionReport() report.mission_status = MissionStatus.Done return report class MissionControl: mission_types = [] def __init__(self): self.current_mission = None def pick_missions(self, backlog): current_body_name = self.vessel.orbit.body.name for i, mission in enumerate(backlog.missions[current_body_name]): if mission.type in self.mission_types: if self.current_mission is None: self.plan_mission(mission) else: self.current_orbit_missions.append(mission) del (backlog.missions[current_body_name][i]) def plan_mission(self, mission): self.current_mission = mission planning_duration = 60 ut = ManeuverScheduler.next_free_timeslot( from_ut=get_connexion().space_center.ut + planning_duration, duration=planning_duration) ManeuverScheduler.book_timeslot(ut, self.vessel, duration=planning_duration) def execute_mission(self, alarm): if self.current_mission is None: if self.current_orbit_missions: self.current_mission = self.current_orbit_missions.pop(0) else: return report = self.current_mission.execute(self) if report and report.mission_status == MissionStatus.Done: self.current_mission = None class ShuttleKerbin(MissionControl): mission_types = [MissionType.rescue, MissionType.transport] PISTON_MAX_EXTENSION = 2.4 def __init__(self, vessel_name): super().__init__() self.vessel_name = vessel_name self.vessel = get_vessel(vessel_name) for e in self.vessel.parts.engines: e.active = True self.current_orbit_missions = [] def toggle_grappling(self, value=True): piston = self.vessel.parts.robotic_pistons[0] piston.target_extension = self.PISTON_MAX_EXTENSION if value else 0 arm = piston.part.children[0] if arm.modules[1].has_event('Arm') and not value \ or arm.modules[1].has_event('Disarm') and value: arm.modules[1].set_action_by_id('ToggleAction', True) def get_grappling(self): piston = self.vessel.parts.robotic_pistons[0] return piston.part.children[0] class ComsatKerbin(MissionControl): mission_types = [MissionType.comsat] def __init__(self, vessel_name): super().__init__() self.vessel_name = vessel_name self.vessel = get_vessel(vessel_name) def toggle_engines(self, value=True): self.vessel.parts.engines[0].active = value class Backlog: missions = { 'Kerbin': [RescueMission('Rescue Rossby from orbit of Kerbin.'), ] # ComSatNetworkMission('Kerbin')] } kerbin_to_orbit = [] kerbin_to_ground = [] def signal_handler(signal, frame): print("\nBye!") sys.exit(0) if __name__ == '__main__': signal.signal(signal.SIGINT, signal_handler) ships = [] ships.append(ShuttleKerbin('KKS Gagarin')) ships.append(ComsatKerbin('KKR Shepard')) conn = get_connexion() # conn.space_center.GameMode space_center = conn.space_center for s in ships: s.pick_missions(Backlog) while True: for s in ships: s.pick_missions(Backlog) space_center.rails_warp_factor = 7 with conn.stream(getattr, space_center, 'rails_warp_factor') as rails_warp_factor: with rails_warp_factor.condition: while rails_warp_factor() > 0: rails_warp_factor.wait() alarm = ManeuverScheduler.get_last_alarm() vessel = alarm.vessel current_ship = None for s in ships: if s.vessel.name == vessel.name: current_ship = s break if current_ship is None: raise LookupError("Current ship {} not found".format(vessel.name)) current_ship.execute_mission(alarm) alarm.remove() print("turn")