Beispiel #1
0
    def write_oem(self, t0, t1, n_items, fname):
        '''Writes OEM format file of orbital state for specific time interval.
        The states are linearly spaced in the specified time interval.

        :param float t0: Start time.
        :param float t1: End time.
        :param int n_items: State points between start and end times.
        '''
        tv = n.linspace(t0, t1, num=n_items, dtype=n.float)

        state = self.get_state(tv)

        ut0 = dpt.jd_to_unix(dpt.mjd_to_jd(self.mjd0))

        ccsds_write.write_oem(tv + ut0, state, oid=self.oid, fname=fname)
Beispiel #2
0
def _get_MicrosatR_state(mjd):
    tle_raw = '''1 43947U 19006A   19085.80962006  .00050945  29637-5  93510-4 0  9994
    2 43947  96.6379 359.2115 0016283 220.5574 212.4511 16.01198803  9765'''

    tle_raw = [line.strip() for line in tle_raw.split('\n')]
    if len(tle_raw) % 2 != 0:
        raise Exception('Not even number of lines [not TLE compatible]')
    line1, line2 = tle_raw[0], tle_raw[1]


    jd0 = tle.tle_jd(line1)
    mjd0 = dpt.jd_to_mjd(jd0)
    sat_id = tle.tle_id(line1)

    state_TEME = tle.TLE_propagation_TEME(line1, line2, dpt.mjd_to_jd(mjd))

    return state_TEME, sat_id
Beispiel #3
0
    def propagate(self, dt, frame_transformation, frame_options={}):
        '''Propagate and change the epoch of this space object

        Frame transformations available:
            * TEME: From ITRF to TEME
            * ITRF: From TEME to ITRF
            * None: Do not perform transformation
            * function pointer: use custom transformation function that takes state as first argument (in SI units) and keyword arguments
        
        '''

        state = self.get_state(np.array([dt], dtype=n.float64))
        self.mjd0 = self.mjd0 + dt / (3600.0 * 24.0)

        if isinstance(frame_transformation, str):
            jd_ut1 = dpt.mjd_to_jd(self.mjd0)

            frame_options.setdefault('xp', 0.0)
            frame_options.setdefault('yp', 0.0)

            if frame_transformation == 'ITRF':
                state_frame = tle.TEME_to_ITRF(state[:, 0], jd_ut1,
                                               **frame_options)
            elif frame_transformation == 'TEME':
                state_frame = tle.ITRF_to_TEME(state[:, 0], jd_ut1,
                                               **frame_options)
            else:
                raise ValueError('Tranformation {} not recognized'.format(
                    frame_transformation))
        elif isinstance(frame_transformation, None):
            pass
        else:
            state_frame = frame_transformation(state, jd_ut1, **frame_options)

        x, y, z, vx, vy, vz = (state_frame * 1e-3).flatten()

        self.update(
            x=x,
            y=y,
            z=z,
            vx=vx,
            vy=vy,
            vz=vz,
        )
Beispiel #4
0
    def __init__(self, population, known=False):
        self.size = len(population)
        assert self.size > 0, 'Population must contain at least one object.'

        self.population = population

        self._type = self.population._default_dtype

        self._data_format = [
            'oid',  #0
            'known',  #1
            't0_unix',  #2
            'tracks',  #3
            'tracklets',  #4
            'discovered',  #5
            'discovery_time',  #6
        ]

        mjd0s = population['mjd0']
        self._t0_unix = np.empty((self.size, ), dtype=self._type)
        for ind, mjd0 in enumerate(mjd0s):
            self._t0_unix[ind] = dpt.jd_to_unix(dpt.mjd_to_jd(mjd0))

        self._discovered = np.full((self.size, ), False, dtype=np.bool)
        self._discovery_track = np.empty((self.size, ), dtype=np.int64)
        self._discovery_time = np.empty((self.size, ), dtype=self._type)

        self._known = np.empty((self.size, ), dtype=np.bool)
        if isinstance(known, bool):
            for ind in range(self.size):
                self._known[ind] = known
        else:
            for ind in range(self.size):
                self._known[ind] = known[ind]

        self._oids = population['oid']

        self._maintinence = [None] * self.size
        self._detections = [None] * self.size

        self._det_fields = [
            "t0", "t1", "snr", 'tm', "range", "range_rate", "tx_gain",
            "rx_gain", "on_axis_angle"
        ]

        self._track_format = [
            ('t0', self._type),
            ('dt', self._type),
            ('tracklet', np.bool),
            ('tracklet_index', np.int64),
            ('tracklet_len', np.int64),
            ('SNRdB', self._type),
            ('SNRdB-t', self._type),
            ('index', np.int64),
            ('baselines', np.int64),
            ('type', '|S8'),
        ]
        self.tracks = np.empty((0, ), dtype=self._track_format)

        self._tracking_summary_dtype = [
            ('index', np.int64),
            ('peak-SNR-time', self._type),
            ('peak-SNRdB', self._type),
            ('tracking-time', self._type),
        ]
        self._scan_summary_dtype = [
            ('index', np.int64),
            ('detection-time', self._type),
            ('SNRdB', self._type),
            ('tracking-time', self._type),
        ]
        self._tracklet_statistics_dtype = [
            ('index', np.int64),
            ('track-id', np.int64),
            ('points-deviation-mean', self._type),
            ('points-deviation-std', self._type),
            ('points-deviation-skew', self._type),
            ('points', self._type),
            ('peak-SNRdB', self._type),
            ('span', self._type),
            ('points-deviation-normalized-mean', self._type),
            ('points-deviation-normalized-std', self._type),
            ('normalized-span', self._type),
        ]
        self._tracks_summary_dtype = [
            ('index', np.int64),
            ('tracks', self._type),
            ('type', '|S8'),
            ('tracklets', self._type),
            ('tracklet-len-sum', self._type),
            ('tracklet-len-mean', self._type),
            ('tracklet-len-std', self._type),
            ('peak-SNRdB-mean', self._type),
            ('peak-SNRdB-std', self._type),
        ]
        self._prior_dtype = [
            ('date', 'datetime64[us]'),
            ('index', np.int64),
            ('x', self._type),
            ('y', self._type),
            ('z', self._type),
            ('vx', self._type),
            ('vy', self._type),
            ('vz', self._type),
            ('cov', self._type, (6, 6)),
        ]
        self.priors = np.empty((0, ), dtype=self._prior_dtype)

        self._tracklet_statistics = np.empty(
            (0, ), dtype=self._tracklet_statistics_dtype)
        self._tracks_summary = np.empty((0, ),
                                        dtype=self._tracks_summary_dtype)
        self._tracking_summary = np.empty((0, ),
                                          dtype=self._tracking_summary_dtype)
        self._scan_summary = np.empty((0, ), dtype=self._scan_summary_dtype)

        self._tracklet_format = {
            'track_id': None,
            't': None,
            'index': None,
            'fnames': None,
            'is_prior': None,
        }
        self.tracklets = []
Beispiel #5
0
tle_mjds = np.empty((len(TLEs), ), dtype=np.float64)
for line_id, lines in enumerate(TLEs):
    line1, line2 = lines
    jd0 = tle.tle_jd(line1)
    mjd0 = dpt.jd_to_mjd(jd0)
    tle_mjds[line_id] = mjd0

best_tle = np.argmin(np.abs(tle_mjds - event_mjd))

line1, line2 = TLEs[best_tle]
sat_id = tle.tle_id(line1)
jd0 = tle.tle_jd(line1)
mjd0 = dpt.jd_to_mjd(jd0)

state_TEME = tle.TLE_propagation_TEME(line1, line2, dpt.mjd_to_jd(event_mjd))

kep = dpt.cart2kep(state_TEME, m=mass, M_cent=M_earth, radians=False)

