Esempio n. 1
0
    def setup_spacecraft(self, spacecraft=None, oneshot=False):
        """Create Spacecraft and respective blender object."""

        sc_state = None
        sc_rot_state = None
        if spacecraft is None:
            sssb_state = self.sssb.get_state(self.encounter_date)
            sc_state = sc.Spacecraft.calc_encounter_state(sssb_state,
                                                       self.minimum_distance,
                                                       self.relative_velocity,
                                                       self.with_terminator,
                                                       self.with_sunnyside)
        else:
            if 'r' in spacecraft:
                sc_state = PVCoordinates(Vector3D(spacecraft['r']), 
                                         Vector3D(spacecraft.get('v', [0.0, 0.0, 0.0])))
            if 'angleaxis' in spacecraft:
                sc_pxpz_rot = Rotation(Vector3D(spacecraft['angleaxis'][1:4]),
                                       spacecraft['angleaxis'][0],
                                       RotationConvention.FRAME_TRANSFORM)

                # transform camera where +x is forward and +z is up into -z is forward and +y is up
                mzpy_rot = self.pxpz_to_mzpy(sc_pxpz_rot)
                sc_rot_state = AngularCoordinates(mzpy_rot, Vector3D(0., 0., 0.))

        self.spacecraft = sc.Spacecraft("CI",
                                     self.mu_sun,
                                     sc_state,
                                     self.encounter_date,
                                     rot_state=sc_rot_state,
                                     oneshot=oneshot)
Esempio n. 2
0
    def change_initial_conditions(self, new_state, new_epoch, new_mass):
        """Change the initial conditions given to the propagator without initializing it again.

        Args:
            initial_state (Cartesian): New initial state of the satellite in cartesian coordinates.
            epoch (datetime.datetime): New starting date of the propagator.
            mass (float64): New satellite mass.

        """
        # Create position and velocity vectors as Vector3D
        p = Vector3D(
            1e3,  # convert to [m]
            Vector3D(float(new_state.R[0]), float(new_state.R[1]),
                     float(new_state.R[2])))
        v = Vector3D(
            1e3,  # convert to [m/s]
            Vector3D(float(new_state.V[0]), float(new_state.V[1]),
                     float(new_state.V[2])))

        # Extract frame from initial/pre-propagated state
        orbit_frame = self._propagator._propagator_num.getInitialState(
        ).getFrame()

        orekit_date = to_orekit_date(new_epoch)

        # Evaluate new initial orbit
        initialOrbit = CartesianOrbit(PVCoordinates(p, v), orbit_frame,
                                      orekit_date, Cst.WGS84_EARTH_MU)

        # Create new spacecraft state
        newSpacecraftState = SpacecraftState(initialOrbit, new_mass)

        # Rewrite propagator initial conditions
        self._propagator._propagator_num.setInitialState(newSpacecraftState)
Esempio n. 3
0
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)
Esempio n. 4
0
def orekit_state(x0):
    if type(x0) == np.ndarray:
        x0 = [xi.item() for xi in x0]

    r = Vector3D(*(x0[0:3]))
    v = Vector3D(*(x0[3:6]))
    return PVCoordinates(r, v)
Esempio n. 5
0
File: frame.py Progetto: rev0nat/SMS
def itrs_gcrs_single(itrs):
  """ Transformation ITRS to GCRS.
  """

  utc = TimeScalesFactory.getUTC()
  date = itrs.index[0]
  X = float(itrs['x[m]'][0])
  Y = float(itrs['y[m]'][0])
  Z = float(itrs['z[m]'][0])
  Vx = float(itrs['vx[m/s]'][0])
  Vy = float(itrs['vy[m/s]'][0])
  Vz = float(itrs['vz[m/s]'][0])
  ok_date = AbsoluteDate(date.year, date.month, date.day, date.hour, date.minute,
                         date.second + float(date.microsecond) / 1000000., utc)
  PV_coordinates = PVCoordinates(Vector3D(X, Y, Z), Vector3D(Vx, Vy, Vz))
  start_state = TimeStampedPVCoordinates(ok_date, PV_coordinates)
  state_itrf = AbsolutePVCoordinates(itrf, start_state)
  state_gcrf = AbsolutePVCoordinates(gcrf, state_itrf.getPVCoordinates(gcrf))
  pos = state_gcrf.position
  vel = state_gcrf.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=itrs.index)

  return dframe
