Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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)