def test_solar_pressure(): # based on example 12.9 from Howard Curtis solar_system_ephemeris.set('de432s') j_date = 2438400.5 * u.day tof = 600 * u.day sun_r = build_ephem_interpolant(Sun, 365 * u.day, (j_date, j_date + tof), rtol=1e-2) epoch = Time(j_date, format='jd', scale='tdb') drag_force_orbit = [10085.44 * u.km, 0.025422 * u.one, 88.3924 * u.deg, 45.38124 * u.deg, 227.493 * u.deg, 343.4268 * u.deg] initial = Orbit.from_classical(Earth, *drag_force_orbit, epoch=epoch) # in Curtis, the mean distance to Sun is used. In order to validate against it, we have to do the same thing sun_normalized = functools.partial(normalize_to_Curtis, sun_r=sun_r) r, v = cowell(initial, np.linspace(0, (tof).to(u.s).value, 4000), rtol=1e-8, ad=radiation_pressure, R=Earth.R.to(u.km).value, C_R=2.0, A=2e-4, m=100, Wdivc_s=Sun.Wdivc.value, star=sun_normalized) delta_as, delta_eccs, delta_incs, delta_raans, delta_argps, delta_hs = [], [], [], [], [], [] for ri, vi in zip(r, v): orbit_params = rv2coe(Earth.k.to(u.km**3 / u.s**2).value, ri, vi) delta_eccs.append(orbit_params[1] - drag_force_orbit[1].value) delta_incs.append((orbit_params[2] * u.rad).to(u.deg).value - drag_force_orbit[2].value) delta_raans.append((orbit_params[3] * u.rad).to(u.deg).value - drag_force_orbit[3].value) delta_argps.append((orbit_params[4] * u.rad).to(u.deg).value - drag_force_orbit[4].value) # averaging over 5 last values in the way Curtis does for check in solar_pressure_checks: index = int(1.0 * check['t_days'] / tof.to(u.day).value * 4000) delta_ecc, delta_inc, delta_raan, delta_argp = np.mean(delta_eccs[index - 5:index]), \ np.mean(delta_incs[index - 5:index]), np.mean(delta_raans[index - 5:index]), \ np.mean(delta_argps[index - 5:index]) assert_quantity_allclose([delta_ecc, delta_inc, delta_raan, delta_argp], check['deltas_expected'], rtol=1e-1, atol=1e-4)
def test_propagate_with_lunar_third_body(): x = [66666, 0, 0, 0, 2.451, 0] dt = 8600 r = x[0:3] * u.km v = x[3:6] * u.km / u.s epoch = Time(2454283.0, format="jd", scale="tdb") epoch_f = epoch + (dt * u.s) prop_params = PropParams(epoch) prop_params.add_perturbation(Perturbations.Moon, build_lunar_third_body(epoch)) k_moon = Moon.k.to(u.km**3 / u.s**2).value body_moon = build_ephem_interpolant( Moon, lunar_period, (epoch.value * u.day, epoch.value * u.day + 60 * u.day), rtol=1e-2) sat_i = Orbit.from_vectors(Earth, r, v, epoch=epoch) sat_f = sat_i.cov_propagate(dt * u.s, method=cowell, ad=third_body, k_third=k_moon, third_body=body_moon) x_poli = np.concatenate([sat_f.r.value, sat_f.v.value]) x_custom = state_propagate(np.array(x), epoch_f, prop_params) assert np.array_equal(x_custom, x_poli)
def test_3rd_body_Curtis(test_params): # based on example 12.11 from Howard Curtis body = test_params['body'] solar_system_ephemeris.set('de432s') j_date = 2454283.0 * u.day tof = (test_params['tof']).to(u.s).value body_r = build_ephem_interpolant(body, test_params['period'], (j_date, j_date + test_params['tof']), rtol=1e-2) epoch = Time(j_date, format='jd', scale='tdb') initial = Orbit.from_classical(Earth, *test_params['orbit'], epoch=epoch) r, v = cowell(initial, np.linspace(0, tof, 400), rtol=1e-10, ad=third_body, k_third=body.k.to(u.km**3 / u.s**2).value, third_body=body_r) incs, raans, argps = [], [], [] for ri, vi in zip(r, v): angles = Angle(rv2coe(Earth.k.to(u.km**3 / u.s**2).value, ri, vi)[2:5] * u.rad) # inc, raan, argp angles = angles.wrap_at(180 * u.deg) incs.append(angles[0].value) raans.append(angles[1].value) argps.append(angles[2].value) # averaging over 5 last values in the way Curtis does inc_f, raan_f, argp_f = np.mean(incs[-5:]), np.mean(raans[-5:]), np.mean(argps[-5:]) assert_quantity_allclose([(raan_f * u.rad).to(u.deg) - test_params['orbit'][3], (inc_f * u.rad).to(u.deg) - test_params['orbit'][2], (argp_f * u.rad).to(u.deg) - test_params['orbit'][4]], [test_params['raan'], test_params['inc'], test_params['argp']], rtol=1e-1)
def test_propagate_with_srp(): x = [66666, 0, 0, 0, 2.451, 0] dt = 1 * u.day r = x[0:3] * u.km v = x[3:6] * u.km / u.s epoch = Time(2454283.0, format="jd", scale="tdb") epoch_obs = epoch + dt C_R = 1 A = 10 m = 1000 srp = build_srp(C_R, A, m, epoch) prop_params = PropParams(epoch) prop_params.add_perturbation(Perturbations.SRP, srp) body_sun = build_ephem_interpolant( Sun, solar_period, (epoch.value * u.day, epoch.value * u.day + 60 * u.day), rtol=1e-2) sat_i = Orbit.from_vectors(Earth, r, v, epoch=epoch) sat_f = sat_i.cov_propagate(dt, method=cowell, ad=radiation_pressure, R=R, C_R=C_R, A=A, m=m, Wdivc_s=Wdivc_sun.value, star=body_sun) x_poli = np.concatenate([sat_f.r.value, sat_f.v.value]) x_custom = state_propagate(x, epoch_obs, prop_params) assert np.array_equal(x_custom, x_poli)
def test_solar_pressure(): # based on example 12.9 from Howard Curtis with solar_system_ephemeris.set('builtin'): j_date = 2438400.5 * u.day tof = 600 * u.day sun_r = build_ephem_interpolant(Sun, 365 * u.day, (j_date, j_date + tof), rtol=1e-2) epoch = Time(j_date, format='jd', scale='tdb') drag_force_orbit = [10085.44 * u.km, 0.025422 * u.one, 88.3924 * u.deg, 45.38124 * u.deg, 227.493 * u.deg, 343.4268 * u.deg] initial = Orbit.from_classical(Earth, *drag_force_orbit, epoch=epoch) # in Curtis, the mean distance to Sun is used. In order to validate against it, we have to do the same thing sun_normalized = functools.partial(normalize_to_Curtis, sun_r=sun_r) r, v = cowell(initial, np.linspace(0, (tof).to(u.s).value, 4000), rtol=1e-8, ad=radiation_pressure, R=Earth.R.to(u.km).value, C_R=2.0, A=2e-4, m=100, Wdivc_s=Sun.Wdivc.value, star=sun_normalized) delta_eccs, delta_incs, delta_raans, delta_argps = [], [], [], [] for ri, vi in zip(r, v): orbit_params = rv2coe(Earth.k.to(u.km**3 / u.s**2).value, ri, vi) delta_eccs.append(orbit_params[1] - drag_force_orbit[1].value) delta_incs.append((orbit_params[2] * u.rad).to(u.deg).value - drag_force_orbit[2].value) delta_raans.append((orbit_params[3] * u.rad).to(u.deg).value - drag_force_orbit[3].value) delta_argps.append((orbit_params[4] * u.rad).to(u.deg).value - drag_force_orbit[4].value) # averaging over 5 last values in the way Curtis does for check in solar_pressure_checks: index = int(1.0 * check['t_days'] / tof.to(u.day).value * 4000) delta_ecc, delta_inc, delta_raan, delta_argp = np.mean(delta_eccs[index - 5:index]), \ np.mean(delta_incs[index - 5:index]), np.mean(delta_raans[index - 5:index]), \ np.mean(delta_argps[index - 5:index]) assert_quantity_allclose([delta_ecc, delta_inc, delta_raan, delta_argp], check['deltas_expected'], rtol=1e-1, atol=1e-4)
def test_3rd_body_Curtis(test_params): # based on example 12.11 from Howard Curtis body = test_params['body'] with solar_system_ephemeris.set('builtin'): j_date = 2454283.0 * u.day tof = (test_params['tof']).to(u.s).value body_r = build_ephem_interpolant(body, test_params['period'], (j_date, j_date + test_params['tof']), rtol=1e-2) epoch = Time(j_date, format='jd', scale='tdb') initial = Orbit.from_classical(Earth, *test_params['orbit'], epoch=epoch) r, v = cowell(initial, np.linspace(0, tof, 400), rtol=1e-10, ad=third_body, k_third=body.k.to(u.km**3 / u.s**2).value, third_body=body_r) incs, raans, argps = [], [], [] for ri, vi in zip(r, v): angles = Angle(rv2coe(Earth.k.to(u.km**3 / u.s**2).value, ri, vi)[2:5] * u.rad) # inc, raan, argp angles = angles.wrap_at(180 * u.deg) incs.append(angles[0].value) raans.append(angles[1].value) argps.append(angles[2].value) # averaging over 5 last values in the way Curtis does inc_f, raan_f, argp_f = np.mean(incs[-5:]), np.mean(raans[-5:]), np.mean(argps[-5:]) assert_quantity_allclose([(raan_f * u.rad).to(u.deg) - test_params['orbit'][3], (inc_f * u.rad).to(u.deg) - test_params['orbit'][2], (argp_f * u.rad).to(u.deg) - test_params['orbit'][4]], [test_params['raan'], test_params['inc'], test_params['argp']], rtol=1e-1)
def test_3rd_body_Curtis(test_params): # based on example 12.11 from Howard Curtis body = test_params["body"] with solar_system_ephemeris.set("builtin"): j_date = 2454283.0 * u.day tof = (test_params["tof"]).to(u.s).value body_r = build_ephem_interpolant( body, test_params["period"], (j_date, j_date + test_params["tof"]), rtol=1e-2, ) epoch = Time(j_date, format="jd", scale="tdb") initial = Orbit.from_classical(Earth, *test_params["orbit"], epoch=epoch) rr, vv = cowell( Earth.k, initial.r, initial.v, np.linspace(0, tof, 400) * u.s, rtol=1e-10, ad=third_body, k_third=body.k.to(u.km**3 / u.s**2).value, perturbation_body=body_r, ) incs, raans, argps = [], [], [] for ri, vi in zip(rr.to(u.km).value, vv.to(u.km / u.s).value): angles = Angle( rv2coe(Earth.k.to(u.km**3 / u.s**2).value, ri, vi)[2:5] * u.rad) # inc, raan, argp angles = angles.wrap_at(180 * u.deg) incs.append(angles[0].value) raans.append(angles[1].value) argps.append(angles[2].value) # averaging over 5 last values in the way Curtis does inc_f, raan_f, argp_f = ( np.mean(incs[-5:]), np.mean(raans[-5:]), np.mean(argps[-5:]), ) assert_quantity_allclose( [ (raan_f * u.rad).to(u.deg) - test_params["orbit"][3], (inc_f * u.rad).to(u.deg) - test_params["orbit"][2], (argp_f * u.rad).to(u.deg) - test_params["orbit"][4], ], [test_params["raan"], test_params["inc"], test_params["argp"]], rtol=1e-1, )
def test_3rd_body_Curtis(test_params): # based on example 12.11 from Howard Curtis body = test_params["body"] with solar_system_ephemeris.set("builtin"): j_date = 2454283.0 * u.day tof = (test_params["tof"]).to(u.s).value body_r = build_ephem_interpolant( body, test_params["period"], (j_date, j_date + test_params["tof"]), rtol=1e-2, ) epoch = Time(j_date, format="jd", scale="tdb") initial = Orbit.from_classical(Earth, *test_params["orbit"], epoch=epoch) rr, vv = cowell( Earth.k, initial.r, initial.v, np.linspace(0, tof, 400) * u.s, rtol=1e-10, ad=third_body, k_third=body.k.to(u.km ** 3 / u.s ** 2).value, third_body=body_r, ) incs, raans, argps = [], [], [] for ri, vi in zip(rr.to(u.km).value, vv.to(u.km / u.s).value): angles = Angle( rv2coe(Earth.k.to(u.km ** 3 / u.s ** 2).value, ri, vi)[2:5] * u.rad ) # inc, raan, argp angles = angles.wrap_at(180 * u.deg) incs.append(angles[0].value) raans.append(angles[1].value) argps.append(angles[2].value) # averaging over 5 last values in the way Curtis does inc_f, raan_f, argp_f = ( np.mean(incs[-5:]), np.mean(raans[-5:]), np.mean(argps[-5:]), ) assert_quantity_allclose( [ (raan_f * u.rad).to(u.deg) - test_params["orbit"][3], (inc_f * u.rad).to(u.deg) - test_params["orbit"][2], (argp_f * u.rad).to(u.deg) - test_params["orbit"][4], ], [test_params["raan"], test_params["inc"], test_params["argp"]], rtol=1e-1, )
def build_srp(c_r, a, m, epoch, rtol=1e-2) -> SRP: """ Build Solar Radiation Object used in perturbation. :param c_r: Comparable to coefficient of Drag but for radiation pressure. Unitless :param a: Cross sectional area exposed to radiation pressure. Units [m^2] :param m: Mass of the satellite. Units [kg] :param epoch: Time required to interpolate solar position :param rtol: determines number of points generated. Drives the time of execution significantly. Example online used rtol=1e-2. A smaller number is not accepted. Could be increased for more accuracy, that being said, the position of the Sun does not need to be that accurate. """ body_sun = build_ephem_interpolant(Sun, 1 * u.year, (epoch.value * u.day, epoch.value * u.day + 60 * u.day), rtol=rtol) return SRP(R, c_r, a, m, Wdivc_sun.value, body_sun)
def build_solar_third_body(epoch: Time, rtol=1e-2) -> ThirdBody: """ This function creates a callable Sun object for third_body and SRP perturbation. Over long periods of integration, this may longer prove to be an accurate description. Needs to be investigated. :param epoch: The time about which the interpolating function is created. :param rtol: determines number of points generated. Drives the time of execution significantly. Example online used rtol=1e-2. A smaller number is not accepted. Could be increased for more accuracy, that being said, the position of the Sun does not need to be that accurate. :return: Returns callable object that describes the Sun's position """ k_sun = Sun.k.to(u.km ** 3 / u.s ** 2).value body_sun = build_ephem_interpolant(Sun, solar_period, (epoch.value * u.day, epoch.value * u.day + 60 * u.day), rtol=rtol) return ThirdBody(k_sun, body_sun)
def third_body_moon( initial, time, f_time): # propogate under perturbation of a third body(moon) # database keeping positions of bodies in Solar system over time x_ephem = "de432s" questions = [ inquirer.List( 'Ephemerides', message= "Select ephemerides[de432s(default,small in size,faster)','de430(more precise)]:", choices=['de432s', 'de430'], ), ] answers = inquirer.prompt(questions) x_ephem = answers["Ephemerides"] solar_system_ephemeris.set(x_ephem) #epoch = Time(time, format='iso', scale='utc') # setting the exact event date is important epoch = Time(time, format='iso').jd f_time_1 = Time(f_time, format='iso').jd # create interpolant of 3rd body coordinates (calling in on every iteration will be just too slow) #check body_r = build_ephem_interpolant( Moon, 28 * u.day, (epoch * u.day, f_time_1 * u.day), rtol=1e-2 #check ) k_third = Moon.k.to(u.km**3 / u.s**2).value x = 400 print( "Use default constants or you want to customize?\n1.Default.\n2.Custom." ) check = input() if (check == '1'): pass else: k_third = input("Enter moon's gravity:") x = input( "Multiply Moon's gravity by X times so that effect is visible,input X:" ) datetimeFormat = '%Y-%m-%d %H:%M:%S.%f' diff =datetime.strptime(str(f_time), datetimeFormat)\ - datetime.strptime(str(time), datetimeFormat) print("Time difference:") print(diff) tofs = TimeDelta(f_time - time) tofs = TimeDelta(np.linspace(0, 31 * u.day, num=1)) # multiply Moon gravity by x so that effect is visible :) rr = propagate( initial, tofs, method=cowell, rtol=1e-6, ad=third_body, k_third=x * k_third, third_body=body_r, ) print("") print("Positions and velocity vectors are:") #print(str(rr.x)) #print([float(s) for s in re.findall(r'-?\d+\.?\d*',str(rr.x))]) r = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.z))][0]] * u.km v = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_z))][0]] * u.km / u.s f_orbit = Orbit.from_vectors(Earth, r, v) print(r) print(v) #f_orbit.plot() print("") print("Orbital elements:") print(f_orbit.classical()) #print("") #print(f_orbit.ecc) plotOrbit((f_orbit.a.value), (f_orbit.ecc.value), (f_orbit.inc.value), (f_orbit.raan.value), (f_orbit.argp.value), (f_orbit.nu.value))
def sun_r(): j_date = 2_438_400.5 * u.day tof = 600 * u.day return build_ephem_interpolant(Sun, 365 * u.day, (j_date, j_date + tof), rtol=1e-2)
# ### 3rd body # # Apart from time-independent perturbations such as atmospheric drag, J2/J3, we have time-dependend perturbations. Lets's see how Moon changes the orbit of GEO satellite over time! # In[9]: # database keeping positions of bodies in Solar system over time solar_system_ephemeris.set("de432s") epoch = Time(2454283.0, format="jd", scale="tdb") # setting the exact event date is important # create interpolant of 3rd body coordinates (calling in on every iteration will be just too slow) body_r = build_ephem_interpolant( Moon, 28 * u.day, (epoch.value * u.day, epoch.value * u.day + 60 * u.day), rtol=1e-2) initial = Orbit.from_classical( Earth, 42164.0 * u.km, 0.0001 * u.one, 1 * u.deg, 0.0 * u.deg, 0.0 * u.deg, 0.0 * u.rad, epoch=epoch, ) tofs = TimeDelta(np.linspace(0, 60 * u.day, num=1000))