def test_cart2kep_circ(self): res = 100 nu = n.linspace(0, 360.0, num=res, dtype=n.float) x = n.empty((6, res), dtype=n.float) v = dpt.orbital_speed(self.a, self.a, scipy.constants.G * (self.m[0] + self.M_e)) r = self.a o_ref = n.empty((6, res), dtype=n.float) for i in range(res): o_ref[:5, i] = self.orb_init o_ref[5, i] = nu[i] x[0, i] = r * n.cos(n.radians(nu[i])) x[1, i] = r * n.sin(n.radians(nu[i])) x[2, i] = 0.0 x[3, i] = -v * n.sin(n.radians(nu[i])) x[4, i] = v * n.cos(n.radians(nu[i])) x[5, i] = 0.0 o = dpt.cart2kep(x, m=self.m, M_cent=self.M_e, radians=False) nt.assert_array_almost_equal(o_ref[2:, :], o[2:, :], decimal=7) nt.assert_array_almost_equal(o_ref[1, :], o[1, :], decimal=4) nt.assert_array_almost_equal(o_ref[0, :] / self.R_e, o[0, :] / self.R_e, decimal=3)
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 mass :code:`m` in kg and is not required. They also contain a option to give angles in radians or degrees. By default input is assumed to be degrees. **Frame:** The input frame is always the same as the output frame. :param float m: Mass of the object in kg. :param bool radians: If true, all angles are assumed to be in radians. ''' radians = kwargs.setdefault('radians', False) m = kwargs.setdefault('m', 0.0) cart0 = np.array([x, y, z, vx, vy, vz], dtype=np.float64) orb0 = dpt.cart2kep(cart0, m=m, M_cent=M_earth, radians=radians) a = orb0[0] e = orb0[1] inc = orb0[2] aop = orb0[3] raan = orb0[4] mu0 = dpt.true2mean(orb0[5], orb0[1], radians=radians) return self.get_orbit(t, a, e, inc, raan, aop, mu0, mjd0, **kwargs)
def get_orbit_cart(self, t, x, y, z, vx, vy, vz, mjd0, **kwargs): ''' **Implementation:** Converts Cartesian vector to Kepler elements and calls :func:`propagator_orekit.PropagatorOrekit.get_orbit`. All units are in m and m/s. **Uses:** * :func:`dpt_tools.cart2kep` * :func:`dpt_tools.true2mean` See :func:`propagator_base.PropagatorBase.get_orbit_cart`. ''' cart = np.array([x, y, z, vx, vy, vz], dtype=np.float) orb = dpt.cart2kep( cart, m=kwargs['m'], M_cent=self.M_earth, radians=False, ) a = orb[0] e = orb[1] inc = orb[2] aop = orb[3] raan = orb[4] mu0 = dpt.true2mean(orb[5], e, radians=False) return self.get_orbit(t, a, e, inc, raan, aop, mu0, mjd0, **kwargs)
def test_cart_kep_loop(self): orb_init = n.array([self.a, 0.2, 23.0, 136.0, 44.0, 10.0], dtype=n.float) x = dpt.kep2cart(orb_init, m=self.m, M_cent=self.M_e, radians=False) x_ref = x.copy() for ind in range(200): o = dpt.cart2kep(x, m=self.m, M_cent=self.M_e, radians=False) x = dpt.kep2cart(o, m=self.m, M_cent=self.M_e, radians=False) nt.assert_array_almost_equal(x, x_ref, decimal=6)
def propagate_population(population, mjd): obj_gen = population.object_generator() new_elements = np.empty((6,len(population)), dtype=np.float64) prop_ok = np.full((len(population),), True, dtype=np.bool) my_iter = list(range(comm.rank, len(population), comm.size)) for ind, obj in enumerate(obj_gen): if ind in my_iter: tt = (mjd - obj.mjd0)*3600.0*24.0 print('PID{}: propagating obj {} {:.2f} h'.format(comm.rank, ind, tt/3600.0)) try: state = obj.get_state(tt) except: prop_ok[ind] = False continue kep = dpt.cart2kep(state, m=obj.m, M_cent=obj.M_cent, radians=False) if np.any(np.isnan(kep))\ or kep[1] > 1.0: prop_ok[ind] = False continue new_elements[0,ind] = kep[0]*1e-3 new_elements[1,ind] = kep[1] new_elements[2,ind] = kep[2] new_elements[3,ind] = kep[4] new_elements[4,ind] = kep[3] new_elements[5,ind] = dpt.true2mean(kep[5], kep[1], radians=False) for pid in range(comm.size): for ind in range(pid, len(population), comm.size): new_elements[:,ind] = comm.bcast(new_elements[:,ind], root=pid) prop_ok[ind] = comm.bcast(prop_ok[ind], root=pid) population.objs['a'] = new_elements[0,:] population.objs['e'] = new_elements[1,:] population.objs['i'] = new_elements[2,:] population.objs['raan'] = new_elements[3,:] population.objs['aop'] = new_elements[4,:] population.objs['mu0'] = new_elements[5,:] population.objs['mjd0'] = mjd population.objs = population.objs[prop_ok] return population
def _cart2sgp4_elems(cart, radians=True): '''Cartesian coordinates to orbital elements. Wrap DPT-function to use mean anomaly, km and reversed order on aoe and raan. Neglecting mass is sufficient for this calculation (the standard gravitational parameter is 24 orders larger then the change). ''' kep = dpt.cart2kep(cart * 1e3, m=0.0, M_cent=propagator_sgp4.M_earth, radians=radians) kep[0] *= 1e-3 tmp = kep[4] kep[4] = kep[3] kep[3] = tmp kep[5] = dpt.true2mean(kep[5], kep[1], radians=radians) return kep
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') mjd = dpt.npdt2mjd(dt)
C_D=2.3, A=1.0, m=1.0, diam=0.1) #ecef needs earth rotation as a function of time from keplerian_sgp4 import gmst theta = gmst(obj.mjd0) eart_rot = dpt.rot_mat_z(-theta) x = obj.get_state(0.0) M_e = 5.972e24 x_dpt = dpt.kep2cart(o, m=n.array([1.0]), M_cent=M_e, radians=False) o_dpt = dpt.cart2kep(x, m=n.array([1.0]), M_cent=M_e, radians=False) x_dpt[:3] = eart_rot.dot(x_dpt[:3]) x_dpt[3:] = eart_rot.dot(x_dpt[3:]) print('Initial Kepler:', o) print('Initial Cart as from propagator:', x) print('Converted Kepler:', o_dpt) print('Converted Cart:', x_dpt) #n.testing.assert_almost_equal(x/au,x_dpt/au, decimal=4) #n.testing.assert_almost_equal(o,o_dpt, decimal=2) nu = n.mod(n.linspace(0.0, 360.0, num=100) + 90.0, 360.0) ''' fig = plt.figure(figsize=(15,15))
def test_cart_kep_inverse(self): a = n.linspace(self.a, self.a + self.R_e, num=5, dtype=n.float64) e = n.linspace(0.0, 0.99, num=10, dtype=n.float64) inc = n.linspace(0.0, n.pi, num=10, dtype=n.float64) omega = n.linspace(0.0, 2.0 * n.pi, num=10, dtype=n.float64) Omega = omega.copy() nu = omega.copy() av, ev, incv, omegav, Omegav, nuv = n.meshgrid(a, e, inc, omega, Omega, nu) ait = n.nditer(av) eit = n.nditer(ev) incit = n.nditer(incv) omegait = n.nditer(omegav) Omegait = n.nditer(Omegav) nuit = n.nditer(nuv) o = n.empty((6, av.size), dtype=n.float64) for ind in range(av.size): o[0, ind] = next(ait) o[1, ind] = next(eit) o[2, ind] = next(incit) o[3, ind] = next(omegait) o[4, ind] = next(Omegait) o[5, ind] = next(nuit) x = dpt.kep2cart(o, m=self.m, M_cent=self.M_e, radians=False) o_calc = dpt.cart2kep(x, m=self.m, M_cent=self.M_e, radians=False) x_calc = dpt.kep2cart(o_calc, m=self.m, M_cent=self.M_e, radians=False) for ind in range(av.size): try: nt.assert_array_almost_equal(x[:3, ind] / o[0, ind], x_calc[:3, ind] / o[0, ind], decimal=6) nt.assert_array_almost_equal(x[3:, ind] / o[0, ind], x_calc[3:, ind] / o[0, ind], decimal=6) except AssertionError: print(ind) print(x[:3, ind] - x_calc[:3, ind]) print(o[:, ind]) print(o_calc[:, ind]) print(o_calc[:, ind] - o[:, ind]) raise x = dpt.kep2cart(o, m=self.m, M_cent=self.M_e, radians=False) o_calc = dpt.cart2kep(x, m=self.m, M_cent=self.M_e, radians=False) o[3, o[1, :] < 1e-3] *= 0.0 o[4, o[2, :] < 180e-3] *= 0.0 for ind in range(av.size): test = n.isclose(o_calc[0, ind] / self.R_e, o[0, ind] / self.R_e, atol=1e-3) test = n.logical_and( test, n.isclose(o_calc[1, ind], o[1, ind], atol=1e-4)) test_ang = n.logical_or( n.isclose(o_calc[2:, ind], o[2:, ind], atol=1e-7), n.isclose(n.mod(o_calc[2:, ind] + 180.0, 360.0), n.mod(o[2:, ind] + 180.0, 360.0), atol=1e-7), ) test = n.logical_and(test, test_ang) if not n.all(test): print(ind) print(o[:, ind]) print(o_calc[:, ind]) print(o_calc[:, ind] - o[:, ind]) assert n.all(test)
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
def tle_snapshot(tle_file, sgp4_propagation=True, propagator = default_propagator, propagator_options = {}): '''Reads a TLE-snapshot file and converts the TLE's to orbits in a TEME frame and creates a population file. The BSTAR parameter is saved in column BSTAR (or :code:`_objs[:,12`). A snapshot generally contains several TLE's for the same object thus will this population also contain duplicate objects. *Numerical propagator assumptions:* To propagate with a numerical propagator one needs to make assumptions. * Density is :math:`5\cdot 10^3 \;\frac{kg}{m^3}`. * Object is a sphere * Drag coefficient is 2.3. :param str/list tle_file: Path to the input TLE snapshot file. Or the TLE-set can be given directly as a list of two lines that can be unpacked in a loop, e.g. :code:`[(tle1_l1, tle1_l2), (tle2_l1, tle2_l2)]`. :param bool sgp4_propagation: If :code:`False` then the population is specifically constructed to be propagated with :class:`propagator_orekit.PropagatorOrekit` and assumptions are made on mass, density and shape of objects. Otherwise the :class:`space_object.SpaceObject` is configured to use SGP4 propagation. :return: TLE snapshot as a population with numerical propagator :rtype: population.Population ''' if isinstance(tle_file, str): tle_raw = [line.rstrip('\n') for line in open(tle_file)] 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]) pop_name = tle_file.split('/')[-1] else: TLEs = tle_file pop_name = 'TLE database' M_earth = propagator_sgp4.SGP4.GM*1e9/consts.G if sgp4_propagation: pop = Population( name=pop_name, extra_columns = ['A', 'm', 'd', 'C_D', 'C_R'] + ['line1', 'line2'], dtypes = ['float64']*5 + ['U70', 'U70'], space_object_uses = [True, True, True, True, True] + [True, True], propagator = propagator_sgp4.PropagatorTLE, propagator_options = { 'out_frame': 'ITRF', 'polar_motion': False, }, ) else: pop = Population( name=pop_name, 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)) 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, epoch = tle.TLE_to_TEME(line1,line2) kep = dpt.cart2kep(state_TEME, m=0.0, M_cent=M_earth, radians=False) pop.objs[line_id][1] = kep[0]*1e-3 pop.objs[line_id][2] = kep[1] pop.objs[line_id][3] = kep[2] pop.objs[line_id][4] = kep[4] pop.objs[line_id][5] = kep[3] pop.objs[line_id][6] = dpt.true2mean(kep[5], kep[1], radians=False) pop.objs[line_id][0] = float(sat_id) pop.objs[line_id][7] = mjd0 if sgp4_propagation: for line_id, lines in enumerate(TLEs): line1, line2 = lines pop.objs[line_id][13] = line1[:-1] pop.objs[line_id][14] = line2[:-1] for line_id, lines in enumerate(TLEs): line1, line2 = lines bstar = tle.tle_bstar(line1)/(propagator_sgp4.SGP4.R_EARTH*1000.0) B = bstar*2.0/propagator_sgp4.SGP4.RHO0 if B < 1e-9: rho = 500.0 C_D = 0.0 r = 0.1 A = np.pi*r**2 m = rho*4.0/3.0*np.pi*r**3 else: C_D = 2.3 rho = 5.0 r = (3.0*C_D)/(B*rho) A = np.pi*r**2 m = rho*4.0/3.0*np.pi*r**3 pop.objs[line_id][8] = A pop.objs[line_id][9] = m pop.objs[line_id][10] = r*2.0 pop.objs[line_id][11] = C_D pop.objs[line_id][12] = 1.0 return pop
def NESCv9_mini_moons(albedo, propagate_SNR = None, radar = None, truncate = None): from propagator_rebound import PropagatorRebound _opts = dict( in_frame = 'HeliocentricECLIPJ2000', out_frame = 'ITRF', ) #fname = './data/NESCv9reintv1.TCO.withoutH.kep.des' fname = './data/NESCv9reintv1.TCO.withH.kep.des' data = np.genfromtxt(fname) if truncate is not None: _trunc = np.full((data.shape[0],), True, dtype=np.bool) _trunc[truncate] = False data = data[_trunc, :] print('Data truncated to: {}'.format(data.shape[0])) AU = 149597871.0 #km max_check = 365.0*3600.0*24.0 ''' 1. synthetic orbit designation 2. orbital element type (KEP for heliocentric Keplerian) 3. semimajor axis (au) 4. eccentricity 5. inclination (deg) 6. longitude of ascending node (deg) 7. argument of perihelion (deg) 8. mean anomaly (deg) 9. H-magnitude (filler value) 10. epoch for which the input orbit is valid (modified Julian date) 11. index (1) 12. number of parameters (6) 13. MOID (filler value) 14. Code with which created (OPENORB) ''' pop = Population( name='NESCv9', extra_columns = ['d'], space_object_uses = [True], propagator = PropagatorRebound, propagator_options = _opts, ) pop.allocate(data.shape[0]) pop['oid'] = np.arange(len(pop)) pop['a'] = data[:,2]*AU pop['e'] = data[:,3] pop['i'] = data[:,4] pop['raan'] = data[:,5] pop['aop'] = data[:,6] pop['mu0'] = data[:,7] pop['mjd0'] = data[:,9] pop['d'] = 10.0**(3.1236 - 0.5*np.log10(albedo) - 0.2*data[:,8]) if propagate_SNR is not None: my_iter = list(range(comm.rank, len(pop), comm.size)) ranges = np.empty((len(pop),), dtype=np.float64) for ind, _d in enumerate(pop['d']): if ind in my_iter: ranges[ind], _snr = _find_range_for_snr(radar, _d, AU*1e3 ,propagate_SNR) print('Object {} found range {:.3f} LD @ {:.2f} SNR'.format(ind, ranges[ind]/384400e3, _snr)) t_at_dist = np.empty((len(pop),), dtype=np.float64) new_elements = np.empty((6,len(pop)), dtype=np.float64) prop_ok = np.full((len(pop),), True, dtype=np.bool) obj_gen = pop.object_generator() t_v = np.arange(0.0, max_check, 3600.0) for ind, obj in enumerate(obj_gen): if ind in my_iter: print('Checking object {}'.format(ind)) states = obj.get_orbit(t_v) dists = np.linalg.norm(states, axis=0) _check = dists < ranges[ind] if np.any(_check): t_at_dist[ind] = t_v[np.argmax(_check)] print('|- Passed @ {:.2f} days'.format(t_at_dist[ind]/(24.0*3600.0))) else: prop_ok[ind] = False if 'out_frame' in pop.propagator_options: out_f = pop.propagator_options['out_frame'] else: out_f = 'ITRF' pop.propagator_options['out_frame'] = _opts['in_frame'] obj_gen = pop.object_generator() for ind, obj in enumerate(obj_gen): if ind in my_iter and prop_ok[ind]: print('PID{}: propagating obj {} {:.2f} h'.format(comm.rank, ind, t_at_dist[ind]/3600.0)) try: state = obj.get_state(t_at_dist[ind]) except: prop_ok[ind] = False continue kep = dpt.cart2kep(state, m=obj.m, M_cent=obj.M_cent, radians=False) if np.any(np.isnan(kep)): prop_ok[ind] = False continue new_elements[0,ind] = kep[0]*1e-3 new_elements[1,ind] = kep[1] new_elements[2,ind] = kep[2] new_elements[3,ind] = kep[4] new_elements[4,ind] = kep[3] new_elements[5,ind] = dpt.true2mean(kep[5], kep[1], radians=False) for pid in range(comm.size): for ind in range(pid, len(pop), comm.size): new_elements[:,ind] = comm.bcast(new_elements[:,ind], root=pid) prop_ok[ind] = comm.bcast(prop_ok[ind], root=pid) t_at_dist[ind] = comm.bcast(t_at_dist[ind], root=pid) pop.objs['a'] = new_elements[0,:] pop.objs['e'] = new_elements[1,:] pop.objs['i'] = new_elements[2,:] pop.objs['raan'] = new_elements[3,:] pop.objs['aop'] = new_elements[4,:] pop.objs['mu0'] = new_elements[5,:] pop.objs['mjd0'] += t_at_dist/(3600.0*24.0) pop.objs = pop.objs[prop_ok] pop.propagator_options['out_frame'] = out_f return pop
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
def test_PropagatorSGP4_cart_kep_inverse(self): prop = propagator_sgp4.PropagatorSGP4(polar_motion=False) t = np.array([0], dtype=np.float) reci = np.array([ -5339.76186573000, 5721.43584226500, 921.276953805000, ], dtype=np.float) veci = np.array([ -4.88969089550000, -3.83304653050000, 3.18013811100000, ], dtype=np.float) state_TEME = np.concatenate((reci*1e3, veci*1e3), axis=0) M_earth = propagator_sgp4.SGP4.GM*1e9/consts.G kep = dpt.cart2kep(state_TEME, m=self.m, M_cent=M_earth, radians=False) kep[5] = dpt.true2mean(kep[5], kep[1], radians=False) ecefs_kep = prop.get_orbit( t=t, mjd0=self.mjd0, a=kep[0], e=kep[1], inc=kep[2], raan=kep[4], aop=kep[3], mu0=kep[5], C_D=self.C_D, m=self.m, A=self.A, ) p = ecefs_kep[:3]*1e-3 p.shape=(3,1) v = ecefs_kep[3:]*1e-3 v.shape=(3,1) kep_TEME = propagator_sgp4.ecef2teme(np.array([0.0]), p, v, mjd0=self.mjd0)*1e3 kep_TEME.shape = (6,) state_diff1 = np.abs(kep_TEME - state_TEME) nt.assert_array_less(state_diff1[:3], np.full((3,), 1e-2, dtype=state_diff1.dtype)) nt.assert_array_less(state_diff1[3:], np.full((3,), 1e-5, dtype=state_diff1.dtype)) ecefs_cart = prop.get_orbit_cart( t=t, mjd0=self.mjd0, x=-5339.76186573000e3, y=5721.43584226500e3, z=921.276953805000e3, vx=-4.88969089550000e3, vy=-3.83304653050000e3, vz=3.18013811100000e3, C_D=self.C_D, m=self.m, A=self.A, ) p = ecefs_cart[:3]*1e-3 p.shape=(3,1) v = ecefs_cart[3:]*1e-3 v.shape=(3,1) cart_TEME = propagator_sgp4.ecef2teme(np.array([0.0]), p, v, mjd0=self.mjd0)*1e3 cart_TEME.shape = (6,) state_diff2 = np.abs(cart_TEME - state_TEME) nt.assert_array_less(state_diff2[:3], np.full((3,), 1e-2, dtype=state_diff2.dtype)) nt.assert_array_less(state_diff2[3:], np.full((3,), 1e-5, dtype=state_diff2.dtype)) state_diff = np.abs(cart_TEME - kep_TEME) nt.assert_array_less(state_diff[:3], np.full((3,), 1e-2, dtype=state_diff.dtype)) nt.assert_array_less(state_diff[3:], np.full((3,), 1e-5, dtype=state_diff.dtype))
def cartesian(so_class, x, y, z, vx, vy, vz, d=0.01, C_D=2.3, A=1.0, m=1.0, mjd0=57125.7729, oid=42, M_cent=M_e, C_R=1.0, propagator=default_propagator, propagator_options={}, **kwargs): '''Creates a space object using Cartesian elements. :param float x: X position in km :param float y: Y position in km :param float z: Z position in km :param float vx: X-direction velocity in km/s :param float vy: Y-direction velocity in km/s :param float vz: Z-direction velocity in km/s :param float C_D: Drag coefficient :param float C_R: Radiation pressure coefficient :param float A: Area :param float m: Mass in kg :param float mjd0: Epoch for state :param int oid: Identifying object ID :param float d: Diameter in meters :param float M_cent: Mass of central body :param PropagatorBase propagator: Propagator class pointer :param dict propagator_options: Propagator initialization keyword arguments :param dict kwargs: All additional keyword arguments will be passed to the propagator call. ''' state = n.array([x, y, z, vx, vy, vz], dtype=n.float) * 1e3 eart_rot_inv = dpt.rot_mat_z(-dpt.gmst(mjd0)) #state[3:] = eart_rot_inv.dot(state[3:]) #state[:3] = eart_rot_inv.dot(state[:3]) orb_c = dpt.cart2kep(state, m=m, M_cent=M_cent, radians=False) a = orb_c[0] * 1e-3 e = orb_c[1] i = orb_c[2] raan = orb_c[4] aop = orb_c[3] mu0 = dpt.true2mean(orb_c[5], orb_c[1], radians=False) return so_class(a=a, e=e, i=i, raan=raan, aop=aop, mu0=mu0, d=d, C_D=C_D, A=A, m=m, mjd0=mjd0, oid=oid, M_cent=M_cent, C_R=C_R, propagator=propagator, propagator_options=propagator_options, **kwargs)
def update(self, **kwargs): '''Updates the orbital elements and Cartesian state vector of the space object. Can update any of the related state parameters, all others will automatically update. Cannot update Keplerian and Cartesian elements simultaneously. :param float a: Semi-major axis in km :param float e: Eccentricity :param float i: Inclination in degrees :param float aop: Argument of perigee in degrees :param float raan: Right ascension of the ascending node in degrees :param float mu0: Mean anomaly in degrees :param float x: X position in km :param float y: Y position in km :param float z: Z position in km :param float vx: X-direction velocity in km/s :param float vy: Y-direction velocity in km/s :param float vz: Z-direction velocity in km/s ''' kep = ['a', 'e', 'i', 'raan', 'aop', 'mu0'] cart = ['x', 'y', 'z', 'vx', 'vy', 'vz'] kep_orb = False cart_orb = False for key, val in kwargs.items(): if key in kep: kep_orb = True setattr(self, key, val) elif key in cart: cart_orb = True setattr(self, key, val) else: raise TypeError('{} variable cannot be updated'.format(key)) if kep_orb and cart_orb: raise TypeError( 'Cannot update both Cartesian and Kepler elements at the same time' ) if kep_orb: orb = n.array([ self.a * 1e3, self.e, self.i, self.aop, self.raan, dpt.mean2true(self.mu0, self.e, radians=False) ], dtype=n.float) state_c = dpt.kep2cart( orb, m=n.array([self.m ]), M_cent=self.M_cent, radians=False) * 1e-3 if cart_orb: state = n.array( [self.x, self.y, self.z, self.vx, self.vy, self.vz], dtype=n.float) * 1e3 self.state_cart = state orb_c = dpt.cart2kep(state, m=self.m, M_cent=self.M_cent, radians=False) if kep_orb: self.x = state_c[0] self.y = state_c[1] self.z = state_c[2] self.vx = state_c[3] self.vy = state_c[4] self.vz = state_c[5] self.state_cart = state_c * 1e3 if cart_orb: self.a = orb_c[0] * 1e-3 self.e = orb_c[1] self.i = orb_c[2] self.raan = orb_c[4] self.aop = orb_c[3] self.mu0 = dpt.true2mean(orb_c[5], orb_c[1], radians=False)
def simulate_Microsat_R_debris_v2(num, max_dv, rho_range, mass_range, seed, propagator, propagator_options, mjd): mass = 740 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', 'dV', 'dx', 'dy', 'dz'], space_object_uses = [True, True, True, True, True, False, False, False, False], propagator = propagator, propagator_options = propagator_options, ) pop.allocate(num) state_TEME, sat_id = _get_MicrosatR_state(event_mjd) #first has no pert states = np.repeat(state_TEME, num, axis=1) np.random.seed(seed) popts = copy.deepcopy(propagator_options) popts['out_frame'] = propagator_options['in_frame'] prop = propagator(**popts) def mrho2d(m,rho): V = m/rho return 2.0*(V*3.0/(4.0*np.pi))**(1.0/3.0) prop_data = {} ind = 0 trys = 0 while ind < num: trys += 1 print('try number {}'.format(trys)) prop_data['C_D'] = 2.3 prop_data['C_R'] = 1.0 prop_data['mjd0'] = event_mjd rho_v = np.random.rand(1)*(rho_range[1] - rho_range[0]) + rho_range[0] m_v = np.random.rand(1)*(mass_range[1] - mass_range[0]) + mass_range[0] d_v = mrho2d(m_v, rho_v) prop_data['m'] = m_v[0] prop_data['d'] = d_v[0] prop_data['A'] = np.pi*d_v[0]**2/4.0 pert_state = state_TEME[:,0].copy() dv = np.random.rand(1)*max_dv ddir = _rand_sph(1).T pert_state[3:] += ddir[:,0]*dv prop_data['x'], prop_data['y'], prop_data['z'] = pert_state[:3] prop_data['vx'], prop_data['vy'], prop_data['vz'] = pert_state[3:] prop_data['t'] = (mjd - event_mjd)*3600.0*24.0 try: prop_pert_state = prop.get_orbit_cart(**prop_data) except Exception as e: #print(e) continue print('object added - {} of {}'.format(ind, num)) kep = dpt.cart2kep(prop_pert_state[:,0], m=mass, M_cent=M_earth, radians=False) 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] = mjd pop.objs[ind]['A'] = prop_data['A'] pop.objs[ind]['d'] = prop_data['d'] pop.objs[ind]['m'] = prop_data['m'] pop.objs[ind]['C_D'] = prop_data['C_D'] pop.objs[ind]['C_R'] = prop_data['C_R'] pop.objs[ind]['dV'] = dv pop.objs[ind]['dx'] = ddir[0,0] pop.objs[ind]['dy'] = ddir[1,0] pop.objs[ind]['dz'] = ddir[2,0] ind += 1 return pop