def validate_elliptic_propagation(): # Orbit initial state vectors and time of flight rx_0, ry_0, rz_0 = 1131.340e3, -2282.343e3, 6672.423e3 vx_0, vy_0, vz_0 = -5.64305e3, 4.30333e3, 2.42879e3 tof = 1.5 * 3600 # Build the initial Orekit orbit k = C.IAU_2015_NOMINAL_EARTH_GM r0_vec = Vector3D(rx_0, ry_0, rz_0) v0_vec = Vector3D(vx_0, vy_0, vz_0) rv_0 = PVCoordinates(r0_vec, v0_vec) epoch_00 = AbsoluteDate.J2000_EPOCH gcrf_frame = FramesFactory.getGCRF() ss0_orekit = KeplerianOrbit(rv_0, gcrf_frame, epoch_00, k) orekit_propagator = KeplerianPropagator(ss0_orekit) ssf_orekit = orekit_propagator.propagate( epoch_00.shiftedBy(tof)).getOrbit() # Build poliastro orbit r0_vec = [rx_0, ry_0, rz_0] * u.m v0_vec = [vx_0, vy_0, vz_0] * u.m / u.s ss0_poliastro = Orbit.from_vectors(Earth, r0_vec, v0_vec) ssf_poliastro = ss0_poliastro.propagate(tof * u.s) # Retrieve Orekit final state vectors r_orekit = ssf_orekit.getPVCoordinates().position.toArray() * u.m v_orekit = ssf_orekit.getPVCoordinates().velocity.toArray() * u.m / u.s # Retrieve poliastro final state vectors r_poliastro, v_poliastro = ssf_poliastro.rv() # Assert final state vectors assert_quantity_allclose(r_poliastro, r_orekit, atol=10 * u.m) assert_quantity_allclose(v_poliastro, v_orekit, rtol=1e-5)
def test_analytical_propagator(self): """ analytical_propagator test """ parameters = { "eccentricity": 0.0008641, "semimajor_axis": 6801395.04, "inclination": radians(87.0), "perigee_argument": radians(20.0), "right_ascension_of_ascending_node": radians(10.0), "anomaly": radians(0.0), "anomaly_type": "TRUE", "orbit_update_date": '2021-12-02T00:00:00.000', "frame": "EME" } k_orbit = keplerian_orbit(parameters) test1 = analytical_propagator(parameters) test2 = KeplerianPropagator(keplerian_orbit(parameters), Constants.WGS84_EARTH_MU) time1 = orekit_utils.absolute_time_converter_utc_string( '2022-01-02T00:00:00.000') self.assertTrue( test1.getPVCoordinates(time1, FramesFactory.getEME2000()).toString( ) == test2.getPVCoordinates(time1, FramesFactory.getEME2000()).toString())
def test_get_ground_passes(self): """ Testing whether OreKit finds ground passess """ # test will fail if setup_orekit fails utc = TimeScalesFactory.getUTC() ra = 500 * 1000 # Apogee rp = 400 * 1000 # Perigee i = radians(55.0) # inclination omega = radians(20.0) # perigee argument raan = radians(10.0) # right ascension of ascending node lv = radians(0.0) # True anomaly epochDate = AbsoluteDate(2020, 1, 1, 0, 0, 00.000, utc) initial_date = epochDate a = (rp + ra + 2 * Constants.WGS84_EARTH_EQUATORIAL_RADIUS) / 2.0 e = 1.0 - (rp + Constants.WGS84_EARTH_EQUATORIAL_RADIUS) / a ## Inertial frame where the satellite is defined inertialFrame = FramesFactory.getEME2000() ## Orbit construction as Keplerian initialOrbit = KeplerianOrbit(a, e, i, omega, raan, lv, PositionAngle.TRUE, inertialFrame, epochDate, Constants.WGS84_EARTH_MU) propagator = KeplerianPropagator(initialOrbit) durand_lat = 37.4269 durand_lat = -122.1733 durand_alt = 10.0 output = get_ground_passes(propagator, durand_lat, durand_lat, durand_alt, initial_date, initial_date.shiftedBy(3600.0 * 24), ploting_param=False) assert len(output) == 5
def __init__(self, name, mu, state, trj_date, rot_state=None, oneshot=False): """Currently hard implemented for SC.""" super().__init__(name) self.trj_date = trj_date self.auto_targeting = rot_state is None att_provider = [] if rot_state is not None: attitude = Attitude(trj_date, self.ref_frame, rot_state) att_provider = [FixedRate(attitude)] if oneshot: self.date_history = [trj_date] self.pos_history = [state.getPosition()] self.vel_history = [state.getVelocity()] self.rot_history = [ None if rot_state is None else rot_state.getRotation() ] else: self.trajectory = KeplerianOrbit(state, self.ref_frame, self.trj_date, mu) self.propagator = KeplerianPropagator(self.trajectory, *att_provider) self.payload = None logger.debug("Init finished")
def analytical_propagator(parameters): """ Takes in a dictionary of keplarian parameters and returns an Keplarian analytical propogator Args: Args: parameters (dict): dictionary of parameters containg eccentricity, semimajor_axis (meters), inclination, perigee argument, right ascension of ascending node, orbit_update_date, and anomoly with another defining key ["anomaly_type"] = "MEAN" or "TRUE" ["frame"] = "EME2000", "J2000", or "TEME" only Ex. parameters = { "eccentricity": 0.0008641, "semimajor_axis": 6801395.04, "inclination": radians(87.0), "perigee_argument": radians(20.0), "right_ascension_of_ascending_node":radians(10.0), "anomaly": radians(0.0), "anomaly_type": "TRUE", "orbit_update_date":'2021-12-02T00:00:00.000', "frame": "EME"} Returns: AbstractAnalyticalPropagator: propagator that can be used to propagate an orbit and acts as a PVCoordinatesProvider (PV = position, velocity) """ return KeplerianPropagator(keplerian_orbit(parameters), Constants.WGS84_EARTH_MU)
def __init__(self, name, mu, trj, att, model_file=None): """Currently hard implemented for Didymos.""" super().__init__(name, model_file=model_file) date = trj["date"] trj_date = AbsoluteDate(int(date["year"]), int(date["month"]), int(date["day"]), int(date["hour"]), int(date["minutes"]), float(date["seconds"]), self.timescale) # rotation axis self.axis_ra = math.radians(att["RA"]) if "RA" in att else 0. self.axis_dec = math.radians( att["Dec"]) if "Dec" in att else math.pi / 2 # rotation offset, zero longitude right ascension at epoch self.rotation_zlra = math.radians(att["ZLRA"]) if "ZLRA" in att else 0. # rotation angular velocity [rad/s] if "rotation_rate" in att: self.rotation_rate = att["rotation_rate"] * 2.0 * math.pi / 180.0 else: self.rotation_rate = 2. * math.pi / (2.2593 * 3600 ) # didymain by default # Define initial rotation, set rotation convention # - For me, FRAME_TRANSFORM order makes more sense, the rotations are applied from left to right # so that the following rotations apply on previously rotated axes +Olli self.rot_conv = RotationConvention.FRAME_TRANSFORM init_rot = Rotation(RotationOrder.ZYZ, self.rot_conv, self.axis_ra, math.pi / 2 - self.axis_dec, self.rotation_zlra) if "r" in trj: self.date_history = [trj_date] self.pos_history = [Vector3D(*trj["r"])] self.vel_history = [ Vector3D(*(trj["v"] if "v" in trj else [0., 0., 0.])) ] self.rot_history = [init_rot] return # Define trajectory/orbit self.trajectory = KeplerianOrbit( trj["a"] * ok_utils.Constants.IAU_2012_ASTRONOMICAL_UNIT, trj["e"], math.radians(trj["i"]), math.radians(trj["omega"]), math.radians(trj["Omega"]), math.radians(trj["M"]), PositionAngle.MEAN, self.ref_frame, trj_date, mu) rotation = ok_utils.AngularCoordinates( init_rot, Vector3D(0., 0., self.rotation_rate)) attitude = Attitude(trj_date, self.ref_frame, rotation) att_provider = FixedRate(attitude) # Create propagator self.propagator = KeplerianPropagator(self.trajectory, att_provider) # Loaded coma object, currently only used with OpenGL based rendering self.coma = None
def __init__(self, name, mu, state, trj_date): """Currently hard implemented for SC.""" super().__init__(name) self.trj_date = trj_date self.trajectory = KeplerianOrbit(state, self.ref_frame, self.trj_date, mu) self.propagator = KeplerianPropagator(self.trajectory) self.payload = None
def validate_event_detector(event_name): # Unpack orekit and poliastro events orekit_event, poliastro_event = DICT_OF_EVENTS[event_name] # Time of fliht for propagating the orbit tof = float(2 * 24 * 3600) # Build the orekit propagator and add the event to it. propagator = KeplerianPropagator(ss0_orekit) propagator.addEventDetector(orekit_event) # Propagate orekit's orbit state = propagator.propagate(epoch0_orekit, epoch0_orekit.shiftedBy(tof)) orekit_event_epoch_raw = state.orbit.getPVCoordinates().getDate() # Convert orekit epoch to astropy Time instance orekit_event_epoch_str = orekit_event_epoch_raw.toString( TimeScalesFactory.getUTC()) orekit_event_epoch = Time(orekit_event_epoch_str, scale="utc", format="isot") orekit_event_epoch.format = "iso" print(f"{orekit_event_epoch}") # Propagate poliastro's orbit _, _ = cowell( Earth.k, ss0_poliastro.r, ss0_poliastro.v, # Generate a set of tofs, each one for each propagation second np.linspace(0, tof, 100) * u.s, events=[poliastro_event], ) poliastro_event_epoch = ss0_poliastro.epoch + poliastro_event.last_t print(f"{poliastro_event_epoch}") # Test both event epochs by checking the distance in seconds between them dt = np.abs((orekit_event_epoch - poliastro_event_epoch).to(u.s)) assert_quantity_allclose(dt, 0 * u.s, atol=5 * u.s, rtol=1e-7)
def __init__(self, name, mu, trj, att, model_file=None): """Currently hard implemented for Didymos.""" super().__init__(name, model_file=model_file) date = trj["date"] trj_date = AbsoluteDate(int(date["year"]), int(date["month"]), int(date["day"]), int(date["hour"]), int(date["minutes"]), float(date["seconds"]), self.timescale) if "a" and "e" and "i" and "omega" and "Omega" and "M" not in trj: a = 1.644641475071416E+00 * utils.Constants.IAU_2012_ASTRONOMICAL_UNIT P = 7.703805051391988E+02 * utils.Constants.JULIAN_DAY e = 3.838774437558215E-01 i = math.radians(3.408231185574551E+00) omega = math.radians(3.192958853076784E+02) Omega = math.radians(7.320940216397703E+01) M = math.radians(1.967164895190036E+02) if "rotation_rate" not in att: rotation_rate = 2. * math.pi / (2.2593 * 3600) else: rotation_rate = att["rotation_rate"] * 2.0 * math.pi / 180.0 if "RA" not in att: self.RA = 0. else: self.RA = math.radians(att["RA"]) if "Dec" not in att: self.Dec = 0. else: self.Dec = math.radians(att["Dec"]) # Define trajectory/orbit self.trajectory = KeplerianOrbit( trj["a"] * utils.Constants.IAU_2012_ASTRONOMICAL_UNIT, trj["e"], math.radians(trj["i"]), math.radians(trj["omega"]), math.radians(trj["Omega"]), math.radians(trj["M"]), PositionAngle.MEAN, self.ref_frame, trj_date, mu) # Define attitude self.rot_conv = RotationConvention.valueOf("VECTOR_OPERATOR") rotation = utils.AngularCoordinates(Rotation.IDENTITY, Vector3D(0., 0., rotation_rate)) attitude = Attitude(trj_date, self.ref_frame, rotation) att_provider = FixedRate(attitude) # Create propagator self.propagator = KeplerianPropagator(self.trajectory, att_provider)
def simple_keplarian(initialOrbit, initialDate): """ :param initialOrbit: initial Keplarian orbit and central body :param initialDate: intial start date :return: plot xy orbit """ # Simple extrapolation with Keplerian motion kepler = KeplerianPropagator(initialOrbit) # Set the propagator to slave mode (could be omitted as it is the default mode) kepler.setSlaveMode() # Setup propagation time # Overall duration in seconds for extrapolation duration = 24 * 60.0**2 # Stop date finalDate = AbsoluteDate(initial_date, duration, utc) # Step duration in seconds stepT = 30.0 # Perform propagation # Extrapolation loop cpt = 1.0 extrapDate = initial_date px, py = [], [] while extrapDate.compareTo(finalDate) <= 0: currentState = kepler.propagate(extrapDate) print('step {}: time {} {}\n'.format(cpt, currentState.getDate(), currentState.getOrbit())) coord = currentState.getPVCoordinates().getPosition() px.append(coord.getX()) py.append(coord.getY()) # P[:,cpt]=[coord.getX coord.getY coord.getZ] extrapDate = AbsoluteDate(extrapDate, stepT, utc) cpt += 1 plt.plot(px, py) plt.show() pass
def propagate_keplerian_elements(self): propagator = KeplerianPropagator(self.initial_orbit) return propagator.propagate(self.initial_date, self.shifted_date)
def validate_3D_hohmann(): # Initial orbit state vectors, final radius and time of flight # This orbit has an inclination of 22.30 [deg] so the maneuver will not be # applied on an equatorial orbit. See associated GMAT script: # gmat_validate_hohmann3D.script rx_0, ry_0, rz_0 = 7200e3, -1000.0e3, 0.0 vx_0, vy_0, vz_0 = 0.0, 8.0e3, 3.25e3 rf_norm = 35781.35e3 tof = 19800.00 # Build the initial Orekit orbit k = C.IAU_2015_NOMINAL_EARTH_GM r0_vec = Vector3D(rx_0, ry_0, rz_0) v0_vec = Vector3D(vx_0, vy_0, vz_0) rv_0 = PVCoordinates(r0_vec, v0_vec) epoch_00 = AbsoluteDate.J2000_EPOCH gcrf_frame = FramesFactory.getGCRF() ss_0 = KeplerianOrbit(rv_0, gcrf_frame, epoch_00, k) # Final desired orbit radius and auxiliary variables a_0, ecc_0 = ss_0.getA(), ss_0.getE() rp_norm = a_0 * (1 - ecc_0) vp_norm = np.sqrt(2 * k / rp_norm - k / a_0) a_trans = (rp_norm + rf_norm) / 2 # Compute the magnitude of Hohmann's deltaV dv_a = np.sqrt(2 * k / rp_norm - k / a_trans) - vp_norm dv_b = np.sqrt(k / rf_norm) - np.sqrt(2 * k / rf_norm - k / a_trans) # Convert previous magnitudes into vectors within the TNW frame, which # is aligned with local velocity vector dVa_vec, dVb_vec = [ Vector3D(float(dV), float(0), float(0)) for dV in (dv_a, dv_b) ] # Local orbit frame: X-axis aligned with velocity, Z-axis towards momentum attitude_provider = LofOffset(gcrf_frame, LOFType.TNW) # Setup impulse triggers; default apside detector stops on increasing g # function (aka at perigee) at_apoapsis = ApsideDetector(ss_0).withHandler(StopOnDecreasing()) at_periapsis = ApsideDetector(ss_0) # Build the impulsive maneuvers; ISP is only related to fuel mass cost ISP = float(300) imp_A = ImpulseManeuver(at_periapsis, attitude_provider, dVa_vec, ISP) imp_B = ImpulseManeuver(at_apoapsis, attitude_provider, dVb_vec, ISP) # Generate the propagator and add the maneuvers propagator = KeplerianPropagator(ss_0, attitude_provider) propagator.addEventDetector(imp_A) propagator.addEventDetector(imp_B) # Apply the maneuver by propagating the orbit epoch_ff = epoch_00.shiftedBy(tof) rv_f = propagator.propagate(epoch_ff).getPVCoordinates(gcrf_frame) # Retrieve orekit final state vectors r_orekit, v_orekit = ( rv_f.getPosition().toArray() * u.m, rv_f.getVelocity().toArray() * u.m / u.s, ) # Build initial poliastro orbit and apply the maneuver r0_vec = [rx_0, ry_0, rz_0] * u.m v0_vec = [vx_0, vy_0, vz_0] * u.m / u.s ss0_poliastro = Orbit.from_vectors(Earth, r0_vec, v0_vec) man_poliastro = Maneuver.hohmann(ss0_poliastro, rf_norm * u.m) # Retrieve propagation time after maneuver has been applied tof_prop = tof - man_poliastro.get_total_time().to(u.s).value ssf_poliastro = ss0_poliastro.apply_maneuver(man_poliastro).propagate( tof_prop * u.s) # Retrieve poliastro final state vectors r_poliastro, v_poliastro = ssf_poliastro.rv() # Assert final state vectors assert_quantity_allclose(r_poliastro, r_orekit, rtol=1e-6) assert_quantity_allclose(v_poliastro, v_orekit, rtol=1e-6)