Esempio n. 6
0
def _pose_absolute_keplerian(ns_spacecraft, init_coords, init_epoch):
    pos = init_coords["init_coord"]
    init_state = Cartesian()

    init_pose_oe = KepOrbElem()
    init_pose_oe.a = float(pos["a"])
    init_pose_oe.e = float(pos["e"])
    init_pose_oe.i = float(radians(pos["i"]))
    init_pose_oe.O = float(radians(pos["O"]))
    init_pose_oe.w = float(radians(pos["w"]))
    try:
        init_pose_oe.v = float(radians(pos["v"]))
    except KeyError:
        try:
            init_pose_oe.m = float(radians(pos["m"]))
        except KeyError:
            raise ValueError("No Anomaly for initialization of spacecraft: " +
                             ns_spacecraft)

    # Coordinates given in J2000 Frame
    # ----------------------------------------------------------------------------------------
    if init_coords["coord_frame"] == "J2000":
        init_state.from_keporb(init_pose_oe)
    # ----------------------------------------------------------------------------------------

    if init_coords["coord_frame"] == "TEME":
        teme_state = CartesianTEME()
        teme_state.from_keporb(init_pose_oe)

        init_frame = FramesFactory.getTEME()
        inertialFrame = FramesFactory.getEME2000()

        TEME2EME = init_frame.getTransformTo(inertialFrame,
                                             to_orekit_date(init_epoch))
        p = Vector3D(
            float(1e3),  # convert to [m]
            Vector3D(float(teme_state.R[0]), float(teme_state.R[1]),
                     float(teme_state.R[2])))
        v = Vector3D(
            float(1e3),  # convert to [m/s]
            Vector3D(float(teme_state.V[0]), float(teme_state.V[1]),
                     float(teme_state.V[2])))

        pv_EME = TEME2EME.transformPVCoordinates(PVCoordinates(p, v))

        init_state.R = np.array([
            pv_EME.position.x, pv_EME.position.y, pv_EME.position.z
        ]) / 1e3  # convert to [km]
        init_state.V = np.array([
            pv_EME.velocity.x, pv_EME.velocity.y, pv_EME.velocity.z
        ]) / 1e3  # convert to [km/s]

    # ----------------------------------------------------------------------------------------

    return init_state
Esempio n. 7
0
def _pose_absolute_cartesian(ns_spacecraft, init_coords, init_epoch):
    pos = init_coords["init_coord"]
    init_state = Cartesian()

    # Coordinates given in J2000 Frame
    # ----------------------------------------------------------------------------------------
    if init_coords["coord_frame"] == "J2000":
        init_state.R = np.array(
            [float(pos["x"]),
             float(pos["y"]),
             float(pos["z"])])

        init_state.V = np.array(
            [float(pos["v_x"]),
             float(pos["v_y"]),
             float(pos["v_z"])])
    # ----------------------------------------------------------------------------------------

    # Coordinates given in ITRF Frame
    # ----------------------------------------------------------------------------------------
    elif init_coords["coord_frame"] == "ITRF":
        inertialFrame = FramesFactory.getEME2000()
        init_frame = FramesFactory.getITRF(
            IERS.IERS_2010, False)  # False -> don't ignore tidal effects
        p = Vector3D(
            float(1e3),  # convert to [m]
            Vector3D(float(pos["x"]), float(pos["y"]), float(pos["z"])))
        v = Vector3D(
            float(1e3),  # convert to [m/s]
            Vector3D(float(pos["v_x"]), float(pos["v_y"]), float(pos["v_z"])))

        ITRF2EME = init_frame.getTransformTo(inertialFrame,
                                             to_orekit_date(init_epoch))
        pv_EME = ITRF2EME.transformPVCoordinates(PVCoordinates(p, v))

        init_state.R = np.array([
            pv_EME.position.x, pv_EME.position.y, pv_EME.position.z
        ]) / 1e3  # convert to [km]
        init_state.V = np.array([
            pv_EME.velocity.x, pv_EME.velocity.y, pv_EME.velocity.z
        ]) / 1e3  # convert to [km/s]

    else:
        raise ValueError(
            "[" + ns_spacecraft + " ]: " +
            "Conversion from coordinate frame " + init_coords["coord_frame"] +
            " not implemented. Please provided coordinates in a different reference frame."
        )
    # ----------------------------------------------------------------------------------------

    return init_state
