Spaces:
Sleeping
Sleeping
File size: 6,579 Bytes
5dce9ae |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
import streamlit as st
import numpy as np
import matplotlib.pyplot as plt
# ===============================
# Streamlit Interface Setup
# ===============================
st.title("Spin Launch & Orbital Attachment Simulation")
st.markdown(
"""
This simulation demonstrates a two‑phase launch:
1. **Spin‑Launch Phase:** A payload is accelerated from an elevated platform.
2. **Orbital Phase:** At a chosen altitude, the payload “docks” with a human‑rated upper stage by
instantly setting its velocity to that of a circular orbit.
Adjust the parameters in the sidebar and click "Run Simulation" to see the result.
"""
)
# Sidebar parameters for simulation
st.sidebar.header("Simulation Parameters")
# Time and integration parameters:
dt = st.sidebar.number_input("Time Step (s)", min_value=0.01, max_value=1.0, value=0.1, step=0.01)
t_max = st.sidebar.number_input("Total Simulation Time (s)", min_value=100, max_value=5000, value=1000, step=100)
# Launch conditions:
initial_altitude_km = st.sidebar.number_input("Initial Altitude (km)", min_value=1, max_value=100, value=50, step=1)
initial_velocity = st.sidebar.number_input("Initial Velocity (m/s)", min_value=100, max_value=5000, value=1200, step=100)
# Docking/Orbital attachment altitude:
docking_altitude_km = st.sidebar.number_input("Docking Altitude (km)", min_value=1, max_value=500, value=100, step=1)
# Button to run simulation
run_sim = st.sidebar.button("Run Simulation")
if run_sim:
# ===============================
# Physical Constants and Conversions
# ===============================
mu = 3.986e14 # Earth's gravitational parameter, m^3/s^2
R_E = 6.371e6 # Earth's radius, m
# Convert altitude values from km to m:
initial_altitude = initial_altitude_km * 1000.0 # initial altitude above Earth's surface (m)
docking_altitude = docking_altitude_km * 1000.0 # docking altitude above Earth's surface (m)
r_dock = R_E + docking_altitude # docking radius from Earth's center (m)
# ===============================
# Initial Conditions for the Simulation
# ===============================
# Starting at a point along the x-axis at a radial distance (Earth's radius + initial altitude)
initial_position = np.array([R_E + initial_altitude, 0.0])
# Initial velocity is chosen to be radial (pointing outward) at the chosen speed.
initial_velocity_vec = np.array([initial_velocity, 0.0])
# ===============================
# Define the Acceleration Function
# ===============================
def acceleration(pos):
"""
Compute acceleration due to Earth's gravity at position pos (in m).
"""
r = np.linalg.norm(pos)
return -mu * pos / r**3
# ===============================
# Run the Simulation Loop
# ===============================
states = [] # Will store tuples of (time, x, y, phase)
phase = 1 # Phase 1: spin-launch, Phase 2: orbital phase after docking
t = 0.0
pos = initial_position.copy()
vel = initial_velocity_vec.copy()
docking_done = False
docking_event_time = None
docking_event_coords = None
while t < t_max:
# --- Check for the Docking Event ---
# When the payload's distance from Earth's center exceeds the docking radius
# and it is still moving outward (positive radial velocity), we trigger the docking.
if phase == 1 and not docking_done and np.linalg.norm(pos) >= r_dock and vel.dot(pos) > 0:
docking_done = True
phase = 2 # Switch to orbital phase
r_current = np.linalg.norm(pos)
# Compute the circular orbital speed at the current radius:
v_circ = np.sqrt(mu / r_current)
# For a prograde orbit, choose a tangential direction (perpendicular to the radial vector):
tangential_dir = np.array([-pos[1], pos[0]]) / r_current
vel = v_circ * tangential_dir # Instantaneously change velocity for orbital insertion
docking_event_time = t
docking_event_coords = pos.copy()
st.write(f"**Docking Event:** t = {t:.1f} s, Altitude = {(r_current - R_E)/1000:.1f} km, Circular Speed = {v_circ:.1f} m/s")
# Record current state: (time, x, y, phase)
states.append((t, pos[0], pos[1], phase))
# --- Propagate the state using simple Euler integration ---
a = acceleration(pos)
pos = pos + vel * dt
vel = vel + a * dt
t += dt
# Convert states to a NumPy array for easier slicing:
states = np.array(states) # columns: time, x, y, phase
# ===============================
# Create the Trajectory Plot with Matplotlib
# ===============================
fig, ax = plt.subplots(figsize=(8, 8))
ax.set_aspect('equal')
ax.set_xlabel("x (km)")
ax.set_ylabel("y (km)")
ax.set_title("Trajectory: Spin Launch and Orbital Attachment")
# Draw Earth as a blue circle (Earth's radius in km)
earth = plt.Circle((0, 0), R_E / 1000, color='blue', alpha=0.3, label="Earth")
ax.add_artist(earth)
# Define plot limits (extend to show orbit, e.g., Earth's radius plus 300 km):
max_extent = (R_E + 300e3) / 1000 # in km
ax.set_xlim(-max_extent, max_extent)
ax.set_ylim(-max_extent, max_extent)
# Separate the recorded states into spin-launch and orbital phases:
spin_phase = states[states[:, 3] == 1]
orbital_phase = states[states[:, 3] == 2]
# Plot the spin-launch phase in red:
if spin_phase.size > 0:
ax.plot(spin_phase[:, 1] / 1000, spin_phase[:, 2] / 1000, 'r-', label="Spin‑Launch Phase")
# Plot the orbital phase in green:
if orbital_phase.size > 0:
ax.plot(orbital_phase[:, 1] / 1000, orbital_phase[:, 2] / 1000, 'g-', label="Orbital Phase")
# Mark the launch start:
ax.plot(initial_position[0] / 1000, initial_position[1] / 1000, 'ko', label="Launch Start")
# Mark the docking event, if it occurred:
if docking_done and docking_event_coords is not None:
ax.plot(docking_event_coords[0] / 1000, docking_event_coords[1] / 1000, 'bo', markersize=8, label="Docking Event")
ax.legend()
st.pyplot(fig)
st.markdown("**Note:** This is a simplified simulation. In a realistic system, the spin‑launch phase, docking maneuver, and orbital insertion would be modeled with far more complexity (including aerodynamic forces, gradual burns, and detailed guidance dynamics).")
|