def propagate(self, value, method=mean_motion, rtol=1e-10, **kwargs): """Propagates an orbit a specified time. If value is true anomaly, propagate orbit to this anomaly and return the result. Otherwise, if time is provided, propagate this `Orbit` some `time` and return the result. Parameters ---------- value : ~astropy.units.Quantity, ~astropy.time.Time, ~astropy.time.TimeDelta Scalar time to propagate. rtol : float, optional Relative tolerance for the propagation algorithm, default to 1e-10. method : function, optional Method used for propagation **kwargs parameters used in perturbation models Returns ------- Orbit New orbit after propagation. """ if isinstance(value, time.Time) and not isinstance(value, time.TimeDelta): time_of_flight = value - self.epoch else: # Works for both Quantity and TimeDelta objects time_of_flight = time.TimeDelta(value) cartesian = propagate(self, time_of_flight, method=method, rtol=rtol, **kwargs) new_epoch = self.epoch + time_of_flight # TODO: Unify with sample # If the frame supports obstime, set the time values try: kwargs = {} if "obstime" in self.frame.frame_attributes: kwargs["obstime"] = new_epoch # Use of a protected method instead of frame.realize_frame # because the latter does not let the user choose the representation type # in one line despite its parameter names, see # https://github.com/astropy/astropy/issues/7784 coords = self.frame._replicate( cartesian, representation_type="cartesian", **kwargs ) return self.from_coords(self.attractor, coords, plane=self.plane) except NotImplementedError: return self.from_vectors( self.attractor, cartesian[0].xyz, cartesian[0].differentials["s"].d_xyz, new_epoch, )
def _init_groundtrack_packet_cords_(self, i, rtol): """ Parameters ---------- i: int Index of referenced orbit rtol: float Maximum relative error permitted Returns ------- coordinate list """ cart_cords = [] # type: List[float] h = (self.end_epoch - self.orbits[i][2]).to( u.second) / self.orbits[i][1] # Get rounding factor given the relative tolerance rf = 0 while rtol < 1: rtol *= 10 rf += 1 ellipsoid = self.cust_prop[0] for k in range(self.orbits[i][1] + 2): position = propagate(self.orbits[i][0], TimeDelta(k * h), rtol=rtol) cords = position.represent_as(CartesianRepresentation).xyz.to( u.meter).value cords = np.insert(cords, 0, h.value * k, axis=0) # flatten list cords = list(map(lambda x: round(x[0], rf), cords.tolist())) t, p = cords[0], cords[1:] pr_p = project_point_on_ellipsoid(p[0], p[1], p[2], ellipsoid[0], ellipsoid[1], ellipsoid[2]) # Add a small number to ensure that our point lies above the surface of the # ellipsoid. We do this because small losses in precision may cause the point # to lie slightly bellow the surface. An iterative method could be used instead # but the error margin is too small to be worth it. _cords = t, pr_p[0] + 0.1, pr_p[1] + 0.1, pr_p[2] + 0.1 cart_cords += _cords return cart_cords
def propagate(self, value, method=mean_motion, rtol=1e-10, **kwargs): """Propagates an orbit. If value is true anomaly, propagate orbit to this anomaly and return the result. Otherwise, if time is provided, propagate this `Orbit` some `time` and return the result. Parameters ---------- value : Multiple options True anomaly values or time values. If given an angle, it will always propagate forward. rtol : float, optional Relative tolerance for the propagation algorithm, default to 1e-10. method : function, optional Method used for propagation **kwargs parameters used in perturbation models """ if hasattr(value, "unit") and value.unit in ("rad", "deg"): p, ecc, inc, raan, argp, _ = rv2coe( self.attractor.k.to(u.km ** 3 / u.s ** 2).value, self.r.to(u.km).value, self.v.to(u.km / u.s).value, ) # Compute time of flight for correct epoch M = nu_to_M(self.nu, self.ecc) new_M = nu_to_M(value, self.ecc) time_of_flight = Angle(new_M - M).wrap_at(360 * u.deg) / self.n return self.from_classical( self.attractor, p / (1.0 - ecc ** 2) * u.km, ecc * u.one, inc * u.rad, raan * u.rad, argp * u.rad, value, epoch=self.epoch + time_of_flight, plane=self._plane, ) else: if isinstance(value, time.Time) and not isinstance(value, time.TimeDelta): time_of_flight = value - self.epoch else: time_of_flight = time.TimeDelta(value) return propagate(self, time_of_flight, method=method, rtol=rtol, **kwargs)
def _setcoords(self): """Update tofs and coords. Note ---- After updating T or kwargs this method is going to be called in order to update the times of flight of the propagator as well as the resulting coordinate for the new timeframe or perturbative force. """ self.tofs = TimeDelta(np.linspace(0,self.T*24*3600*u.s, num=int(self.T*24*3600/self._DT))) self.coords = propagation.propagate(self.orbit, self.tofs,method=self.method,**self.kwargs)
def sample(self, values=100, *, min_anomaly=None, max_anomaly=None): r"""Samples an orbit to some specified time values. .. versionadded:: 0.8.0 Parameters ---------- values : int Number of interval points (default to 100). min_anomaly, max_anomaly : ~astropy.units.Quantity, optional Anomaly limits to sample the orbit. For elliptic orbits the default will be :math:`E \in \left[0, 2 \pi \right]`, and for hyperbolic orbits it will be :math:`\nu \in \left[-\nu_c, \nu_c \right]`, where :math:`\nu_c` is either the current true anomaly or a value that corresponds to :math:`r = 3p`. Returns ------- positions: ~astropy.coordinates.BaseCoordinateFrame Array of x, y, z positions, with proper times as the frame attributes if supported. Notes ----- When specifying a number of points, the initial and final position is present twice inside the result (first and last row). This is more useful for plotting. Examples -------- >>> from astropy import units as u >>> from poliastro.examples import iss >>> iss.sample() # doctest: +ELLIPSIS <CartesianRepresentation (x, y, z) in km ... >>> iss.sample(10) # doctest: +ELLIPSIS <CartesianRepresentation (x, y, z) in km ... """ if self.ecc < 1: nu_values = self._sample_closed(values, min_anomaly, max_anomaly) else: nu_values = self._sample_open(values, min_anomaly, max_anomaly) time_values = time.TimeDelta(self._generate_time_values(nu_values)) cartesian = propagate(self, time_values) return cartesian
def propagate(self, value, method=mean_motion, rtol=1e-10, **kwargs): """Propagates an orbit a specified time. If value is true anomaly, propagate orbit to this anomaly and return the result. Otherwise, if time is provided, propagate this `Orbit` some `time` and return the result. Parameters ---------- value : ~astropy.units.Quantity, ~astropy.time.Time, ~astropy.time.TimeDelta Scalar time to propagate. rtol : float, optional Relative tolerance for the propagation algorithm, default to 1e-10. method : function, optional Method used for propagation **kwargs parameters used in perturbation models Returns ------- Orbit New orbit after propagation. """ if isinstance(value, time.Time) and not isinstance(value, time.TimeDelta): time_of_flight = value - self.epoch else: # Works for both Quantity and TimeDelta objects time_of_flight = time.TimeDelta(value) # TODO: Create a from_coordinates method coords = propagate(self, time_of_flight, method=method, rtol=rtol, **kwargs)[0] # Even after indexing the result of propagate, # the frame obstime might have an array of times # See the propagate function for reasoning about the usage of a # protected method coords = coords._replicate(coords.data, representation_type="cartesian", obstime=coords.obstime[0]) return self.from_coords(self.attractor, coords, plane=self.plane)
def propagate(self, epoch_or_duration, rtol=1e-10): """Propagate this `Orbit` some `time` and return the result. Parameters ---------- epoch_or_duration : Time, TimeDelta or equivalent Final epoch or time of flight. rtol : float, optional Relative tolerance for the propagation algorithm, default to 1e-10. """ if isinstance(epoch_or_duration, time.Time) and not isinstance( epoch_or_duration, time.TimeDelta): time_of_flight = epoch_or_duration - self.epoch else: time_of_flight = time.TimeDelta(epoch_or_duration) return propagate(self, time_of_flight, rtol=rtol)
def propagate(self, value, method=mean_motion, rtol=1e-10, **kwargs): """Propagates an orbit a specified time. If value is true anomaly, propagate orbit to this anomaly and return the result. Otherwise, if time is provided, propagate this `Orbit` some `time` and return the result. Parameters ---------- value : ~astropy.units.Quantity, ~astropy.time.Time, ~astropy.time.TimeDelta Scalar time to propagate. rtol : float, optional Relative tolerance for the propagation algorithm, default to 1e-10. method : function, optional Method used for propagation **kwargs parameters used in perturbation models Returns ------- Orbit New orbit after propagation. """ if isinstance(value, time.Time) and not isinstance(value, time.TimeDelta): time_of_flight = value - self.epoch else: # Works for both Quantity and TimeDelta objects time_of_flight = time.TimeDelta(value) cartesian = propagate(self, time_of_flight, method=method, rtol=rtol, **kwargs) new_epoch = self.epoch + time_of_flight return self.from_vectors( self.attractor, cartesian[0].xyz, cartesian[0].differentials["s"].d_xyz, new_epoch, plane=self.plane, )
def _init_orbit_packet_cords_(self, i): """ Parameters ---------- i: int Index of referenced orbit """ h = (self.end_epoch - self.orbits[i][2]).to( u.second) / self.orbits[i][1] for k in range(self.orbits[i][1] + 2): position = propagate(self.orbits[i][0], TimeDelta(k * h)) cords = position.represent_as(CartesianRepresentation).xyz.to( u.meter).value cords = np.insert(cords, 0, h.value * k, axis=0) self.czml[i]["position"]["cartesian"] += list( map(lambda x: x[0], cords.tolist()))
def no_pert_earth(initial, time, f_time): # No perturbation # parameters of a body C_D = 2.2 # dimentionless (any value would do) A = ((np.pi / 4.0) * (u.m**2)).to(u.km**2).value # km^2 m = 100 # kg B = C_D * A / m datetimeFormat = '%Y-%m-%d %H:%M:%S.%f' diff =datetime.strptime(str(f_time), datetimeFormat)\ - datetime.strptime(str(time), datetimeFormat) print("Time difference:") print(diff) tofs = TimeDelta(f_time - time) tofs = TimeDelta(np.linspace(0, 31 * u.day, num=1)) rr = propagate(initial, tofs, method=cowell, ad=None) print("") print("Positions and velocity vectors are:") #print(str(rr.x)) #print([float(s) for s in re.findall(r'-?\d+\.?\d*',str(rr.x))]) r = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.z))][0]] * u.km v = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_z))][0]] * u.km / u.s f_orbit = Orbit.from_vectors(Earth, r, v) print(r) print(v) #f_orbit.plot() print("") print("Orbital elements:") print(f_orbit.classical()) print("") #print("") #print(f_orbit.ecc) plotOrbit((f_orbit.a.value), (f_orbit.ecc.value), (f_orbit.inc.value), (f_orbit.raan.value), (f_orbit.argp.value), (f_orbit.nu.value))
def propagate(self, value, method=mean_motion, rtol=1e-10, **kwargs): """Propagates an orbit. If value is true anomaly, propagate orbit to this anomaly and return the result. Otherwise, if time is provided, propagate this `Orbit` some `time` and return the result. Parameters ---------- value : Multiple options True anomaly values, Time values. rtol : float, optional Relative tolerance for the propagation algorithm, default to 1e-10. method : function, optional Method used for propagation **kwargs parameters used in perturbation models """ if hasattr(value, "unit") and value.unit in ('rad', 'deg'): p, ecc, inc, raan, argp, _ = rv.rv2coe( self.attractor.k.to(u.km**3 / u.s**2).value, self.r.to(u.km).value, self.v.to(u.km / u.s).value) return self.from_classical(self.attractor, p / (1.0 - ecc**2) * u.km, ecc * u.one, inc * u.rad, raan * u.rad, argp * u.rad, value) else: if isinstance(value, time.Time) and not isinstance(value, time.TimeDelta): time_of_flight = value - self.epoch else: time_of_flight = time.TimeDelta(value) return propagate(self, time_of_flight, method=method, rtol=rtol, **kwargs)
def propagate(self, value, method=mean_motion, rtol=1e-10, **kwargs): """Propagates an orbit. If value is true anomaly, propagate orbit to this anomaly and return the result. Otherwise, if time is provided, propagate this `Orbit` some `time` and return the result. Parameters ---------- value : Multiple options True anomaly values or time values. If given an angle, it will always propagate forward. rtol : float, optional Relative tolerance for the propagation algorithm, default to 1e-10. method : function, optional Method used for propagation **kwargs parameters used in perturbation models """ if hasattr(value, "unit") and value.unit in ('rad', 'deg'): p, ecc, inc, raan, argp, _ = rv2coe(self.attractor.k.to(u.km ** 3 / u.s ** 2).value, self.r.to(u.km).value, self.v.to(u.km / u.s).value) # Compute time of flight for correct epoch M = nu_to_M(self.nu, self.ecc) new_M = nu_to_M(value, self.ecc) time_of_flight = Angle(new_M - M).wrap_at(360 * u.deg) / self.n return self.from_classical(self.attractor, p / (1.0 - ecc ** 2) * u.km, ecc * u.one, inc * u.rad, raan * u.rad, argp * u.rad, value, epoch=self.epoch + time_of_flight, plane=self._plane) else: if isinstance(value, time.Time) and not isinstance(value, time.TimeDelta): time_of_flight = value - self.epoch else: time_of_flight = time.TimeDelta(value) return propagate(self, time_of_flight, method=method, rtol=rtol, **kwargs)
def _get_raw_coords(self, ss, t_deltas): """Generates raw orbit coordinates for given epochs Parameters ---------- ss: ~poliastro.twobody.orbit Orbit to be propagated t_deltas: ~astropy.time.DeltaTime Desired observation time Returns ------- raw_xyz: array A collection of raw cartessian position vectors raw_epochs: array Associated epoch with previously raw coordinates """ # Solve for raw coordinates and epochs raw_xyz = propagate(ss, t_deltas) raw_epochs = ss.epoch + t_deltas return raw_xyz, raw_epochs
def from_orbit( cls, orbit, epochs, plane=Planes.EARTH_EQUATOR, ): """Return 'Ephem` from an `Orbit` at certain epochs. Parameters ---------- orbit: ~poliastro.twobody.orbit.Orbit Orbit. epochs: ~astropy.time.Time Epochs to sample the orbit positions. plane: ~poliastro.frames.Planes, optional Fundamental plane of the frame, default to Earth Equator. """ if epochs.isscalar: epochs = epochs.reshape(1) time_of_flights = epochs - orbit.epoch coordinates = propagate(orbit, time_of_flights) return cls(coordinates, epochs, plane)
def _init_orbit_packet_cords_(self, i, rtol): """ Parameters ---------- i: int Index of referenced orbit rtol: float Maximum relative error permitted Returns ------- coordinate list """ cart_cords = [] # type: List[float] h = (self.end_epoch - self.orbits[i][2]).to( u.second) / self.orbits[i][1] # Get rounding factor given the relative tolerance rf = 0 while rtol < 1: rtol *= 10 rf += 1 for k in range(self.orbits[i][1] + 2): position = propagate(self.orbits[i][0], TimeDelta(k * h), rtol=rtol) cords = position.represent_as(CartesianRepresentation).xyz.to( u.meter).value cords = np.insert(cords, 0, h.value * k, axis=0) # flatten list cart_cords += list(map(lambda x: round(x[0], rf), cords.tolist())) return cart_cords
def fx_obj(state, dt): return propagate(state, time.TimeDelta(dt * u.s), method=markley)
A_over_m = ((np.pi / 4.0) * (u.m**2) / (100 * u.kg)).to_value(u.km**2 / u.kg) # km^2/kg B = C_D * A_over_m # parameters of the atmosphere rho0 = rho0_earth.to(u.kg / u.km**3).value # kg/km^3 H0 = H0_earth.to(u.km).value tofs = TimeDelta(np.linspace(0 * u.h, 100000 * u.s, num=2000)) rr = propagate( orbit, tofs, method=cowell, ad=atmospheric_drag_exponential, R=R, C_D=C_D, A_over_m=A_over_m, H0=H0, rho0=rho0, ) # In[4]: plt.ylabel("h(t)") plt.xlabel("t, days") plt.plot(tofs.value, rr.norm() - Earth.R) # ### Orbital Decay # # If atmospheric drag causes the orbit to fully decay, additional code
def custom(initial, choice, state, time, f_time): # requires modification and validation R = Earth.R.to(u.km).value k = Earth.k.to(u.km**3 / u.s**2).value #s0 = Orbit.from_classical(Earth, x[0] * u.km, x[1] * u.one, x[4] * u.deg, * u.deg, x[3] * u.deg, 0 * u.deg, epoch=Time(0, format='jd', scale='tdb')) #orbit = Orbit.circular( # Earth, 250 * u.km, epoch=Time(0.0, format="jd", scale="tdb")) # parameters of a body C_D = 2.2 # dimentionless (any value would do) A = ((np.pi / 4.0) * (u.m**2)).to(u.km**2).value # km^2 m = 100 # kg B = C_D * A / m # parameters of the atmosphere rho0 = Earth.rho0.to(u.kg / u.km**3).value # kg/km^3 H0 = Earth.H0.to(u.km).value #J2,J3 parameters J3 = Earth.J3.value J2 = Earth.J2.value datetimeFormat = '%Y-%m-%d %H:%M:%S.%f' diff =datetime.strptime(str(f_time), datetimeFormat)\ - datetime.strptime(str(time), datetimeFormat) print("Time difference:") print(diff) tofs = TimeDelta(f_time - time) tofs = TimeDelta(np.linspace(0, 31 * u.day, num=1)) if (choice == '7'): rr = propagate( initial, tofs, method=cowell, ad=accel, #k=k, ) elif (choice == '5'): rr = propagate( initial, tofs, method=cowell, ad=a_d_1, #k=k, J2=J2, R=R, C_D=C_D, A=A, m=m, H0=H0, rho0=rho0) elif (choice == '6'): rr = propagate( initial, tofs, method=cowell, ad=a_d_2, #k=k, J3=J3, R=R, C_D=C_D, A=A, m=m, H0=H0, rho0=rho0) else: pass print("") print("Positions and velocity vectors are:") #print(str(rr.x)) #print([float(s) for s in re.findall(r'-?\d+\.?\d*',str(rr.x))]) r = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.z))][0]] * u.km v = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_z))][0]] * u.km / u.s f_orbit = Orbit.from_vectors(Earth, r, v) print(r) print(v) #f_orbit.plot() print("") print("Orbital elements:") print(f_orbit.classical()) print("") #print("") #print(f_orbit.ecc) plotOrbit((f_orbit.a.value), (f_orbit.ecc.value), (f_orbit.inc.value), (f_orbit.raan.value), (f_orbit.argp.value), (f_orbit.nu.value))
def atmd_earth(initial, time, f_time): # perturbation for atmospheric drag R = Earth.R.to(u.km).value k = Earth.k.to(u.km**3 / u.s**2).value #s0 = Orbit.from_classical(Earth, x[0] * u.km, x[1] * u.one, x[4] * u.deg, * u.deg, x[3] * u.deg, 0 * u.deg, epoch=Time(0, format='jd', scale='tdb')) #orbit = Orbit.circular( # Earth, 250 * u.km, epoch=Time(0.0, format="jd", scale="tdb")) # parameters of a body C_D = 2.2 # dimentionless (any value would do) A = ((np.pi / 4.0) * (u.m**2)).to(u.km**2).value # km^2 m = 100 # kg B = C_D * A / m # parameters of the atmosphere rho0 = Earth.rho0.to(u.kg / u.km**3).value # kg/km^3 H0 = Earth.H0.to(u.km).value print( "Use default constants or you want to customize?\n1.Default.\n2.Custom." ) check = input() if (check == '1'): pass else: m = input("Enter mass of the body in kg:") R = input("Enter radius of earth in km:") C_D = input("Enter C_D(dimension):") H0 = input("Enter atmospheric parameter H0:") #rho0=input("Enter atmospheric parameter rho0:") R = R * u.km H0 = H0 * u.km #rho0=rho0*(u.kg / u.km ** 3) datetimeFormat = '%Y-%m-%d %H:%M:%S.%f' diff =datetime.strptime(str(f_time), datetimeFormat)\ - datetime.strptime(str(time), datetimeFormat) print("Time difference:") print(diff) tofs = TimeDelta(f_time - time) tofs = TimeDelta(np.linspace(0, 31 * u.day, num=1)) #print("tofs:") #print(tofs) #print("ie:") #print(initial.epoch.iso) rr = propagate( initial, tofs, method=cowell, ad=atmospheric_drag, R=R, C_D=C_D, A=A, m=m, H0=H0, rho0=rho0, ) print("") print("Positions and velocity vectors are:") #print(str(rr.x)) #print([float(s) for s in re.findall(r'-?\d+\.?\d*',str(rr.x))]) r = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.z))][0]] * u.km v = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_z))][0]] * u.km / u.s f_orbit = Orbit.from_vectors(Earth, r, v) print(r) print(v) #f_orbit.plot() print("") print("Orbital elements:") print(f_orbit.classical()) print("") #print("") #print(f_orbit.ecc) plotOrbit((f_orbit.a.value), (f_orbit.ecc.value), (f_orbit.inc.value), (f_orbit.raan.value), (f_orbit.argp.value), (f_orbit.nu.value))
def j3_earth(initial, time, f_time): # perturbation for oblateness R = Earth.R.to(u.km).value k = Earth.k.to(u.km**3 / u.s**2).value #s0 = Orbit.from_classical(Earth, x[0] * u.km, x[1] * u.one, x[4] * u.deg, * u.deg, x[3] * u.deg, 0 * u.deg, epoch=Time(0, format='jd', scale='tdb')) #orbit = Orbit.circular( # Earth, 250 * u.km, epoch=Time(0.0, format="jd", scale="tdb")) # parameters of a body C_D = 2.2 # dimentionless (any value would do) A = ((np.pi / 4.0) * (u.m**2)).to(u.km**2).value # km^2 m = 100 # kg B = C_D * A / m J3 = Earth.J3.value print( "Use default constants or you want to customize?\n1.Default.\n2.Custom." ) check = input() if (check == '1'): pass else: J3 = input("Enter J3 constant:") R = input("Enter radius of earth in km:") datetimeFormat = '%Y-%m-%d %H:%M:%S.%f' diff =datetime.strptime(str(f_time), datetimeFormat)\ - datetime.strptime(str(time), datetimeFormat) print("Time difference:") print(diff) tofs = TimeDelta(f_time - time) tofs = TimeDelta(np.linspace(0, 31 * u.day, num=1)) rr = propagate(initial, tofs, method=cowell, ad=J3_perturbation, J3=J3, R=R) print("") print("Positions and velocity vectors are:") #print(str(rr.x)) #print([float(s) for s in re.findall(r'-?\d+\.?\d*',str(rr.x))]) r = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.z))][0]] * u.km v = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_z))][0]] * u.km / u.s f_orbit = Orbit.from_vectors(Earth, r, v) print(r) print(v) #f_orbit.plot() print("") print("Orbital elements:") print(f_orbit.classical()) print("") #print("") #print(f_orbit.ecc) plotOrbit((f_orbit.a.value), (f_orbit.ecc.value), (f_orbit.inc.value), (f_orbit.raan.value), (f_orbit.argp.value), (f_orbit.nu.value))
#create time and time step start_date = time.Time('2018-01-01 00:00', scale='utc') step = time.TimeDelta(1.0, format='jd') end_date = time.Time('2018-12-31 00:00', scale='utc') #create orbit with start_date #for asteroid a = (1.11 + 0.90) / 2 * u.AU ecc = 0.104 * u.one inc = 7.77 * u.deg raan = 66.51 * u.deg argp = 307.23 * u.deg nu = np.rad2deg(ang.M_to_nu(np.deg2rad(297.53 * u.deg), ecc)) asteroid = Orbit.from_classical(Sun, a, ecc, inc, raan, argp, nu, start_date) asteroid = propagate(asteroid, 150 * 3600 * 24 * u.second) #for earth a = 1 * u.AU ecc = 0.0167086 * u.one nu = np.rad2deg(ang.M_to_nu(np.deg2rad(358.617 * u.deg), ecc)) inc = 7.155 * u.deg raan = -11.26064 * u.deg argp = 114.207 * u.deg earth = Orbit.from_classical(Sun, a, ecc, inc, raan, argp, nu, start_date) op = OrbitPlotter() op.plot(asteroid, label='asteroid') op.plot(earth, label='earth') plt.show() day = 3600 * 24 * u.second
def third_body_moon( initial, time, f_time): # propogate under perturbation of a third body(moon) # database keeping positions of bodies in Solar system over time x_ephem = "de432s" questions = [ inquirer.List( 'Ephemerides', message= "Select ephemerides[de432s(default,small in size,faster)','de430(more precise)]:", choices=['de432s', 'de430'], ), ] answers = inquirer.prompt(questions) x_ephem = answers["Ephemerides"] solar_system_ephemeris.set(x_ephem) #epoch = Time(time, format='iso', scale='utc') # setting the exact event date is important epoch = Time(time, format='iso').jd f_time_1 = Time(f_time, format='iso').jd # create interpolant of 3rd body coordinates (calling in on every iteration will be just too slow) #check body_r = build_ephem_interpolant( Moon, 28 * u.day, (epoch * u.day, f_time_1 * u.day), rtol=1e-2 #check ) k_third = Moon.k.to(u.km**3 / u.s**2).value x = 400 print( "Use default constants or you want to customize?\n1.Default.\n2.Custom." ) check = input() if (check == '1'): pass else: k_third = input("Enter moon's gravity:") x = input( "Multiply Moon's gravity by X times so that effect is visible,input X:" ) datetimeFormat = '%Y-%m-%d %H:%M:%S.%f' diff =datetime.strptime(str(f_time), datetimeFormat)\ - datetime.strptime(str(time), datetimeFormat) print("Time difference:") print(diff) tofs = TimeDelta(f_time - time) tofs = TimeDelta(np.linspace(0, 31 * u.day, num=1)) # multiply Moon gravity by x so that effect is visible :) rr = propagate( initial, tofs, method=cowell, rtol=1e-6, ad=third_body, k_third=x * k_third, third_body=body_r, ) print("") print("Positions and velocity vectors are:") #print(str(rr.x)) #print([float(s) for s in re.findall(r'-?\d+\.?\d*',str(rr.x))]) r = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.z))][0]] * u.km v = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_z))][0]] * u.km / u.s f_orbit = Orbit.from_vectors(Earth, r, v) print(r) print(v) #f_orbit.plot() print("") print("Orbital elements:") print(f_orbit.classical()) #print("") #print(f_orbit.ecc) plotOrbit((f_orbit.a.value), (f_orbit.ecc.value), (f_orbit.inc.value), (f_orbit.raan.value), (f_orbit.argp.value), (f_orbit.nu.value))
def sample( self, values=100, *, min_anomaly=None, max_anomaly=None, method=mean_motion ): r"""Samples an orbit to some specified time values. .. versionadded:: 0.8.0 Parameters ---------- values : int Number of interval points (default to 100). min_anomaly, max_anomaly : ~astropy.units.Quantity, optional Anomaly limits to sample the orbit. For elliptic orbits the default will be :math:`E \in \left[0, 2 \pi \right]`, and for hyperbolic orbits it will be :math:`\nu \in \left[-\nu_c, \nu_c \right]`, where :math:`\nu_c` is either the current true anomaly or a value that corresponds to :math:`r = 3p`. method : function, optional Method used for propagation Returns ------- positions: ~astropy.coordinates.BaseCoordinateFrame Array of x, y, z positions, with proper times as the frame attributes if supported. Notes ----- When specifying a number of points, the initial and final position is present twice inside the result (first and last row). This is more useful for plotting. Examples -------- >>> from astropy import units as u >>> from poliastro.examples import iss >>> iss.sample() # doctest: +ELLIPSIS <GCRS Coordinate ...> >>> iss.sample(10) # doctest: +ELLIPSIS <GCRS Coordinate ...> """ if self.ecc < 1: nu_values = self._sample_closed(values, min_anomaly, max_anomaly) else: nu_values = self._sample_open(values, min_anomaly, max_anomaly) time_values = time.TimeDelta(self._generate_time_values(nu_values)) cartesian = propagate(self, time_values, method=method) # TODO: Unify with propagate # If the frame supports obstime, set the time values try: kwargs = {} if "obstime" in self.frame.frame_attributes: kwargs["obstime"] = self.epoch + time_values else: warn( "Frame {} does not support 'obstime', time values were not returned".format( self.frame.__class__ ) ) # Use of a protected method instead of frame.realize_frame # because the latter does not let the user choose the representation type # in one line despite its parameter names, see # https://github.com/astropy/astropy/issues/7784 coords = self.frame._replicate( cartesian, representation_type="cartesian", **kwargs ) return coords except NotImplementedError: warn( "No frame found for attractor {}, returning only cartesian coordinates instead".format( self.attractor ) ) return cartesian
def sample(self, values=100, *, min_anomaly=None, max_anomaly=None): r"""Samples an orbit to some specified time values. .. versionadded:: 0.8.0 Parameters ---------- values : int Number of interval points (default to 100). min_anomaly, max_anomaly : ~astropy.units.Quantity, optional Anomaly limits to sample the orbit. For elliptic orbits the default will be :math:`E \in \left[0, 2 \pi \right]`, and for hyperbolic orbits it will be :math:`\nu \in \left[-\nu_c, \nu_c \right]`, where :math:`\nu_c` is either the current true anomaly or a value that corresponds to :math:`r = 3p`. Returns ------- positions: ~astropy.coordinates.BaseCoordinateFrame Array of x, y, z positions, with proper times as the frame attributes if supported. Notes ----- When specifying a number of points, the initial and final position is present twice inside the result (first and last row). This is more useful for plotting. Examples -------- >>> from astropy import units as u >>> from poliastro.examples import iss >>> iss.sample() # doctest: +ELLIPSIS <GCRS Coordinate ...> >>> iss.sample(10) # doctest: +ELLIPSIS <GCRS Coordinate ...> """ if self.ecc < 1: nu_values = self._sample_closed(values, min_anomaly, max_anomaly) else: nu_values = self._sample_open(values, min_anomaly, max_anomaly) time_values = time.TimeDelta(self._generate_time_values(nu_values)) cartesian = propagate(self, time_values) # TODO: Unify with propagate # If the frame supports obstime, set the time values try: kwargs = {} if "obstime" in self.frame.frame_attributes: kwargs["obstime"] = self.epoch + time_values else: warn( "Frame {} does not support 'obstime', time values were not returned" .format(self.frame.__class__)) # Use of a protected method instead of frame.realize_frame # because the latter does not let the user choose the representation type # in one line despite its parameter names, see # https://github.com/astropy/astropy/issues/7784 coords = self.frame._replicate(cartesian, representation_type="cartesian", **kwargs) return coords except NotImplementedError: warn( "No frame found for attractor {}, returning only cartesian coordinates instead" .format(self.attractor)) return cartesian
def propagate(self, value, method=mean_motion, rtol=1e-10, **kwargs): """Propagates an orbit a specified time. If value is true anomaly, propagate orbit to this anomaly and return the result. Otherwise, if time is provided, propagate this `Orbit` some `time` and return the result. Parameters ---------- value : ~astropy.units.Quantity, ~astropy.time.Time, ~astropy.time.TimeDelta Scalar time to propagate. rtol : float, optional Relative tolerance for the propagation algorithm, default to 1e-10. method : function, optional Method used for propagation **kwargs parameters used in perturbation models Returns ------- Orbit New orbit after propagation. """ if isinstance(value, time.Time) and not isinstance(value, time.TimeDelta): time_of_flight = value - self.epoch else: # Works for both Quantity and TimeDelta objects time_of_flight = time.TimeDelta(value) cartesian = propagate(self, time_of_flight, method=method, rtol=rtol, **kwargs) new_epoch = self.epoch + time_of_flight # TODO: Unify with sample # If the frame supports obstime, set the time values try: kwargs = {} if "obstime" in self.frame.frame_attributes: kwargs["obstime"] = new_epoch # Use of a protected method instead of frame.realize_frame # because the latter does not let the user choose the representation type # in one line despite its parameter names, see # https://github.com/astropy/astropy/issues/7784 coords = self.frame._replicate(cartesian, representation_type="cartesian", **kwargs) return self.from_coords(self.attractor, coords, plane=self.plane) except NotImplementedError: return self.from_vectors( self.attractor, cartesian[0].xyz, cartesian[0].differentials["s"].d_xyz, new_epoch, )
) #Min kommentar: Här tror jag att jag kan ändra på värdet hos radien på omloppsbanan tofs = TimeDelta( np.linspace(0 * u.h, 100 * u.d, num=200) ) #Min kommentar: Här tror jag deltatiden beskrivs, att den mäter mellan noll timmar till ett max antal dagar, samt att den mäter 2000 gånger. from poliastro.twobody.events import LithobrakeEvent lithobrake_event = LithobrakeEvent(R) events = [lithobrake_event] rr = propagate( orbit, tofs, method=cowell, ad=atmospheric_drag_exponential, R=R, C_D= x, #Min kommentar: Här ändrade jag från C_D till x på högra sidan likhetstecknet A_over_m=A_over_m, H0=H0, rho0=rho0, events=events, ) print('{0} {1:.2f} {2}'.format('orbital decay seen after', lithobrake_event.last_t.to(u.d).value, 'days')) plt.ylabel("h(t)") plt.xlabel("t, days") plt.plot(tofs.value, rr.norm() - Earth.R)
def propagate(self, time_of_flight, rtol=1e-10): """Propagate this `Orbit` some `time` and return the result. """ return propagate(self, time_of_flight, rtol=rtol)
return accel * v / norm_v return constant_accel # In[5]: times = np.linspace(0, 10 * iss.period, 500) times # In[6]: positions = propagate( iss, time.TimeDelta(times), method=cowell, rtol=1e-11, ad=constant_accel_factory(accel), ) # And we plot the results: # In[7]: frame = OrbitPlotter3D() frame.set_attractor(Earth) frame.plot_trajectory(positions, label="ISS") # ## Error checking
orbit = Orbit.circular(Earth, 200 * u.km, epoch=Time(0.0, format="jd", scale="tdb")) tofs = TimeDelta(np.linspace(0 * u.h, 100000000 * u.d, num=200)) from poliastro.twobody.events import LithobrakeEvent lithobrake_event = LithobrakeEvent(R) events = [lithobrake_event] rr = propagate( orbit, tofs, method=cowell, ad=atmospheric_drag_exponential, R=R, C_D=C_D, A_over_m=A_over_m, H0=H0, rho0=rho0, events=events, ) print('{0} {1:.2f} {2}'.format('orbital decay seen after', lithobrake_event.last_t.to(u.d).value, 'days')) plt.ylabel("h(t)") plt.xlabel("t, days") plt.plot(tofs.value, rr.norm() - Earth.R)