print('{}'.format(kep[0, 0]))
print('{}'.format(kep[1, 0]))
print('{}'.format(kep[2, 0]))
print('{}'.format(kep[3, 0]))
print('{}'.format(kep[4, 0]))
print('{}'.format(kep[5, 0]))
'''

os.environ['TZ'] = 'GMT'
time.tzset()

dt = np.datetime64('2019-04-02T12:01')
Beispiel #6
0
def tle_jd(line1):
    np_date = tle_npdt(line1)
    return dpt.mjd_to_jd(dpt.npdt2mjd(np_date))
Beispiel #7
0
def correlate(data, station, population, metric, n_closest = 1, out_file = None, verbose=False, MPI_on=False):
    '''Given a mono-static measurement of ranges and rage-rates, a radar model and a population: correlate measurements with population.

    :param dict data: Dictionary that contains measurement data. Contents are described below.
    :param AntennaRX station: Model of receiver station that performed the measurement.
    :param Population population: Population to correlate against.
    :param function metric: Metric used to correlate measurement and simulation of population.
    :param int n_closest: Number of closest matches to output.
    :param str out_file: If not :code:`None`, save the output data to this path.
    :param bool MPI_on: If True use internal parallelization with MPI to calculate correlation. Turn to False to externally parallelize with MPI.
    

    **Measurement data:**

      The file must be a dictionary that contains three data-sets:
        * 't': Times in unix-seconds
        * 'r': Ranges in meters
        * 'v': Range-rates in meters per second
      They should all be numpy vectors of equal length.

    '''

    
    r = data['r']
    t = data['t']
    v = data['v']

    t_sort = t.argsort()
    t = t[t_sort]
    r = r[t_sort]
    v = v[t_sort]
    
    #lt correction
    lt_correction = r/scipy.constants.c
    t += lt_correction

    _day = 3600.0*24.0

    loc_ecef = station.ecef.copy()
    loc_ecef_norm = loc_ecef/n.linalg.norm(loc_ecef)

    jd_check = dpt.unix_to_jd(t)

    r_ref = n.empty(r.shape, dtype=r.dtype)
    v_ref = n.empty(v.shape, dtype=v.dtype)

    correlation_data = {}
    SO_generator = population.object_generator()

    if MPI_on:
        step = MPI.COMM_WORLD.size
        next_check = MPI.COMM_WORLD.rank
    else:
        step = 1
        next_check = 0

    for ind, obj in enumerate(SO_generator):
        if ind == next_check:
            if verbose:
                print('\n\nPID {} correlating {}/{} -------'.format(MPI.COMM_WORLD.rank, ind+1, len(population)))
                print(obj)
            
            jd_obj = dpt.mjd_to_jd(obj.mjd0)
            
            t_check = (jd_check - jd_obj)*_day
            states = obj.get_state(t_check)

            for jdi in range(jd_check.size):
                r_tmp = loc_ecef - states[:3,jdi]

                r_ref[jdi] = n.linalg.norm(r_tmp)
                v_ref[jdi] = n.dot(
                    states[3:,jdi],
                    r_tmp/r_ref[jdi],
                )

            residual_r_mu = n.mean(r_ref - r)
            residual_r_std = n.std(r_ref - r)
            residual_v_mu = n.mean(v_ref - v)
            residual_v_std = n.std(v_ref - v)
            if len(v_ref) > 1:
                residual_a = ((v_ref[-1] - v_ref[0]) - v[-1] - v[0])/(t[-1] - t[0])
            else:
                residual_a = 0

            if verbose:
                print('Residuals:')
                print('residual_r_mu  = {} m'.format(residual_r_mu))
                print('residual_r_std = {} m'.format(residual_r_std))
                print('residual_v_mu  = {} m/s'.format(residual_v_mu))
                print('residual_v_std = {} m/s'.format(residual_v_std))
                print('residual_a     = {} m/s^2'.format(residual_a))
            
            cdat = {
                    'r_ref': r_ref.copy(),
                    'v_ref': v_ref.copy(),
                    'sat_id': obj.oid,
                    'stat': [residual_r_mu, residual_r_std, residual_v_mu, residual_v_std, residual_a]
                }
            if obj.oid in correlation_data:
                correlation_data[obj.oid].append(cdat)
            else:
                correlation_data[obj.oid] = [cdat]

            next_check += step

    oids = population['oid']

    if step > 1:

        if MPI.COMM_WORLD.rank == 0:
            if verbose:
                print('---> PID %i: Receiving all results <barrier>'%(MPI.COMM_WORLD.rank))

            for T in range(1,MPI.COMM_WORLD.size):
                for ID in range(T,len(population),MPI.COMM_WORLD.size):
                    oid = oids[ID]
                    correlation_data[oid] = MPI.COMM_WORLD.recv(source=T, tag=oid)
                    if verbose:
                        print('PID{} recived packet {} from PID{} '.format(MPI.COMM_WORLD.rank, oid, T))
        else:
            if verbose:
                print('---> PID %i: Distributing all correlation results to process 0 <barrier>'%(MPI.COMM_WORLD.rank))

            for ID in range(MPI.COMM_WORLD.rank,len(population),MPI.COMM_WORLD.size):
                oid = oids[ID]
                MPI.COMM_WORLD.send(correlation_data[oid], dest=0, tag=oid)
        
        if verbose:
            print('---> Distributing done </barrier>')

    matches_cdat = []

    if MPI.COMM_WORLD.rank == 0 or not MPI_on:
        if verbose:
            print('Finding best matches.')
        
        match_metric = n.empty((len(correlation_data), 2), dtype = n.float64)
        key_list = []
        key_cnt = 0
        for key, cdats in correlation_data.items():
            key_list.append(key)
            tmp_metrics = n.empty((len(cdats),), dtype=n.float64)
            for cind, cdat in enumerate(cdats):
                tmp_metrics[cind] = metric(t, r, v, cdat['r_ref'], cdat['v_ref'])
            tmp_match = n.argmin(tmp_metrics)

            match_metric[key_cnt, 0] = tmp_metrics[tmp_match]
            match_metric[key_cnt, 1] = tmp_match
            if verbose:
                print('{}: {} metric'.format(key, match_metric[key_cnt]))
            key_cnt += 1


        match = n.argmin(match_metric[:,0])
        

        if len(match_metric) > n_closest:
            all_match = n.argpartition(match_metric[:,0], n_closest)
        else:
            all_match = list(range(len(correlation_data)))

        if verbose:
            print('Best match {}:{} at {} match metric'.format(
                key_list[match],
                int(match_metric[match,1]),
                match_metric[match,0],
            ))
        cdat = correlation_data[key_list[match]][int(match_metric[match,1])]

        r_ref = cdat['r_ref']
        v_ref = cdat['v_ref']

        if out_file is not None:

            with h5py.File(out_file, 'w') as h_corr:
                for key, cdat in correlation_data.items():
                    for dat_key, dat in cdat.items():
                        h_corr[key+'/'+dat_key] = n.array(dat)

                h_corr.attrs['sat_match'] = key_list[match]
                h_corr['residuals'] = n.array(cdat['stat'])

        if len(match_metric) > n_closest:
            for may_match in all_match[:n_closest]:
                matches_cdat.append(correlation_data[key_list[may_match]][int(match_metric[may_match,1])])
        else:
            for may_match in all_match:
                matches_cdat.append(correlation_data[key_list[may_match]][int(match_metric[may_match,1])])
    if step > 1:
        matches_cdat = MPI.COMM_WORLD.bcast(matches_cdat, root=0)

    return matches_cdat
Beispiel #8
0
def simulate_Microsat_R_debris(num, max_dv, radii_range, mass_range, C_D_range, seed, propagator, propagator_options, mjd):

    tle_raw = '''1 43947U 19006A   19069.62495353  .00222140  22344-4  39735-3 0  9995
    2 43947  96.6263 343.1609 0026772 226.5664 224.4731 16.01032328  7176
    1 43947U 19006A   19069.68634861  .00217235  21442-4  38851-3 0  9995
    2 43947  96.6282 343.2231 0026267 227.5469 217.1086 16.01062873  7183
    1 43947U 19006A   19069.81093322  .00066734  37128-5  12017-3 0  9992
    2 43947  96.6282 343.3467 0026246 227.0726 215.1493 16.01048534  7204
    1 43947U 19006A   19070.54563657  .00111882  69857-5  20248-3 0  9991
    2 43947  96.6271 344.0664 0025783 228.7058 125.4384 16.00925959  7318
    1 43947U 19006A   19070.80923755  .00013653  19858-5  25403-4 0  9991
    2 43947  96.6268 344.3320 0024927 225.1848 207.3499 16.01142181  7364
    1 43947U 19006A   19071.12831853  .00154965  11740-4  27719-3 0  9998
    2 43947  96.6279 344.6467 0025572 226.6832 243.5148 16.01113233  7412
    1 43947U 19006A   19071.80921646  .00118874  76545-5  21379-3 0  9993
    2 43947  96.6279 345.3224 0025491 224.0468 208.0149 16.01043615  7523
    1 43947U 19006A   19072.44153689  .00037015  24665-5  66863-4 0  9999
    2 43947  96.6279 345.9498 0025442 221.6016 252.7257 16.01159223  7620
    1 43947U 19006A   19072.74405995  .00022228  21113-5  40609-4 0  9997
    2 43947  96.6279 346.2500 0025432 220.3955 196.4626 16.01147542  7675
    1 43947U 19006A   19073.12825718  .00008242  19370-5  15873-4 0  9996
    2 43947  96.6304 346.6133 0023002 223.0617 246.6563 16.01114545  7738
    1 43947U 19006A   19073.44154376  .00035052  24102-5  63784-4 0  9998
    2 43947  96.6300 346.9244 0022588 225.2511 249.1037 16.01188227  7782
    1 43947U 19006A   19073.80920446 -.00023017  21041-5 -40417-4 0  9994
    2 43947  96.6337 347.2908 0022039 223.4278 208.5467 16.01076766  7841
    1 43947U 19006A   19074.74408622  .00119327  76982-5  21614-3 0  9994
    2 43947  96.6289 348.2321 0022856 222.6623 194.1149 16.01049775  7992
    1 43947U 19006A   19075.01672454  .00167822  13470-4  30180-3 0  9994
    2 43947  96.6290 348.5015 0022778 221.4659 325.7020 16.01154108  8039
    1 43947U 19006A   19075.54702546  .00026769  22010-5  48973-4 0  9993
    2 43947  96.6290 349.0278 0022754 219.3583 142.5100 16.01177853  8128
    1 43947U 19006A   19075.74902949  .00160298  12418-4  29196-3 0  9995
    2 43947  96.6301 349.2308 0021693 223.2409 221.9908 16.00986874  8150
    1 43947U 19006A   19075.80608134  .00151204  11245-4  27527-3 0  9991
    2 43947  96.6283 349.2862 0021642 222.7701 191.0541 16.01000711  8166
    1 43947U 19006A   19075.80608134  .00152613  11422-4  27780-3 0  9994
    2 43947  96.6283 349.2862 0021642 222.7701 191.0553 16.01002279  8160
    1 43947U 19006A   19076.04950662  .00212767  20643-4  38419-3 0  9990
    2 43947  96.6283 349.5277 0021615 221.8443 154.0766 16.01125308  8205
    1 43947U 19006A   19076.38314227  .00228397  23614-4  40852-3 0  9999
    2 43947  96.6283 349.8588 0021611 220.6464 277.1313 16.01285801  8254
    1 43947U 19006A   19076.56965602  .00375665  62286-4  68387-3 0  9990
    2 43947  96.6317 350.0396 0020897 222.9971 269.0493 16.01007118  8281
    1 43947U 19006A   19076.62489356  .00301460  40170-4  54811-3 0  9991
    2 43947  96.6317 350.0945 0020879 222.7479 227.4454 16.01029701  8290
    1 43947U 19006A   19076.74888822  .00206456  19517-4  37455-3 0  9990
    2 43947  96.6317 350.2206 0020779 222.3519 222.0257 16.01081824  8311
    1 43947U 19006A   19076.80334391  .00189842  16753-4  34417-3 0  9997
    2 43947  96.6317 350.2747 0020760 222.1378 175.8977 16.01098177  8326
    1 43947U 19006A   19077.25548485  .00042586  26475-5  77957-4 0  9991
    2 43947  96.6337 350.7139 0018680 228.2848 254.2224 16.01199217  8396
    1 43947U 19006A   19077.49923692  .00048049  28483-5  87602-4 0  9993
    2 43947  96.6337 350.9559 0018675 227.3154 219.3457 16.01241589  8433
    1 43947U 19006A   19077.73867148  .00176479  14671-4  32436-3 0  9999
    2 43947  96.6324 351.1992 0019599 225.2817 160.3011 16.00913438  8475
    1 43947U 19006A   19078.62402633  .00193781  17362-4  35487-3 0  9996
    2 43947  96.6337 352.0814 0019337 224.7610 220.1468 16.00981700  8611
    1 43947U 19006A   19079.44446882  .00056887  32197-5  10424-3 0  9994
    2 43947  96.6318 352.8859 0017932 222.6020 267.9762 16.01149860  8742
    1 43947U 19006A   19079.56114259  .00331197  48376-4  60603-3 0  9996
    2 43947  96.6357 353.0133 0018767 223.2624 219.3325 16.01004143  8769
    1 43947U 19006A   19079.87121502  .00017670  20377-5  33169-4 0  9996
    2 43947  96.6348 353.3097 0018626 221.5456 207.0221 16.01103300  8819
    1 43947U 19006A   19080.12837572  .00018161  20446-5  34105-4 0  9991
    2 43947  96.6342 353.5628 0017856 223.7454 246.0274 16.01109643  8852
    1 43947U 19006A   19080.25184005  .00021666  21015-5  40443-4 0  9990
    2 43947  96.6342 353.6854 0017855 223.2528 237.6932 16.01123784  8871
    1 43947U 19006A   19080.56838169  .00007182  19289-5  14116-4 0  9996
    2 43947  96.6323 353.9969 0018497 223.3308 260.9364 16.01125965  8927
    1 43947U 19006A   19080.80934521 -.00010028  19397-5 -17132-4 0  9998
    2 43947  96.6323 354.2362 0018496 222.3649 209.7823 16.01086764  8962
    1 43947U 19006A   19081.01817130 -.00000602  19026-5  00000+0 0  9994
    2 43947  96.6305 354.4520 0018602 217.7557 337.0831 16.00999357  8992
    1 43947U 19006A   19081.19970958  .00192780  17239-4  35047-3 0  9995
    2 43947  96.6332 354.6387 0017808 222.1497 298.3751 16.01166044  9020
    1 43947U 19006A   19081.44288380  .00132357  90623-5  24030-3 0  9997
    2 43947  96.6332 354.8802 0017799 221.2143 260.0465 16.01211967  9068
    1 43947U 19006A   19081.68209472  .00185493  16056-4  34001-3 0  9993
    2 43947  96.6354 355.1161 0017576 220.8387 198.1644 16.01033820  9107
    1 43947U 19006A   19081.80977756  .00126608  84347-5  23219-3 0  9995
    2 43947  96.6356 355.2444 0017575 222.5408 211.8678 16.01049036  9124
    1 43947U 19006A   19082.19785193  .00009851  19489-5  19026-4 0  9997
    2 43947  96.6356 355.6299 0017571 221.0666 288.6619 16.01097025  9186
    1 43947U 19006A   19082.25710510  .00009887  19472-5  19026-4 0  9996
    2 43947  96.6318 355.6880 0017118 220.4674 270.5748 16.01171238  9192
    1 43947U 19006A   19082.38407701  .00138221  97199-5  25077-3 0  9994
    2 43947  96.6325 355.8124 0017241 219.6702 282.7837 16.01240682  9219
    1 43947U 19006A   19082.68646591  .00149753  11067-4  27555-3 0  9993
    2 43947  96.6363 356.1139 0016876 222.4115 221.6813 16.01004284  9261
    1 43947U 19006A   19082.81114447  .00088395  50732-5  16304-3 0  9995
    2 43947  96.6363 356.2377 0016873 221.9425 220.2429 16.01009980  9289
    1 43947U 19006A   19083.00642146  .00143972  10375-4  26369-3 0  9992
    2 43947  96.6358 356.4314 0016878 221.0757 265.8708 16.01087252  9317
    1 43947U 19006A   19083.49288397 -.03265362  32488-2 -61588-2 0  9990
    2 43947  96.6406 356.9162 0017256 219.6745 189.3161 16.00630469  9392
    1 43947U 19006A   19083.74911125  .00084825  48174-5  15749-3 0  9999
    2 43947  96.6345 357.1709 0015989 224.4362 220.2191 16.00930159  9436
    1 43947U 19006A   19083.81116759  .00103815  62739-5  19235-3 0  9995
    2 43947  96.6324 357.2279 0015947 223.4735 218.5865 16.00945210  9446
    1 43947U 19006A   19083.93495759  .00147725  10814-4  27243-3 0  9990
    2 43947  96.6324 357.3507 0015945 222.9977 212.0347 16.00998010  9463
    1 43947U 19006A   19084.04992207  .00154144  11623-4  28342-3 0  9996
    2 43947  96.6354 357.4673 0016254 222.4775 154.7117 16.01036332  9486
    1 43947U 19006A   19084.56994306 -.00389064  56746-4 -71643-3 0  9995
    2 43947  96.6360 357.9786 0015819 222.1151 270.2904 16.00942425  9569
    1 43947U 19006A   19084.68712708  .00107795  66250-5  19877-3 0  9992
    2 43947  96.6366 358.0976 0015957 221.7662 225.5779 16.01024149  9583
    1 43947U 19006A   19084.74556389  .00097765  57838-5  18034-3 0  9991
    2 43947  96.6363 358.1566 0015910 221.6645 202.2537 16.01028963  9598
    1 43947U 19006A   19084.98720666  .00152043  11367-4  27860-3 0  9992
    2 43947  96.6362 358.3958 0015832 220.6056 155.1371 16.01110841  9636
    1 43947U 19006A   19085.19976117  .00022830  21215-5  42802-4 0  9998
    2 43947  96.6349 358.6073 0016094 221.4560 298.5857 16.01085713  9665
    1 43947U 19006A   19085.49952644  .00052661  30351-5  96803-4 0  9996
    2 43947  96.6377 358.9036 0016197 221.8414 224.9544 16.01169686  9718
    1 43947U 19006A   19085.56842683  .00054526  31167-5  10000-3 0  9997
    2 43947  96.6377 358.9720 0016198 221.5803 262.1287 16.01202917  9722
    1 43947U 19006A   19085.80962006  .00050945  29637-5  93510-4 0  9994
    2 43947  96.6379 359.2115 0016283 220.5574 212.4511 16.01198803  9765'''

    mass = 740

    tle_raw = [line.strip() for line in tle_raw.split('\n')]
    if len(tle_raw) % 2 != 0:
        raise Exception('Not even number of lines [not TLE compatible]')
    TLEs = zip(tle_raw[0::2], tle_raw[1::2])

    event_date = np.datetime64('2019-03-27T05:40')
    event_mjd = dpt.npdt2mjd(event_date)

    M_earth = propagator_sgp4.SGP4.GM*1e9/consts.G

    pop = Population(
        name='Simulated Microsat R debris',
        extra_columns = ['A', 'm', 'd', 'C_D', 'C_R'],
        space_object_uses = [True, True, True, True, True],
        propagator = propagator,
        propagator_options = propagator_options,
    )

    pop.allocate(num)


    tle_mjds = np.empty((len(TLEs),), dtype=np.float64)
    for line_id, lines in enumerate(TLEs):
        line1, line2 = lines
        jd0 = tle.tle_jd(line1)
        mjd0 = dpt.jd_to_mjd(jd0)
        tle_mjds[line_id] = mjd0

    best_tle = np.argmin(np.abs(tle_mjds - event_mjd))


    line1, line2 = TLEs[best_tle]
    sat_id = tle.tle_id(line1)
    jd0 = tle.tle_jd(line1)
    mjd0 = dpt.jd_to_mjd(jd0)

    state_TEME = tle.TLE_propagation_TEME(line1, line2, dpt.mjd_to_jd(event_mjd))

    #first has no pert

    states = np.repeat(state_TEME, num, axis=1)

    np.random.seed(seed)

    kep = dpt.cart2kep(state_TEME, m=mass, M_cent=M_earth, radians=False)
    pop.objs[0][1] = kep[0]*1e-3
    pop.objs[0][2] = kep[1]
    pop.objs[0][3] = kep[2]
    pop.objs[0][4] = kep[4]
    pop.objs[0][5] = kep[3]
    pop.objs[0][6] = dpt.true2mean(kep[5], kep[1], radians=False)
        
    pop.objs[0][0] = float(sat_id)
    pop.objs[0][7] = mjd0

    pop.objs[0][8] = np.pi*1.0**2
    pop.objs[0][9] = mass
    pop.objs[0][10] = 2.0
    pop.objs[0][11] = 2.3
    pop.objs[0][12] = 1.0

    ind = 1
    while ind < num:
        C_D = np.random.rand(1)*(C_D_range[1] - C_D_range[0]) + C_D_range[0]
        rho = 11e3
        while rho > 10e3:
            r = np.random.rand(1)*(radii_range[1] - radii_range[0]) + radii_range[0]
            A = np.pi*r**2
            m = np.random.rand(1)*(mass_range[1] - mass_range[0]) + mass_range[0]
            vol = 4.0/3.0*np.pi*r**3
            rho = m/vol

        pert_state = states[:,ind].copy()

        dv = np.random.rand(1)*max_dv
        ddir = _rand_sph(1).T

        pert_state[:3] += ddir[:,0]*dv

        kep = dpt.cart2kep(pert_state, m=mass, M_cent=M_earth, radians=False)

        if kep[0]*(1.0 - kep[1]) > 6353.0e3+100e3:

            pop.objs[ind][1] = kep[0]*1e-3
            pop.objs[ind][2] = kep[1]
            pop.objs[ind][3] = kep[2]
            pop.objs[ind][4] = kep[4]
            pop.objs[ind][5] = kep[3]
            pop.objs[ind][6] = dpt.true2mean(kep[5], kep[1], radians=False)
                    
            pop.objs[ind][0] = float(sat_id) + num
            pop.objs[ind][7] = mjd0

            pop.objs[ind][8] = A
            pop.objs[ind][9] = m
            pop.objs[ind][10] = r*2.0
            pop.objs[ind][11] = C_D
            pop.objs[ind][12] = 1.0

            ind += 1

    if 'out_frame' in pop.propagator_options:
        out_f = pop.propagator_options['out_frame']
    else:
        out_f = 'ITRF'
    pop.propagator_options['out_frame'] = 'TEME'
    pop = propagate_population(pop, mjd)
    pop.propagator_options['out_frame'] = out_f

    return pop
Beispiel #9
0
def create_tracklet(o,
                    radar,
                    t_obs,
                    hdf5_out=True,
                    ccsds_out=True,
                    dname="./tracklets",
                    noise=False,
                    dx=10.0,
                    dv=10.0,
                    dt=0.01,
                    ignore_elevation_thresh=False):
    '''Simulate tracks of objects.

    ionospheric limit is a lower limit on precision after ionospheric corrections
    '''

    if noise:
        noise = 1.0
    else:
        noise = 0.0

    # TDB, kludge, this should be allowed to change as a function of time
    bw = radar._tx[0].tx_bandwidth
    txlen = radar._tx[0].pulse_length * 1e6  # pulse length in microseconds
    ipp = radar._tx[0].ipp  # pulse length in microseconds
    n_ipp = int(radar._tx[0].n_ipp)  # pulse length in microseconds
    rfun, dopfun = debris.precalculate_dr(txlen, bw, ipp=ipp, n_ipp=n_ipp)

    t0_unix = dpt.jd_to_unix(dpt.mjd_to_jd(o.mjd0))

    if debug_low:
        for tx in radar._tx:
            print("TX %s" % (tx.name))
        for rx in radar._tx:
            print("RX %s" % (rx.name))

    rx_p = []
    tx_p = []
    for tx in radar._tx:
        tx_p.append(coord.geodetic2ecef(tx.lat, tx.lon, tx.alt))

    for rxi, rx in enumerate(radar._rx):
        rx_p.append(coord.geodetic2ecef(rx.lat, rx.lon, rx.alt))

    ecefs = o.get_orbit(t_obs)
    state = o.get_state(t_obs)
    ecefs_p_dt = o.get_orbit(t_obs + dt)
    ecefs_m_dt = o.get_orbit(t_obs - dt)

    # velocity in ecef
    ecef_vel = (0.5 * ((ecefs_p_dt - ecefs) + (ecefs - ecefs_m_dt)) / dt)

    # linearized error estimates for ecef state vector error std_dev, when three or more
    # delays and doppl er shifts are measured
    ecef_stdevs = []
    meas = []

    for tx in radar._tx:
        ecef_stdevs.append({"time_idx": [], "m_time": [], "ecef_stdev": []})

    for tx in radar._tx:
        m_rx = []
        for rx in radar._rx:
            m_rx.append({
                "time_idx": [],
                "m_time": [],
                "m_delay": [],
                "m_delay_std": [],
                "m_range": [],
                "m_range_std": [],
                "m_range_rate": [],
                "m_range_rate_std": [],
                "m_doppler": [],
                "m_doppler_std": [],
                "gain_tx": [],
                "gain_rx": [],
                "enr": [],
                "true_state": [],
                "true_time": [],
                "g_lat": [],
                "g_lon": []
            })
        meas.append(m_rx)

    # largest possible number of state vector measurements
    n_state_meas = len(radar._tx) * len(radar._rx)
    # jacobian for error covariance calc
    J = n.zeros([2 * n_state_meas, 6])
    Sigma_Lin = n.zeros([2 * n_state_meas, 2 * n_state_meas])

    # error standard deviation for state vector estimates at each position
    state_vector_errors = n.zeros([6, len(t_obs)])

    # go through all times
    for ti, t in enumerate(t_obs):
        p = n.array([ecefs[0, ti], ecefs[1, ti], ecefs[2, ti]])
        p_p = n.array(
            [ecefs_p_dt[0, ti], ecefs_p_dt[1, ti], ecefs_p_dt[2, ti]])
        p_m = n.array(
            [ecefs_m_dt[0, ti], ecefs_m_dt[1, ti], ecefs_m_dt[2, ti]])

        # for linearized state vector error determination
        p_dx0 = n.array([ecefs[0, ti] + dx, ecefs[1, ti], ecefs[2, ti]])
        p_dx1 = n.array([ecefs[0, ti], ecefs[1, ti] + dx, ecefs[2, ti]])
        p_dx2 = n.array([ecefs[0, ti], ecefs[1, ti], ecefs[2, ti] + dx])
        # doppler error comes from linear least squares

        # initialize jacobian
        J[:, :] = 0.0
        Sigma_Lin[:, :] = 0.0
        state_meas_idx = 0

        # go through all transmitters
        for txi, tx in enumerate(radar._tx):
            pos_vec_tx = -tx_p[txi] + p
            pos_vec_tx_p = -tx_p[txi] + p_p
            pos_vec_tx_m = -tx_p[txi] + p_m

            # for linearized errors
            pos_vec_tx_dx0 = -tx_p[txi] + p_dx0
            pos_vec_tx_dx1 = -tx_p[txi] + p_dx1
            pos_vec_tx_dx2 = -tx_p[txi] + p_dx2

            # incident k-vector
            k_inc = -2.0 * n.pi * pos_vec_tx / n.linalg.norm(
                pos_vec_tx) / tx.wavelength

            elevation_tx = 90.0 - coord.angle_deg(tx_p[txi], pos_vec_tx)

            if elevation_tx > tx.el_thresh or ignore_elevation_thresh:
                k0 = tx.point_ecef(
                    pos_vec_tx)  # we are pointing at the object when tracking
                gain_tx = tx.beam.gain(k0)  # get antenna gain
                range_tx = n.linalg.norm(pos_vec_tx)
                range_tx_p = n.linalg.norm(pos_vec_tx_p)
                range_tx_m = n.linalg.norm(pos_vec_tx_m)

                range_tx_dx0 = n.linalg.norm(pos_vec_tx_dx0)
                range_tx_dx1 = n.linalg.norm(pos_vec_tx_dx1)
                range_tx_dx2 = n.linalg.norm(pos_vec_tx_dx2)

                tx_to_target_time = range_tx / c.c

                # go through all receivers
                for rxi, rx in enumerate(radar._rx):
                    pos_vec_rx = -rx_p[rxi] + p
                    pos_vec_rx_p = -rx_p[rxi] + p_p
                    pos_vec_rx_m = -rx_p[rxi] + p_m

                    # rx k-vector
                    k_rec = 2.0 * n.pi * pos_vec_rx / n.linalg.norm(
                        pos_vec_rx) / tx.wavelength
                    # scattered k-vector
                    k_scat = k_rec - k_inc

                    # for linearized pos error
                    pos_vec_rx_dx0 = -rx_p[rxi] + p_dx0
                    pos_vec_rx_dx1 = -rx_p[rxi] + p_dx1
                    pos_vec_rx_dx2 = -rx_p[rxi] + p_dx2

                    elevation_rx = 90.0 - coord.angle_deg(
                        rx_p[rxi], pos_vec_rx)

                    if elevation_rx > rx.el_thresh or ignore_elevation_thresh:

                        k0 = rx.point_ecef(
                            pos_vec_rx
                        )  # we are pointing at the object when tracking

                        gain_rx = rx.beam.gain(k0)  # get antenna gain

                        range_rx = n.linalg.norm(pos_vec_rx)
                        range_rx_p = n.linalg.norm(pos_vec_rx_p)
                        range_rx_m = n.linalg.norm(pos_vec_rx_m)

                        range_rx_dx0 = n.linalg.norm(pos_vec_rx_dx0)
                        range_rx_dx1 = n.linalg.norm(pos_vec_rx_dx1)
                        range_rx_dx2 = n.linalg.norm(pos_vec_rx_dx2)

                        target_to_rx_time = range_rx / c.c
                        # SNR of object at measured location
                        enr_rx = debris.hard_target_enr(
                            gain_tx,
                            gain_rx,
                            tx.wavelength,
                            tx.tx_power,
                            range_tx,
                            range_rx,
                            o.diam,
                            bandwidth=tx.
                            coh_int_bandwidth,  # coherent integration bw
                            rx_noise_temp=rx.rx_noise)

                        if enr_rx > 1e8:
                            enr_rx = 1e8

                        if enr_rx < 0.1:
                            enr_rx = 0.1

                        #print("snr %1.2f"%(enr_rx))

                        dr = 10.0**(rfun(n.log10(enr_rx)))
                        ddop = 10.0**(dopfun(n.log10(enr_rx)))

                        # Unknown doppler shift due to ionosphere can be up to 0.1 Hz,
                        # estimate based on typical GNU Ionospheric tomography receiver phase curves.
                        if ddop < 0.1:
                            ddop = 0.1

                        dr = n.sqrt(dr**2.0 + iono_errfun(range_tx / 1e3)**
                                    2.0)  # add ionospheric error

                        if dr < o.diam:  # if object diameter is larger than range error, make it at least as big as target
                            dr = o.diam

                        r0 = range_tx + range_rx
                        rp = range_tx_p + range_rx_p
                        rm = range_tx_m + range_rx_m
                        range_rate_d = 0.5 * (
                            (rp - r0) +
                            (r0 - rm)) / dt  # symmetric numerical derivative

                        # doppler (m/s) using scattering k-vector
                        range_rate = n.dot(
                            pos_vec_rx / range_rx, state[3:6, ti]) + n.dot(
                                pos_vec_tx / range_tx, state[3:6, ti])

                        doppler = range_rate / tx.wavelength

                        #                        print("rr1 %1.1f rr2 %1.1f"%(range_rate_d,range_rate))
                        doppler_k = n.dot(k_scat, ecef_vel[:, ti]) / 2.0 / n.pi
                        range_rate_k = doppler_k * tx.wavelength

                        # for linearized errors, range rate at small perturbations to state vector velocity parameters
                        range_rate_k_dv0 = tx.wavelength * n.dot(
                            k_scat,
                            ecef_vel[:, ti] + n.array([dv, 0, 0])) / 2.0 / n.pi
                        range_rate_k_dv1 = tx.wavelength * n.dot(
                            k_scat,
                            ecef_vel[:, ti] + n.array([0, dv, 0])) / 2.0 / n.pi
                        range_rate_k_dv2 = tx.wavelength * n.dot(
                            k_scat,
                            ecef_vel[:, ti] + n.array([0, 0, dv])) / 2.0 / n.pi

                        # full range for error calculation, with small perturbations to position state
                        full_range_dx0 = range_rx_dx0 + range_tx_dx0
                        full_range_dx1 = range_rx_dx1 + range_tx_dx1
                        full_range_dx2 = range_rx_dx2 + range_tx_dx2

                        if enr_rx > tx.enr_thresh:
                            # calculate jacobian row for state vector errors
                            # range
                            J[2 * state_meas_idx,
                              0:3] = n.array([(full_range_dx0 - r0) / dx,
                                              (full_range_dx1 - r0) / dx,
                                              (full_range_dx2 - r0) / dx])
                            # range inverse variance
                            Sigma_Lin[2 * state_meas_idx,
                                      2 * state_meas_idx] = 1.0 / dr**2.0
                            # range-rate
                            J[2 * state_meas_idx + 1, 3:6] = n.array([
                                (range_rate_k_dv0 - range_rate_k) / dv,
                                (range_rate_k_dv1 - range_rate_k) / dv,
                                (range_rate_k_dv2 - range_rate_k) / dv
                            ])
                            # range-rate inverse variance
                            Sigma_Lin[2 * state_meas_idx + 1,
                                      2 * state_meas_idx +
                                      1] = 1.0 / (tx.wavelength * ddop)**2.0

                            state_meas_idx += 1

                            # detection!
                            if debug_low:
                                print(
                                    "rx %d tx el %1.2f rx el %1.2f gain_tx %1.2f gain_rx %1.2f enr %1.2f rr %1.2f prop time %1.6f dr %1.2f"
                                    % (rxi, elevation_tx, elevation_rx,
                                       gain_tx, gain_rx, enr_rx, range_rate,
                                       tx_to_target_time, dr))

                            # ground foot point in geodetic
                            llh = coord.ecef2geodetic(p[0], p[1], p[2])

                            # time is time of transmit pulse
                            meas[txi][rxi]["time_idx"].append(ti)
                            meas[txi][rxi]["m_time"].append(t + t0_unix)
                            meas[txi][rxi]["m_range"].append(
                                (range_tx + range_rx) / 1e3 +
                                noise * n.random.randn() * dr / 1e3)
                            meas[txi][rxi]["m_range_std"].append(dr / 1e3)

                            rr_std = c.c * ddop / radar._tx[
                                txi].freq / 2.0 / 1e3
                            meas[txi][rxi]["m_range_rate"].append(
                                range_rate / 1e3 +
                                noise * n.random.randn() * rr_std)
                            # 0.1 m/s error due to ionosphere
                            meas[txi][rxi]["m_range_rate_std"].append(rr_std)
                            meas[txi][rxi]["m_doppler"].append(
                                doppler +
                                noise * n.random.randn() * ddop / 1e3)
                            meas[txi][rxi]["m_doppler_std"].append(ddop)
                            meas[txi][rxi]["m_delay"].append(
                                tx_to_target_time + target_to_rx_time)
                            meas[txi][rxi]["g_lat"].append(llh[0])
                            meas[txi][rxi]["g_lon"].append(llh[1])
                            meas[txi][rxi]["enr"].append(enr_rx)

                            meas[txi][rxi]["gain_tx"].append(gain_tx)
                            meas[txi][rxi]["gain_rx"].append(gain_rx)

                            true_state = n.zeros(6)
                            true_state[3:6] = (0.5 * ((p_p - p) +
                                                      (p - p_m)) / dt) / 1e3
                            true_state[0:3] = p / 1e3

                            meas[txi][rxi]["true_state"].append(true_state)
                            meas[txi][rxi]["true_time"].append(t_obs[ti] +
                                                               t0_unix)
                        else:
                            if debug_high:
                                print("not detected: enr_rx {}".format(enr_rx))
                    else:
                        if debug_high:
                            print("not detected: elevation_rx {}".format(
                                elevation_rx))
            else:
                if debug_high:
                    print("not detected: elevation_tx {}".format(elevation_tx))

        # if more than three measurements of range and range-rate, then we maybe able to
        # observe true state. if so, calculate the linearized covariance matrix
        if state_meas_idx > 2:
            # use only the number of measurements that were good
            JJ = J[0:(2 * state_meas_idx), :]
            try:
                Sigma_post = n.linalg.inv(
                    n.dot(n.dot(n.transpose(JJ), Sigma_Lin), JJ))
                ecef_stdevs[txi]["time_idx"].append(ti)
                ecef_stdevs[txi]["m_time"].append(t)
                ecef_stdevs[txi]["ecef_stdev"].append(Sigma_post)

            except:
                print("Singular posterior covariance...")

    if debug_low:
        print(meas)
    fnames = write_tracklets(o,
                             meas,
                             radar,
                             dname,
                             hdf5_out=hdf5_out,
                             ccsds_out=ccsds_out)

    return (meas, fnames, ecef_stdevs)
Beispiel #10
0
def test_envisat_detection():
    from mpi4py import MPI

    # SORTS imports CORE
    import population_library as plib
    from simulation import Simulation

    #SORTS Libraries
    import radar_library as rlib
    import radar_scan_library as rslib
    import scheduler_library as schlib
    import antenna_library as alib
    import rewardf_library as rflib

    #SORTS functions
    import ccsds_write
    import dpt_tools as dpt

    sim_root = './tests/tmp_test_data/envisat_sim_test'

    radar = rlib.eiscat_uhf()
    radar.set_FOV(max_on_axis=30.0, horizon_elevation=25.0)

    scan = rslib.beampark_model(
        lat=radar._tx[0].lat,
        lon=radar._tx[0].lon,
        alt=radar._tx[0].alt,
        az=90.0,
        el=75.0,
    )
    radar.set_scan(scan)

    #tle files for envisat in 2016-09-05 to 2016-09-07 from space-track.
    TLEs = [
        ('1 27386U 02009A   16249.14961597  .00000004  00000-0  15306-4 0  9994',
         '2 27386  98.2759 299.6736 0001263  83.7600 276.3746 14.37874511760117'
         ),
        ('1 27386U 02009A   16249.42796553  .00000002  00000-0  14411-4 0  9997',
         '2 27386  98.2759 299.9417 0001256  82.8173 277.3156 14.37874515760157'
         ),
        ('1 27386U 02009A   16249.77590267  .00000010  00000-0  17337-4 0  9998',
         '2 27386  98.2757 300.2769 0001253  82.2763 277.8558 14.37874611760201'
         ),
        ('1 27386U 02009A   16250.12384028  .00000006  00000-0  15974-4 0  9995',
         '2 27386  98.2755 300.6121 0001252  82.5872 277.5467 14.37874615760253'
         ),
        ('1 27386U 02009A   16250.75012691  .00000017  00000-0  19645-4 0  9999',
         '2 27386  98.2753 301.2152 0001254  82.1013 278.0311 14.37874790760345'
         ),
    ]

    pop = plib.tle_snapshot(TLEs, sgp4_propagation=True)

    pop['d'] = n.sqrt(4 * 2.3 * 4 / n.pi)
    pop['m'] = 2300.
    pop['C_R'] = 1.0
    pop['C_D'] = 2.3
    pop['A'] = 4 * 2.3

    ccsds_file = './data/uhf_test_data/events/2002-009A-2016-09-06_08:27:08.tdm'

    obs_data = ccsds_write.read_ccsds(ccsds_file)
    jd_obs = dpt.mjd_to_jd(dpt.npdt2mjd(obs_data['date']))

    jd_sort = jd_obs.argsort()
    jd_obs = jd_obs[jd_sort]

    jd_det = jd_obs[0]

    pop.delete([0, 1, 2, 4])  #now just best ID left

    jd_pop = dpt.mjd_to_jd(pop['mjd0'][0])
    tt_obs = (jd_obs - jd_pop) * 3600.0 * 24.0

    sim = Simulation(
        radar=radar,
        population=pop,
        root=sim_root,
        scheduler=schlib.dynamic_scheduler,
    )

    sim.observation_parameters(
        duty_cycle=0.125,
        SST_fraction=1.0,
        tracking_fraction=0.0,
        SST_time_slice=0.2,
    )

    sim.run_observation(jd_obs[-1] - jd_pop + 1.0)

    sim.print_maintenance()
    sim.print_detections()

    sim.set_scheduler_args(logger=sim.logger, )

    sim.run_scheduler()
    sim.print_tracks()

    print(sim.catalogue.tracklets[0]['t'])
    print(jd_obs)

    shutil.rmtree(sim_root)
    assert False
Beispiel #11
0
    #propagator_options = {
    #    'in_frame': 'TEME',
    #    'out_frame': 'ITRF',
    #},
)

#it seems to around 25m^2 area
d = np.sqrt(25.0 * 4 / np.pi)
pop['d'] = d

measurement_file = './data/uhf_test_data/events/pass-1473150428660000.h5'
#ccsds_file = './data/uhf_test_data/events/2002-009A-1473150428.tdm'
ccsds_file = './data/uhf_test_data/events/2002-009A-2016-09-06_08:27:08.tdm'

obs_data = ccsds_write.read_ccsds(ccsds_file)
jd_obs = dpt.mjd_to_jd(dpt.npdt2mjd(obs_data['date']))

date_obs = obs_data['date']
sort_obs = np.argsort(date_obs)
date_obs = date_obs[sort_obs]
r_obs = obs_data['range'][sort_obs] * 0.5
v_obs = obs_data['doppler_instantaneous'][sort_obs]

#print(v_obs)
#exit()

#TO DEBUG
#jd_obs = jd_obs[:3]
#date_obs = date_obs[:3]
#r_obs = r_obs[:3]
Beispiel #12
0
    def get_orbit_cart(self, t, x, y, z, vx, vy, vz, 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 always ECEF.

        :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.
        '''
        t = self._make_numpy(t)

        if 'B' in kwargs:
            B = kwargs['B']
        else:
            B = 0.5*kwargs['C_D']*kwargs['A']/kwargs['m']

        state_c = np.array([x,y,z,vx,vy,vz], dtype=np.float)
        state_c *= 1e-3 #to km

        mean_elements = tle.TEME_to_TLE(state_c, mjd0=mjd0, kepler=False)

        if np.any(np.isnan(mean_elements)):
            raise Exception('Could not compute SGP4 initial state: {}'.format(mean_elements))

        # Create own SGP4 object
        obj = SGP4(mjd0, mean_elements, B)

        mjdates = mjd0 + t/86400.0
        pos=np.zeros([3,t.size])
        vel=np.zeros([3,t.size])

        for mi,mjd in enumerate(mjdates):
            y = obj.state(mjd)
            pos[:,mi] = y[:3]
            vel[:,mi] = y[3:]

        if self.out_frame == 'TEME':
            states=np.empty((6,t.size), dtype=np.float)
            states[:3,:] = pos*1e3
            states[3:,:] = vel*1e3
            return states

        elif self.out_frame == 'ITRF':
            if self.polar_motion:
                PM_data = tle.get_Polar_Motion(dpt.mjd_to_jd(mjdates))
                xp = PM_data[:,0]
                xp.shape = (1,xp.size)
                yp = PM_data[:,1]
                yp.shape = (1,yp.size)
            else:
                xp = 0.0
                yp = 0.0

            ecefs = teme2ecef(t, pos, vel, mjd0=mjd0, xp=xp, yp=yp ,model=self.polar_motion_model)
            ecefs *= 1e3 #to meter
            return ecefs
        else:
            raise Exception('Output frame {} not found'.format(self.out_frame))
