def state_from_orbit(ra, rp, lat, lng, node_dir, vel_dir, gm): inc = lat + (np.pi / 2 - lat) * 0.05 a = (ra + rp) / 2 e = (ra - rp) / (ra + rp) dt = 2 * np.pi * np.sqrt(a**3 / gm) / 6 dt = 616.0809208241426 r = np.array([1, 0, 0]) r = um.vector_axis_angle(r, np.array([0, 0, 1]), lng) r = rp * um.vector_axis_angle(r, np.cross(r, np.array([0, 0, 1])), lat) longitude_of_node = lng + node_dir * abs( um.safe_asin(np.tan(lat) / np.tan(inc))) print('LAN', np.degrees(longitude_of_node)) print('a', a) print('e', e) print('dt', dt) n = np.array([1, 0, 0]) n = um.vector_axis_angle(n, np.array([0, 0, 1]), longitude_of_node) normal = vel_dir * um.normalize(np.cross(n, r)) v = np.sqrt((1 + e) / (1 - e) * gm / a) * um.normalize(np.cross(normal, r)) r, v = um.cse_rv(r, v, -dt, gm) return r, v
def landing_site(d, lat, lng): li = np.array([1, 0, 0]) li = um.vector_axis_angle(li, np.array([0, 0, 1]), lng) li = d * um.vector_axis_angle(li, np.cross(li, np.array([0, 0, 1])), lat) return li
def calculate_landing_normal(self, longitude_of_ascending_node, delta_longitude): ref_axis = -np.array( self.vessel.orbit.reference_plane_normal(self.ref_frame)) ref_direction = np.array( self.vessel.orbit.reference_plane_direction(self.ref_frame)) node_1 = um.vector_axis_angle( ref_direction, ref_axis, longitude_of_ascending_node + delta_longitude) node_2 = um.vector_axis_angle( ref_direction, ref_axis, longitude_of_ascending_node - delta_longitude) velocity_1 = um.vector_axis_angle(np.cross(ref_axis, node_1), node_1, self.inclination) velocity_2 = um.vector_axis_angle(np.cross(ref_axis, node_2), node_2, -self.inclination) normal_1p = np.cross(node_1, velocity_1) normal_1n = np.cross(node_1, -velocity_1) normal_2p = np.cross(node_2, velocity_2) normal_2n = np.cross(node_2, -velocity_2) angle_1p = um.vector_angle(normal_1p, self.normal) angle_1n = um.vector_angle(normal_1n, self.normal) angle_2p = um.vector_angle(normal_2p, self.normal) angle_2n = um.vector_angle(normal_2n, self.normal) angles = [angle_1p, angle_1n, angle_2p, angle_2n] normals = [normal_1p, normal_1n, normal_2p, normal_2n] return normals[angles.index(min(angles))]
def node_vector(inclination, vessel, ref_frame): position = np.array(vessel.position(ref_frame)) latitude = np.radians(vessel.flight().latitude) ref_axis = np.array(vessel.orbit.reference_plane_normal(ref_frame)) node_vector_projection_delta = um.safe_asin( np.tan(latitude) / np.tan(inclination)) longitude_vector = um.vector_exclude(ref_axis, position) return um.vector_axis_angle( longitude_vector, ref_axis, node_vector_projection_delta), um.vector_axis_angle( longitude_vector, ref_axis, np.pi - node_vector_projection_delta)
def p63_ignition_algorithm(mission): t = mission.time_initial tg = mission.guide_time_initial li = mission.landing_position_initial unfcp = -um.normalize(mission.velocity_initial) mission.target = mission.brtg while True: r, v = um.cse_rv(mission.position_initial, mission.velocity_initial, t, mission.gravitational_parameter) lt = um.vector_axis_angle(li, np.array([0, 1, 0]), mission.body_rotation[1] * t) for i in range(3): v += mission.aftrim * unfcp * mission.ttrim afcp, tg, rg, vg = guide(tg, 0, r, v, lt, mission) unfcp = um.normalize(afcp) dt = np.dot( np.array([ rg[0] - mission.brig[0][0], rg[1]**2, rg[2] - mission.brig[0][2], um.magnitude(vg) - um.magnitude(mission.brig[1]) ]), mission.kgt) / (vg[2] + mission.kgt[0] * vg[0]) if abs(dt) > 1: dt *= 1 / abs(dt) t -= dt if abs(dt) < 1 / 128: break t -= (mission.tullage + mission.ttrim) mission.time = t mission.guide_time = tg
def calculate_descent_orbit_time(self): ref_axis = np.array( self.vessel.orbit.reference_plane_normal(self.ref_frame)) normal = um.normalize( np.cross(self.vessel.position(self.ref_frame), self.vessel.velocity(self.ref_frame))) node = np.cross(normal, ref_axis) landing_site = self.moon.surface_position(self.latitude, self.longitude, self.ref_frame) angle_dir = 1 if np.dot(node, landing_site) > 0: angle_dir = -1 node = -node theta = um.safe_asin( np.sin(np.radians(self.latitude)) / np.sin(self.inclination)) target = um.vector_axis_angle(node, normal, theta * angle_dir) target_angle = um.vector_angle(self.vessel.position(self.ref_frame), target) delta_direction = np.dot( normal, np.cross(target, self.vessel.position(self.ref_frame))) if delta_direction > 0: target_angle = 2 * np.pi - target_angle target_time = target_angle * self.vessel.orbit.period / (2 * np.pi) return target_time
def burn_wait(self, angle_burn): vessel_angle = self.vessel.orbit.true_anomaly + self.vessel.orbit.argument_of_periapsis while vessel_angle > 2 * np.pi: vessel_angle -= 2 * np.pi while angle_burn > 2 * np.pi: angle_burn -= 2 * np.pi if angle_burn < vessel_angle: delta_true_anomaly = 2 * np.pi + angle_burn - vessel_angle else: delta_true_anomaly = angle_burn - vessel_angle position = np.array(self.vessel.position(self.ref_frame)) velocity = np.array(self.vessel.velocity(self.ref_frame)) normal = np.cross(position, velocity) attitude = um.normalize(np.cross(normal, position)) attitude = um.vector_axis_angle(attitude, normal, delta_true_anomaly) time_wait = delta_true_anomaly / (2 * np.pi) * self.vessel.orbit.period return attitude, time_wait
def node_delta(self, inclination, longitude_of_ascending_node, vessel, ref_frame): ref_axis = np.array(vessel.orbit.reference_plane_normal(ref_frame)) ref_direction = np.array( vessel.orbit.reference_plane_direction(ref_frame)) node_north, node_south = self.node_vector(inclination, vessel, ref_frame) target_node = um.vector_axis_angle(ref_direction, ref_axis, -longitude_of_ascending_node) node_delta_north = um.vector_angle(node_north, target_node) node_delta_south = um.vector_angle(node_south, target_node) delta_direction_north = np.dot(ref_axis, np.cross(target_node, node_north)) delta_direction_south = np.dot(ref_axis, np.cross(target_node, node_south)) if delta_direction_north < 0: node_delta_north = 2 * np.pi - node_delta_north if delta_direction_south < 0: node_delta_south = 2 * np.pi - node_delta_south return node_delta_north, node_delta_south
def simulate(mission, target, time_limit, delta_time, afcp_limit, guide_time_flag): mission.target = target t0 = mission.time rg_out = [] thrott_out = [] while True: lt = um.vector_axis_angle(mission.landing_position_initial, np.array([0, 1, 0]), mission.body_rotation[1] * mission.time) afcp, mission.guide_time, rg, vg = guide(mission.guide_time, delta_time, mission.position, mission.velocity, lt, mission) maxafcp = mission.maxthrust / mission.mass if afcp_limit == -1: if um.magnitude(afcp) > maxafcp * mission.minthrottle: afcp = um.normalize(afcp) * maxafcp elif not mission.throttflag: mission.throttflag = True mission.throtta = mission.guide_time else: afcp = um.normalize(afcp) * afcp_limit mission.position, mission.velocity = runge_kutta( mission.position, mission.velocity, afcp, delta_time, mission.gravitational_parameter) mission.mass -= um.magnitude( afcp) * mission.mass / mission.vexh * delta_time mission.time += delta_time rg_out.append(rg) thrott_out.append([mission.guide_time, um.magnitude(afcp) / maxafcp]) if guide_time_flag and mission.guide_time > time_limit: break if not guide_time_flag and mission.time - t0 > time_limit: break return rg_out, thrott_out