def test_parabolic(self): """Shouldn't work since parabolas have infinite a """ a = np.infty ecc = 1 p = kepler.semilatus_rectum(a, ecc) np.testing.assert_allclose(p, 0)
def test_planar_orbit_intersection(): ecc1 = 0.75 p1 = kepler.semilatus_rectum(4.5*constants.earth.radius, ecc1) a2, p2, ecc2 = kepler.perapo2aecc(2 * constants.earth.radius, 6 * constants.earth.radius) dargp = np.deg2rad(35) nu = maneuver.planar_conic_orbit_intersection(p1, p2, ecc1, ecc2, dargp) np.testing.assert_allclose(nu, np.deg2rad(110.342156))
def j2dragpert(inc0, ecc0, n0, ndot2, mu=398600.5, re=6378.137, J2=0.00108263): """Perturbed Kepler Propogator including J2 and drag Inputs: inc0 - initial inclination (radians) ecc0 - initial eccentricity (unitless) n0 - initial mean motion (rad/sec) ndot2 - mean motion rate divided by 2 (rad/sec^2) Outputs: raandot - nodal rate (rad/sec) argdot - argument of periapsis rate (rad/sec) eccdot - eccentricity rate (1/sec) adot - semi major axis rate (km/sec) Globals: None Constants: mu - 398600.5 Earth gravitational parameter in km^3/sec^2 re - 6378.137 Earth radius in km J2 - 0.00108263 J2 perturbation factor Coupling: kepler.semilatus_rectum - compute semilatus rectum Author: C2C Shankar Kulumani USAFA/CS-19 719-333-4741 12 5 2014 - modified to remove global varaibles 17 Jun 2017 - Now in Python for awesomeness 29 Nov 2017 - Include drag effect on a, ecc References: Vallado """ # calculate initial semi major axis and semilatus rectum a0 = (mu / n0**2) ** (1 / 3) p0 = kepler.semilatus_rectum(a0, ecc0) # mean motion with J2 nvec = n0 * (1 + 1.5 * J2 * (re / p0)**2 * np.sqrt(1 - ecc0**2) * (1 - 1.5 * np.sin(inc0)**2)) # eccentricity rate eccdot = (-2 * (1 - ecc0) * 2 * ndot2) / (3 * nvec) # calculate nodal rate raandot = (-1.5 * J2 * (re / p0)**2 * np.cos(inc0)) * nvec # argument of periapsis rate argdot = (1.5 * J2 * (re / p0)**2 * (2 - 2.5 * np.sin(inc0)**2)) * nvec # semi major axis rate adot = - 2 / 3 * a0 / nvec * 2 * ndot2 return (raandot, argdot, eccdot, adot)
def j2dragpert(inc0, ecc0, n0, ndot2, mu=398600.5, re=6378.137, J2=0.00108263): """Perturbed Kepler Propogator including J2 and drag Inputs: inc0 - initial inclination (radians) ecc0 - initial eccentricity (unitless) n0 - initial mean motion (rad/sec) ndot2 - mean motion rate divided by 2 (rad/sec^2) Outputs: raandot - nodal rate (rad/sec) argdot - argument of periapsis rate (rad/sec) eccdot - eccentricity rate (1/sec) adot - semi major axis rate (km/sec) Globals: None Constants: mu - 398600.5 Earth gravitational parameter in km^3/sec^2 re - 6378.137 Earth radius in km J2 - 0.00108263 J2 perturbation factor Coupling: kepler.semilatus_rectum - compute semilatus rectum Author: C2C Shankar Kulumani USAFA/CS-19 719-333-4741 12 5 2014 - modified to remove global varaibles 17 Jun 2017 - Now in Python for awesomeness 29 Nov 2017 - Include drag effect on a, ecc References: Vallado """ # calculate initial semi major axis and semilatus rectum a0 = (mu / n0**2)**(1 / 3) p0 = kepler.semilatus_rectum(a0, ecc0) # mean motion with J2 nvec = n0 * (1 + 1.5 * J2 * (re / p0)**2 * np.sqrt(1 - ecc0**2) * (1 - 1.5 * np.sin(inc0)**2)) # eccentricity rate eccdot = (-2 * (1 - ecc0) * 2 * ndot2) / (3 * nvec) # calculate nodal rate raandot = (-1.5 * J2 * (re / p0)**2 * np.cos(inc0)) * nvec # argument of periapsis rate argdot = (1.5 * J2 * (re / p0)**2 * (2 - 2.5 * np.sin(inc0)**2)) * nvec # semi major axis rate adot = -2 / 3 * a0 / nvec * 2 * ndot2 return (raandot, argdot, eccdot, adot)
def roadster_coe(jd): """Output the COES of the roadster at the given JD """ epoch = 2458190.500000000 ecc = 2.560214125839113E-01 # eccentricy per = 9.860631722474498E-01 * au2km # periapsis inc = 1.078548455272089E+00 * deg2rad # inclination raan = 3.171871226218810E+02 * deg2rad # arg_p = 1.774087594994931E+02 * deg2rad jd_per = 2458153.531206728425 mean_motion = 6.459332187157216E-01 * deg2rad * sec2day mean_anom = 2.387937163002724E+01 * deg2rad E, nu, count = kepler.kepler_eq_E(mean_anom, ecc) nu = 4.031991175737090E+01 * deg2rad sma = 1.325391871387247E+00 * au2km apo = 1.664720570527044E+00 * au2km period = 5.573331570030891E+02 * day2sec # compute some other elements p = kepler.semilatus_rectum(sma, ecc) deltat = (jd - epoch) * day2sec # propogate from epoch to JD and find nu Ef, Mf, nuf = kepler.tof_delta_t(p, ecc, constants.sun.mu, nu, deltat) roadster_coe = planets.COE(p=p, ecc=ecc, inc=inc, raan=raan, argp=arg_p, nu=nuf) # compute the vector in J2000 Ecliptic frame r_ecliptic, v_ecliptic, r_pqw, v_pqw = kepler.coe2rv( p, ecc, inc, raan, arg_p, nuf, constants.sun.mu) return roadster_coe, r_ecliptic, v_ecliptic
def test_hyperbolic(self): a = -8000 ecc = 1.5 p = kepler.semilatus_rectum(a, ecc) np.testing.assert_allclose(p, a * (1 - ecc**2))
def test_elliptical(self): a = 8000 ecc = 0.5 p = kepler.semilatus_rectum(a, ecc) np.testing.assert_allclose(p, a * (1 - ecc**2))
def test_circular(self): a = 8000 ecc = 0 p = kepler.semilatus_rectum(a, ecc) np.testing.assert_allclose(p, a)
"""Problem 3 HW4 2017 """ from astro import kepler, constants import numpy as np import matplotlib.pyplot as plt # define orbital elements a = 3 * constants.earth.radius ecc = 0.4 p = kepler.semilatus_rectum(a, ecc) inc = np.deg2rad(28.5) raan = np.deg2rad(45) argp = np.deg2rad(90) nu = np.deg2rad(235) mu = constants.earth.mu re = constants.earth.radius output = kepler.orbit_el(p, ecc, inc, raan, argp, nu, mu, True) # generate a plot of orbit plane # plot the orbit state_eci, state_pqw, state_lvlh, state_sat_eci, state_sat_pqw, state_sat_lvlh = kepler.conic_orbit( p, ecc, inc, raan, argp, nu, nu) fig, ax = plt.subplots() ax.plot(state_pqw[:, 0], state_pqw[:, 1]) ax.plot(re * np.cos(np.linspace(0, 2 * np.pi)), re * np.sin(np.linspace(0, 2 * np.pi))) ax.plot([0, state_sat_pqw[0]], [0, state_sat_pqw[1]], 'b-', linewidth=3) ax.plot(state_sat_pqw[0], state_sat_pqw[1], 'b.', markersize=20)
""" from astro import constants, kepler, maneuver import numpy as np import matplotlib.pyplot as plt import pdb ra = 7000 rb = 14000 mu = constants.earth.mu # define hyperbolic arrival orbit va1 = 12 e_h = va1**2 / 2 - mu / ra a_h = -mu / e_h / 2 ecc_h = ra / np.absolute(a_h) + 1 p_h = kepler.semilatus_rectum(np.absolute(a_h), ecc_h) nu_h = 0 # hohmann transfer from hyperbolic orbit to circular orbit rb a_t, p_t, ecc_t = kepler.perapo2aecc(ra, rb) vt1 = maneuver.vel_mag(ra, a_t, mu) dva1, _, toft, phaset = maneuver.hohmann(ra, rb, ecc_h, 0, 0, 0, mu) # final orbit mean motion n2 = np.sqrt(mu / rb**3) angle = n2 * toft p2 = 2 * np.pi * np.sqrt(rb**3 / mu) phasing_period = p2 - toft # design of phasing orbit
def tle_update(self, jd_span, mu=398600.5): """Update the state of satellite given a JD time span This procedure uses the method of general perturbations to update classical elements from epoch to a future time for inclined elliptical orbits. It includes the effects due to first order secular rates (second order for mean motion) caused by drag and J2. Author: C2C Shankar Kulumani USAFA/CS-19 719-333-4741 Inputs: deltat - elapsed time since epoch (sec) n0 - mean motion at epoch (rad/sec) ndot2 - mean motion rate divided by 2 (rad/sec^2) ecc0 - eccentricity at epoch (unitless) eccdot - eccentricity rate (1/sec) raan0 - RAAN at epoch (rad) raandot - RAAN rate (rad/sec) argp0 - argument of periapsis at epoch (rad) argdot - argument of periapsis rate (rad/sec) mean0 - mean anomaly at epoch Outputs: n - mean motion at epoch + deltat (rad/sec) ecc - eccentricity at epoch + deltat (unitless) raan - RAAN at epoch + deltat (rad) argp - argument of periapsis at epoch + deltat (rad) nu - true anomaly at epoch + deltat (rad) Globals: None Constants: None Coupling: newton.m References: Astro 321 PREDICT LSN 24-25 """ deltat = (jd_span - self.epoch_jd) * day2sec # epoch orbit parameters n0 = self.n0 ecc0 = self.ecc0 ndot2 = self.ndot2 nddot6 = self.nddot6 raan0 = self.raan0 argp0 = self.argp0 mean0 = self.mean0 inc0 = self.inc0 adot = self.adot eccdot = self.eccdot raandot = self.raandot argpdot = self.argpdot _, nu0, _ = kepler.kepler_eq_E(mean0, ecc0) a0 = kepler.n2a(n0, mu) M0, E0 = kepler.nu2anom(nu0, ecc0) # propogated elements a1 = a0 + adot * deltat # either use this or compute a1 from n1 instead ecc1 = ecc0 + eccdot * deltat raan1 = raan0 + raandot * deltat argp1 = argp0 + argpdot * deltat inc1 = inc0 * np.ones_like(ecc1) n1 = n0 + ndot2 * 2 * deltat # a1 = kepler.n2a(n1, mu) p1 = kepler.semilatus_rectum(a1, ecc1) M1 = M0 + n0 * deltat+ ndot2 *deltat**2 + nddot6 *deltat**3 M1 = attitude.normalize(M1, 0, 2 * np.pi) E1, nu1, _ = kepler.kepler_eq_E(M1, ecc1) # convert to vectors r_eci, v_eci, _, _ = kepler.coe2rv(p1, ecc1, inc1, raan1, argp1, nu1, mu) # save all of the variables to the object self.jd_span = jd_span self.coe = COE(n=n1, ecc=ecc1, raan=raan1, argp=argp1, mean=M1, E=E1, nu=nu1, a=a1, p=p1, inc=inc1) self.r_eci = r_eci self.v_eci = v_eci return 0
import numpy as np from astro import constants, maneuver, kepler, transform import matplotlib.pyplot as plt from kinematics import attitude import pdb mu = constants.earth.mu re2km = constants.re2km deg2rad = constants.deg2rad rad2deg = constants.rad2deg # initial orbit ecc_i = .4 a_i = 6 * re2km nu_i = 90 * deg2rad p_i = kepler.semilatus_rectum(a_i, ecc_i) inc_i = 0 raan_i = 0 arg_p_i = 0 mag_dv = 0.75 alpha = -60 * deg2rad # calculate orbital elements print('Initial Orbit') kepler.orbit_el(p_i, ecc_i, inc_i, raan_i, arg_p_i, nu_i, mu, 'True') _, _, rpqw_i, vpqw_i = kepler.coe2rv(p_i, ecc_i, inc_i, raan_i, arg_p_i, nu_i, mu) fpa_i = kepler.fpa_solve(nu_i, ecc_i) # convert delta v and alpha into various reference frames
mu = constants.sun.mu a_e = constants.earth.orbit_sma a_n = constants.neptune.orbit_sma km2au = constants.km2au ecc_e = 0 ecc_n = 0 # circular earth velocity v_1 = np.sqrt(mu / a_e) v_2 = np.sqrt(mu / a_n) # transfer orbit a_t = .5 * (a_e + a_n) ecc_t = a_n / a_t - 1 p_t = kepler.semilatus_rectum(a_t, ecc_t) # velocity of transfer orbit at initial and final orbit sme_t = -mu / (2 * a_t) vt_1 = np.sqrt(2 * (sme_t + mu / a_e)) vt_2 = np.sqrt(2 * (sme_t + mu / a_n)) (dv_a, dv_b, tof, phase_angle) = maneuver.hohmann( a_e, a_n, ecc_e, ecc_n, 0, np.pi, mu) print('Initial Orbit Velocity : {} km/sec'.format(v_1)) print('Final Orbit Velocity : {} km/sec'.format(v_2)) print('Transfer SMA : {} km Eccentricity : {}'.format(a_t, ecc_t)) print('Transfer Periapsis velocity : {} km/sec'.format(vt_1)) print('Transfer Apoapsis velocity : {} km/sec'.format(vt_2)) print('Delta V1 : {} km/sec'.format(dv_a))
def tle_update(self, jd_span, mu=398600.5): """Update the state of satellite given a JD time span This procedure uses the method of general perturbations to update classical elements from epoch to a future time for inclined elliptical orbits. It includes the effects due to first order secular rates (second order for mean motion) caused by drag and J2. Author: C2C Shankar Kulumani USAFA/CS-19 719-333-4741 Inputs: deltat - elapsed time since epoch (sec) n0 - mean motion at epoch (rad/sec) ndot2 - mean motion rate divided by 2 (rad/sec^2) ecc0 - eccentricity at epoch (unitless) eccdot - eccentricity rate (1/sec) raan0 - RAAN at epoch (rad) raandot - RAAN rate (rad/sec) argp0 - argument of periapsis at epoch (rad) argdot - argument of periapsis rate (rad/sec) mean0 - mean anomaly at epoch Outputs: n - mean motion at epoch + deltat (rad/sec) ecc - eccentricity at epoch + deltat (unitless) raan - RAAN at epoch + deltat (rad) argp - argument of periapsis at epoch + deltat (rad) nu - true anomaly at epoch + deltat (rad) Globals: None Constants: None Coupling: newton.m References: Astro 321 PREDICT LSN 24-25 """ deltat = (jd_span - self.epoch_jd) * day2sec # epoch orbit parameters n0 = self.n0 ecc0 = self.ecc0 ndot2 = self.ndot2 nddot6 = self.nddot6 raan0 = self.raan0 argp0 = self.argp0 mean0 = self.mean0 inc0 = self.inc0 adot = self.adot eccdot = self.eccdot raandot = self.raandot argpdot = self.argpdot _, nu0, _ = kepler.kepler_eq_E(mean0, ecc0) a0 = kepler.n2a(n0, mu) M0, E0 = kepler.nu2anom(nu0, ecc0) # propogated elements a1 = a0 + adot * deltat # either use this or compute a1 from n1 instead ecc1 = ecc0 + eccdot * deltat raan1 = raan0 + raandot * deltat argp1 = argp0 + argpdot * deltat inc1 = inc0 * np.ones_like(ecc1) n1 = n0 + ndot2 * 2 * deltat # a1 = kepler.n2a(n1, mu) p1 = kepler.semilatus_rectum(a1, ecc1) M1 = M0 + n0 * deltat + ndot2 * deltat**2 + nddot6 * deltat**3 M1 = attitude.normalize(M1, 0, 2 * np.pi) E1, nu1, _ = kepler.kepler_eq_E(M1, ecc1) # convert to vectors r_eci, v_eci, _, _ = kepler.coe2rv(p1, ecc1, inc1, raan1, argp1, nu1, mu) # save all of the variables to the object self.jd_span = jd_span self.coe = COE(n=n1, ecc=ecc1, raan=raan1, argp=argp1, mean=M1, E=E1, nu=nu1, a=a1, p=p1, inc=inc1) self.r_eci = r_eci self.v_eci = v_eci return 0