Beispiel #13
0
def wls_state_est(mcmc=False, n_tracklets=1, track_length=600.0, n_points=3, oid=145128, N_samples=5000):
    """
    Weighted linear least squares estimation of orbital elements
    
    Simulate measurements using create tracklet and estimate 
    orbital parameters, which include six keplerian and area to mass ratio. 

    Use fmin search. 
    Optionally utilize MCMC to sample the distribution of parameters.
    
    number of tracklets, tracklet length, and number of tracklet points per tracklet are
    user definable, allowing one to try out different measurement strategies. 
    """
    # first we shall simulate some measurement
    # Envisat

    m = plib.master_catalog(sort=False)
    o = m.get_object(oid)

    dname="./test_tracklets_%d"%(oid)
    print(o)

    # figure out epoch in unix seconds
    t0_unix = dpt.jd_to_unix(dpt.mjd_to_jd(o.mjd0))

    if rank == 0:
        os.system("rm -Rf %s"%(dname))
        os.system("mkdir %s"%(dname))    
        
        e3d = rlib.eiscat_3d(beam='gauss')

        # time in seconds after mjd0
        t_all = n.linspace(0, 24*3600, num=1000)
    
        passes, _, _, _, _ = simulate_tracking.find_pass_interval(t_all, o, e3d)
        print(passes)
        if n_tracklets == None:
            n_tracklets = len(passes[0])
        n_tracklets = n.min([n_tracklets,len(passes[0])])

        for pi in range(n_tracklets):
            p = passes[0][pi]
            mean_t=0.5*(p[1]+p[0])
            print("duration %1.2f"%(p[1]-p[0]))
            if p[1]-p[0] > 50.0:
                if n_points == 1:
                    t_obs=n.array([mean_t])
                else:
                    t_obs=n.linspace(n.max([p[0],mean_t-track_length/2]), n.min([p[1],mean_t+track_length/2]),num=n_points)
                
                print(t_obs)
                meas, fnames, ecef_stdevs = st.create_tracklet(o, e3d, t_obs, hdf5_out=True, ccsds_out=True, dname=dname)

    # then we read these measurements
    comm.Barrier()
    
    fl=glob.glob("%s/*"%(dname))
    for f in fl:
        print(f)
        fl2=glob.glob("%s/*.h5"%(f))
        print(fl2)
        fl2.sort()
        
        true_states=[]
        all_r_meas=[]
        all_rr_meas=[]
        all_t_meas=[]
        all_true_states=[]
        tx_locs=[]
        rx_locs=[]
        range_stds=[]
        range_rate_stds=[]        
        
        for mf in fl2:
            h=h5py.File(mf,"r")
            all_r_meas.append(n.copy(h["m_range"].value))
            all_rr_meas.append(n.copy(h["m_range_rate"].value))
            all_t_meas.append(n.copy(h["m_time"].value-t0_unix))
            all_true_states.append(n.copy(h["true_state"].value))
            tx_locs.append(n.copy(h["tx_loc"].value))
            rx_locs.append(n.copy(h["rx_loc"].value))
            range_stds.append(n.copy(h["m_range_rate_std"].value))
            range_rate_stds.append(h["m_range_std"].value)
            h.close()
            
        # determine orbital elements
        o_prior = m.get_object(oid)

        # get best fit space object
        o_fit=mcmc_od(all_t_meas, all_r_meas, all_rr_meas, range_stds, range_rate_stds, tx_locs, rx_locs, o_prior, mcmc=mcmc, odir=dname, N_samples=N_samples)
