Source code for ssapy_toolkit.Accelerations.accel_circularize

# ssapy_toolkit/Accelerations/accel_circularize.py

import numpy as np
from ..constants import EARTH_MU, EARTH_RADIUS  # [56]

_orbit_achieved = False  # global variable to track circularization


[docs] def reset_orbit_status(): """Reset the internal latch so circularization thrust can be used again.""" global _orbit_achieved _orbit_achieved = False
[docs] def accel_to_circular(r, v, t=None, *, thrust, tol=10.0, min_altitude=100e3): """ Acceleration command that steers (r, v) toward a circular orbit at radius |r|. Designed to be passed into leapfrog(..., accels=[...]) where leapfrog may call accelerations as f(r,v,t) (t is accepted but not required here). Parameters ---------- r : array_like, shape (3,) Position vector (m). v : array_like, shape (3,) Velocity vector (m/s). t : optional Time (ignored; present for integrator compatibility). thrust : float Magnitude of available acceleration (m/s^2). tol : float, optional Convergence tolerance on ||v_target - v|| (m/s). Default 10. min_altitude : float, optional Minimum altitude above Earth's surface to allow control (m). Default 100 km. Returns ------- a : ndarray, shape (3,) Acceleration command (m/s^2), or zeros if converged/disabled. """ global _orbit_achieved if _orbit_achieved: return np.zeros(3, dtype=float) r = np.asarray(r, dtype=float).reshape(3) v = np.asarray(v, dtype=float).reshape(3) r_norm = np.linalg.norm(r) if r_norm == 0.0 or thrust == 0.0: return np.zeros(3, dtype=float) if r_norm < EARTH_RADIUS + float(min_altitude): return np.zeros(3, dtype=float) # Unit radial direction r_hat = r / r_norm # Tangential velocity component v_r = float(np.dot(v, r_hat)) v_t_vec = v - v_r * r_hat v_t = np.linalg.norm(v_t_vec) if v_t > 0.0: t_hat = v_t_vec / v_t else: # Fallback if velocity is purely radial: pick a consistent tangential direction t_hat = np.cross(np.array([0.0, 0.0, 1.0]), r_hat) n = np.linalg.norm(t_hat) if n == 0.0: return np.zeros(3, dtype=float) t_hat /= n # Circular speed at current radius v_circ = np.sqrt(EARTH_MU / r_norm) # Desired circular velocity vector (purely tangential) v_target = v_circ * t_hat dv = v_target - v dv_norm = np.linalg.norm(dv) if dv_norm <= float(tol) or dv_norm == 0.0: _orbit_achieved = True return np.zeros(3, dtype=float) return float(thrust) * (dv / dv_norm)