def __init__(self, orekit_data, settings=None, **kwargs): super(Orekit, self).__init__(settings=settings, **kwargs) if self.logger is not None: self.logger.debug(f'sorts.propagator.Orekit:init') if self.profiler is not None: self.profiler.start('Orekit:init') setup_orekit_curdir(filename=orekit_data) if self.logger is not None: self.logger.debug(f'Orekit:init:orekit-data = {orekit_data}') self.utc = TimeScalesFactory.getUTC() self.__settings = dict() self.__settings['SolarStrengthLevel'] = getattr( org.orekit.forces.drag.atmosphere.data. MarshallSolarActivityFutureEstimation.StrengthLevel, self.settings['solar_activity_strength']) self._tolerances = None if self.settings['constants_source'] == 'JPL-IAU': self.mu = Constants.JPL_SSD_EARTH_GM self.R_earth = Constants.IAU_2015_NOMINAL_EARTH_EQUATORIAL_RADIUS self.f_earth = (Constants.IAU_2015_NOMINAL_EARTH_EQUATORIAL_RADIUS - Constants.IAU_2015_NOMINAL_EARTH_POLAR_RADIUS ) / Constants.IAU_2015_NOMINAL_EARTH_POLAR_RADIUS else: self.mu = Constants.WGS84_EARTH_MU self.R_earth = Constants.WGS84_EARTH_EQUATORIAL_RADIUS self.f_earth = Constants.WGS84_EARTH_FLATTENING self.M_earth = self.mu / scipy.constants.G self.__params = None self._forces = {} if self.settings['radiation_pressure']: self._forces['radiation_pressure'] = None if self.settings['drag_force']: self._forces['drag_force'] = None if self.settings['earth_gravity'] == 'HolmesFeatherstone': provider = org.orekit.forces.gravity.potential.GravityFieldFactory.getNormalizedProvider( self.settings['gravity_order'][0], self.settings['gravity_order'][1]) holmesFeatherstone = org.orekit.forces.gravity.HolmesFeatherstoneAttractionModel( FramesFactory.getITRF(IERSConventions.IERS_2010, True), provider, ) self._forces['earth_gravity'] = holmesFeatherstone elif self.settings['earth_gravity'] == 'Newtonian': Newtonian = org.orekit.forces.gravity.NewtonianAttraction(self.mu) self._forces['earth_gravity'] = Newtonian else: raise Exception( 'Supplied Earth gravity model "{}" not recognized'.format( self.settings['earth_gravity'])) if self.settings['solarsystem_perturbers'] is not None: for body in self.settings['solarsystem_perturbers']: body_template = getattr(CelestialBodyFactory, 'get{}'.format(body)) body_instance = body_template() perturbation = org.orekit.forces.gravity.ThirdBodyAttraction( body_instance) self._forces['perturbation_{}'.format(body)] = perturbation if self.logger is not None: for key in self._forces: if self._forces[key] is not None: self.logger.debug( f'Orekit:init:_forces:{key} = {type(self._forces[key])}' ) else: self.logger.debug(f'Orekit:init:_forces:{key} = None') if self.profiler is not None: self.profiler.stop('Orekit:init')
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 __init__( self, in_frame='EME', out_frame='ITRF', frame_tidal_effects=False, integrator='DormandPrince853', min_step=0.001, max_step=120.0, position_tolerance=10.0, earth_gravity='HolmesFeatherstone', gravity_order=(10, 10), solarsystem_perturbers=['Moon', 'Sun'], drag_force=True, atmosphere='DTM2000', radiation_pressure=True, solar_activity='Marshall', constants_source='WGS84', solar_activity_strength='WEAK', logger_func=None, ): super(PropagatorOrekit, self).__init__() self.logger_func = logger_func self.__log = {} self.__log_tmp = {} if self.logger_func is not None: self._logger_start('__init__') self.solarsystem_perturbers = solarsystem_perturbers self.in_frame = in_frame self.frame_tidal_effects = frame_tidal_effects self.out_frame = out_frame self.drag_force = drag_force self.gravity_order = gravity_order self.atmosphere = atmosphere self.radiation_pressure = radiation_pressure self.solar_activity = solar_activity self.SolarStrengthLevel = getattr( org.orekit.forces.drag.atmosphere.data. MarshallSolarActivityFutureEstimation.StrengthLevel, solar_activity_strength) self.integrator = integrator self.minStep = min_step self.maxStep = max_step self.position_tolerance = position_tolerance self._tolerances = None self.constants_source = constants_source if constants_source == 'JPL-IAU': self.mu = Constants.JPL_SSD_EARTH_GM self.R_earth = Constants.IAU_2015_NOMINAL_EARTH_EQUATORIAL_RADIUS self.f_earth = (Constants.IAU_2015_NOMINAL_EARTH_EQUATORIAL_RADIUS - Constants.IAU_2015_NOMINAL_EARTH_POLAR_RADIUS ) / Constants.IAU_2015_NOMINAL_EARTH_POLAR_RADIUS else: self.mu = Constants.WGS84_EARTH_MU self.R_earth = Constants.WGS84_EARTH_EQUATORIAL_RADIUS self.f_earth = Constants.WGS84_EARTH_FLATTENING self.M_earth = self.mu / scipy.constants.G self.earth_gravity = earth_gravity self.__params = None self.inputFrame = self._get_frame(self.in_frame) self.outputFrame = self._get_frame(self.out_frame) if self.inputFrame.isPseudoInertial(): self.inertialFrame = self.inputFrame else: self.inertialFrame = FramesFactory.getEME2000() self.body = OneAxisEllipsoid(self.R_earth, self.f_earth, self.outputFrame) self._forces = {} if self.radiation_pressure: self._forces['radiation_pressure'] = None if self.drag_force: self._forces['drag_force'] = None if self.earth_gravity == 'HolmesFeatherstone': provider = org.orekit.forces.gravity.potential.GravityFieldFactory.getNormalizedProvider( self.gravity_order[0], self.gravity_order[1]) holmesFeatherstone = org.orekit.forces.gravity.HolmesFeatherstoneAttractionModel( FramesFactory.getITRF(IERSConventions.IERS_2010, True), provider, ) self._forces['earth_gravity'] = holmesFeatherstone elif self.earth_gravity == 'Newtonian': Newtonian = org.orekit.forces.gravity.NewtonianAttraction(self.mu) self._forces['earth_gravity'] = Newtonian else: raise Exception( 'Supplied Earth gravity model "{}" not recognized'.format( self.earth_gravity)) if self.solarsystem_perturbers is not None: for body in self.solarsystem_perturbers: body_template = getattr(CelestialBodyFactory, 'get{}'.format(body)) body_instance = body_template() perturbation = org.orekit.forces.gravity.ThirdBodyAttraction( body_instance) self._forces['perturbation_{}'.format(body)] = perturbation if self.logger_func is not None: self._logger_record('__init__')
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)