def validate_coe2rv(): # Initial COE of the orbit a, ecc, inc, raan, argp, nu = 8788e3, 0.1712, 2.6738, 4.4558, 0.3502, 0.4965 # Build Orekit orbit k = C.IAU_2015_NOMINAL_EARTH_GM epoch_00 = AbsoluteDate.J2000_EPOCH gcrf_frame = FramesFactory.getGCRF() ss0_orekit = KeplerianOrbit(a, ecc, inc, argp, raan, nu, PositionAngle.TRUE, gcrf_frame, epoch_00, k) # Build poliastro orbit ss0_poliastro = Orbit.from_classical( Earth, a * u.m, ecc * u.one, inc * u.rad, raan * u.rad, argp * u.rad, nu * u.rad, ) # Retrieve Orekit final state vectors r_orekit = ss0_orekit.getPVCoordinates().position.toArray() * u.m v_orekit = ss0_orekit.getPVCoordinates().velocity.toArray() * u.m / u.s # Retrieve poliastro final state vectors r_poliastro, v_poliastro = ss0_poliastro.rv() # Assert final state vector assert_quantity_allclose(r_poliastro, r_orekit) assert_quantity_allclose(v_poliastro, v_orekit)
def get_keplerian_parameters(spacecraft_state, anomaly_type="TRUE"): """ Given a SpaceCraftState object this function computes the keplerian orbit parameters Note: parameter values may change but they'll define the same orbit Args: spacecraft_state (SpaceCraftState): SpaceCraftState orekit object that has an orbit attribute anomaly_type (string; "MEAN" or "TRUE"): tells to return true or mean anomaly, defaults to TRUE Returns: dict: dictionary of parameters containg eccentricity, semimajor_axis, inclination, perigee argument, right ascension of ascending node, anomaly, anomaly_type, and orbit_update_date """ parameters = dict() new_orbit = KeplerianOrbit(spacecraft_state.getOrbit()) parameters["semimajor_axis"] = new_orbit.getA() parameters["eccentricity"] = new_orbit.getE() parameters["inclination"] = new_orbit.getI() parameters["perigee_argument"] = new_orbit.getPerigeeArgument() parameters[ "right_ascension_of_ascending_node"] = new_orbit.getRightAscensionOfAscendingNode( ) parameters["orbit_update_date"] = new_orbit.getDate().toString() parameters["frame"] = frame_to_string(spacecraft_state.getFrame()) if (anomaly_type == "MEAN"): parameters["anomaly"] = new_orbit.getMeanAnomaly() parameters["anomaly_type"] = "MEAN" else: parameters["anomaly"] = new_orbit.getTrueAnomaly() parameters["anomaly_type"] = "TRUE" return parameters
def keplerian_orbit(parameters): """ Given a dictionary of parameters containg eccentricity, semimajor_axis, inclination, perigee_argument, right acension of ascending node, anomaly, anomaly_type and orbit_update_date this function returns a keplerian orbit orekit object 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: KeplerianOrbit: Keplerian orbit orekit object """ eccentricity = float(parameters["eccentricity"]) semimajor_axis = float(parameters["semimajor_axis"]) inclination = float(parameters["inclination"]) perigee_argument = float(parameters["perigee_argument"]) right_ascension_of_ascending_node = float( parameters["right_ascension_of_ascending_node"]) anomaly = float(parameters["anomaly"]) orbit_update_date = absolute_time_converter_utc_string( parameters["orbit_update_date"]) frame = string_to_frame(parameters["frame"]) if (parameters["anomaly_type"] == "TRUE"): return KeplerianOrbit(semimajor_axis, eccentricity, inclination, perigee_argument, right_ascension_of_ascending_node, anomaly, PositionAngle.TRUE, frame, orbit_update_date, Constants.WGS84_EARTH_MU) elif (parameters["anomaly_type"] == "MEAN"): return KeplerianOrbit(semimajor_axis, eccentricity, inclination, perigee_argument, right_ascension_of_ascending_node, anomaly, PositionAngle.MEAN, frame, orbit_update_date, Constants.WGS84_EARTH_MU) else: return ( "Error: Need to redefine anomoly_type, see function documentation")
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_keplerian_orbit(self): """ keplerian_orbit 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) eccentricity = parameters["eccentricity"] semimajor_axis = parameters["semimajor_axis"] inclination = parameters["inclination"] perigee_argument = parameters["perigee_argument"] right_ascension_of_ascending_node = parameters["right_ascension_of_ascending_node"] true_anomaly = parameters["anomaly"] orbit_update_date = parameters["orbit_update_date"] epochDate = absolute_time_converter_utc_string(orbit_update_date) frame = orekit_utils.string_to_frame(parameters["frame"]) self.assertTrue(KeplerianOrbit(semimajor_axis, eccentricity, inclination, perigee_argument, right_ascension_of_ascending_node, true_anomaly, PositionAngle.TRUE, frame, epochDate, Constants.WGS84_EARTH_MU).toString() == k_orbit.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 __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 kepler_gcrs_single(kep): date = kep.index[0] ok_date = AbsoluteDate(date.year, date.month, date.day, date.hour, date.minute, date.second + float(date.microsecond) / 1000000., utc) kep = kep.astype(float) a, e, f, i, raan, w, date = kep['a[m]'][0], kep['e'][0], kep['ta[rad]'][0], kep['i[rad]'][0], kep['raan[rad]'][0], kep['omega[rad]'][0], \ kep.index[0] kep_orbit = KeplerianOrbit(a, e, i, w, raan, f, PositionAngle.TRUE, teme_f, ok_date, muearth) state = AbsolutePVCoordinates(gcrf_f, kep_orbit.getPVCoordinates(gcrf_f)) pos = state.position vel = state.velocity X = pos.getX() Y = pos.getY() Z = pos.getZ() Vx = vel.getX() Vy = vel.getY() Vz = vel.getZ() dframe = pd.DataFrame({'x[m]': [X], 'y[m]': [Y], 'z[m]': [Z], 'vx[m/s]': [Vx], 'vy[m/s]': [Vy], 'vz[m/s]': [Vz]},index=kep.index) return dframe
def validate_rv2coe(): # Orbit initial state vectors rx_0, ry_0, rz_0 = -6045.0e3, -3490.0e3, 2500.0e3 vx_0, vy_0, vz_0 = -3.457e3, 6.618e3, 2.533e3 # 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) # 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) # Orekit bounds COE angular magnitudes between [-pi, +pi]. Let us define a # converter function to map values between [0, +2pi] def unbound_angle(angle): """ Bound angle between [0, +2pi] """ if -np.pi <= angle <= 0.0: angle += 2 * np.pi return angle # Map angles orekit_raan = unbound_angle(ss0_orekit.getRightAscensionOfAscendingNode()) orekit_argp = unbound_angle(ss0_orekit.getPerigeeArgument()) orekit_nu = unbound_angle(ss0_orekit.getTrueAnomaly()) # Assert classical orbital elements assert_quantity_allclose(ss0_poliastro.a, ss0_orekit.getA() * u.m, rtol=1e-6) assert_quantity_allclose(ss0_poliastro.ecc, ss0_orekit.getE() * u.one, rtol=1e-6) assert_quantity_allclose(ss0_poliastro.inc, ss0_orekit.getI() * u.rad, rtol=1e-6) assert_quantity_allclose(ss0_poliastro.raan, orekit_raan * u.rad, rtol=1e-6) assert_quantity_allclose(ss0_poliastro.argp, orekit_argp * u.rad, rtol=1e-6) assert_quantity_allclose(ss0_poliastro.nu, orekit_nu * u.rad, rtol=1e-6)
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 propagate(tle_line1, tle_line2, duration, step, maneuvers=[]): tle = create_tle(tle_line1, tle_line2) tle_propagator = TLEPropagator.selectExtrapolator(tle) propagator_with_maneuvers = AdapterPropagator(tle_propagator) # TODO works only for chronological maneuvers, because of the "propagate" to get the state for maneuver in maneuvers: date, frame, deltaV, isp = maneuver propagator_with_maneuvers.addEffect( SmallManeuverAnalyticalModel( propagator_with_maneuvers.propagate( datetime_to_absolutedate(date)), frame, deltaV, isp)) ITRF = FramesFactory.getITRF(IERSConventions.IERS_2010, True) earth = OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, Constants.WGS84_EARTH_FLATTENING, ITRF) time = [tle.getDate().shiftedBy(float(dt)) \ for dt in np.arange(0, duration, step)] orbits = [ KeplerianOrbit(propagator_with_maneuvers.propagate(date).getOrbit()) for date in time ] subpoints = [ earth.transform( propagator_with_maneuvers.propagate(date).getPVCoordinates(), tle_propagator.getFrame(), date) for date in time ] return pd.DataFrame({ 'time': [absolutedate_to_datetime(orbit.getDate()) for orbit in orbits], 'a': [orbit.getA() for orbit in orbits], 'e': [orbit.getE() for orbit in orbits], 'i': [orbit.getI() for orbit in orbits], 'pom': [orbit.getPerigeeArgument() for orbit in orbits], 'RAAN': [orbit.getRightAscensionOfAscendingNode() for orbit in orbits], 'v': [orbit.getTrueAnomaly() for orbit in orbits], 'ex': [orbit.getEquinoctialEx() for orbit in orbits], 'ey': [orbit.getEquinoctialEy() for orbit in orbits], 'hx': [orbit.getHx() for orbit in orbits], 'hy': [orbit.getHy() for orbit in orbits], 'latitude': [np.degrees(gp.getLatitude().getReal()) for gp in subpoints], 'longitude': [np.degrees(gp.getLongitude().getReal()) for gp in subpoints] })
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)
setup_orekit_curdir() # To activate once if a problem of orekit.Exception appears. (.getUtc()) # orekit.pyhelpers.download_orekit_data_curdir() utc = TimeScalesFactory.getUTC() ra = 400 * 1000 # Apogee rp = 500 * 1000 # Perigee i = numpy.radians(87.0) # inclination # FIXME: Use Hipparchus Library instead of numpy omega = numpy.radians(20.0) # perigee argument raan = numpy.radians(10.0) # right ascension of ascending node lv = numpy.radians(0.0) # True anomaly epochDate = AbsoluteDate(2020, 1, 1, 0, 0, 00.000, utc) 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(24464560.0, 0.7311, 0.122138, 3.10686, 1.00681, 0.048363, PositionAngle.MEAN, FramesFactory.getEME2000(), epochDate, Constants.GRS80_EARTH_MU) print(initialOrbit)
def init_keplerian_elements(self): return KeplerianOrbit(self.a, self.e, self.i, self.w, self.gom, self.anomaly, self.position_angle, self.frame, self.current_date, self.mu)
def osc_elems_transformation_ore(self, other, dir): self._orekit_lock.acquire() self.load_orekit() KepOrbElem.vm.attachCurrentThread() utc = TimeScalesFactory.getUTC() orekit_date = AbsoluteDate(2017, 1, 1, 12, 1, 1.0, utc) inertialFrame = FramesFactory.getEME2000() a = float(other.a) e = float(other.e) i = float(other.i) w = float(other.w) O = float(other.O) v = float(other.v) initialOrbit = KeplerianOrbit(a * 1000.0, e, i, w, O, v, PositionAngle.TRUE, inertialFrame, orekit_date, Constants.mu_earth * 1e9) initialState = SpacecraftState(initialOrbit, 1.0) #zonal_forces= DSSTZonal(provider,2,1,5) zonal_forces = DSSTZonal(KepOrbElem.provider, 6, 4, 6) forces = ArrayList() forces.add(zonal_forces) try: equinoctial = None if dir: equinoctial = DSSTPropagator.computeMeanState( initialState, None, forces) else: equinoctial = DSSTPropagator.computeOsculatingState( initialState, None, forces) newOrbit = KeplerianOrbit(equinoctial.getOrbit()) self.a = newOrbit.getA() / 1000.0 self.e = newOrbit.getE() self.i = newOrbit.getI() self.w = newOrbit.getPerigeeArgument() self.O = newOrbit.getRightAscensionOfAscendingNode() self.v = newOrbit.getAnomaly(PositionAngle.TRUE) # correct ranges if self.i < 0: self.i += 2 * np.pi if self.w < 0: self.w += 2 * np.pi if self.O < 0: self.O += 2 * np.pi if self.v < 0: self.v += 2 * np.pi finally: self._orekit_lock.release()
def get_orbit(self, t, a, e, inc, raan, aop, mu0, mjd0, **kwargs): ''' **Implementation:** Units are in meters and degrees. Keyword arguments are: * float A: Area in m^2 * float C_D: Drag coefficient * float C_R: Radiation pressure coefficient * float m: Mass of object in kg *NOTE:* * If the eccentricity is below 1e-10 the eccentricity will be set to 1e-10 to prevent Keplerian Jacobian becoming singular. The implementation first checks if the input frame is Pseudo inertial, if this is true this is used as the propagation frame. If not it is automatically converted to EME (ECI-J2000). Since there are forces that are dependent on the space-craft parameters, if these parameter has been changed since the last iteration the numerical integrator is re-initialized at every call of this method. The forces that can be initialized without spacecraft parameters (e.g. Earth gravitational field) are done at propagator construction. **Uses:** * :func:`propagator_base.PropagatorBase._make_numpy` * :func:`propagator_orekit.PropagatorOrekit._construct_propagator` * :func:`propagator_orekit.PropagatorOrekit._set_forces` * :func:`dpt_tools.kep2cart` * :func:`dpt_tools.cart2kep` * :func:`dpt_tools.true2mean` * :func:`dpt_tools.mean2true` See :func:`propagator_base.PropagatorBase.get_orbit`. ''' if self.logger_func is not None: self._logger_start('get_orbit') if self.radiation_pressure: if 'C_R' not in kwargs: raise Exception( 'Radiation pressure force enabled but no coefficient "C_R" given' ) else: kwargs['C_R'] = 1.0 if self.drag_force: if 'C_D' not in kwargs: raise Exception( 'Drag force enabled but no drag coefficient "C_D" given') else: kwargs['C_D'] = 1.0 t = self._make_numpy(t) initialDate = mjd2absdate(mjd0) if not self.inputFrame.isPseudoInertial(): orb = np.array( [a, e, inc, aop, raan, dpt.mean2true(mu0, e, radians=False)], dtype=np.float) cart = dpt.kep2cart( orb, m=kwargs['m'], M_cent=self.M_earth, radians=False, ) pos = org.hipparchus.geometry.euclidean.threed.Vector3D( float(cart[0]), float(cart[1]), float(cart[2])) vel = org.hipparchus.geometry.euclidean.threed.Vector3D( float(cart[3]), float(cart[4]), float(cart[5])) PV_state = PVCoordinates(pos, vel) transform = self.inputFrame.getTransformTo(self.inertialFrame, initialDate) new_PV = transform.transformPVCoordinates(PV_state) initialOrbit = CartesianOrbit( new_PV, self.inertialFrame, initialDate, self.mu + float(scipy.constants.G * kwargs['m']), ) else: #this is to prevent Keplerian Jacobian to become singular use_equinoctial = False if e < dpt.e_lim: use_equinoctial = True if inc < dpt.i_lim: use_equinoctial = True if use_equinoctial: ex = e * np.cos(np.radians(aop) + np.radians(raan)) ey = e * np.sin(np.radians(aop) + np.radians(raan)) hx = np.tan(np.radians(inc) * 0.5) * np.cos(np.radians(raan)) hy = np.tan(np.radians(inc) * 0.5) * np.sin(np.radians(raan)) lv = np.radians(mu0) + np.radians(aop) + np.radians(raan) initialOrbit = EquinoctialOrbit( float(a), float(ex), float(ey), float(hx), float(hy), float(lv), PositionAngle.MEAN, self.inertialFrame, initialDate, self.mu + float(scipy.constants.G * kwargs['m']), ) else: initialOrbit = KeplerianOrbit( float(a), float(e), float(np.radians(inc)), float(np.radians(aop)), float(np.radians(raan)), float(np.radians(mu0)), PositionAngle.MEAN, self.inertialFrame, initialDate, self.mu + float(scipy.constants.G * kwargs['m']), ) self._construct_propagator(initialOrbit) self._set_forces(kwargs['A'], kwargs['C_D'], kwargs['C_R']) initialState = SpacecraftState(initialOrbit) self.propagator.setInitialState(initialState) tb_inds = t < 0.0 t_back = t[tb_inds] tf_indst = t >= 0.0 t_forward = t[tf_indst] if len(t_forward) == 1: if np.any(t_forward == 0.0): t_back = t t_forward = [] tb_inds = t <= 0 state = np.empty((6, len(t)), dtype=np.float) step_handler = PropagatorOrekit.OrekitVariableStep() if self.logger_func is not None: self._logger_start('propagation') if len(t_back) > 0: _t = t_back _t_order = np.argsort(np.abs(_t)) _t_res = np.argsort(_t_order) _t = _t[_t_order] _state = np.empty((6, len(_t)), dtype=np.float) step_handler.set_params(_t, initialDate, _state, self.outputFrame) self.propagator.setMasterMode(step_handler) self.propagator.propagate(initialDate.shiftedBy(float(_t[-1]))) #now _state is full and in the order of _t state[:, tb_inds] = _state[:, _t_res] if len(t_forward) > 0: _t = t_forward _t_order = np.argsort(np.abs(_t)) _t_res = np.argsort(_t_order) _t = _t[_t_order] _state = np.empty((6, len(_t)), dtype=np.float) step_handler.set_params(_t, initialDate, _state, self.outputFrame) self.propagator.setMasterMode(step_handler) self.propagator.propagate(initialDate.shiftedBy(float(_t[-1]))) #now _state is full and in the order of _t state[:, tf_indst] = _state[:, _t_res] if self.logger_func is not None: self._logger_record('propagation') if self.logger_func is not None: self._logger_record('get_orbit') return state
def main(): a = 24396159.0 # semi major axis (m) e = 0.720 # eccentricity i = radians(10.0) # inclination omega = radians(50.0) # perigee argument raan = radians(150) # right ascension of ascending node lM = 0.0 # mean anomaly # Set inertial frame inertialFrame = FramesFactory.getEME2000() # Initial date in UTC time scale utc = TimeScalesFactory.getUTC() initial_date = AbsoluteDate(2004, 1, 1, 23, 30, 00.000, utc) # Setup orbit propagator # gravitation coefficient mu = 3.986004415e+14 # Orbit construction as Keplerian initialOrbit = KeplerianOrbit(a, e, i, omega, raan, lM, PositionAngle.MEAN, inertialFrame, initial_date, mu) initial_state = SpacecraftState(initialOrbit) # use a numerical propogator min_step = 0.001 max_step = 1000.0 position_tolerance = 10.0 propagation_type = OrbitType.KEPLERIAN tolerances = NumericalPropagator.tolerances(position_tolerance, initialOrbit, propagation_type) integrator = DormandPrince853Integrator(min_step, max_step, 1e-5, 1e-10) propagator = NumericalPropagator(integrator) propagator.setOrbitType(propagation_type) # force model gravity field provider = GravityFieldFactory.getNormalizedProvider(10, 10) holmesFeatherstone = HolmesFeatherstoneAttractionModel( FramesFactory.getITRF(IERSConventions.IERS_2010, True), provider) # SRP # ssc = IsotropicRadiationSingleCoefficient(100.0, 0.8) # Spacecraft surface area (m^2), C_r absorbtion # srp = SolarRadiationPressure(CelestialBodyFactory.getSun(), a, ssc) # sun, semi-major Earth, spacecraft sensitivity propagator.addForceModel(holmesFeatherstone) # propagator.addForceModel(ThirdBodyAttraction(CelestialBodyFactory.getSun())) # propagator.addForceModel(ThirdBodyAttraction(CelestialBodyFactory.getMoon())) # propagator.addForceModel(srp) propagator.setMasterMode(60.0, TutorialStepHandler()) propagator.setInitialState(initial_state) # propagator.setEphemerisMode() finalstate = propagator.propagate(initial_date.shiftedBy( 10. * 24 * 60**2)) # TIme shift in seconds
FramesFactory.getITRF(IERSConventions.IERS_2010, True), ) # The COE for the orbit to be defined a, ecc, inc, raan, argp, nu = (6828137.0, 0.0073, 87.0, 20.0, 10.0, 0) # Define the orkeit and poliastro orbits to be used for all the event validation # cases in this script epoch0_orekit = AbsoluteDate(2020, 1, 1, 0, 0, 00.000, TimeScalesFactory.getUTC()) ss0_orekit = KeplerianOrbit( float(a), float(ecc), float(inc * DEG_TO_RAD), float(argp * DEG_TO_RAD), float(raan * DEG_TO_RAD), float(nu * DEG_TO_RAD), PositionAngle.TRUE, FramesFactory.getEME2000(), epoch0_orekit, Constants.WGS84_EARTH_MU, ) epoch0_poliastro = Time("2020-01-01", scale="utc") ss0_poliastro = Orbit.from_classical( Earth, a * u.m, ecc * u.one, inc * u.deg, raan * u.deg, argp * u.deg, nu * u.deg, epoch0_poliastro,