Beispiel #14
0
def test_OD(root, sub_path):

    import orbit_determination
    import TLE_tools as tle
    import dpt_tools as dpt
    import radar_library as rlib
    import propagator_sgp4
    #import propagator_orekit
    #import propagator_neptune
    import ccsds_write

    radar = rlib.eiscat_3d(beam='interp', stage=1)

    radar.set_FOV(max_on_axis=90.0, horizon_elevation=10.0)
    radar.set_SNR_limits(min_total_SNRdb=10.0, min_pair_SNRdb=1.0)
    radar.set_TX_bandwith(bw = 1.0e6)
    
    #prop = propagator_neptune.PropagatorNeptune()
    prop = propagator_sgp4.PropagatorSGP4()

    mass=0.8111E+04
    diam=0.8960E+01
    m_to_A=128.651

    params = dict(
        A = {
            'dist': None,
            'val': mass/m_to_A,
        },
        d = {
            'dist': None,
            'val': diam,
        },
        m = {
            'dist': None,
            'val': mass,
        },
        C_D = {
            'dist': None,
            'val': 2.3,
        },
    )

    fname = glob.glob(root + sub_path + '*.oem')[0]
    prior_data, prior_meta = ccsds_write.read_oem(fname)
    prior_sort = np.argsort(prior_data['date'])
    prior_data = prior_data[prior_sort][0]

    prior_mjd = dpt.npdt2mjd(prior_data['date'])
    prior_jd = dpt.mjd_to_jd(prior_mjd)

    state0 = np.empty((6,), dtype=np.float64)
    state0[0] = prior_data['x']
    state0[1] = prior_data['y']
    state0[2] = prior_data['z']
    state0[3] = prior_data['vx']
    state0[4] = prior_data['vy']
    state0[5] = prior_data['vz']
    
    #state0_ITRF = state0.copy()
    state0 = tle.ITRF_to_TEME(state0, prior_jd, 0.0, 0.0)
    #state0_TEME = state0.copy()
    
    #state0_ITRF_ref = tle.TEME_to_ITRF(state0_TEME, prior_jd, 0.0, 0.0)
    
    #print(state0_ITRF_ref - state0_ITRF)
    #exit()
    
    data_folder = root + sub_path
    
    data_h5 = glob.glob(data_folder + '*.h5')
    
    data_h5_sort = np.argsort(np.array([int(_h.split('/')[-1].split('-')[1]) for _h in data_h5])).tolist()
    
    true_prior_h5 = data_h5[data_h5_sort[0]]
    true_obs_h5 = data_h5[data_h5_sort[1]]
    
    print(true_prior_h5)
    print(true_obs_h5)
    
    with h5py.File(true_prior_h5, 'r') as hf:
        true_prior = hf['true_state'].value.T*1e3
        true_prior_jd = dpt.unix_to_jd(hf['true_time'].value)
    
    print('-- True time diff prior [s] --')
    prior_match_ind = np.argmin(np.abs(true_prior_jd-prior_jd))
    jd_diff = prior_jd - true_prior_jd[prior_match_ind]
    state0_true = true_prior[:,prior_match_ind]
    state0_true = tle.ITRF_to_TEME(state0_true, true_prior_jd[prior_match_ind], 0.0, 0.0)
    
    print(prior_match_ind)
    print(jd_diff*3600.0*24.0)

    with h5py.File(true_obs_h5, 'r') as hf:
        true_obs = hf['true_state'].value.T*1e3
        true_obs_jd = dpt.unix_to_jd(hf['true_time'].value)

    data_tdm = glob.glob(data_folder + '*.tdm')
    #this next line i wtf, maybe clean up
    data_tdm_sort = np.argsort(np.array([int(_h.split('/')[-1].split('-')[-1][2]) for _h in data_tdm])).tolist()
    
    ccsds_files = [data_tdm[_tdm] for _tdm in data_tdm_sort]
    
    print('prior true vs prior mean')
    print(state0_true - state0)
    
    for _fh in ccsds_files:
        print(_fh)
    
    r_obs_v = []
    r_sig_v = []
    v_obs_v = []
    v_sig_v = []
    t_obs_v = []

    for ccsds_file in ccsds_files:
        obs_data = ccsds_write.read_ccsds(ccsds_file)
        sort_obs = np.argsort(obs_data['date'])
        obs_data = obs_data[sort_obs]
        jd_obs = dpt.mjd_to_jd(dpt.npdt2mjd(obs_data['date']))

        date_obs = obs_data['date']
        sort_obs = np.argsort(date_obs)
        date_obs = date_obs[sort_obs]
        r_obs = obs_data['range'][sort_obs]*1e3 #to m
        v_obs = -obs_data['doppler_instantaneous'][sort_obs]*1e3 #to m/s
        #v_obs = obs_data['doppler_instantaneous'][sort_obs]*1e3 #to m/s
        r_sig = 2.0*obs_data['range_err'][sort_obs]*1e3 #to m
        v_sig = 2.0*obs_data['doppler_instantaneous_err'][sort_obs]*1e3 #to m/s

        #TRUNCATE FOR DEBUG
        inds = np.linspace(0,len(jd_obs)-1,num=10,dtype=np.int64)
        jd_obs = jd_obs[inds]
        r_obs = r_obs[inds]
        v_obs = v_obs[inds]
        r_sig = r_sig[inds]
        v_sig = v_sig[inds]

        if ccsds_file.split('/')[-1].split('.')[0] == true_obs_h5.split('/')[-1].split('.')[0]:
            print('-- True time diff obs [s] --')
            jd_diff = jd_obs - true_obs_jd[inds]
            print(jd_diff*3600.0*24.0)

        #r_sig = np.full(r_obs.shape, 100.0, dtype=r_obs.dtype)
        #v_sig = np.full(v_obs.shape, 10.0, dtype=v_obs.dtype)
        
        r_obs_v.append(r_obs)
        r_sig_v.append(r_sig)
        v_obs_v.append(v_obs)
        v_sig_v.append(v_sig)

        t_obs = (jd_obs - prior_jd)*(3600.0*24.0)

        #correct for light time approximently
        lt_correction = r_obs*0.5/scipy.constants.c
        t_obs -= lt_correction

        t_obs_v.append(t_obs)


    print('='*10 + 'Dates' + '='*10)
    print('{:<8}: {} JD'.format('Prior', prior_jd))
    for ind, _jd in enumerate(jd_obs):
        print('Obs {:<4}: {} JD'.format(ind, _jd))
    

    print('='*10 + 'Observations' + '='*10)
    print(len(jd_obs))
    
    prior = {}
    prior['cov'] = np.diag([1e3, 1e3, 1e3, 1e1, 1e1, 1e1])*1.0
    prior['mu'] = state0
    
    print('='*10 + 'Prior Mean' + '='*10)
    print(prior['mu'])

    print('='*10 + 'Prior Covariance' + '='*10)
    print(prior['cov'])
    
    rx_ecef = []
    for rx in radar._rx:
        rx_ecef.append(rx.ecef)
    tx_ecef = radar._tx[0].ecef
    tune = 0

    trace = orbit_determination.determine_orbit(
        num = 2000,
        r = r_obs_v,
        sd_r = r_sig_v,
        v = v_obs_v,
        sd_v = v_sig_v,
        grad_dx = [10.0]*3 + [1.0]*3,
        rx_ecef = rx_ecef,
        tx_ecef = tx_ecef,
        t = t_obs_v,
        mjd0 = prior_mjd,
        params = params,
        prior = prior,
        propagator = prop,
        step = 'Metropolis',
        step_opts = {
            'scaling': 0.75,
        },
        pymc_opts = {
            'tune': tune,
            'discard_tuned_samples': True,
            'cores': 1,
            'chains': 1,
            'parallelize': True,
        },
    )
    
    #if comm.rank != 0:
    #    exit()

    var = ['$X$ [km]', '$Y$ [km]', '$Z$ [km]', '$V_X$ [km/s]', '$V_Y$ [km/s]', '$V_Z$ [km/s]']

    fig = plt.figure(figsize=(15,15))

    for ind in range(6):
        ax = fig.add_subplot(231+ind)
        ax.plot(trace['state'][:,ind]*1e-3)
        ax.set(
            xlabel='Iteration',
            ylabel='{}'.format(var[ind]),
        )


    state1 = np.mean(trace['state'], axis=0)

    print('='*10 + 'Trace summary' + '='*10)
    print(pm.summary(trace))

    _form = '{:<10}: {}'

    print('='*10 + 'Prior Mean' + '='*10)
    for ind in range(6):
        print(_form.format(var[ind], state0[ind]*1e-3))

    print('='*10 + 'Posterior state mean' + '='*10)
    for ind in range(6):
        print(_form.format(var[ind], state1[ind]*1e-3))
    
    stated = state1 - state0

    print('='*10 + 'State shift' + '='*10)
    for ind in range(6):
        print(_form.format(var[ind], stated[ind]*1e-3))

    print('='*10 + 'True posterior' + '='*10)
    for ind in range(6):
        print(_form.format(var[ind], state0_true[ind]*1e-3))
    
    print('='*10 + 'Posterior error' + '='*10)
    for ind in range(6):
        print(_form.format(var[ind],(state1[ind] - state0_true[ind])*1e-3))
    
    print('='*10 + 'Parameter shift' + '='*10)
    theta0 = {}
    theta1 = {}
    for key, val in params.items():
        if val['dist'] is not None:
            theta0[key] = val['mu']
            theta1[key] = np.mean(trace[key], axis=0)[0]
            print('{}: {}'.format(key, theta1[key] - theta0[key]))
        else:
            theta0[key] = val['val']
            theta1[key] = val['val']


    range_v_prior = []
    vel_v_prior = []
    range_v = []
    vel_v = []
    range_v_true = []
    vel_v_true = []

    for rxi in range(len(rx_ecef)):
        t_obs = t_obs_v[rxi]
        print('Generating tracklet simulated data RX {}: {} points'.format(rxi, len(t_obs)))

        states0 = orbit_determination.propagate_state(state0, t_obs, dpt.jd_to_mjd(prior_jd), prop, theta0)
        states1 = orbit_determination.propagate_state(state1, t_obs, dpt.jd_to_mjd(prior_jd), prop, theta1)
        states0_true = orbit_determination.propagate_state(state0_true, t_obs, dpt.jd_to_mjd(prior_jd), prop, theta1)

        range_v_prior += [np.empty((len(t_obs), ), dtype=np.float64)]
        vel_v_prior += [np.empty((len(t_obs), ), dtype=np.float64)]
    
        range_v += [np.empty((len(t_obs), ), dtype=np.float64)]
        vel_v += [np.empty((len(t_obs), ), dtype=np.float64)]
    
        range_v_true += [np.empty((len(t_obs), ), dtype=np.float64)]
        vel_v_true += [np.empty((len(t_obs), ), dtype=np.float64)]

        for ind in range(len(t_obs)):
            range_v_prior[rxi][ind], vel_v_prior[rxi][ind] = orbit_determination.generate_measurements(states0[:,ind], rx_ecef[rxi], tx_ecef)
            range_v[rxi][ind], vel_v[rxi][ind] = orbit_determination.generate_measurements(states1[:,ind], rx_ecef[rxi], tx_ecef)
            range_v_true[rxi][ind], vel_v_true[rxi][ind] = orbit_determination.generate_measurements(states0_true[:, ind], rx_ecef[rxi], tx_ecef)


    prop_states = orbit_determination.propagate_state(
        state0,
        np.linspace(0, (np.max(jd_obs) - prior_jd)*(3600.0*24.0), num=1000),
        dpt.jd_to_mjd(prior_jd),
        prop,
        theta1,
    )
    
    '''
    pop = gen_pop()
    obj = pop.get_object(0)
    
    t_obs_pop = t_obs + (dpt.jd_to_mjd(prior_jd) - obj.mjd0)*3600.0*24.0
    states0_true2 = obj.get_state(t_obs_pop)
    
    print(states0_true2)
    print(states0_true2 - states0_true)
    '''
    fig = plt.figure(figsize=(15,15))
    ax = fig.add_subplot(111, projection='3d')
    plothelp.draw_earth_grid(ax)
    for ind, ecef in enumerate(rx_ecef):
        if ind == 0:
            ax.plot([ecef[0]], [ecef[1]], [ecef[2]], 'or', label='EISCAT 3D RX')
        else:
            ax.plot([ecef[0]], [ecef[1]], [ecef[2]], 'or')

    ax.plot(states0[0,:], states0[1,:], states0[2,:], 'xb', label = 'Prior', alpha = 0.75)
    ax.plot(states1[0,:], states1[1,:], states1[2,:], 'xr', label = 'Posterior', alpha = 0.75)
    ax.plot(prop_states[0,:], prop_states[1,:], prop_states[2,:], '-k', label = 'Prior-propagation', alpha = 0.5)
    ax.plot(true_prior[0,:], true_prior[1,:], true_prior[2,:], '-b', label = 'Prior-True', alpha = 0.75)
    ax.plot(true_obs[0,:], true_obs[1,:], true_obs[2,:], '-r', label = 'Posterior-True', alpha = 0.75)
    
    ax.legend()

    for rxi in range(len(rx_ecef)):

        fig = plt.figure(figsize=(15,15))
    
        t_obs_h = t_obs_v[rxi]/3600.0
        
        ax = fig.add_subplot(221)
        lns = []
        line1 = ax.plot(t_obs_h, (r_obs_v[rxi] - range_v[rxi])*1e-3, '-b', label='Maximum a posteriori: RX{}'.format(rxi))
        line0 = ax.plot(t_obs_h, (r_obs_v[rxi] - range_v_true[rxi])*1e-3, '.b', label='True prior: RX{}'.format(rxi))
        ax.set(
            xlabel='Time [h]',
            ylabel='2-way-Range residuals [km]',
        )
        ax2 = ax.twinx()
        line2 = ax2.plot(t_obs_h, (r_obs_v[rxi] - range_v_prior[rxi])*1e-3, '-k', label='Maximum a priori: RX{}'.format(rxi))
        ax.tick_params(axis='y', labelcolor='b')
        ax2.tick_params(axis='y', labelcolor='k')
    
        lns += line0+line1+line2
        labs = [l.get_label() for l in lns]
        ax.legend(lns, labs, loc=0)
    
        ax = fig.add_subplot(222)
        lns = []
        line1 = ax.plot(t_obs_h, (v_obs_v[rxi] - vel_v[rxi])*1e-3, '-b', label='Maximum a posteriori: RX{}'.format(rxi))
        line0 = ax.plot(t_obs_h, (v_obs_v[rxi] - vel_v_true[rxi])*1e-3, '.b', label='True prior: RX{}'.format(rxi))
        ax.set(
            xlabel='Time [h]',
            ylabel='2-way-Velocity residuals [km/s]',
        )
        ax2 = ax.twinx()
        line2 = ax2.plot(t_obs_h, (v_obs_v[rxi] - vel_v_prior[rxi])*1e-3, '-k', label='Maximum a priori: RX{}'.format(rxi))
        ax.tick_params(axis='y', labelcolor='b')
        ax2.tick_params(axis='y', labelcolor='k')
        
        lns += line0+line1+line2
        labs = [l.get_label() for l in lns]
        ax.legend(lns, labs, loc=0)

        ax = fig.add_subplot(223)
        ax.errorbar(t_obs_h, r_obs_v[rxi]*1e-3, yerr=r_sig_v[rxi]*1e-3, label='Measurements: RX{}'.format(rxi))
        ax.plot(t_obs_h, range_v[rxi]*1e-3, label='Maximum a posteriori: RX{}'.format(rxi))
        ax.plot(t_obs_h, range_v_prior[rxi]*1e-3, label='Maximum a priori: RX{}'.format(rxi))
        ax.set(
            xlabel='Time [h]',
            ylabel='2-way-Range [km]',
        )
        ax.legend()
        
        ax = fig.add_subplot(224)
        ax.errorbar(t_obs_h, v_obs_v[rxi]*1e-3, yerr=v_sig_v[rxi]*1e-3, label='Measurements: RX{}'.format(rxi))
        ax.plot(t_obs_h, vel_v[rxi]*1e-3, label='Maximum a posteriori: RX{}'.format(rxi))
        ax.plot(t_obs_h, vel_v_prior[rxi]*1e-3, label='Maximum a priori: RX{}'.format(rxi))
        ax.set(
            xlabel='Time [h]',
            ylabel='2-way-Velocity [km/s]',
        )
        ax.legend()
    
    #dpt.posterior(trace['state']*1e-3, var, show=False)
    plt.show()
