def test_propagator_options_sgp4(self): from propagator_sgp4 import PropagatorSGP4 obj0 = so.SpaceObject(propagator=PropagatorSGP4, propagator_options={'polar_motion': False}, **self.init_obj) obj1 = so.SpaceObject(propagator=PropagatorSGP4, propagator_options={'polar_motion': True}, **self.init_obj) t = n.array([0.0], dtype=n.float) xv1 = obj0.get_state(t) xv0 = obj1.get_state(t)
def test_propagator_options_orekit(self): from propagator_orekit import PropagatorOrekit obj0 = so.SpaceObject(propagator=PropagatorOrekit, propagator_options={'drag_force': False}, **self.init_obj) obj1 = so.SpaceObject(propagator=PropagatorOrekit, propagator_options={'drag_force': True}, **self.init_obj) t = n.array([0.0], dtype=n.float) xv1 = obj0.get_state(t) xv0 = obj1.get_state(t) nt.assert_array_almost_equal(xv0, xv1, decimal=2)
def test_propagator_change_orekit(self): from propagator_orekit import PropagatorOrekit obj = so.SpaceObject(propagator=PropagatorOrekit, propagator_options={}, **self.init_obj) t = n.array([0.0], dtype=n.float) xv1 = obj.get_state(t) xv0 = self.o.get_state(t) self.assertEqual(xv1.shape, xv0.shape)
def example_err_cov2(): radar_e3d = rl.eiscat_3d(beam='interp', stage=1) # o=so.SpaceObject(a=7000.0,e=1e-3,i=69,raan=89,aop=12,mu0=47,d=1.0,A=1.0,m=1.0) o = so.SpaceObject(a=26571.100000, e=0.606000, i=69.320000, d=3.154000, A=7.813436, m=1239.000000, raan=89, aop=12, mu0=47, oid=43) tau, beta, t1, alpha = ade.atmospheric_errors(o, a_err_std=0.05, N_samps=200, plot=False, threshold_error=100.0) o.alpha = alpha o.beta = beta o.t1 = t1 for n_points in [1, 3, 10, 100]: t_obs, n_tracklets, t_means, t_lens = get_t_obs(o, radar_e3d, n_tracklets=50, track_length=3600.0, n_points=n_points, h0=-48, h1=24 + 48, sort_by_length=False) error_cov, range_0 = linearized_errors(o, radar_e3d, t_obs, include_drag=True) idx = n.where((t_means > -24 * 3600) & (t_means < 48 * 3600))[0] idx2 = n.where((t_obs > -24 * 3600) & (t_obs < 48 * 3600))[0] mean_error, last_error = sample_orbit( o, error_cov, t_means[idx], plot_t_means=t_obs[idx2], plot=True, t_obs=n.linspace(-24 * 3600, 48 * 3600, num=1000), use_atmospheric_errors=True, fname="report_plots/main_%d_%04d_%d.png" % (o.oid, n_points, n.log10(o.A / o.m)))
def get_object(self,n): '''Get the one row from the population as a :class:`space_object.SpaceObject` instance. ''' kw = {} for head, use in zip(self.header, self.space_object_uses): if use: kw[head] = self.objs[head][n] o=so.SpaceObject( propagator = self.propagator, propagator_options = self.propagator_options, **kw ) return o
def setUp(self): self.init_obj = { 'a': 7000, 'e': 0.0, 'i': 69, 'raan': 0.0, 'aop': 0.0, 'mu0': 0.0, 'C_D': 2.3, 'C_R': 1.0, 'A': 1.0, 'm': 1.0, } self.o = so.SpaceObject(**self.init_obj) self.R_e = 6371.0
def ss(x): a = x[0] e = 10**(x[1]) i = x[2] raan = x[3] aop = x[4] mu0 = x[5] A_to_m = 10**(x[6]) if x[6] < -4.0 or x[6] > 100.0: return (1e6) o = spo.SpaceObject(a=a, e=e, i=i, raan=raan, aop=aop, mu0=mu0, A=A_to_m, m=1.0, mjd0=o_prior.mjd0) # forward model s_range, s_range_rate = sim_meas(o, m_time, rx_locs, tx_locs) s = 0.0 for i in range(n_tracklets): s += 0.5 * n.sum( (n.abs(m_range[i] - s_range[i])**2.0) / (m_range_std[i]**2.0) + n.sum((n.abs(m_range_rate[i] - s_range_rate[i])**2.0) / (m_range_rate_std[i]**2.0))) # Gaussian prior for log10(A/m) mean = -0.5, std=0.77, based on the # approximate distribution of log10(A/m) in the MASTER 2009 catalog s += 0.5 * n.sum((x[6] + 0.5)**2.0 / 0.77**2.0) # Gaussian prior distribution for Keplerian parameters s += 0.5 * n.sum((x[0] - x0[0])**2.0 / sigma_a**2.0) s += 0.5 * n.sum((x[1] - x0[1])**2.0 / sigma_e**2.0) s += 0.5 * n.sum((x[2] - x0[2])**2.0 / sigma_i**2.0) s += 0.5 * n.sum((x[3] - x0[3])**2.0 / sigma_raan**2.0) s += 0.5 * n.sum((x[4] - x0[4])**2.0 / sigma_aop**2.0) s += 0.5 * n.sum((x[5] - x0[5])**2.0 / sigma_mu0**2.0) print(s) return (s)
A[row_idx, midx[i]] = 1.0 A[row_idx, j] = -1.0 dt = t[midx[i]] - t[j] # print(dt) print(error_var(n.abs(dt))) S[row_idx] = error_var(n.abs(dt)) row_idx += 1 for i in range(n_meas): A[i, :] = A[i, :] / n.sqrt(S[i]) Sp = n.linalg.inv(n.dot(n.transpose(A), A)) plt.semilogy(t / 3600.0, n.sqrt(n.diag(Sp)), label="Position error stdev") plt.ylabel("Position error standard deviation (m)") for i in range(n_tracklets): plt.axvline(t_obs[i] / 3600.0, color="red", label="measurement") plt.xlabel("Time (hours)") plt.legend() plt.title("Atmospheric drag uncertainty related errors") plt.show() o = spo.SpaceObject(a=7070.0, e=1e-4, i=89.0, raan=12.0, aop=23.0, mu0=32.0, A=10**(-2.0), m=1.0, d=1.0) atmospheric_errors_rw(o, n_tracklets=3)
def test_envisat(): import space_object as so mass = 0.8111E+04 diam = 0.8960E+01 m_to_A = 128.651 a = 7159.5 e = 0.0001 i = 98.55 raan = 248.99 aop = 90.72 M = 47.37 A = mass / m_to_A # epoch in unix seconds ut0 = 1241136000.0 # modified julian day epoch mjd0 = dpt.jd_to_mjd(dpt.unix_to_jd(ut0)) print(mjd0) o = so.SpaceObject( a=a, e=e, i=i, raan=raan, aop=aop, mu0=M, C_D=2.3, A=A, m=mass, diam=diam, mjd0=mjd0, #propagator = PropagatorNeptune, propagator=PropagatorSGP4, propagator_options={'out_frame': 'ITRF'}, ) e3d = rlib.eiscat_3d() print("EISCAT Skibotn location x,y,z ECEF (meters)") print(e3d._tx[0].ecef) ski_ecef = e3d._tx[0].ecef print("EISCAT Skibotn location %1.3f %1.3f %1.3f (lat,lon,alt)" % (e3d._tx[0].lat, e3d._tx[0].lon, 0.0)) t_obs = np.linspace(4440, 5280, num=100) + 31.974890 t_obs2 = np.linspace(4440, 5280, num=100) + 31.974890 + 1.0 print("MJD %1.10f %sZ" % (mjd0 + t_obs[0] / 3600.0 / 24.0, ccsds_write.unix2datestr(ut0 + t_obs[0]))) ecef = o.get_state(t_obs) ecef2 = o.get_state(t_obs2) print("ECEF state x,y,z,vx,vy,vz (km and km/s)") print(ecef[:, 0] / 1e3) print( "Time (UTC) Range (km) Vel (km/s) ECEF X (km) ECEF Y (km) ECEF Z (km)" ) for i in range(len(t_obs)): dist = np.linalg.norm(ecef[0:3, i] - ski_ecef) dist2 = np.linalg.norm(ecef2[0:3, i] - ski_ecef) vel = (dist2 - dist) / 1.0 print("%s %1.3f %1.3f %1.3f %1.3f %1.3f" % (ccsds_write.unix2datestr(ut0 + t_obs[i]), dist / 1e3, vel / 1e3, ecef[0, i] / 1e3, ecef[1, i] / 1e3, ecef[2, i] / 1e3))
def example_err_cov(): radar_e3d = rl.eiscat_3d(beam='interp', stage=1) o = so.SpaceObject(a=7000.0, e=1e-3, i=69, raan=89, aop=12, mu0=47, d=1.0, A=1.0, m=1.0) t_obs, n_tracklets, t_means, t_lens = get_t_obs(o, radar_e3d, n_tracklets=1, track_length=3600.0, n_points=3, h0=0, h1=24, sort_by_length=True) o1 = change_of_epoch_test(o, t_obs[0], plot=False) o1.alpha = 4.1 o1.beta = 7.8 o1.t1 = 8943.65 t_obs, n_tracklets, t_means, t_lens = get_t_obs(o1, radar_e3d, n_tracklets=1, track_length=3600.0, n_points=3, h0=-1, h1=1, sort_by_length=True) error_cov, range_0 = linearized_errors(o1, radar_e3d, t_obs, include_drag=True) mean_error, last_error = sample_orbit( o1, error_cov, t_obs, # mean measurement times plot_t_means=t_obs, # where to plot lines for measurement times plot=True, t_obs=n.linspace(-12 * 3600, 12 * 3600, num=1000), use_atmospheric_errors=False, fname="report_plots/err_cov_ex1.png") t_obs, n_tracklets, t_means, t_lens = get_t_obs(o1, radar_e3d, n_tracklets=2, track_length=3600.0, n_points=3, h0=-12, h1=12, sort_by_length=True) error_cov, range_0 = linearized_errors(o1, radar_e3d, t_obs, include_drag=True) mean_error, last_error = sample_orbit( o1, error_cov, t_means, # mean measurement times plot_t_means=t_obs, # where to plot lines for measurement times plot=True, t_obs=n.linspace(-12 * 3600, 12 * 3600, num=1000), use_atmospheric_errors=False, fname="report_plots/err_cov_ex2.png") t_obs, n_tracklets, t_means, t_lens = get_t_obs(o1, radar_e3d, n_tracklets=10, track_length=3600.0, n_points=3, h0=-12, h1=12, sort_by_length=True) error_cov, range_0 = linearized_errors(o1, radar_e3d, t_obs, include_drag=True) mean_error, last_error = sample_orbit(o1, error_cov, t_means, plot_t_means=t_obs, plot=True, t_obs=n.linspace(-12 * 3600, 12 * 3600, num=1000), use_atmospheric_errors=False, fname="report_plots/err_cov_ex3.png") mean_error, last_error = sample_orbit(o1, error_cov, t_means, plot_t_means=t_obs, plot=True, t_obs=n.linspace(-96 * 3600, 96 * 3600, num=1000), use_atmospheric_errors=True, fname="report_plots/err_cov_ex4.png")
box = 1000e3 ax.set_xlim([radar._tx[0].ecef[0] - box, radar._tx[0].ecef[0] + box]) ax.set_ylim([radar._tx[0].ecef[1] - box, radar._tx[0].ecef[1] + box]) ax.set_zlim([radar._tx[0].ecef[2] - box, radar._tx[0].ecef[2] + box]) space_o = space_object.SpaceObject( a=7000, e=0.0, i=69, raan=0, aop=0, mu0=0, C_D=2.3, A=1.0, m=1.0, C_R=1.0, oid=42, d=0.1, mjd0=57125.7729, ) print(space_o) radars = [ radar_library.eiscat_uhf(), radar_library.eiscat_3d(), ]
def atmospheric_errors(o, a_err_std=0.01, N_samps=200): """ Estimate position errors as a function of time, assuming a certain error in atmospheric drag. """ o0 = so.SpaceObject(a=o.a, e=o.e, i=o.i, raan=o.raan, aop=o.aop, mu0=o.mu0, d=o.diam, A=o.A, m=o.m, C_D=o.C_D) print(o0) t = 10**(n.linspace(2, 6.2, num=100)) t_dt = n.copy(t) + 1.0 ecef0 = o0.get_orbit(t) print(ecef0.shape) print("n_days %d" % (n.max(t) / 24.0 / 3600.0)) err = n.copy(ecef0) err[:, :] = 0.0 for i in range(N_samps): mu0 = n.random.rand(1) * 360.0 print(o.m) print(o.C_D) o0 = so.SpaceObject(a=o.a, e=o.e, i=o.i, raan=o.raan, aop=o.aop, mu0=mu0, d=o.diam, A=o.A, m=o.m, C_D=o.C_D) ecef0 = o0.get_orbit(t) ecef0_dt = o0.get_orbit(t_dt) at, norm, ct = get_inertial_basis(ecef0, ecef0_dt) C_D = o0.C_D + o0.C_D * n.random.randn(1)[0] * a_err_std print(C_D) o1 = so.SpaceObject(a=o.a, e=o.e, i=o.i, raan=o.raan, aop=o.aop, mu0=mu0, d=o.diam, A=o.A, m=o.m, C_D=C_D) ecef1 = o1.get_orbit(t) err_now = (ecef1 - ecef0) err[0, :] += n.abs(err_now[0, :] * at[0, :] + err_now[1, :] * at[1, :] + err_now[2, :] * at[2, :])**2.0 # err[1,:]+=n.abs(err_now[0,:]*norm[0,:]+err_now[1,:]*norm[1,:]+err_now[2,:]*norm[2,:])**2.0 # difference in radius err[1, :] += n.abs( n.sqrt(ecef0[0, :]**2.0 + ecef0[1, :]**2.0 + ecef0[2, :]**2.0) - n.sqrt(ecef1[0, :]**2.0 + ecef1[1, :]**2.0 + ecef1[2, :]**2.0)) err[2, :] += n.abs(err_now[0, :] * ct[0, :] + err_now[1, :] * ct[1, :] + err_now[2, :] * ct[2, :])**2.0 ate = n.sqrt(err[0, :] / N_samps) if n.max(ate) > 100.0: idx0 = n.where(ate > 100.0)[0][0] days = t / 24.0 / 3600.0 plt.loglog(t / 24.0 / 3600.0, n.sqrt(err[0, :] / N_samps), label="Along track") plt.loglog(t / 24.0 / 3600.0, n.sqrt(err[1, :] / N_samps), label="Radial") plt.loglog(t / 24.0 / 3600.0, n.sqrt(err[2, :] / N_samps), label="Cross-track") if n.max(ate) > 100.0: plt.axvline(days[idx0]) plt.text(days[idx0], 100, "$\\tau=%1.1f$ hours" % (24 * days[idx0])) plt.grid() plt.axvline(n.max(t) / 24.0 / 3600.0) plt.xlim([0, n.max(t) / 24.0 / 3600.0]) plt.legend() plt.ylabel("Cartesian position error (m)") plt.xlabel("Time (days)") plt.title( "a %1.0f (km) e %1.2f i %1.0f (deg) aop %1.0f (deg) raan %1.0f (deg)\nA %1.2f$\pm$ %d%% (m$^2$) mass %1.2f (kg)" % (o.a, o.e, o.i, o.aop, o.raan, o.A, int(a_err_std * 100.0), o.m)) plt.show()
os.environ['TZ'] = 'GMT' time.tzset() ####### RUN CONFIG ####### scenario = 0 ########################## event_date = np.datetime64('2018-03-27T05:40') event_mjd = dpt.npdt2mjd(event_date) so_list = [ space_object.SpaceObject( a=6800.0, e=0.01, i=98.0, aop=56.0, raan=79.0, mu0=220.0, mjd0=event_mjd, ), space_object.SpaceObject( a=6800.0, e=0.01, i=98.0, aop=56.0, raan=199.0, mu0=250.0, mjd0=event_mjd, ), ]
def mcmc_od( m_time, m_range, m_range_rate, m_range_std, m_range_rate_std, tx_locs, rx_locs, o_prior, dt=0.1, method="Nelder-Mead", sigma_a=1000.0, # very non-informative priors for the orbital elements sigma_e=10.0, # means based on o_prior sigma_i=100.0, sigma_raan=100.0, sigma_aop=100.0, sigma_mu0=100.0, sigma_am=0.77, # log10(A/m) stdev, default based on all master catalog objects am_mean=-0.5, # log10(A/m) mean, default based on all master catalog objects N_samples=5000, mcmc=False, thinning=10, odir="./test_tracklets", plot=False): """ fmin search and mcmc based OD using weighted linear-least squares. The MCMC algorithm uses the Single Component Adaptive Metropolis-hastings (SCAM) algorithm, which is relatively robust, and somewhat efficient. This could be in the future augmented with online estimation of proposal distribution covriance from initial samples to improve sampling efficiency. """ tx_locs = n.array(tx_locs) rx_locs = n.array(rx_locs) n_tracklets = len(m_time) print("n_tracklets %d" % (n_tracklets)) s_ranges, s_range_rates = sim_meas(o_prior, m_time, rx_locs, tx_locs) print("range residuals") for i in range(n_tracklets): print(s_ranges[i] - m_range[i]) print("range_rate residuals") for i in range(n_tracklets): print(s_range_rates[i] - m_range_rate[i]) A_to_m = o_prior.A / o_prior.m # don't start with real values to make map estimate realistic x0 = n.array([ o_prior.a + n.random.randn(1) * 0.0, n.log10(o_prior.e) + n.random.randn(1) * 0.0, o_prior.i + n.random.randn(1) * 0.0, o_prior.raan + n.random.randn(1) * 0.0, o_prior.aop + n.random.randn(1) * 0.0, o_prior.mu0 + n.random.randn(1) * 0.0, n.log10(A_to_m) + n.random.randn(1) * 0.1 ]) xtrue = n.array([ o_prior.a, n.log10(o_prior.e), o_prior.i, o_prior.raan, o_prior.aop, o_prior.mu0, n.log10(A_to_m) ]) # object used for least squares c def ss(x): a = x[0] e = 10**(x[1]) i = x[2] raan = x[3] aop = x[4] mu0 = x[5] A_to_m = 10**(x[6]) if x[6] < -4.0 or x[6] > 100.0: return (1e6) o = spo.SpaceObject(a=a, e=e, i=i, raan=raan, aop=aop, mu0=mu0, A=A_to_m, m=1.0, mjd0=o_prior.mjd0) # forward model s_range, s_range_rate = sim_meas(o, m_time, rx_locs, tx_locs) s = 0.0 for i in range(n_tracklets): s += 0.5 * n.sum( (n.abs(m_range[i] - s_range[i])**2.0) / (m_range_std[i]**2.0) + n.sum((n.abs(m_range_rate[i] - s_range_rate[i])**2.0) / (m_range_rate_std[i]**2.0))) # Gaussian prior for log10(A/m) mean = -0.5, std=0.77, based on the # approximate distribution of log10(A/m) in the MASTER 2009 catalog s += 0.5 * n.sum((x[6] + 0.5)**2.0 / 0.77**2.0) # Gaussian prior distribution for Keplerian parameters s += 0.5 * n.sum((x[0] - x0[0])**2.0 / sigma_a**2.0) s += 0.5 * n.sum((x[1] - x0[1])**2.0 / sigma_e**2.0) s += 0.5 * n.sum((x[2] - x0[2])**2.0 / sigma_i**2.0) s += 0.5 * n.sum((x[3] - x0[3])**2.0 / sigma_raan**2.0) s += 0.5 * n.sum((x[4] - x0[4])**2.0 / sigma_aop**2.0) s += 0.5 * n.sum((x[5] - x0[5])**2.0 / sigma_mu0**2.0) print(s) return (s) print("maximum a posteriori search...") xhat = so.minimize(ss, x0, method=method).x # xhat=so.fmin(ss,x0,full_output=False,disp=True) print(xhat) print(xhat - xtrue) o_fit = spo.SpaceObject(a=xhat[0], e=10**xhat[1], i=xhat[2], raan=xhat[3], aop=xhat[4], mu0=xhat[5], A=10**xhat[6], m=1.0, mjd0=o_prior.mjd0) best_fit_ranges, best_fit_range_rates = sim_meas(o_fit, m_time, rx_locs, tx_locs) if rank == 0: if plot: plt.subplot(121) for i in range(n_tracklets): plt.plot(m_time[i], 1e3 * (best_fit_ranges[i] - m_range[i]), "o", label="tracklet %d" % (i)) plt.xlabel("Time (s)") plt.ylabel("Range residual (m)") plt.subplot(122) for i in range(n_tracklets): plt.plot(m_time[i], 1e3 * (best_fit_range_rates[i] - m_range_rate[i]), "o", label="tracklet %d" % (i)) plt.xlabel("Time (s)") plt.ylabel("Range-rate residual (m/s)") plt.show() # s_time, range_resid, vel_resid = compare_states(o_prior, o_fit, m_time, plot=plot) comm.Barrier() if not mcmc: return (o_fit, s_time, range_resid, vel_resid, m_time) print("mcmc sampling...") # Single Component Adaptive Metropolis-hastings MCMC (SCAM) chain = n.zeros([N_samples, len(x0)]) xnow = n.copy(xhat) logss = -ss(xnow) # log likelihood n_par = len(xhat) step = n.array([1e-4, 0.002, 0.5e-4, 1.5e-4, 1e-4, 1e-4, 0.01]) * 1.0 accept = n.zeros(len(step)) tries = n.zeros(len(step)) for i in range(N_samples * thinning): xtry = n.copy(xnow) pi = int(n.floor(n.random.rand(1) * n_par)) xtry[pi] += n.random.randn(1) * step[pi] logss_try = -ss(xtry) # log likelihood alpha = n.log(n.random.rand(1)) # proposal step # accept always if logss_try > logss: logss = logss_try xnow = xtry accept[pi] += 1 # accept by random chance elif (logss_try - alpha) > logss: logss = logss_try xnow = xtry accept[pi] += 1 # # TBD: Use DRAM to speed up sampling, because parameters # TBD2: use linearized error estimate to come up with cov matrix for proposal # are highly correlated. # After sufficiently many samples drawn with SCAM # estimate covariance with C=n.cov(n.transpose(chain)) # use n.random.multivariate_normal to sample from C # chain[int(i / thinning), :] = xnow tries[pi] += 1.0 # adaptive step scam. adjust proposal # based on acceptance probability if i % 100 == 0 and i > 0: print("step %d/%d" % (i, N_samples * thinning)) print("logss %1.2f current state" % (logss)) print(xnow) print("acceptance probability") print(accept / tries) print("step size") print(step) print("---") ratio = accept / tries too_many = n.where(ratio > 0.5)[0] too_few = n.where(ratio < 0.3)[0] step[too_many] = step[too_many] * 2.0 step[too_few] = step[too_few] / 2.0 accept[:] = 0.0 tries[:] = 0.0 if i % 100 == 0 and i > 0: print("saving") ho = h5py.File("%s/chain-%03d.h5" % (odir, rank), "w") ho["chain"] = chain[0:(int(i / thinning)), :] ho.close() return (o_fit)
wls_state_est(mcmc=False, oidx=8, n_tracklets=1, track_length=600.0, n_points=512, N_samples=50000) # use fmin search if __name__ == "__main__": # oid 8400199 # 008400199 0.1000E+01 0.6021E-01 0.5581E-01 35.180 7355.7 0.0008 65.82 26.92 304.76 295.20 o = spo.SpaceObject(a=7355.7, e=0.0008, i=80.82, raan=26.92, aop=304.76, mu0=295.20, A=1 / 35.180, m=1.0, d=1.0) wls_state_est(mcmc=True, o=o, n_tracklets=4, track_length=1000.0, n_points=10, N_samples=500000) # wls_state_est(mcmc=False, oidx=8, n_tracklets=16, track_length=600.0, n_points=10, N_samples=50000) # initial_iod_accuracy()
import logging_setup import logging t0 = time.time() #radar=rl.eiscat_3d(beam='array') radar = rl.eiscat_3d(beam='gauss') # get all detections for this space object obj = so.SpaceObject( a=7000, e=0.0, i=72, raan=0, aop=0, mu0=0, C_D=2.3, A=1.0, m=1.0, d=0.7, propagator=PropagatorSGP4, propagator_options={'polar_motion': False}, ) print(obj) rs1 = rslib.ns_fence_model(0, 0, 0, min_el=30, angle_step=1, dwell_time=0.1) rs2 = rslib.sph_rng_model(0, 0, 0, min_el=30, dwell_time=0.1)