Esempio n. 8
0
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)
Esempio n. 9
0
    def calc_encounter_state(cls,
                             sssb_state,
                             min_dist,
                             rel_vel,
                             terminator=True,
                             sunnyside=False):
        """Calculate the state of a Spacecraft at closest distance to SSSB."""
        (sssb_pos, sssb_vel) = sssb_state

        sc_pos = cls.calc_encounter_pos(sssb_pos, min_dist, terminator,
                                        sunnyside)

        sc_vel = sssb_vel.scalarMultiply(
            (sssb_vel.getNorm() - rel_vel) / sssb_vel.getNorm())

        #logger.info("Spacecraft relative velocity: %s", sc_vel)
        #logger.info("Spacecraft distance from sun: %s",
        #                 sc_pos.getNorm()/Constants.IAU_2012_ASTRONOMICAL_UNIT)

        return PVCoordinates(sc_pos, sc_vel)
Esempio n. 10
0
    def change_initial_conditions(self, initial_state, date, mass):
        """
            Allows to change the initial conditions given to the propagator without initializing it again.

        Args:
            initial_state (Cartesian): New initial state of the satellite in cartesian coordinates.
            date (datetime): New starting date of the propagator.
            mass (float64): New satellite mass.
        """
        # Redefine the start date
        self.date = date

        # Create position and velocity vectors as Vector3D
        p = Vector3D(
            float(initial_state.R[0]) * 1e3,
            float(initial_state.R[1]) * 1e3,
            float(initial_state.R[2]) * 1e3)
        v = Vector3D(
            float(initial_state.V[0]) * 1e3,
            float(initial_state.V[1]) * 1e3,
            float(initial_state.V[2]) * 1e3)

        # Initialize orekit date
        seconds = float(date.second) + float(date.microsecond) / 1e6
        orekit_date = AbsoluteDate(date.year, date.month, date.day, date.hour,
                                   date.minute, seconds,
                                   TimeScalesFactory.getUTC())

        # Extract frame
        inertialFrame = FramesFactory.getEME2000()

        # Evaluate new initial orbit
        initialOrbit = CartesianOrbit(PVCoordinates(p, v), inertialFrame,
                                      orekit_date, Cst.WGS84_EARTH_MU)

        # Create new spacecraft state
        newSpacecraftState = SpacecraftState(initialOrbit, mass)

        # Rewrite propagator initial conditions
        self.orekit_prop._propagator_num.setInitialState(newSpacecraftState)
Esempio n. 11
0
def frame_conversion(state, mjd, orekit_in_frame, orekit_out_frame):
    '''Convert Cartesian state between two frames. Currently options are:

    * EME
    * CIRF
    * ITRF
    * TIRF
    * ITRFEquinox
    * TEME

    # TODO: finish docstring
    '''

    state_out = np.empty(state.shape, dtype=state.dtype)

    pos = org.hipparchus.geometry.euclidean.threed.Vector3D(
        float(state[0]), float(state[1]), float(state[2]))
    vel = org.hipparchus.geometry.euclidean.threed.Vector3D(
        float(state[3]), float(state[4]), float(state[5]))
    PV_state = PVCoordinates(pos, vel)

    transform = orekit_in_frame.getTransformTo(orekit_out_frame,
                                               mjd2absdate(mjd))
    new_PV = transform.transformPVCoordinates(PV_state)

    x_tmp = new_PV.getPosition()
    v_tmp = new_PV.getVelocity()

    state_out[0] = x_tmp.getX()
    state_out[1] = x_tmp.getY()
    state_out[2] = x_tmp.getZ()
    state_out[3] = v_tmp.getX()
    state_out[4] = v_tmp.getY()
    state_out[5] = v_tmp.getZ()

    return state_out
Esempio n. 12
0
File: frame.py Progetto: rev0nat/SMS
def convert_cart_single_orekit(to_conv,ref_to_conv,target_ref):
  """ Coordinate frame transformation with Orekit modules.
 
  INPUTS
  ------

  to_conv: dataframe
    Cartesian coordinates.
  ref_to_conv: string
    Initial reference frame ('itrf','gcrf','teme', 'eme2000')
  target_ref: string
    Final reference frame ('itrf','gcrf','teme', 'eme2000')
  
  RETURN
  ------

  dframe: dataframe
    Cartesian coordinates.

  """

  date = to_conv.index[0]
  X = float(to_conv['x[m]'][0])
  Y = float(to_conv['y[m]'][0])
  Z = float(to_conv['z[m]'][0])
  Vx = float(to_conv['vx[m/s]'][0])
  Vy = float(to_conv['vy[m/s]'][0])
  Vz = float(to_conv['vz[m/s]'][0])
  ok_date = AbsoluteDate(date.year, date.month, date.day, date.hour, date.minute,
                         date.second + float(date.microsecond) / 1000000., utc)
  PV_coordinates = PVCoordinates(Vector3D(X, Y, Z), Vector3D(Vx, Vy, Vz))
  start_state = TimeStampedPVCoordinates(ok_date, PV_coordinates)
  if ref_to_conv == 'itrf':
    frame_to_conv = itrf_f
  elif ref_to_conv == 'gcrf':
    frame_to_conv = gcrf_f
  elif ref_to_conv == 'teme':
    frame_to_conv = teme_f
  elif ref_to_conv == 'eme2000':
    frame_to_conv = eme2000_f
  else:
    print(f'Unknown reference frame: {ref_to_conv}')
  if target_ref == 'itrf':
    target_frame = itrf_f
  elif target_ref == 'gcrf':
    target_frame = gcrf_f
  elif target_ref == 'teme':
    target_frame = teme_f
  elif target_ref == 'eme2000':
    target_frame = eme2000_f
  else:
    print(f'Unknown reference frame: {target_ref}')

  state_to_conv = AbsolutePVCoordinates(frame_to_conv,start_state)
  target_state = AbsolutePVCoordinates(target_frame,state_to_conv.getPVCoordinates(target_frame))
  pos = target_state.position
  vel = target_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=to_conv.index)

  return dframe
