Basic mission vessel tunnel
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class ManeuverAlarmType(Enum):
|
||||
ManeuverNode = 1,
|
||||
SOI = 2
|
||||
|
||||
|
||||
class Maneuver:
|
||||
def __init__(self, conn, vessel):
|
||||
self.vessel = vessel
|
||||
self.conn = conn
|
||||
|
||||
def plan_next_maneuver(self, conn):
|
||||
pass
|
||||
|
||||
|
||||
class NodeManeuver(Maneuver):
|
||||
alarm_type = ManeuverAlarmType.ManeuverNode
|
||||
|
||||
def __init__(self, conn, vessel):
|
||||
super().__init__(conn, vessel)
|
||||
self.mech_jeb = conn.mech_jeb
|
||||
self.node_executor = self.mech_jeb.node_executor
|
||||
|
||||
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()
|
||||
|
||||
return self.plan_next_maneuver()
|
||||
|
||||
def _execute_node(self):
|
||||
self.node_executor.execute_all_nodes()
|
||||
|
||||
with self.conn.stream(getattr, self.node_executor, "enabled") as enabled:
|
||||
enabled.rate = 1
|
||||
with enabled.condition:
|
||||
while enabled():
|
||||
enabled.wait()
|
||||
|
||||
|
||||
class MechJebManeuver(NodeManeuver):
|
||||
def __init__(self, conn, vessel):
|
||||
super().__init__(conn, vessel)
|
||||
self.maneuver_planner = self.mech_jeb.maneuver_planner
|
||||
|
||||
|
||||
@@ -3,11 +3,53 @@ from krpc.services.spacecenter import SASMode
|
||||
import numpy as np
|
||||
from time import time, sleep
|
||||
|
||||
from utils import magnitude, kill_relative_velocity, correct_course
|
||||
from .utils import magnitude, unitary, kill_relative_velocity, correct_course
|
||||
|
||||
from . import Maneuver
|
||||
|
||||
|
||||
def unitary(vector):
|
||||
return np.array(vector) / magnitude(vector)
|
||||
class ApproachManeuver(Maneuver):
|
||||
|
||||
def __init__(self, conn, vessel_id, reference_frame):
|
||||
super().__init__(conn, vessel_id)
|
||||
self.reference_frame = reference_frame
|
||||
|
||||
def start(self):
|
||||
sc = self.conn.space_center
|
||||
vessel = sc.active_vessel
|
||||
target = sc.target_vessel
|
||||
|
||||
kill_relative_velocity(self.conn, vessel, self.reference_frame)
|
||||
|
||||
self.conn.drawing.add_direction((0, 1, 0), self.reference_frame)
|
||||
|
||||
vessel.control.rcs = False
|
||||
|
||||
pv = vessel.position(self.reference_frame)
|
||||
|
||||
safety_radius = get_safety_radius(vessel) + get_safety_radius(target) + SAFETY_RADIUS_MARGIN
|
||||
|
||||
# if under and inside safety cylinder's circle
|
||||
if pv[1] < safety_radius and pow(pv[0], 2) + pow(pv[2], 2) <= pow(safety_radius, 2):
|
||||
print("We're under the target and inside the safety cylinder, getting out")
|
||||
# get out of the cylinder
|
||||
plane_move_vector = unitary(tuple((pv[0], pv[2]))) * (safety_radius - magnitude(tuple((pv[0], pv[2]))))
|
||||
|
||||
pv = vessel.position(self.reference_frame)
|
||||
move_vector = np.array((plane_move_vector[0], 0, plane_move_vector[1]))
|
||||
move_to_waypoint(self.conn, vessel, pv + move_vector, self.reference_frame)
|
||||
|
||||
print("We're outside of the safety cylinder, setting vertical distance")
|
||||
pv = vessel.position(self.reference_frame)
|
||||
move_to_waypoint(self.conn, vessel, (pv[0], safety_radius, pv[2]), self.reference_frame)
|
||||
|
||||
# should be above and outside => get inside
|
||||
print("We're at the right vertical distance to the target, setting horizontal position")
|
||||
move_to_waypoint(self.conn, vessel, (0, safety_radius, 0), self.reference_frame)
|
||||
|
||||
point_toward_direction(vessel, - np.array(vessel.position(self.reference_frame)), self.reference_frame)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def get_safety_radius(vessel):
|
||||
@@ -106,8 +148,6 @@ def move_to_waypoint(conn, vessel, waypoint, reference_frame):
|
||||
thrust(vessel, -velocity, reference_frame)
|
||||
print("Ship decelerated")
|
||||
|
||||
#do positition correction
|
||||
|
||||
sa.autopilot_mode = mj.SmartASSAutopilotMode.off
|
||||
sa.update(True)
|
||||
|
||||
@@ -118,6 +158,7 @@ def move_to_waypoint(conn, vessel, waypoint, reference_frame):
|
||||
SAFETY_RADIUS_MARGIN = 10
|
||||
|
||||
|
||||
# DEPRECATED
|
||||
def maneuver_to_approach(conn, reference_frame):
|
||||
print("Handling approach")
|
||||
sc = conn.space_center
|
||||
@@ -158,6 +199,7 @@ def maneuver_to_approach(conn, reference_frame):
|
||||
TARGET_VELOCITY = 2
|
||||
|
||||
|
||||
# DEPRECATED
|
||||
def move_with_vector(conn, vessel, vector, reference_frame):
|
||||
mj = conn.mech_jeb
|
||||
sa = mj.smart_ass
|
||||
|
||||
@@ -1,6 +1,42 @@
|
||||
from time import sleep
|
||||
|
||||
from utils import kill_relative_velocity, correct_course, magnitude
|
||||
from .utils import kill_relative_velocity, correct_course, magnitude
|
||||
|
||||
from . import Maneuver
|
||||
|
||||
|
||||
class DockingManeuver(Maneuver):
|
||||
def __init__(self, conn, vessel_id, docking_part, reference_frame):
|
||||
super().__init__(conn, vessel_id)
|
||||
self.docking_part = docking_part
|
||||
self.reference_frame = reference_frame
|
||||
|
||||
def start(self):
|
||||
vessel = self.conn.space_center.active_vessel
|
||||
self.conn.drawing.add_direction((0, 1, 0), self.reference_frame)
|
||||
self.conn.drawing.add_direction((1, 0, 0), self.reference_frame)
|
||||
vessel.parts.controlling = self.docking_part
|
||||
|
||||
kill_relative_velocity(self.conn, vessel, self.reference_frame)
|
||||
set_attitude_and_roll(self.conn, vessel, self.reference_frame)
|
||||
align_horizontally(self.conn, vessel, self.reference_frame)
|
||||
|
||||
print("Starting docking procedure")
|
||||
vessel.control.set_action_group(0, True)
|
||||
rcs_push(vessel, {"y": 1}, .5)
|
||||
|
||||
vessel.control.rcs = True
|
||||
try:
|
||||
while vessel.position(self.reference_frame)[1] > 0:
|
||||
print(vessel.position(self.reference_frame)[1])
|
||||
correct_course(self.conn, vessel, (0, 0, 0), self.reference_frame)
|
||||
sleep(1)
|
||||
except ValueError as e:
|
||||
vessel = self.conn.space_center.active_vessel
|
||||
finally:
|
||||
vessel.control.rcs = False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def set_attitude_and_roll(conn, vessel, reference_frame):
|
||||
@@ -127,30 +163,3 @@ def align_horizontally(conn, vessel, reference_frame):
|
||||
|
||||
kill_rcs_velocity(vessel, reference_frame)
|
||||
print("Vertical alignment done!")
|
||||
|
||||
|
||||
def dock_ship(conn, vessel, docking_part, reference_frame):
|
||||
conn.drawing.add_direction((0, 1, 0), reference_frame)
|
||||
conn.drawing.add_direction((1, 0, 0), reference_frame)
|
||||
vessel.parts.controlling = docking_part
|
||||
|
||||
kill_relative_velocity(conn, vessel, reference_frame)
|
||||
|
||||
set_attitude_and_roll(conn, vessel, reference_frame)
|
||||
|
||||
align_horizontally(conn, vessel, reference_frame)
|
||||
|
||||
print("Starting docking procedure")
|
||||
vessel.control.set_action_group(0, True)
|
||||
rcs_push(vessel, {"y": 1}, .5)
|
||||
|
||||
vessel.control.rcs = True
|
||||
try:
|
||||
while vessel.position(reference_frame)[1] > 0:
|
||||
print(vessel.position(reference_frame)[1])
|
||||
correct_course(conn, vessel, (0, 0, 0), reference_frame)
|
||||
sleep(1)
|
||||
except ValueError as e:
|
||||
vessel = conn.space_center.active_vessel
|
||||
finally:
|
||||
vessel.control.rcs = False
|
||||
|
||||
@@ -1,103 +1,87 @@
|
||||
import numpy as np
|
||||
|
||||
from utils import execute_node, magnitude
|
||||
from .utils import magnitude
|
||||
|
||||
from maneuver_scheduler import ManeuverScheduler
|
||||
|
||||
from . import MechJebManeuver
|
||||
|
||||
|
||||
def align_orbit_planes(conn):
|
||||
print("Aligning planes")
|
||||
mj = conn.mech_jeb
|
||||
mp = mj.maneuver_planner
|
||||
oi = mp.operation_inclination
|
||||
oi.time_selector.time_reference = mj.TimeReference.eq_nearest_ad
|
||||
nodes = oi.make_nodes()
|
||||
class RendezvousManeuver(MechJebManeuver):
|
||||
def start(self):
|
||||
self.plan_next_maneuver()
|
||||
|
||||
# kac = conn.kerbal_alarm_clock
|
||||
# kac.create_alarm(
|
||||
# kac.AlarmType.maneuver,
|
||||
# "{}'s Orbital transfer".format(v.name),
|
||||
# nodes[0].ut
|
||||
# )
|
||||
def plan_next_maneuver(self):
|
||||
sc = self.conn.space_center
|
||||
vessel = sc.active_vessel
|
||||
target = sc.target_vessel
|
||||
|
||||
execute_node(conn)
|
||||
if vessel.orbit.distance_at_closest_approach(target.orbit) > 1000:
|
||||
if vessel.orbit.relative_inclination(target.orbit) > 0.0001:
|
||||
AlignOrbitPlaneWithTarget(self.conn, vessel).prepare_maneuver()
|
||||
|
||||
print("Planes aligned!")
|
||||
elif vessel.orbit.distance_at_closest_approach(target.orbit) > 10000:
|
||||
InterceptTargetOrbit(self.conn, vessel).prepare_maneuver()
|
||||
|
||||
else:
|
||||
TuneClosestApproach(self.conn, vessel).prepare_maneuver()
|
||||
return False
|
||||
|
||||
elif vessel.orbit.distance_at_closest_approach(target.orbit) <= 1000 < magnitude(
|
||||
np.array(vessel.position(vessel.reference_frame)) - np.array(target.position(vessel.reference_frame))):
|
||||
MatchVelocityWithTarget(self.conn, vessel).prepare_maneuver()
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def intercepting_target_orbit(conn):
|
||||
print("Intercepting target orbit")
|
||||
sc = conn.space_center
|
||||
v = sc.active_vessel
|
||||
mj = conn.mech_jeb
|
||||
mp = mj.maneuver_planner
|
||||
ot = mp.operation_transfer
|
||||
ot.time_selector.time_reference = mj.TimeReference.computed
|
||||
nodes = ot.make_nodes()
|
||||
nodes[0].ut = nodes[0].ut + 0.1
|
||||
class AlignOrbitPlaneWithTarget(RendezvousManeuver):
|
||||
name = "Align orbit plane with target's"
|
||||
|
||||
# kac = conn.kerbal_alarm_clock
|
||||
# kac.create_alarm(
|
||||
# kac.AlarmType.maneuver,
|
||||
# "{}'s Orbital transfer".format(v.name),
|
||||
# nodes[0].ut
|
||||
# )
|
||||
def prepare_maneuver(self):
|
||||
oi = self.maneuver_planner.operation_inclination
|
||||
oi.time_selector.time_reference = self.mech_jeb.TimeReference.eq_nearest_ad
|
||||
nodes = oi.make_nodes()
|
||||
|
||||
execute_node(conn)
|
||||
node = nodes[0]
|
||||
|
||||
print("Target orbit intercepted!")
|
||||
ManeuverScheduler.book_timeslot_for_node(self.vessel, node, self)
|
||||
|
||||
|
||||
def tune_closest_approach(conn):
|
||||
print("Tuning closest approach")
|
||||
sc = conn.space_center
|
||||
v = sc.active_vessel
|
||||
mj = conn.mech_jeb
|
||||
mp = mj.maneuver_planner
|
||||
occ = mp.operation_course_correction
|
||||
nodes = occ.make_nodes()
|
||||
class InterceptTargetOrbit(RendezvousManeuver):
|
||||
name = "Intercept target's orbit"
|
||||
|
||||
# kac = conn.kerbal_alarm_clock
|
||||
# kac.create_alarm(
|
||||
# kac.AlarmType.maneuver,
|
||||
# "{}'s Orbital transfer".format(v.name),
|
||||
# nodes[0].ut
|
||||
# )
|
||||
def prepare_maneuver(self):
|
||||
ot = self.maneuver_planner.operation_transfer
|
||||
ot.time_selector.time_reference = self.mech_jeb.TimeReference.computed
|
||||
nodes = ot.make_nodes()
|
||||
|
||||
execute_node(conn)
|
||||
node = nodes[0]
|
||||
node.ut = node.ut + 1
|
||||
|
||||
print("Closest approach tuned!")
|
||||
ManeuverScheduler.book_timeslot_for_node(self.vessel, node, self)
|
||||
|
||||
|
||||
def match_velocities(conn):
|
||||
print("Matching velocities")
|
||||
sc = conn.space_center
|
||||
v = sc.active_vessel
|
||||
mj = conn.mech_jeb
|
||||
mp = mj.maneuver_planner
|
||||
okrv = mp.operation_kill_rel_vel
|
||||
nodes = okrv.make_nodes()
|
||||
class TuneClosestApproach(RendezvousManeuver):
|
||||
name = "Tune closest approach with target"
|
||||
|
||||
# kac = conn.kerbal_alarm_clock
|
||||
# kac.create_alarm(
|
||||
# kac.AlarmType.maneuver,
|
||||
# "{}'s Orbital transfer".format(v.name),
|
||||
# nodes[0].ut
|
||||
# )
|
||||
def prepare_maneuver(self):
|
||||
occ = self.maneuver_planner.operation_course_correction
|
||||
nodes = occ.make_nodes()
|
||||
|
||||
execute_node(conn)
|
||||
node = nodes[0]
|
||||
|
||||
print("Velocities matched!")
|
||||
ManeuverScheduler.book_timeslot_for_node(self.vessel, node, self)
|
||||
|
||||
|
||||
def maneuver_to_rendezvous(conn, vessel, target):
|
||||
if vessel.orbit.distance_at_closest_approach(target.orbit) > 1000:
|
||||
if vessel.orbit.relative_inclination(target.orbit) > 0.0001:
|
||||
align_orbit_planes(conn)
|
||||
class MatchVelocityWithTarget(RendezvousManeuver):
|
||||
name = "Math velocity with target's"
|
||||
duration = 10 * 60
|
||||
|
||||
if vessel.orbit.distance_at_closest_approach(target.orbit) > 10000:
|
||||
intercepting_target_orbit(conn)
|
||||
def prepare_maneuver(self):
|
||||
okrv = self.maneuver_planner.operation_kill_rel_vel
|
||||
nodes = okrv.make_nodes()
|
||||
|
||||
tune_closest_approach(conn)
|
||||
node = nodes[0]
|
||||
|
||||
if vessel.orbit.distance_at_closest_approach(target.orbit) <= 1000 < magnitude(
|
||||
np.array(vessel.position(vessel.reference_frame)) - np.array(target.position(vessel.reference_frame))):
|
||||
match_velocities(conn)
|
||||
ManeuverScheduler.book_timeslot_for_node(self.vessel, node, self, duration=self.duration)
|
||||
|
||||
@@ -3,21 +3,18 @@ from time import time, sleep
|
||||
import numpy as np
|
||||
|
||||
|
||||
def execute_node(conn):
|
||||
ne = conn.mech_jeb.node_executor
|
||||
ne.execute_all_nodes()
|
||||
|
||||
with conn.stream(getattr, ne, "enabled") as enabled:
|
||||
enabled.rate = 1
|
||||
with enabled.condition:
|
||||
while enabled():
|
||||
enabled.wait()
|
||||
|
||||
|
||||
def magnitude(vector):
|
||||
return np.linalg.norm(vector)
|
||||
|
||||
|
||||
def node_thrust_time(vessel, node):
|
||||
return (node.delta_v * vessel.mass) / vessel.available_thrust
|
||||
|
||||
|
||||
def unitary(vector):
|
||||
return np.array(vector) / magnitude(vector)
|
||||
|
||||
|
||||
THROTTLE = .1
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user