Beispiel #15
0
    def test_create_tracklet(self):

        radar = rlib.eiscat_uhf()
        radar.set_FOV(30.0, 25.0)

        #tle files for envisat in 2016-09-05 to 2016-09-07 from space-track.
        TLEs = [
            ('1 27386U 02009A   16249.14961597  .00000004  00000-0  15306-4 0  9994',
             '2 27386  98.2759 299.6736 0001263  83.7600 276.3746 14.37874511760117'
             ),
            ('1 27386U 02009A   16249.42796553  .00000002  00000-0  14411-4 0  9997',
             '2 27386  98.2759 299.9417 0001256  82.8173 277.3156 14.37874515760157'
             ),
            ('1 27386U 02009A   16249.77590267  .00000010  00000-0  17337-4 0  9998',
             '2 27386  98.2757 300.2769 0001253  82.2763 277.8558 14.37874611760201'
             ),
            ('1 27386U 02009A   16250.12384028  .00000006  00000-0  15974-4 0  9995',
             '2 27386  98.2755 300.6121 0001252  82.5872 277.5467 14.37874615760253'
             ),
            ('1 27386U 02009A   16250.75012691  .00000017  00000-0  19645-4 0  9999',
             '2 27386  98.2753 301.2152 0001254  82.1013 278.0311 14.37874790760345'
             ),
        ]

        pop = population_library.tle_snapshot(TLEs, sgp4_propagation=True)

        #it seems to around 25m^2 area
        d = n.sqrt(25.0 * 4 / n.pi)
        pop.add_column('d', space_object_uses=True)
        pop['d'] = d

        ccsds_file = './data/uhf_test_data/events/2002-009A-1473150428.tdm'

        obs_data = ccsds_write.read_ccsds(ccsds_file)
        jd_obs = dpt.mjd_to_jd(dpt.npdt2mjd(obs_data['date']))

        date_obs = obs_data['date']
        sort_obs = n.argsort(date_obs)
        date_obs = date_obs[sort_obs]
        r_obs = obs_data['range'][sort_obs]

        jd_sort = jd_obs.argsort()
        jd_obs = jd_obs[jd_sort]

        jd_det = jd_obs[0]

        jd_pop = dpt.mjd_to_jd(pop['mjd0'])

        pop_id = n.argmin(n.abs(jd_pop - jd_det))
        obj = pop.get_object(pop_id)

        print(obj)

        jd_obj = dpt.mjd_to_jd(obj.mjd0)

        print('Day difference detection - TLE: {}'.format(jd_det - jd_obj))

        t_obs = (jd_obs - jd_obj) * (3600.0 * 24.0)

        meas, fnames, ecef_stdevs = simulate_tracklet.create_tracklet(
            obj,
            radar,
            t_obs,
            hdf5_out=True,
            ccsds_out=True,
            dname="./tests/tmp_test_data",
            noise=False,
        )

        out_h5 = fnames[0] + '.h5'
        out_ccsds = fnames[0] + '.tdm'

        print('FILES: ', fnames)

        with h5py.File(out_h5, 'r') as h_det:
            assert 'm_range' in h_det
            assert 'm_range_rate' in h_det
            assert 'm_time' in h_det

        sim_data = ccsds_write.read_ccsds(out_ccsds)

        date_sim = sim_data['date']
        sort_sim = n.argsort(date_sim)
        date_sim = date_sim[sort_sim]

        r_sim = sim_data['range'][sort_sim]
        v_sim = sim_data['doppler_instantaneous'][sort_sim]

        lt_correction = n.round(r_sim / scipy.constants.c * 1e6).astype(
            n.int64).astype('timedelta64[us]')

        date_sim_cor = date_sim + lt_correction

        t_sim = dpt.jd_to_unix(dpt.mjd_to_jd(dpt.npdt2mjd(date_sim_cor)))

        for ind in range(len(date_sim)):
            time_df = (dpt.npdt2mjd(date_sim_cor[ind]) -
                       dpt.npdt2mjd(date_obs[ind])) * 3600.0 * 24.0
            assert time_df < 0.01

        assert len(r_obs) == len(r_sim)

        dat = {
            't': t_sim,
            'r': r_sim * 1e3,
            'v': v_sim * 1e3,
        }

        cdat = correlator.correlate(
            data=dat,
            station=radar._rx[0],
            population=pop,
            metric=correlator.residual_distribution_metric,
            n_closest=1,
            out_file=None,
            verbose=False,
            MPI_on=False,
        )

        self.assertLess(n.abs(cdat[0]['stat'][0]), 5.0)
        self.assertLess(n.abs(cdat[0]['stat'][1]), 50.0)
        self.assertLess(n.abs(cdat[0]['stat'][2]), 5.0)
        self.assertLess(n.abs(cdat[0]['stat'][3]), 50.0)

        nt.assert_array_less(n.abs(r_sim - r_obs), 1.0)

        os.remove(out_h5)
        print('removed "{}"'.format(out_h5))

        os.remove(out_ccsds)
        print('removed "{}"'.format(out_ccsds))

        sat_folder = os.sep.join(fnames[0].split(os.sep)[:-1])
        os.rmdir(sat_folder)
        print('removed "{}"'.format(sat_folder))
