boinor.twobody.orbit.scalar =========================== .. py:module:: boinor.twobody.orbit.scalar Attributes ---------- .. autoapisummary:: boinor.twobody.orbit.scalar.ORBIT_FORMAT boinor.twobody.orbit.scalar.ORBIT_NO_FRAME_FORMAT Classes ------- .. autoapisummary:: boinor.twobody.orbit.scalar.Orbit Module Contents --------------- .. py:data:: ORBIT_FORMAT :value: '{r_p:.0f} x {r_a:.0f} x {inc:.1f} ({frame}) orbit around {body} at epoch {epoch} ({scale})' .. py:data:: ORBIT_NO_FRAME_FORMAT :value: '{r_p:.0f} x {r_a:.0f} x {inc:.1f} orbit around {body} at epoch {epoch} ({scale})' .. py:class:: Orbit(state, epoch) Bases: :py:obj:`boinor.twobody.orbit.creation.OrbitCreationMixin` Position and velocity of a body with respect to an attractor at a given time (epoch). Regardless of how the Orbit is created, the implicit reference system is an inertial one. For the specific case of the Solar System, this can be assumed to be the International Celestial Reference System or ICRS. .. py:property:: attractor Main attractor. .. py:property:: epoch Epoch of the orbit. .. py:property:: plane Fundamental plane of the frame. .. py:property:: r Position vector. .. py:property:: v Velocity vector. .. py:property:: a Semimajor axis. .. py:property:: p Semilatus rectum. .. py:property:: r_p Radius of pericenter. .. py:property:: r_a Radius of apocenter. .. py:property:: ecc Eccentricity. .. py:property:: inc Inclination. .. py:property:: raan Right ascension of the ascending node. .. py:property:: argp Argument of the perigee. .. py:property:: nu True anomaly. .. py:property:: f Second modified equinoctial element. .. py:property:: g Third modified equinoctial element. .. py:property:: h Fourth modified equinoctial element. .. py:property:: k Fifth modified equinoctial element. .. py:property:: L True longitude. .. py:property:: period Period of the orbit. .. py:property:: n Mean motion. .. py:property:: energy Specific energy. .. py:property:: e_vec Eccentricity vector. .. py:property:: h_vec Specific angular momentum vector. .. py:property:: h_mag Specific angular momentum. .. py:property:: arglat Argument of latitude. .. py:property:: t_p Elapsed time since latest perifocal passage. .. py:method:: get_frame() Get equivalent reference frame of the orbit. .. versionadded:: 0.14.0 .. py:method:: change_attractor(new_attractor, force=False) Changes orbit attractor. Only changes from attractor to parent or the other way around are allowed. :param new_attractor: Desired new attractor. :type new_attractor: boinor.bodies.Body :param force: If `True`, changes attractor even if physically has no-sense. :type force: bool :returns: **ss** -- Orbit with new attractor :rtype: boinor.twobody.orbit.Orbit .. py:method:: change_plane(plane) Changes fundamental plane. :param plane: Fundamental plane of the frame. :type plane: ~boinor.frames.Planes .. py:method:: represent_as(representation, differential_class=None) Converts the orbit to a specific representation. .. versionadded:: 0.11.0 :param representation: Representation object to use. It must be a class, not an instance. :type representation: ~astropy.coordinates.BaseRepresentation :param differential_class: Class in which the differential should be represented, default to None. :type differential_class: ~astropy.coordinates.BaseDifferential, optional .. rubric:: Examples >>> from boinor.examples import iss >>> from astropy.coordinates import SphericalRepresentation >>> iss.represent_as(CartesianRepresentation) >>> iss.represent_as(CartesianRepresentation).xyz >>> iss.represent_as(CartesianRepresentation, CartesianDifferential).differentials['s'] >>> iss.represent_as(CartesianRepresentation, CartesianDifferential).differentials['s'].d_xyz >>> iss.represent_as(SphericalRepresentation, CartesianDifferential) .. py:method:: rv() Position and velocity vectors. .. py:method:: classical() Classical orbital elements. .. py:method:: pqw() Perifocal frame (PQW) vectors. .. py:method:: __str__() .. py:method:: __repr__() .. py:method:: propagate(value, method=FarnocchiaPropagator()) 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. :param value: Scalar time to propagate. :type value: ~astropy.units.Quantity, ~astropy.time.Time, ~astropy.time.TimeDelta :param method: Method used for propagation, default to farnocchia. :type method: function, optional :returns: New orbit after propagation. :rtype: Orbit .. py:method:: time_to_anomaly(value) Returns time required to be in a specific true anomaly. :param value: :type value: ~astropy.units.Quantity :returns: **tof** -- Time of flight required. :rtype: ~astropy.units.Quantity .. py:method:: propagate_to_anomaly(value) Propagates an orbit to a specific true anomaly. :param value: :type value: ~astropy.units.Quantity :returns: Resulting orbit after propagation. :rtype: Orbit .. py:method:: to_ephem(strategy=TrueAnomalyBounds()) Samples Orbit to return an ephemerides. .. versionadded:: 0.17.0 .. py:method:: sample(values=100, *, min_anomaly=None, max_anomaly=None) Samples an orbit to some specified time values. .. versionadded:: 0.8.0 :param values: Number of interval points (default to 100). :type values: int :param min_anomaly: 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`. :type min_anomaly: ~astropy.units.Quantity, optional :param max_anomaly: 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`. :type max_anomaly: ~astropy.units.Quantity, optional :returns: **positions** -- Array of x, y, z positions. :rtype: ~astropy.coordinates.CartesianRepresentation .. rubric:: 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. .. rubric:: Examples >>> from astropy import units as u >>> from boinor.examples import iss >>> iss.sample() # doctest: +ELLIPSIS >> iss.sample(10) # doctest: +ELLIPSIS >> from boinor.twobody.orbit import Orbit >>> apophis_orbit = Orbit.from_sbdb('apophis') # doctest: +REMOTE_DATA .. py:method:: circular(attractor, alt, inc=0 * u.deg, raan=0 * u.deg, arglat=0 * u.deg, epoch=J2000, plane=Planes.EARTH_EQUATOR) :classmethod: Return circular `Orbit`. :param attractor: Main attractor. :type attractor: Body :param alt: Altitude over surface. :type alt: ~astropy.units.Quantity :param inc: Inclination, default to 0 deg (equatorial orbit). :type inc: ~astropy.units.Quantity, optional :param raan: Right ascension of the ascending node, default to 0 deg. :type raan: ~astropy.units.Quantity, optional :param arglat: Argument of latitude, default to 0 deg. :type arglat: ~astropy.units.Quantity, optional :param epoch: Epoch, default to J2000. :type epoch: ~astropy.time.Time, optional :param plane: Fundamental plane of the frame. :type plane: ~boinor.frames.Planes .. py:method:: stationary(attractor) :classmethod: Return the stationary orbit for the given attractor and its rotational speed. :param attractor: Main attractor. :type attractor: Body :returns: New orbit. :rtype: Orbit .. py:method:: synchronous(attractor, period_mul=1 * u.one, ecc=0 * u.one, inc=0 * u.deg, argp=0 * u.deg, arglat=0 * u.deg, raan=0 * u.deg, epoch=J2000, plane=Planes.EARTH_EQUATOR) :classmethod: Returns an orbit where the orbital period equals the rotation rate of the orbited body. The synchronous altitude for any central body can directly be obtained from Kepler's Third Law by setting the orbit period P\ :sub:`sync`, equal to the rotation period of the central body relative to the fixed stars D\ :sup:`*`. In order to obtain this, it's important to match orbital period with sidereal rotation period. :param attractor: Main attractor. :type attractor: Body :param period_mul: Multiplier, default to 1 to indicate that the period of the body is equal to the sidereal rotational period of the body being orbited, 0.5 a period equal to half the average rotational period of the body being orbited, indicates a semi-synchronous orbit. :type period_mul: ~astropy.units.Quantity :param ecc: Eccentricity,default to 0 as a stationary orbit. :type ecc: ~astropy.units.Quantity :param inc: Inclination,default to 0 deg. :type inc: ~astropy.units.Quantity :param raan: Right ascension of the ascending node,default to 0 deg. :type raan: ~astropy.units.Quantity :param argp: Argument of the pericenter,default to 0 deg. :type argp: ~astropy.units.Quantity :param arglat: Argument of latitude, default to 0 deg. :type arglat: ~astropy.units.Quantity, optional :param epoch: Epoch, default to J2000. :type epoch: ~astropy.time.Time, optional :param plane: Fundamental plane of the frame. :type plane: ~boinor.frames.Planes :returns: New orbit. :rtype: Orbit :raises ValueError: If the pericenter is smaller than the attractor's radius. .. rubric:: Notes Thus: .. math:: P_{s y n c}=D^{*} \\ a_{s y n c}=\left(\mu / 4 \pi^{2}\right)^{1 / 3}\left(D^{*}\right)^{2 / 3}\\ H_{s y n c}=a_{s y n c} - R_{p l a n e t}\\ .. py:method:: heliosynchronous(attractor, a=None, ecc=None, inc=None, raan=0 * u.deg, argp=0 * u.deg, nu=0 * u.deg, epoch=J2000, plane=Planes.EARTH_EQUATOR) :classmethod: Creates a Sun-Synchronous orbit. These orbits make use of the J2 perturbation to precess in order to be always towards Sun. At least two parameters of the set {a, ecc, inc} are needed in order to solve for these kind of orbits. Relationships among them are given by: .. math:: \begin{align} a &= \left (\frac{-3R_{\bigoplus}J_{2}\sqrt{\mu}\cos(i)}{2\dot{\Omega}(1-e^2)^2} \right ) ^ {\frac{2}{7}}\\ e &= \sqrt{1 - \sqrt{\frac{-3R_{\bigoplus}J_{2}\sqrt{\mu}cos(i)}{2a^{\frac{7}{2}}\dot{\Omega}}}}\\ i &= \arccos{\left ( \frac{-2a^{\frac{7}{2}}\dot{\Omega}(1-e^2)^2}{3R_{\bigoplus}J_{2}\sqrt{\mu}} \right )}\\ \end{align} :param attractor: Attractor. :type attractor: ~boinor.bodies.SolarSystemPlanet :param a: Semi-major axis. :type a: ~astropy.units.Quantity :param ecc: Eccentricity. :type ecc: ~astropy.units.Quantity :param inc: Inclination. :type inc: ~astropy.units.Quantity :param raan: Right ascension of the ascending node. :type raan: ~astropy.units.Quantity :param argp: Argument of the pericenter. :type argp: ~astropy.units.Quantity :param nu: True anomaly. :type nu: ~astropy.units.Quantity :param epoch: Epoch, default to J2000. :type epoch: ~astropy.time.Time, optional :param plane: Fundamental plane of the frame. :type plane: ~boinor.frames.Planes .. py:method:: parabolic(attractor, p, inc, raan, argp, nu, epoch=J2000, plane=Planes.EARTH_EQUATOR) :classmethod: Return a parabolic `Orbit`. :param attractor: Main attractor. :type attractor: Body :param p: Semilatus rectum or parameter. :type p: ~astropy.units.Quantity :param inc: Inclination. :type inc: ~astropy.units.Quantity, optional :param raan: Right ascension of the ascending node. :type raan: ~astropy.units.Quantity :param argp: Argument of the pericenter. :type argp: ~astropy.units.Quantity :param nu: True anomaly. :type nu: ~astropy.units.Quantity :param epoch: Epoch, default to J2000. :type epoch: ~astropy.time.Time, optional :param plane: Fundamental plane of the frame. :type plane: ~boinor.frames.Planes .. py:method:: frozen(attractor, alt, inc=None, argp=None, raan=0 * u.deg, arglat=0 * u.deg, ecc=None, epoch=J2000, plane=Planes.EARTH_EQUATOR) :classmethod: Return a frozen Orbit. If any of the given arguments results in an impossibility, some values will be overwritten. To achieve frozen orbit these two equations have to be set to zero. .. math:: \dfrac {d\overline {e}}{dt}=\dfrac {-3\overline {n}J_{3}R^{3}_{E}\sin \left( \overline {i}\right) }{2a^{3}\left( 1-\overline {e}^{2}\right) ^{2}}\left( 1-\dfrac {5}{4}\sin ^{2}\overline {i}\right) \cos \overline {w} .. math:: \dfrac {d\overline {\omega }}{dt}=\dfrac {3\overline {n}J_{2}R^{2}_{E}}{a^{2}\left( 1-\overline {e}^{2}\right) ^{2}}\left( 1-\dfrac {5}{4}\sin ^{2}\overline {i}\right) \left[ 1+\dfrac {J_{3}R_{E}}{2J_{2}\overline {a}\left( 1-\overline {e}^{2}\right) }\left( \dfrac {\sin ^{2}\overline {i}-\overline {e}\cos ^{2}\overline {i}}{\sin \overline {i}}\right) \dfrac {\sin \overline {w}}{\overline {e}}\right] The first approach would be to nullify following term to zero: .. math:: ( 1-\dfrac {5}{4}\sin ^{2}) For which one obtains the so-called critical inclinations: i = 63.4349 or 116.5651 degrees. To escape the inclination requirement, the argument of periapsis can be set to w = 90 or 270 degrees to nullify the second equation. Then, one should nullify the right-hand side of the first equation, which yields an expression that correlates the inclination of the object and the eccentricity of the orbit: .. math:: \overline {e}=-\dfrac {J_{3}R_{E}}{2J_{2}\overline {a}\left( 1-\overline {e}^{2}\right) }\left( \dfrac {\sin ^{2}\overline {i}-\overline {e}\cos ^{2} \overline {i}}{\sin \overline {i}}\right) Assuming that e is negligible compared to J2, it can be shown that: .. math:: \overline {e}\approx -\dfrac {J_{3}R_{E}}{2J_{2}\overline {a}}\sin \overline {i} The implementation is divided in the following cases: 1. When the user gives a negative altitude, the method will raise a ValueError 2. When the attractor has not defined J2 or J3, the method will raise an AttributeError 3. When the attractor has J2/J3 outside of range 1 to 10 , the method will raise an NotImplementedError. Special case for Venus.See "Extension of the critical inclination" by Xiaodong Liu, Hexi Baoyin, and Xingrui Ma 4. If argp is not given or the given argp is a critical value: * if eccentricity is none and inclination is none, the inclination is set with a critical value and the eccentricity is obtained from the last formula mentioned * if only eccentricity is none, we calculate this value with the last formula mentioned * if only inclination is none ,we calculate this value with the formula for eccentricity with critical argp. 5. If inc is not given or the given inc is critical: * if the argp and the eccentricity is given we keep these values to create the orbit * if the eccentricity is given we keep this value, if not, default to the eccentricity of the Moon's orbit around the Earth 6. if it's not possible to create an orbit with the the argp and the inclination given, both of them are set to the critical values and the eccentricity is calculate with the last formula :param attractor: Main attractor. :type attractor: Body :param alt: Altitude over surface. :type alt: ~astropy.units.Quantity :param inc: Inclination, default to critical value. :type inc: ~astropy.units.Quantity, optional :param argp: Argument of the pericenter, default to critical value. :type argp: ~astropy.units.Quantity, optional :param raan: Right ascension of the ascending node, default to 0 deg. :type raan: ~astropy.units.Quantity, optional :param arglat: Argument of latitude, default to 0 deg. :type arglat: ~astropy.units.Quantity, optional :param ecc: Eccentricity, default to the eccentricity of the Moon's orbit around the Earth :type ecc: ~astropy.units.Quantity :param epoch: Epoch, default to J2000. :type epoch: ~astropy.time.Time, optional :param plane: Fundamental plane of the frame. :type plane: ~boinor.frames.Planes