Esempio n. 13
0
    def propagate(self, t, state0, epoch, **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.

        See :func:`propagator_base.PropagatorBase.get_orbit`.
        '''
        if self.profiler is not None:
            self.profiler.start('Orekit:propagate')

        if self.settings['in_frame'].startswith('Orekit-'):
            self.inputFrame = self._get_frame(
                self.settings['in_frame'].replace('Orekit-', ''))
            orekit_in_frame = True
        else:
            self.inputFrame = self._get_frame('GCRF')
            orekit_in_frame = False

        if self.settings['out_frame'].startswith('Orekit-'):
            self.outputFrame = self._get_frame(
                self.settings['out_frame'].replace('Orekit-', ''))
            orekit_out_frame = True
        else:
            self.outputFrame = self._get_frame('GCRF')
            orekit_out_frame = False

        if self.inputFrame.isPseudoInertial():
            self.inertialFrame = self.inputFrame
        else:
            self.inertialFrame = FramesFactory.getEME2000()

        self.body = OneAxisEllipsoid(self.R_earth, self.f_earth,
                                     self.outputFrame)

        if isinstance(state0, pyorb.Orbit):
            state0_cart = np.squeeze(state0.cartesian)
        else:
            state0_cart = state0

        if self.settings['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.settings['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

        if 'm' not in kwargs:
            kwargs['m'] = 0.0

        t, epoch = self.convert_time(t, epoch)
        times = epoch + t

        mjd0 = epoch.mjd
        t = t.value
        if not isinstance(t, np.ndarray):
            t = np.array([t])

        if self.logger is not None:
            self.logger.debug(f'Orekit:propagate:len(t) = {len(t)}')

        if not orekit_in_frame:
            state0_cart = frames.convert(
                epoch,
                state0_cart,
                in_frame=self.settings['in_frame'],
                out_frame='GCRS',
                profiler=self.profiler,
                logger=self.logger,
            )

        initialDate = mjd2absdate(mjd0, self.utc)

        pos = org.hipparchus.geometry.euclidean.threed.Vector3D(
            float(state0_cart[0]), float(state0_cart[1]),
            float(state0_cart[2]))
        vel = org.hipparchus.geometry.euclidean.threed.Vector3D(
            float(state0_cart[3]), float(state0_cart[4]),
            float(state0_cart[5]))
        PV_state = PVCoordinates(pos, vel)

        if not self.inputFrame.isPseudoInertial():
            transform = self.inputFrame.getTransformTo(self.inertialFrame,
                                                       initialDate)
            PV_state = transform.transformPVCoordinates(PV_state)

        initialOrbit = CartesianOrbit(
            PV_state,
            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 = Orekit.OrekitVariableStep()

        if self.profiler is not None:
            self.profiler.start('Orekit:propagate:steps')

        if self.settings['heartbeat']:
            __heartbeat = self.heartbeat
        else:
            __heartbeat = None

        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,
                                    __heartbeat,
                                    profiler=self.profiler)

            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,
                                    __heartbeat,
                                    profiler=self.profiler)

            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 not orekit_out_frame:
            state = frames.convert(
                times,
                state,
                in_frame='GCRS',
                out_frame=self.settings['out_frame'],
                profiler=self.profiler,
                logger=self.logger,
            )

        if self.profiler is not None:
            self.profiler.stop('Orekit:propagate:steps')
            self.profiler.stop('Orekit:propagate')

        if self.logger is not None:
            self.logger.debug(f'Orekit:propagate:completed')

        return state
Esempio n. 14
0
    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
Esempio n. 15
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)