def test_mean2true(self): M = n.linspace(0, 1.5 * n.pi, num=100, dtype=n.float) nu = dpt.mean2true(M, 0.0) nt.assert_array_almost_equal(nu, M, decimal=7) e = n.linspace(0, 0.9, num=100, dtype=n.float) nu = dpt.mean2true(n.pi, e) nu0 = n.ones(e.shape, dtype=n.float) * n.pi nt.assert_array_almost_equal(nu, nu0, decimal=7)
def _gen_cart(self, p): orb = n.array([ self.init_data['a'], self.init_data['e'], self.init_data['inc'], self.init_data['aop'], self.init_data['raan'], dpt.mean2true(self.init_data['mu0'], self.init_data['e'], radians=False), ]) cart = dpt.kep2cart(orb, m=self.init_data['m'], M_cent=p.M_earth, radians=False) self.init_data_cart = { 'x': cart[0], 'y': cart[1], 'z': cart[2], 'vx': cart[3], 'vy': cart[4], 'vz': cart[5], 'mjd0': 57125.7729, 'C_D': 2.3, 'C_R': 1.0, 'm': 8000, 'A': 1.0, }
def get_orbit(self,t,a,e,inc,raan,aop,mu0,mjd0, **kwargs): ''' **Implementation:** Units are in meters and degrees. Keyword arguments are: **Uses:** * See :func:`propagator_base.PropagatorBase.get_orbit`. ''' m = kwargs.setdefault('m', 0.0) orb = np.array([a,e,inc,aop,raan,dpt.mean2true(mu0,e, radians = False)], dtype=np.float) if self._inframe_to_heliocentric: M_cent = self.planets_mass[self._earth_ind - 1] else: M_cent = self.m_sun x, y, z, vx, vy, vz = dpt.kep2cart( orb, m=m, M_cent=M_cent, radians=False, ) return self.get_orbit_cart(t, x, y, z, vx, vy, vz, mjd0, **kwargs)
def test_mean_true_inverse_array(self): M = n.linspace(0.0, 1.5 * n.pi, num=100, dtype=n.float) e = n.linspace(0, 0.99, num=100, dtype=n.float) Mv, ev = n.meshgrid(M, e) nu_test = dpt.mean2true(Mv, ev) M_test = dpt.true2mean(nu_test, ev) nt.assert_array_almost_equal(M_test, Mv, decimal=7)
def test_mean_true_inverse_float(self): M = n.linspace(0.0, 1.5 * n.pi, num=100, dtype=n.float) e = n.linspace(0, 0.99, num=100, dtype=n.float) for eit in e: for Mit in M: nu_test = dpt.mean2true(Mit, eit) M_test = dpt.true2mean(nu_test, eit) nt.assert_almost_equal(M_test, Mit, decimal=7)
def get_states(self, M_cent = propagator_sgp4.M_earth): '''Use the orbital parameters and get the state.''' orbs = self.get_all_orbits(order_angs = True).T orbs[:,5] = dpt.mean2true(orbs[:,5], orbs[:,1], radians=False) if 'm' in self.header: mv = self.objs['m'] else: mv = np.zeros(len(self), dtype=self._default_dtype) states = dpt.kep2cart(orbs, m=mv, M_cent=M_cent, radians=False).T return states
def get_orbit(self, t, a, e, inc, raan, aop, mu0, mjd0, **kwargs): ''' **Implementation:** All state-vector units are in meters. Keyword arguments contain only mass :code:`m` in kg and is not required. They also contain a option to give angles in radians or degrees. By default input is assumed to be degrees. **Frame:** The input frame is always the same as the output frame. :param float m: Mass of the object in kg. :param bool radians: If true, all angles are assumed to be in radians. ''' radians = kwargs.setdefault('radians', False) m = kwargs.setdefault('m', 0.0) if radians: one_lap = np.pi*2.0 else: one_lap = 360.0 gravitational_param = consts.G*(M_earth + m) mean_motion = np.sqrt(gravitational_param/(a**3.0))/(np.pi*2.0) t = self._make_numpy(t) mean_anomalies = mu0 + t*mean_motion*one_lap mean_anomalies = np.remainder(mean_anomalies, one_lap) true_anomalies = dpt.mean2true(mean_anomalies, e, radians=radians) orb0 = np.array([a, e, inc, aop, raan], dtype=np.float64) orb0.shape = (5,1) orbs = np.empty((6, len(t)), dtype=np.float64) orbs[:5, :] = np.repeat(orb0, len(t), axis=1) orbs[5, :] = true_anomalies states_raw = dpt.kep2cart(orbs, m=m, M_cent=M_earth, radians=radians) if self.in_frame != self.out_frame: states = frame_conversion(states_raw, t/(3600.0*24.0) + mjd0, self.orekit_in_frame, self.orekit_out_frame) else: states = states_raw return states
def _sgp4_elems2cart(kep, radians=True): '''Orbital elements to cartesian coordinates. Wrap DPT-function to use mean anomaly, km and reversed order on aoe and raan. Neglecting mass is sufficient for this calculation (the standard gravitational parameter is 24 orders larger then the change). ''' _kep = kep.copy() _kep[0] *= 1e3 tmp = _kep[4] _kep[4] = _kep[3] _kep[3] = tmp _kep[5] = dpt.mean2true(_kep[5], _kep[1], radians=radians) cart = dpt.kep2cart(kep, m=0.0, M_cent=propagator_sgp4.M_earth, radians=radians) return cart
def get_orbit(self, t, a, e, inc, raan, aop, mu0, mjd0, **kwargs): ''' **Implementation:** All state-vector units are in meters. Keyword arguments contain only information needed for ballistic coefficient :code:`B` used by SGP4. Either :code:`B` or :code:`C_D`, :code:`A` and :code:`m` must be supplied. They also contain a option to give angles in radians or degrees. By default input is assumed to be degrees. **Frame:** The input frame is ECI (TEME) for orbital elements and Cartesian. The output frame is as standard ECEF (ITRF). But can be set to TEME. :param float B: Ballistic coefficient :param float C_D: Drag coefficient :param float A: Cross-sectional Area :param float m: Mass :param bool radians: If true, all angles are assumed to be in radians. ''' if 'm' in kwargs: m = kwargs['m'] else: m = 0.0 if 'radians' in kwargs: radians = kwargs['radians'] else: radians = False if not radians: inc = np.radians(inc) mu0 = np.radians(mu0) raan = np.radians(raan) aop = np.radians(aop) orb = np.array([a, e, inc, aop, raan, dpt.mean2true(mu0, e, radians=True)],dtype=np.float) state_c = dpt.kep2cart(orb, m=m, M_cent=M_earth, radians=True) return self.get_orbit_cart(t, x=state_c[0], y=state_c[1], z=state_c[2], vx=state_c[3], vy=state_c[4], vz=state_c[5], mjd0=mjd0, **kwargs)
def update(self, **kwargs): '''Updates the orbital elements and Cartesian state vector of the space object. Can update any of the related state parameters, all others will automatically update. Cannot update Keplerian and Cartesian elements simultaneously. :param float a: Semi-major axis in km :param float e: Eccentricity :param float i: Inclination in degrees :param float aop: Argument of perigee in degrees :param float raan: Right ascension of the ascending node in degrees :param float mu0: Mean anomaly in degrees :param float x: X position in km :param float y: Y position in km :param float z: Z position in km :param float vx: X-direction velocity in km/s :param float vy: Y-direction velocity in km/s :param float vz: Z-direction velocity in km/s ''' kep = ['a', 'e', 'i', 'raan', 'aop', 'mu0'] cart = ['x', 'y', 'z', 'vx', 'vy', 'vz'] kep_orb = False cart_orb = False for key, val in kwargs.items(): if key in kep: kep_orb = True setattr(self, key, val) elif key in cart: cart_orb = True setattr(self, key, val) else: raise TypeError('{} variable cannot be updated'.format(key)) if kep_orb and cart_orb: raise TypeError( 'Cannot update both Cartesian and Kepler elements at the same time' ) if kep_orb: orb = n.array([ self.a * 1e3, self.e, self.i, self.aop, self.raan, dpt.mean2true(self.mu0, self.e, radians=False) ], dtype=n.float) state_c = dpt.kep2cart( orb, m=n.array([self.m ]), M_cent=self.M_cent, radians=False) * 1e-3 if cart_orb: state = n.array( [self.x, self.y, self.z, self.vx, self.vy, self.vz], dtype=n.float) * 1e3 self.state_cart = state orb_c = dpt.cart2kep(state, m=self.m, M_cent=self.M_cent, radians=False) if kep_orb: self.x = state_c[0] self.y = state_c[1] self.z = state_c[2] self.vx = state_c[3] self.vy = state_c[4] self.vz = state_c[5] self.state_cart = state_c * 1e3 if cart_orb: self.a = orb_c[0] * 1e-3 self.e = orb_c[1] self.i = orb_c[2] self.raan = orb_c[4] self.aop = orb_c[3] self.mu0 = dpt.true2mean(orb_c[5], orb_c[1], radians=False)
def __init__(self, a, e, i, raan, aop, mu0, d=0.01, C_D=2.3, A=1.0, m=1.0, mjd0=57125.7729, oid=42, M_cent=M_e, C_R=1.0, propagator=default_propagator, propagator_options={}, **kwargs): self.kwargs = kwargs self.M_cent = M_cent orb = n.array( [a * 1e3, e, i, aop, raan, dpt.mean2true(mu0, e, radians=False)], dtype=n.float) state_c = dpt.kep2cart(orb, m=m, M_cent=self.M_cent, radians=False) * 1e-3 x = state_c[0] y = state_c[1] z = state_c[2] vx = state_c[3] vy = state_c[4] vz = state_c[5] self.state_cart = state_c * 1e3 self.a = a self.e = e self.i = i self.oid = oid self.raan = raan self.aop = aop self.mu0 = mu0 self.x = x self.y = y self.z = z self.vx = vx self.vy = vy self.vz = vz self.C_D = C_D self.C_R = C_R self.A = A self.m = m self.mjd0 = mjd0 self._propagator = propagator self.propagator_options = propagator_options self.prop = propagator(**propagator_options) self.d = d
orbs_fail = [] fail_inds = [] fail_err = [] fail_errv = [] for ind, kep in enumerate(orb_init_list): #print('{}/{} done'.format(ind, len(orb_init_list))) M_earth = propagator_sgp4.SGP4.GM * 1e9 / consts.G state_TEME = dpt.kep2cart(kep, m=0.0, M_cent=M_earth, radians=False) * 1e-3 mean_elements = tle.TEME_to_TLE(state_TEME, mjd0=mjd0, kepler=False) mlst = mean_elements.tolist() mlst[0] *= 1e3 mlst[4] = mean_elements[3] mlst[3] = mean_elements[4] mlst[5] = dpt.mean2true(mean_elements[5], mean_elements[1], radians=True) mean_orbs.append(mlst) state = propagator_sgp4.sgp4_propagation(mjd0, mean_elements, B=0, dt=0.0) state_diff = np.abs(state - state_TEME) * 1e3 try: nt.assert_array_less(state_diff[:3], np.full((3, ), 100, dtype=state_diff.dtype)) nt.assert_array_less(state_diff[3:], np.full((3, ), 10, dtype=state_diff.dtype)) orbs_pass.append(kep.tolist()) cols.append(0.0) except AssertionError as err: fail_inds.append(ind) orbs_fail.append(kep.tolist())
import numpy as n from keplerian_sgp4 import sgp4_propagator as sgp_p import dpt_tools as dpt init_data = { 'a': 7000, 'e': 0.0, 'inc': 90.0, 'raan': 10, 'aop': 10, 'mu0': 40.0, 'mjd0': 2457126.2729, 'C_D': 2.3, 'm': 8000, 'A': 1.0, } self.t0 = n.array([0.0], dtype=n.float) p = sgp_p() ecefs = p.get_orbit(self.t, **self.init_data) o = n.array( [7000e3, 0.0, 90.0, 10.0, 10.0, dpt.mean2true(40.0, 0.0, radians=False)]) x = dpt.kep2cart(o, m=init_data['m'], M_cent=5.98e24, radians=False) print(x) print(ecefs)
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