Skip to content

grimgrimberg/orbital-rendezvous-lqi

Repository files navigation

Orbital Rendezvous LQI / MPC

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.

Q1 orbital impact and avoidance animation

Highlights

  • 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 N thrust 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/.

Visual Results

Q1 summary Q2 cached LQI nominal
Q1 summary Q2 nominal LVLH
Q2 animation LQI vs Kalman MPC
Q2 LQI nominal animation Q2 LQI vs MPC comparison

Quick Start

Python >= 3.9 is required.

python -m pip install -r requirements.txt

Run the full validation:

python validate_submission.py

Launch the live app:

streamlit run streamlit_app.py

Then open:

http://localhost:8501

Repository Layout

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/.

Q1: Earth Impact And Avoidance

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:

$$ \ddot{\mathbf r}=-\frac{\mu}{|\mathbf r|^3}\mathbf r,\qquad \mu=G M_E $$

Satellite B is stopped by an event function:

$$ g(t)=|\mathbf r_B(t)|-R_E $$

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 --save

Outputs:

outputs/q1/metrics.json
outputs/q1/q1_summary.png
outputs/q1/q1_animation.gif

Q2: CW Rendezvous Control

Q2 uses the Clohessy-Wiltshire linearized relative dynamics around the 700 km circular reference orbit:

$$ \begin{aligned} \ddot{x}-3n^2x-2n\dot{y} &= \frac{F_x}{m},\\ \ddot{y}+2n\dot{x} &= \frac{F_y}{m},\\ \ddot{z}+n^2z &= \frac{F_z}{m}, \end{aligned} \qquad n=\sqrt{\frac{\mu}{r_0^3}}. $$

The cached LQI baseline solves the continuous Riccati problem on the augmented state:

$$ \dot{z}_I=Cx,\qquad J=\int_0^\infty \left( \begin{bmatrix}x\z_I\end{bmatrix}^{T} Q_{\mathrm{aug}} \begin{bmatrix}x\z_I\end{bmatrix} +u^TRu \right)dt. $$

The raw LQI command is saturated to the actuator limit:

$$ u=\mathrm{clip}(-K_xx-K_Iz_I,-1,1)\ \mathrm{N}. $$

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 --save

Use deterministic measurement noise:

python Q2-Yuval_Grimberg.py --noise --save --seed 1

Run 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" --save

Cached LQI vs Kalman-Estimated MPC

The experimental MPC comparison uses the same CW model but discretizes it:

$$ x_{k+1}=A_dx_k+B_du_k $$

and solves a bounded finite-horizon problem:

$$ \begin{aligned} \min_{u_0,\ldots,u_{N-1}} \quad & \sum_{k=0}^{N-1}x_k^TQx_k+u_k^TRu_k+x_N^TPx_N\\ \text{s.t.}\quad &x_{k+1}=A_dx_k+B_du_k,\\ &-1\leq u_{x,k},u_{y,k},u_{z,k}\leq 1. \end{aligned} $$

With noise enabled, MPC receives a Kalman-filter state estimate rather than the raw noisy measurement:

$$ \hat{x}^{-}_{k+1}=A_d\hat{x}_k+B_du_k,\qquad \hat{x}_{k+1}=\hat{x}^{-}_{k+1}+K_{k+1}(y_{k+1}-\hat{x}^{-}_{k+1}). $$

Run the comparison:

python Q2-Yuval_Grimberg.py --smoke --noise --compare-mpc --save

Run 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 6

The right-cost score is:

$$ S=d_f+250v_f+0.01J_u+2p_{\mathrm{sat}}+0.05t_{\mathrm{settle}} +\mathbb{1}_{\mathrm{not\ settled}}0.25t_f. $$

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

Equation Sheet

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:

Q2 controller equations

To regenerate with a local Tectonic install:

tectonic --outdir docs/equations/build docs/equations/q2_controller_equations.tex

Streamlit Viewer

The 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.py

Expected Outputs

outputs/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

Assumptions And Limits

  • 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 N per 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.

About

Two-body orbital propagator + Clohessy-Wiltshire LQR/LQI rendezvous controller, with Bayesian-optimized cost weights as the bridge from classical control toward learning-based control.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages