AstroScale GNC home-assignment submission by Yuval Grimberg.
This repository contains a reproducible orbital mechanics and rendezvous-control study:
- Q1: two-body orbit propagation with an intentional Earth-impact trajectory and a corrected collision-avoidance trajectory.
- Q2: Clohessy-Wiltshire rendezvous control with cached LQI, deterministic noise support, custom initial conditions, and an experimental Kalman-estimated constrained MPC comparison.
- Streamlit viewer: live Q1/Q2 simulations, browser-native animations, custom Q2 initial conditions, and controller notes.
- Preserves the submitted assignment structure:
Q1-Yuval_Grimberg.py,Q2-Yuval_Grimberg.py, and the original report PDF. - Runs without Bayesian optimization by default by using the cached report Q matrix.
- Terminates Satellite B at Earth impact instead of propagating through Earth.
- Adds a constrained MPC comparison that respects the same
+/- 1 Nthrust limits used by the LQI simulation. - Includes a Streamlit app for visual review and parameter exploration.
- Includes LaTeX/Tectonic-rendered controller equations under
docs/equations/.
| Q1 summary | Q2 cached LQI nominal |
|---|---|
![]() |
![]() |
| Q2 animation | LQI vs Kalman MPC |
|---|---|
![]() |
![]() |
Python >= 3.9 is required.
python -m pip install -r requirements.txtRun the full validation:
python validate_submission.pyLaunch the live app:
streamlit run streamlit_app.pyThen open:
http://localhost:8501
README.md GitHub-facing runbook
LICENSE MIT license
requirements.txt Python dependencies
Q1-Yuval_Grimberg.py Q1 two-body orbit propagator
Q2-Yuval_Grimberg.py Q2 CW LQI / MPC rendezvous simulation
propagator.py Compatibility wrapper for Q1
rendezvous.py Compatibility wrapper for Q2
streamlit_app.py Live Q1/Q2 browser viewer
validate_submission.py Lightweight reproducibility gate
docs/README.md Documentation index
docs/assets/ README images and GIFs
docs/control/ LQI vs Kalman-MPC notes
docs/equations/ LaTeX equation source and compiled PDF
docs/report/ Submitted report PDF
docs/submission/ Archive, live-run, and report-fix notes
outputs/ Generated plots, GIFs, and metrics
The root stays focused on runnable entry points; supporting notes and report artifacts live under docs/.
Satellite A is a circular 700 km altitude reference orbit. Satellite B uses eccentricity e = 0.999 with the same semi-major axis and is intentionally an Earth-impact case. Satellite C is the corrected avoidance trajectory with the same apogee as B and perigee equal to A's orbital radius.
The two-body model is:
Satellite B is stopped by an event function:
with terminal downward crossing. The script reports impact time, impact radius, impact position, minimum radii, and the delta-V needed to move from B's apogee speed to C's apogee speed.
Run Q1:
python Q1-Yuval_Grimberg.py --save
python Q1-Yuval_Grimberg.py --animate --save
python Q1-Yuval_Grimberg.py --smoke --saveOutputs:
outputs/q1/metrics.json
outputs/q1/q1_summary.png
outputs/q1/q1_animation.gif
Q2 uses the Clohessy-Wiltshire linearized relative dynamics around the 700 km circular reference orbit:
The cached LQI baseline solves the continuous Riccati problem on the augmented state:
The raw LQI command is saturated to the actuator limit:
Run the cached controller:
python Q2-Yuval_Grimberg.py --save
python Q2-Yuval_Grimberg.py --smoke --save
python Q2-Yuval_Grimberg.py --t-final 60000 --save
python Q2-Yuval_Grimberg.py --animate --saveUse deterministic measurement noise:
python Q2-Yuval_Grimberg.py --noise --save --seed 1Run a custom initial condition in LVLH coordinates [x y z vx vy vz], with meters and meters/second:
python Q2-Yuval_Grimberg.py --initial-condition 120 -80 40 0.02 -0.03 0.01 --scenario-name "Custom IC" --saveThe experimental MPC comparison uses the same CW model but discretizes it:
and solves a bounded finite-horizon problem:
With noise enabled, MPC receives a Kalman-filter state estimate rather than the raw noisy measurement:
Run the comparison:
python Q2-Yuval_Grimberg.py --smoke --noise --compare-mpc --saveRun the optional profile selector using the mission-oriented right-cost score:
python Q2-Yuval_Grimberg.py --t-final 300 --dt 10 --noise --compare-mpc --optimize-mpc --no-save --mpc-dt 60 --mpc-horizon 6The right-cost score is:
Lower is better. It rewards small final miss distance, low closing speed, lower effort, less saturation, and faster capture.
Saved comparison metrics:
outputs/q2/mpc_comparison_metrics.json
The core Q2 equations are also maintained as LaTeX and compiled with Tectonic:
docs/equations/q2_controller_equations.tex
docs/equations/build/q2_controller_equations.pdf
Preview:
To regenerate with a local Tectonic install:
tectonic --outdir docs/equations/build docs/equations/q2_controller_equations.texThe Streamlit app is the easiest way to inspect behavior interactively:
- Q1 ECI animation and LVLH paths.
- Q2 cached LQI animation and plots.
- Q2 custom initial conditions.
- Cached LQI vs Kalman MPC comparison.
- Controller notes and README in-app.
streamlit run streamlit_app.pyoutputs/q1/metrics.json
outputs/q1/q1_summary.png
outputs/q1/q1_animation.gif
outputs/q2/metrics.json
outputs/q2/mpc_comparison_metrics.json
outputs/q2/*_distance.png
outputs/q2/*_lvlh_trajectory.png
outputs/q2/*_states_controls.png
outputs/q2/1_nominal_scenario_animation.gif
- Q1 uses a two-body Earth model only: no drag, perturbations, or non-spherical gravity.
- Satellite B is intentionally an impact trajectory.
- Q2 uses linearized CW dynamics around the 700 km circular reference orbit.
- Thrust saturation is
+/- 1 Nper axis. - The cached LQI controller remains the default submission controller.
- The Kalman-MPC controller is an experimental comparison path, not a flight-ready controller.
- A production-quality controller would need sensor geometry, actuator dynamics, keep-out constraints, collision constraints, and Monte Carlo validation.