Beispiel #16
0
def Microsat_R_debris(mjd, num, radii_range, mass_range, propagator, propagator_options):

    tle_raw = Microsat_R_debris_raw_tle

    tle_raw = [line.strip() for line in tle_raw.split('\n')]
    if len(tle_raw) % 2 != 0:
        raise Exception('Not even number of lines [not TLE compatible]')
    TLEs = zip(tle_raw[0::2], tle_raw[1::2])

    M_earth = propagator_sgp4.SGP4.GM*1e9/consts.G

    pop = Population(
        name='Microsat R debris',
        extra_columns = ['A', 'm', 'd', 'C_D', 'C_R'],
        space_object_uses = [True, True, True, True, True],
        propagator = propagator,
        propagator_options = propagator_options,
    )

    pop.allocate(len(TLEs)*num)

    delete_inds = []
    cnt = 0
    for ind in range(num):
        for line_id, lines in enumerate(TLEs):
            line1, line2 = lines

            sat_id = tle.tle_id(line1)
            jd0 = tle.tle_jd(line1)
            mjd0 = dpt.jd_to_mjd(jd0)

            state_TEME = tle.TLE_propagation_TEME(line1, line2, dpt.mjd_to_jd(mjd))
            kep = dpt.cart2kep(state_TEME, m=0.0, M_cent=M_earth, radians=False)

            if np.any(np.isnan(kep)):
                delete_inds.append(cnt)
                continue

            pop.objs[cnt][1] = kep[0]*1e-3
            pop.objs[cnt][2] = kep[1]
            pop.objs[cnt][3] = kep[2]
            pop.objs[cnt][4] = kep[4]
            pop.objs[cnt][5] = kep[3]
            pop.objs[cnt][6] = dpt.true2mean(kep[5], kep[1], radians=False)
            
            pop.objs[cnt][0] = float(sat_id)
            pop.objs[cnt][7] = mjd

            rho = 1.1e4
            while rho > 1e4 or rho < 1e2:
                r = np.random.rand(1)*(radii_range[1] - radii_range[0]) + radii_range[0]
                A = np.pi*r**2
                m = np.random.rand(1)*(mass_range[1] - mass_range[0]) + mass_range[0]
                vol = 4.0/3.0*np.pi*r**3
                rho = m/vol

            pop.objs[cnt][8] = A
            pop.objs[cnt][9] = m
            pop.objs[cnt][10] = r*2.0
            pop.objs[cnt][11] = 2.3
            pop.objs[cnt][12] = 1.0

            cnt += 1
        
    pop.delete(delete_inds)

    return pop
