def __init__(self, propagator, propagator_options = {}, propagator_args = {}, parameters = {}, epoch=Time(57125.7729, format='mjd'), oid=1, **kwargs ): self.oid = oid self.parameters = copy.copy(SpaceObject.default_parameters) self.parameters.update(parameters) #assume MJD if not "Time" object if not isinstance(epoch, Time): epoch = Time(epoch, format='mjd', scale='utc') self.epoch = epoch if 'state' in kwargs: self.state = kwargs['state'] else: if 'aop' in kwargs: kwargs['omega'] = kwargs.pop('aop') if 'raan' in kwargs: kwargs['Omega'] = kwargs.pop('raan') if 'mu0' in kwargs: kwargs['anom'] = kwargs.pop('mu0') self.state = pyorb.Orbit( M0 = kwargs.get('M_cent', pyorb.M_earth), degrees = True, type='mean', auto_update = True, direct_update = True, num = 1, m = self.parameters.get('m', 0.0), **kwargs ) self.__propagator = propagator self.propagator_options = propagator_options self.propagator_args = propagator_args self.propagator = propagator(**propagator_options)
def get_orbit(self, n, fields=None, M_cent=pyorb.M_earth, degrees=True, anomaly='mean'): '''Get the one row from the population as a :class:`pyorb.Orbit` instance. ''' if fields is None: fields = self.state_fields kwargs = {} for key in fields: kwargs[key] = self.data[n][key] #TODO: generalize this better if 'aop' in kwargs: kwargs['omega'] = kwargs.pop('aop') if 'raan' in kwargs: kwargs['Omega'] = kwargs.pop('raan') if 'mu0' in kwargs: kwargs['anom'] = kwargs.pop('mu0') for key in ['X', 'Y', 'Z', 'VX', 'VY', 'VZ']: if key in kwargs: kwargs[key.lower()] = kwargs.pop(key) obj = pyorb.Orbit(M0=M_cent, degrees=degrees, type=anomaly, auto_update=True, direct_update=True, num=1, **kwargs) return obj
def propagate(self, t, state0, epoch, **kwargs): '''Propagate a state :param float/list/numpy.ndarray/astropy.time.TimeDelta t: Time to propagate relative the initial state epoch. :param float/astropy.time.Time epoch: The epoch of the initial state. :param numpy.ndarray state0: 6-D Cartesian state vector in SI-units. :param bool radians: If true, all angles are assumed to be in radians. :return: 6-D Cartesian state vectors in SI-units. ''' if self.profiler is not None: self.profiler.start('Kepler:propagate') if self.logger is not None: self.logger.debug(f'Kepler:propagate:len(t) = {len(t)}') t, epoch = self.convert_time(t, epoch) times = epoch + t tv = t.sec if self.profiler is not None: self.profiler.start('Kepler:propagate:in_frame') if isinstance(state0, pyorb.Orbit): orb = state0.copy() elif isinstance(state0, dict): kw = copy.copy(state0) kw.update(kwargs) orb = pyorb.Orbit(**kw) cart0 = frames.convert( epoch, orb.cartesian, in_frame=self.settings['in_frame'], out_frame='GCRS', profiler=self.profiler, logger=self.logger, ) orb.cartesian = cart0 else: cart0 = frames.convert( epoch, state0, in_frame=self.settings['in_frame'], out_frame='GCRS', profiler=self.profiler, logger=self.logger, ) kw = { key: val for key, val in zip(pyorb.Orbit.CARTESIAN, cart0.flatten()) } kw.update(kwargs) orb = pyorb.Orbit(**kw) if self.profiler is not None: self.profiler.stop('Kepler:propagate:in_frame') orb.direct_update = False orb.auto_update = False if self.profiler is not None: self.profiler.start('Kepler:propagate:mean_motion') orb.add( num=len(tv), **{ key: val for key, val in zip(pyorb.Orbit.KEPLER, orb.kepler.flatten()) }) orb.delete(0) orb.propagate(tv) orb.calculate_cartesian() if self.profiler is not None: self.profiler.stop('Kepler:propagate:mean_motion') if self.profiler is not None: self.profiler.start('Kepler:propagate:out_frame') states = frames.convert( times, orb._cart, in_frame='GCRS', out_frame=self.settings['out_frame'], profiler=self.profiler, logger=self.logger, ) if self.profiler is not None: self.profiler.stop('Kepler:propagate:out_frame') if self.profiler is not None: self.profiler.stop('Kepler:propagate') if self.logger is not None: self.logger.debug(f'Kepler:propagate:completed') return states
''' Distribution transformation ============================ ''' import pyorb import numpy as np import matplotlib.pyplot as plt #for reproducibility np.random.seed(12398748) #We first create a standard orbit around the sun in SI units orb = pyorb.Orbit(M0=pyorb.M_sol) #Create 1000 equal orbits orb.add(num=1000, a=pyorb.AU, e=0, i=0, omega=0, Omega=0, anom=0) #calculate cartesian elements orb.calculate_cartesian() #Add a symmetric Gaussian distribution in the plane on the velocity std = 3e3 orb.vx += np.random.randn(orb.num) * std orb.vy += np.random.randn(orb.num) * std #now when we call any Keplerian element, the distribution in kepler space will be calculated automatically fig, axes = plt.subplots(1, 2, figsize=(10, 6)) axes[0].plot(orb.vx * 1e-3, orb.vy * 1e-3, '.') axes[0].set_title('Cartesian velocity', fontsize=22)
import matplotlib.pyplot as plt import pyorb import sorts eiscat3d = sorts.radars.eiscat3d from sorts.propagator import SGP4 Prop_cls = SGP4 Prop_opts = dict( settings = dict( out_frame='ITRS', ), ) prop = Prop_cls(**Prop_opts) orb = pyorb.Orbit(M0 = pyorb.M_earth, direct_update=True, auto_update=True, degrees=True, a=7200e3, e=0.05, i=75, omega=0, Omega=79, anom=72, epoch=53005.0) print(orb) t = sorts.equidistant_sampling( orbit = orb, start_t = 0, end_t = 3600*24*1, max_dpos=1e3, ) print(f'Temporal points: {len(t)}') states = prop.propagate(t, orb.cartesian[:,0], orb.epoch, A=1.0, C_R = 1.0, C_D = 1.0) passes = eiscat3d.find_passes(t, states) fig = plt.figure(figsize=(15,15))
import pyorb from astropy.utils import iers from astropy.time import Time iers.conf.auto_download = False from sorts.propagator import SGP4 from sorts import frames prop = SGP4() orb = pyorb.Orbit( M0=pyorb.M_earth, direct_update=True, auto_update=True, degrees=True, a=7000e3, e=0, i=69, omega=0, Omega=0, anom=0, ) t = np.linspace(0, 3600 * 24.0, num=5000) mjd0 = Time(53005.0, format='mjd', scale='utc') times = Time(mjd0 + t / (3600 * 24.0), format='mjd', scale='utc') states_teme = prop.propagate(t, orb.cartesian[:, 0], epoch=mjd0, A=1.0, C_R=1.0,
location='500@10', epochs=epoch.jd, ) jpl_el = jpl_obj.elements() print(jpl_obj) print(jpl_el) for key in jpl_el.keys(): print(f'{key}:{jpl_el[key].data[0]}') orb = pyorb.Orbit( M0=pyorb.M_sol, direct_update=True, auto_update=True, degrees=True, a=jpl_el['a'].data[0] * pyorb.AU, e=jpl_el['e'].data[0], i=jpl_el['incl'].data[0], omega=jpl_el['w'].data[0], Omega=jpl_el['Omega'].data[0], anom=jpl_el['M'].data[0], type='mean', ) print('Initial orbit:') print(orb) def H_to_D(H, pV): return 10**(3.1236 - 0.5 * np.log10(pV) - 0.2 * H) obj = sorts.SpaceObject(
import matplotlib.pyplot as plt import numpy as np import pyorb num = 500 [ecc, anom] = np.meshgrid( np.linspace(0, 0.99, num=num), np.linspace(0, 360, num=num), ) orb = pyorb.Orbit(M0=pyorb.M_sol, num=num**2, a=1 * pyorb.AU, e=ecc.reshape(num**2), i=0, omega=90, Omega=0, anom=anom.reshape(num**2), degrees=True, type='true') true = orb.true_anomaly.reshape(num, num) mean = orb.mean_anomaly.reshape(num, num) print(orb) print(f'Orbit anomaly type: {orb.type}') fig, ax = plt.subplots(1, 1) c = ax.pcolormesh(ecc, true, mean - true) ax.set_xlabel('Eccentricity [1]')
''' Equinoctial orbits ==================== ''' import pyorb import numpy as np orb = pyorb.Orbit(M0=pyorb.M_sol, degrees=True) #equinoctial orbit orb.update(a=1 * pyorb.AU, e=0.01, i=0.9, omega=24, Omega=0, anom=22) print(orb) equi = orb.equinoctial for ind, var in enumerate(orb.EQUINOCTIAL): print(f'{var:<2}: {equi[ind]}') #change p variable equi[3] += 0.1 #set values, kepler and cart automatically updated orb.equinoctial = equi print(orb) equi = orb.equinoctial for ind, var in enumerate(orb.EQUINOCTIAL): print(f'{var:<2}: {equi[ind]}')
#reproducibility np.random.seed(324245) prop = SGP4(settings=dict( in_frame='TEME', out_frame='TEME', ), ) std_pos = 1e3 #1km std noise on positions orb = pyorb.Orbit(M0=pyorb.M_earth, direct_update=True, auto_update=True, degrees=True, a=7200e3, e=0.05, i=75, omega=0, Omega=79, anom=72, type='mean') print(orb) state0 = orb.cartesian[:, 0] t = np.linspace(0, 600.0, num=100) mjd0 = 53005 params = dict(A=1.0, C_R=1.0, C_D=2.3) states = prop.propagate(t, state0, mjd0, **params) noisy_pos = states[:3, :] + np.random.randn(3, len(t)) * std_pos
''' Orbit transfer =============== ''' import pyorb import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import Slider init = pyorb.Orbit(M0=pyorb.M_sol, degrees=True, a=1 * pyorb.AU, e=0, i=0, omega=0, Omega=0, anom=0) target = pyorb.Orbit(M0=pyorb.M_sol, degrees=True, a=2 * pyorb.AU, e=0, i=23, omega=0, Omega=90, anom=0) sliders = [] def plot_transfer(init, target):
import sorts eiscat3d = sorts.radars.eiscat3d from sorts.controller import Tracker from sorts.propagator import SGP4 from sorts.profiling import Profiler p = Profiler() p.start('total') prop = SGP4(settings=dict(out_frame='ITRF', ), ) orb = pyorb.Orbit(M0=pyorb.M_earth, direct_update=True, auto_update=True, degrees=True, a=6700e3, e=0, i=75, omega=0, Omega=80, anom=72) t = np.linspace(0, 120, num=10) mjd0 = 53005 p.start('propagate') states = prop.propagate(t, orb.cartesian[:, 0], mjd0, A=1.0, C_R=1.0, C_D=1.0) p.stop('propagate') e3d = Tracker(radar=eiscat3d, t=t, ecefs=states[:3, :], profiler=p) fig = plt.figure(figsize=(15, 15)) ax = fig.add_subplot(111, projection='3d')
''' Propagation ============ ''' import pyorb import numpy as np import matplotlib.pyplot as plt #for reproducibility np.random.seed(12398748) #We first create a standard orbit around the sun in SI units #We want it to be completely empty to start with so we set num=0 orb = pyorb.Orbit(M0=pyorb.M_sol, num=0) #Create 10 equal orbits orb.add(num=25, a=pyorb.AU, e=0, i=0, omega=0, Omega=0, anom=0) #calculate cartesian elements orb.calculate_cartesian() #Add a symmetric Gaussian distribution on the velocity std = 3e3 orb.vx += np.random.randn(orb.num) * std orb.vy += np.random.randn(orb.num) * std orb.vz += np.random.randn(orb.num) * std #Go back to kepler based on the cartesian orb.calculate_kepler()
names.append(meta['controller_type'].__name__) targets.append(meta['target']) for ri, rx in enumerate(radar.rx): data[ind, 1 + ri * 2] = rx.beam.azimuth data[ind, 2 + ri * 2] = rx.beam.elevation data = data.T.tolist() + [names, targets] data = list(map(list, zip(*data))) return data orb = pyorb.Orbit(M0=pyorb.M_earth, direct_update=True, auto_update=True, degrees=True, num=3, a=6700e3, e=0, i=75, omega=0, Omega=np.linspace(79, 82, num=3), anom=72, epoch=53005) print(orb) e3d = MyScheduler(radar=eiscat3d, propagator=prop) e3d.update(orb) data = e3d.schedule() rx_head = [ f'rx{i} {co}' for i in range(len(eiscat3d.rx)) for co in ['az', 'el'] ]
''' Perturbation by modifying elements =================================== ''' import pyorb import numpy as np import matplotlib.pyplot as plt #We first create a standard orbit around the sun in SI units orb = pyorb.Orbit( M0=pyorb.M_sol, a=1 * pyorb.AU, e=0.2, i=0, omega=0, Omega=0, anom=0, degrees=True, ) print(orb) #prepare a propagation dt = 3600 * 24.0 num = 1000 r = np.empty((3, num)) for ti in range(num): orb.propagate(dt) # We need to calculate all the perturbations before perturbing it
''' Get started tutorial ========================= ''' import pyorb #We first create a standard orbit around the sun in SI units orb = pyorb.Orbit(M0=pyorb.M_sol) #Lets switch to degrees for more human readable units, this can also be given # at orbit creation as a keyword parameter orb.degrees = True #Currently the orbit has no values print(orb) print('\n') #give it a circular orbit in the plane orb.update(a=1 * pyorb.AU, e=0, i=0, omega=0, Omega=0, anom=0) print(orb) print(f'Orbital period: {orb.period/(3600.0*24)} days') print('\n') #Now as soon as we try to look at any cartesian elements # the orbit will be transformed to cartesian space and the # Cartesian elements are stored print(f'Orbit X-position is {orb.x*1e-3} km') print(f'Orbit velocity vector is {orb.v*1e-3} km/s') print(orb) print('\n')