# Module `trajectory`

This Python module is a part of the KIAM Astrodynamics Toolbox developed in Keldysh Institute of Applied Mathematics (KIAM), Moscow, Russia.

The module provides a useful and convenient a class Trajectory for the design of space trajectories. With this class, the users can propagate trajectories within the selected model of motion, perform change of variables, coordinate systems, and units systems, and visualize the trajectories and their characteristics.

The toolbox is licensed under the MIT License.

For more information see GitHub page of the project: https://github.com/shmaxg/KIAMToolbox

## Functions

`def dict2traj(d: dict) ‑> Trajectory`

  Converts dictionary to trajectory object.

  ## Parameters:

  `d` : dict

  The dictionary containing the attributes of some Trajectory object.

  ## Returns:

  `tr` : Trajectory

  The Trajectory object converted from the dictionary.

`def traj2dict(tr: Trajectory) ‑> dict`

  Converts trajectory object to dictionary.

  ## Parameters:

  `tr` : Trajectory

  The Trajectory object needed to convert into dictionary.

  ## Returns:

  `d` : dict

  The dictionary containing the attributes of the given Trajectory object.

## Classes

`class Trajectory (initial_state: numpy.ndarray, initial_time: float, initial_jd: float, variables: str, system: str, units_name: str)`

  Initialize the Trajectory object with given initial conditions and properties.

  ## Parameters:

  `initial_state` : numpy.ndarray, shape (6,), (7,), (42,)

  Initial state of the spacecraft.

  It can be a

  1. position-velocity vector ('rv'), shape (6,)

  2. position-velocity-mass vector ('rvm'), shape (7,)

  3. position-velocity-stm vector('rv_stm'), shape (42,)

  4. equinoctial orbital elements vector ('ee'), shape (6,)

  5. equinoctial orbital elements extended by mass vector ('eem'), shape (7,)

  6. equinoctial orbital elements extended by stm vector ('ee_stm'), shape (42,)

  7. classical orbital elements vector ('oe'), shape (6,)

  8. classical orbital elements extended by mass vector ('oem'), shape (7,)

  9. classical orbital elements extended by stm vector ('oe_stm'), shape (42,)

  stm means state-transition matrix

  The classical orbital elements:

  a (semi-major axis),

  e (eccentricity),

  i (inclination),

  Omega (right ascension of the ascending node),

  omega (argument of pericenter),

  theta (true anomaly)

  The equinoctial orbital elements:

  h, ex, ey, ix, iy, L

  h = sqrt(p/mu),

  ex = e*cos(Omega+omega),

  ey = e*sin(Omega+omega),

  ix = tan(i/2)*cos(Omega),

  iy = tan(i/2)*sin(Omega),

  L = theta + omega + Omega,

  where

  mu - gravitational parameter,

  p - semi-latus rectum (focal parameter)

  `initial_time` : float

  Initial time.

  `initial_jd` : float

  Julian date corresponding to initial_time.

  `variables` : str

  Variables in terms of which initial_state is given.

  It can be 'rv', 'rvm', 'rv_stm', 'ee', 'eem', 'ee_stm', 'oe', 'oem', 'oe_stm'.

  `system` : str

  The coordinate system in which initial_state is given.

  It can be

  'scrs', 'mer', 'sors', 'ssrm_em' (the Moon-centered systems)

  'gcrs', 'itrs', 'gsrf_em', 'gsrf_se' (the Earth-centered systems)

  'hcrs', 'hsrf_se' (the Sun-centered systems)

  'ine_fb', 'rot_fb' (first primary-centered systems in CR3BP)

  'ine_sb', 'rot_sb' (second primary-centered systems in CR3BP)

  'ine_cm', 'rot_cm' (baricenter-centered systems in CR3BP)

  `units_name` : str

  The name of the units in which initial_state is given.

  It can be 'earth', 'moon', 'dim', 'earth_moon', 'sun_earth'.

  ## Properties:

  `control_history` : numpy.ndarray(3,n)

  The control history, contains 3D thrust force vectors for a controlled trajectory.

  `finalDate` : datetime.datetime

  The date and time of the last phase state in trajectory.

  `initialDate` : datetime.datetime

  The date and time of the first phase state in trajectory.

  `jds` : numpy.ndarray, shape(n,)

  Julian dates corresponding to phase vectors in states property.

  `model` : dict

  The model used for trajectory propagation.

  `parts` : list[int]

  The nodes between which the trajectory was sequentially propagated:

  `tr.states[:, tr.parts[0]:tr.parts[1]+1]` – first part

  `tr.states[:, tr.parts[1]:tr.parts[2]+1]` – second part

  `tr.states[:, tr.parts[2]:tr.parts[3]+1]` – third part

  etc.

  `specific_impulse_history` : numpy.ndarray(n)

  The history of specific impulse for a controlled trajectory.

  `states` : numpy.array, shape(m,n)

  Phase vectors along the trajectory.

  `system` : str

  The current coordinate system.

  `system_graph` : networkx.classes.graph.Graph

  The graph of transormations between coordinate systems.

  `times` : numpy.array(n,)

  Times along the trajectory.

  `units` : dict

  The dictionary of the current units.

  `units_graph` : networkx.classes.graph.Graph

  The graph of transormations between units.

  `units_name` : str

  The name of the current units.

  `vars` : str

  The current variables.

  `vars_graph` : networkx.classes.digraph.DiGraph

  The graph of transormations between variables.

  ## Examples:

  Examples can be found in all_examples.py.

  ### Methods

  `def change_system(self, new_system: str) ‑> None`

    Change coordinate system to the specified one.

    ## Parameters:

    `new_system` : str

    The name of the new coordinate system.

    Options:

    'scrs', 'mer', 'sors', 'ssrm_em' (the Moon-centered systems)

    'gcrs', 'itrs', 'gsrf_em', 'gsrf_se' (the Earth-centered systems)

    'hcrs', 'hsrf_se' (the Sun-centered systems)

    'mercrs', 'mersrf_smer' (the Mercury-centered systems)

    'vcrs', 'vsrf_sv' (the Venus-centered systems)

    'mcrs', 'msrf_sm' (the Mars-centered systems)

    'jcrs', 'jsrf_sj' (the Jupiter-centered systems)

    'satcrs', 'satsrf_ssat' (the Saturn-centered systems)

    'ucrs', 'usrf_su' (the Uranus-centered systems)

    'ncrs', 'nsrf_sn' (the Neptune-centered systems)

    'ine_fb' (non-rotating frame in CR3BP, BR4BP at first primary)

    'ine_cm' (non-rotating frame in CR3BP, BR4BP at barycenter)

    'ine_sb' (non-rotating frame in CR3BP, BR4BP, Hill at secondary primary)

    'rot_fb' (rotating frame in CR3BP, BR4BP at first primary)

    'rot_cm' (rotating frame in CR3BP, BR4BP at barycenter)

    'rot_sb' (rotating frame in CR3BP, BR4BP, Hill at secondary primary)

    All transformations are possible within given rules:

    1. The variables are 'rv', 'rvm', or 'rv_stm'.

    2. Changes with variables 'rv_stm' are possible only in scrs <-> sors and scrs <-> mer translations.

    Implemented transformations:

    Model nbp, both systems should be from: systems_ephemeris.

    Model CR3BP, both systems should be from: systems_cr3bp.

    Model BR4BP, both systems should be from: systems_br4bp.

    Model Hill, both systems should be from: systems_hill.

    The routine automatically find the chain of transformations from the current coordinate system to the specified coordinate system.

  `def change_units(self, new_units: str) ‑> None`

    Change units to the specified ones.

    ## Parameters:

    `new_units` : str

    The name of the new units.

    Options:

    'earth', 'moon', 'dim', 'earth_moon', 'sun_earth'.

    All transformations are possible.

    The routine automatically find the chain of transformations from the current units to the specified units.

  `def change_vars(self, new_vars: str) ‑> None`

    Change variables to the specified ones.

    ## Parameters:

    `new_vars` : str

    The name of the new variables.

    It can be 'rv', 'rvm', 'rv_stm', 'ee', 'eem', 'ee_stm', 'oe', 'oem', 'oe_stm'.

    All transformations are possible with given rules:

    1. units_name are 'earth' or 'moon'

    2. transformations that increases the number of variables are impossible.

    E.g. rv -> rvm or rv -> rv_stm transformations are impossible.

    The routine automatically find the chain of transformations from the current variables to the specified variables.

  `def clear(self) ‑> None`

    Clears states, times, julian dates, parts, and resets the final date.

  `def copy(self, forced: bool = False)`

    Returns independent copy of the trajectory object.

    ## Parameters:

    forced : bool

    If False (default), raise exception if model['control'] is not None. Do not make copy.

    If True (default), erase funtion handle in model['control'] and make copy.

    ## Returns:

    If successfull, the deep copy of the Trajectory object is returned.

  `def propagate(self, tof: float, npoints: int = 2, atol: float = 1e-10, rtol: float = 1e-10) ‑> None`

    Propagate the trajectory.

    ## Parameters:

    `tof` : float

    The time of flight in units specified by the chosen by set_model model.

    The time interval will be [t0, t0 + tof].

    `npoints` : int

    The number of nodes in the propagation time interval.

  `def repropagate(self, tof: float, npoints: int = 2, start_index: int = 0) ‑> None`

    Clears the calculated data in trajectory and propagate the trajectory from the beginning.

    ## Parameters:

    `tof` : float

    The time of flight in units specified by the chosen by set_model model.

    The time interval will be [t0, t0 + tof].

    `npoints` : int

    The number of nodes in the propagation time interval.

    `start_index` : int

    The number of a time node from which the trajectory should be repropagated.

    At the moment, in can be only 0.

  `def set_model(self, variables: str, model_type, primary: str, sources_list: list) ‑> None`

    Set the model used for propagating the trajectory. It also initializes tr.model['data'] property.

    ## Parameters:

    `variables` : str

    Variables in terms of which the equations will be chosen.

    `model_type`: str

    The model type of the dynamics.

    Options:

    1. r2bp (restricted two-body problem)

    2. cr3bp_fb (circular restricted three-body problem with center at the first primary body)

    3. cr3bp_sb (circular restricted three-body problem with center at the secondary primary body)

    4. nbp (generic n-body problem)

    `primary` : str

    The center body or the primaries wrt which the equations will be chosen.

    Options:

    1. 'sun', 'mercury', 'venus', 'earth', 'moon', 'mars', 'jupiter', 'saturn', 'uranus', 'neptune' if model_type = 'r2bp'

    2. 'sun_[planet]' or 'earth_moon if model_type = 'cr3bp_fb' or 'cr3bp_sb'

    3. 'sun', 'mercury', 'venus', 'earth', 'moon', 'mars', 'jupiter', 'saturn', 'uranus', 'neptune' if model_type = 'nbp'

    `sources_lits` : list of str

    Listed sources of perturbations to be taken into account if model_type = 'nbp'.

    The full list of sources:

    'atm' (Earth's atmosphere, mean long term solar and geomagnetic activities)

    'atm_low' (Earth's atmosphere, low long term solar and geomagnetic activities)

    'atm_mean' (Earth's atmosphere, mean long term solar and geomagnetic activities)

    'atm_high' (Earth's atmosphere, high long term solar and geomagnetic activities)

    'j2' (Earth's J2)

    'srp' (Solar radiation pressure)

    'sun' (Gravitational acceleration of the Sun)

    'mercury' (Gravitational acceleration of Mercury)

    'venus' (Gravitational acceleration of Venus)

    'earth' (Gravitational acceleration of the Earth)

    'mars' (Gravitational acceleration of Mars)

    'jupiter' (Gravitational acceleration of Jupiter)

    'saturn' (Gravitational acceleration of Saturn)

    'uranus' (Gravitational acceleration of Uranus)

    'neptune' (Gravitational acceleration of Neptune)

    'moon' (Gravitational acceleration of the Moon)

    'cmplxmoon' (Complex gravitational acceleration of the Moon)

    If `model_type` is 'cr3bp', then `model_specifics` is a dictionary.

    The dictionary contains t0 - the time at which the rotating and non-rotating coordinate systems coincide.

    ## Returns:

    A 'model' dictionary is created in a Trajectory object.

    The dictionary contains the following keys.

    `vars` : str

    Equals to lowerized `variables`. It is better not to change this variable by hand.

    `type` : str

    Equals to lowerized `model_type`. It is better not to change this variable by hand.

    `primary` : str

    Equals to lowerized `primary`. It is better not to change this variable by hand.

    `sources_list` : list[str]

    Equals to list of lowerized elements of `sources_list`. It is better not to change this variable by hand.

    `data` : dict

    A dictionary that containes the following keys:

    `jd_zero` : float

    Julian date that correscponds to t = 0. Defaulf is 0.0. Should be set by hand by the user.

    `area` : float

    The area of the spacecraft. Default is 0.0. Should be set by hand by the user. Used for calculation of the are-to-mass value.

    `mass` : float

    The mass of the spacecraft. Default is 0.0. Should be set by hand by the user. Used for calculation of the are-to-mass value.

    `order` : int

    The order and degree of the lunar complex gravity field. Should be set by hand by the user.

    Other two keys in `model` dictionary:

    `units` : str

    Contains the units of the model. Calculated automatically. It is better not to change this variable by hand.

    `control` : Callable

    Function handle to the control function. The function handle should take two positional variables: time and phase state. By default is None. Can be set by the user.

  `def show(self, variables: str, draw=True, language='eng')`

    Plots the specified characteristics of the trajectory.

    ## Parameters:

    `variables` : str

    Variables that will be plotted.

    Options:

    1. 'xy', '3d', 'r' if self.vars in ['rv', 'rvm', 'rv_stm']

       'xy' plots the trajectory in x-y axes.

       '3d' plots the trajectory in 3d.

       'r' plots the distance to the origin of the coordinate system.

       'm' plots the mass of the spacecraft (if self.vars == 'rvm').

    2. 'a', 'e', 'inc', 'Om', 'w', 'th' if self.vars in ['oe', 'oem', 'oe_stm']

       'a' plots the semi-major axis wrt time

       'e' plots the eccentricity wrt time

       'inc' plots the inclination wrt time

       'Om' plots the right ascension of the ascending node wrt time

       'w' plots the argument of pericenter wrt time

       'th' plots the true anomaly wrt time

       'm' plots the mass of the spacecraft (if self.vars == 'oem').

    3. 'h', 'ex', 'ey', 'ix', 'iy', 'L' if self.vars in ['ee', 'eem', 'ee_stm']

       'h' plots h = sqrt(p/mu) wrt time

       'ex' plots ex = e*cos(Omega+omega) wrt time

       'ey' plots ey = e*sin(Omega+omega) wrt time

       'ix' plots ix = tan(i/2)*cos(Omega) wrt time

       'iy' plots iy = tan(i/2)*sin(Omega) wrt time

       'L' plots L = theta + omega + Omega wrt time

       'm' plots the mass of the spacecraft (if self.vars == 'eem').

    `draw` : bool

    If True (by default), the fig plotly object will be returned and figure will be showed.

    If False, the fig plot object will be returned and the figure will not be showed.

    `language` : str

    Language used for the titles.

    Options: 'eng' (default), 'rus'.

    ## Returns:

    `ax` : matplotlib axis object

    The matplotlib axis object for further work.