Beispiel #17
0
def get_passes(o,
               radar,
               t0,
               t1,
               max_dpos=1e3,
               logger=None,
               plot=False,
               t_samp=None):
    '''Follow object and determine possible maintenance track window. I.e. get all passes of the object inside the radar system FOV.
    
    :param SpaceObject o: Space object to find passes for.
    :param RadarSystem radar: Radar system that defines the FOV.
    :param float t0: Start time for passes search in seconds relative space object epoch.
    :param float t1: Stop time for passes search in seconds relative space object epoch.
    :param float max_dpos: Maximum separation in km between orbital evaluation points.
    :param Logger logger: Logger object for logging the execution of the function.
    :param float t_samp: If not None, overrides the "max_dpos" variable and fixes a time-sampling.
    :return: Dictionary containing information about all passes of the space object inside the radar system FOV.
    :rtype: dict

    **Output dictionary:**

      * t: Three layers of lists where first layer is a list corresponding to every RX antenna of the radar system. Second layer is the a entry in the list for every pass. Last layer of lists is a list of two elements where the first is the time in seconds when object enters the FOV and second is the time in seconds when the object leaves the FOV. I.e. :code:`pass_start_time = passes["t"][tx_index][pass_index][0]` and :code:`pass_end_time = passes["t"][tx_index][pass_index][1]`.
      * snr: This structure has the same format as the "t" item but with an extra layer of lists of receivers before the bottom. Then instead of the bottom layer of lists being start and stop times it records the peak SNR at the first item and the time of that peak SNR in the second item. I.e. :code:`pass_peak_snr = passes["snr"][tx_index][pass_index][rx_index][0]` and :code:`pass_peak_snr_time = passes["snr"][tx_index][pass_index][rx_index][1]`.
    '''
    pass_struct = {"t": [], "snr": []}

    if t_samp is None:
        num_t = find_linspace_num(t0, t1, o.a * 1e3, o.e, max_dpos=max_dpos)
        t = n.linspace(t0, t1, num=num_t, dtype=n.float64)
    else:
        t = n.arange(t0, t1, t_samp, dtype=n.float64)
        num_t = len(t)

    if logger is not None:
        logger.debug("n_points %d %1.2f" % (num_t, max_dpos))

    # time vector

    if logger is not None:
        date0_y, date0_m, date0_d = dpt.jd_to_date(dpt.mjd_to_jd(o.mjd0))
        logger.debug(
            '--> Getting {} orbit location between: {:.5f} h and {:.5f} h relative {}-{}-{}'
            .format(
                num_t,
                t[0] / (3600),
                t[-1] / (3600),
                date0_y,
                date0_m,
                date0_d,
            ))

    passes, passes_id, idx_v, postx_v, posrx_v = find_pass_interval(
        t, o, radar, logger=logger)

    if logger is not None:
        logger.debug("passes:\n {}".format(passes))

    tx_dets = 0
    for idx in idx_v:
        if len(idx) > 0:
            tx_dets += 1

    if tx_dets == 0:
        if logger is not None:
            logger.debug("no passes visible from any RX station")
        return pass_struct

    if logger is not None:
        logger.debug("--> List of passes constructed")
        logger.debug("{}".format(passes))

    snrs = [None] * len(radar._tx)
    for txi, idx in enumerate(idx_v):
        if len(idx) > 0:
            snrs[txi] = [None] * len(passes[txi])
            tx = radar._tx[txi]
            for pid, pass_ids in enumerate(passes_id[txi]):
                idx_p = idx[pass_ids[0]:pass_ids[1]]

                if logger is not None:
                    logger.debug("{}".format(idx_p))
                    logger.debug("{}".format(pass_ids))

                snrs[txi][pid] = [None] * len(radar._rx)
                rx_dets = 0
                for rxi, rx in enumerate(radar._rx):
                    snr_curve = []
                    for I in idx_p:
                        tx_dist = n.linalg.norm(postx_v[txi][:, I])
                        k0 = coord.ecef2local(
                            lat=tx.lat,
                            lon=tx.lon,
                            alt=tx.alt,
                            x=postx_v[txi][0, I],
                            y=postx_v[txi][1, I],
                            z=postx_v[txi][2, I],
                        )
                        tx.beam.point_k0(k0)
                        gain_tx = tx.beam.gain(k0)

                        rx_dist = n.linalg.norm(posrx_v[rxi][:, I])
                        # point towards object
                        k0 = coord.ecef2local(
                            lat=rx.lat,
                            lon=rx.lon,
                            alt=rx.alt,
                            x=posrx_v[txi][0, I],
                            y=posrx_v[txi][1, I],
                            z=posrx_v[txi][2, I],
                        )
                        rx.beam.point_k0(k0)
                        gain_rx = rx.beam.gain(k0)

                        snr = debris.hard_target_enr(
                            gain_tx,
                            gain_rx,
                            rx.wavelength,
                            tx.tx_power,
                            tx_dist,
                            rx_dist,
                            diameter_m=o.d,
                            bandwidth=tx.coh_int_bandwidth,
                            rx_noise_temp=rx.rx_noise)

                        if logger is not None:
                            logger.debug(
                                '\n--> TX-d: %.2f km | TX-g: %.2f dB' %
                                (tx_dist * 1e-3, 10.0 * n.log10(gain_tx)))
                            logger.debug(
                                '--> RX-d: %.2f km | RX-g: %.2f dB' %
                                (rx_dist * 1e-3, 10.0 * n.log10(gain_rx)))
                            logger.debug('--> SNR: %.2f dB ' %
                                         (10.0 * n.log10(snr)))
                        snr_curve.append(snr)

                    snr_curve = n.array(snr_curve)

                    if plot:
                        snr_curve_dB = 10.0 * n.log10(snr_curve)
                        snr_curve_dB[snr_curve_dB < 0] = 0
                        plt.plot(t[idx_p], snr_curve_dB)
                        plt.plot(t[idx_p[n.argmax(snr_curve)]],
                                 n.max(snr_curve_dB), 'or')
                        plt.title("tx %i, pass %i, rx %i" % (txi, pid, rxi))
                        plt.show()
                        print('SNR max: %.2f @ %.2f h' %
                              (n.max(snr_curve_dB),
                               t[idx_p[n.argmax(snr_curve)]] / 3600.0))
                    if len(snr_curve) > 0:
                        snr_max = n.max(snr_curve)
                    else:
                        snr_max = 0.0
                    if snr_max >= tx.enr_thresh:
                        rx_dets += 1
                        snrs[txi][pid][rxi] = [
                            snr_max, t[idx_p[n.argmax(snr_curve)]]
                        ]
                    else:
                        snrs[txi][pid][rxi] = [0, 0]

                if rx_dets == 0:
                    snrs[txi][pid] = None

                if plot:
                    fig = plt.figure(figsize=(15, 15))
                    ax = fig.add_subplot(111, projection='3d')
                    plothelp.draw_earth_grid(ax)
                    ax.plot(ecef[0, :],
                            ecef[1, :],
                            ecef[2, :],
                            alpha=1,
                            color="black")
                    for I in idx_p:
                        ax.plot([tx.ecef[0], tx.ecef[0] + postx_v[txi][0, I]],
                                [tx.ecef[1], tx.ecef[1] + postx_v[txi][1, I]],
                                [tx.ecef[2], tx.ecef[2] + postx_v[txi][2, I]],
                                alpha=0.5,
                                color="red")
                        for rxi, rx in enumerate(radar._rx):
                            ax.plot(
                                [rx.ecef[0], rx.ecef[0] + posrx_v[rxi][0, I]],
                                [rx.ecef[1], rx.ecef[1] + posrx_v[rxi][1, I]],
                                [rx.ecef[2], rx.ecef[2] + posrx_v[rxi][2, I]],
                                alpha=0.5,
                                color="red")
                    delta = 1000e3
                    ax.set_xlim([tx.ecef[0] - delta, tx.ecef[0] + delta])
                    ax.set_ylim([tx.ecef[1] - delta, tx.ecef[1] + delta])
                    ax.set_zlim([tx.ecef[2] - delta, tx.ecef[2] + delta])
                    plt.show()
            passes[txi] = [
                x for ix, x in enumerate(passes[txi])
                if snrs[txi][ix] is not None
            ]  #remove tracks that were not above detection tresholds at any pair
            snrs[txi] = [
                x for x in snrs[txi] if x is not None
            ]  #remove tracks that were not above detection tresholds at any pair

    for txi, tx_snr in enumerate(snrs):
        if tx_snr is None:
            snrs[txi] = []
    for txi, tx_pass in enumerate(passes):
        if tx_pass is None:
            passes[txi] = []

    pass_struct['snr'] = snrs
    pass_struct['t'] = passes

    return pass_struct