--- jupytext: text_representation: extension: .md format_name: myst format_version: 0.13 jupytext_version: 1.14.0 kernelspec: display_name: Python 3 language: python name: python3 --- # Tisserand plots and applications in gravity assisted maneuvers Spacecraft fuel is limited and thus becomes a constrain when developing interplanetary maneuvers. In order to save propellant, the mission analysis team usually benefits from the so called **gravity assisted maneuvers**. Although they are usually applied for increasing spacecraft velocity, they might also be used for the opposite objective. Previous kind of maneuvers are not only useful for interplanetary trips but also extremely important when designing so-called "moon tours" in Jupiter and Saturn systems. ![Tisserand Geometry](gravity_assist.png) In order to perform a preliminary gravity assist analysis, it is possible to make use of Tisserand plots. These plots illustrate how to move within different bodies for a variety of $V_{\infty}$ and $\alpha$, $\alpha$ being the pump angle. Tisserand plots assume: * Perfectly circular and coplanar planet orbits. Although it is possible to include inclination within the analysis, Tisserand would no longer be 2D plots but would instead become surfaces in a three dimensional space. * Phasing is not taken into account. That means only orbits are taken into account, not rendezvous between departure and target body. Please, note that **boinor solves `mean orbital elements` for Solar System bodies. Although their orbital parameters do not have great variations among time, planet orbits are assumed not to be perfectly circular or coplanar.** However, Tisserand figures are still useful for quick-design gravity assisted maneuvers. +++ ## How to read the graphs As said before, these kind of plots assume perfectly circular and coplanar orbits. Each point in a Tisserand graph is just a fly-by orbit wiht a given $V_{\infty}$ and pump angle. That particular orbit has some energy associated, which can be computed as $C_{Tiss}=3 - V_{\infty}^2$. The question then is, **where can a spacecraft come and reach that orbit with those particular conditions?** Although Tisserand figures come in many different ways, they might be usually representing: * Periapsis VS. Apoapsis * Orbital period VS. Periapsis * Specific Energy VS. Periapsis Let us plot a very simple Tisserand-energy kind plot for the inner planets except Mercury: ```{code-cell} from astropy import units as u from matplotlib import pyplot as plt import numpy as np from boinor.bodies import Venus, Earth, Mars from boinor.plotting.tisserand import TisserandPlotter, TisserandKind from boinor.plotting.util import BODY_COLORS ``` Notice that we imported the `TisserandKind` class, which will help us to indicate the kind of Tisserand plot we want to generate: ```{code-cell} # Show all possible Tisserand kinds for kind in TisserandKind: print(f"{kind}", end="\t") ``` We will start by defining a `TisserandPlotter` instance with custom axis for a better look of the final figure. In addition, user can also make use of `plot` and `plot_line` method for representing both a collection of lines or just isolated ones. ```{code-cell} # Build custom axis fig, ax = plt.subplots(1, 1, figsize=(15, 7)) ax.set_title("Energy Tisserand for Venus, Earth and Mars") ax.set_xlabel("$R_{p} [AU]$") ax.set_ylabel("Heliocentric Energy [km2 / s2]") ax.set_xscale("log") ax.set_xlim(10**-0.4, 10**0.15) ax.set_ylim(-700, 0) # Generate a Tisserand plotter tp = TisserandPlotter(axes=ax, kind=TisserandKind.ENERGY) # Plot Tisserand lines within 1km/s and 10km/s for planet in [Venus, Earth, Mars]: ax = tp.plot(planet, (1, 14) * u.km / u.s, num_contours=14) # Let us label previous figure tp.ax.text(0.70, -650, "Venus", color=BODY_COLORS["Venus"]) tp.ax.text(0.95, -500, "Earth", color=BODY_COLORS["Earth"]) tp.ax.text(1.35, -350, "Mars", color=BODY_COLORS["Mars"]) # Plot final desired path by making use of `plot_line` method ax = tp.plot_line( Venus, 7 * u.km / u.s, alpha_lim=(47 * np.pi / 180, 78 * np.pi / 180), color="black", ) ax = tp.plot_line( Mars, 5 * u.km / u.s, alpha_lim=(119 * np.pi / 180, 164 * np.pi / 180), color="black", ) ``` Previous black lines represent an **EVME**, which means **Earth-Venus-Mars-Earth**. Our spacecraft starts at an orbit with $V_{\infty}=5$km/s at **Earth**'s location. At this point, a trajectory shared with a $V_{\infty}=7$km/s for **Venus** is shared. This new orbit would take us to a new orbit for $V_{\infty}=5$km/s around **Mars**, which is also intercepted at some point by **Earth** again. +++ More complex tisserand graphs can be developed, for example for the whole Solar System planets. Let us check! ```{code-cell} # Let us import the rest of the planets from boinor.bodies import Mercury, Jupiter, Saturn, Uranus, Neptune SS_BODIES_INNER = [ Mercury, Venus, Earth, Mars, ] SS_BODIES_OUTTER = [ Jupiter, Saturn, Uranus, Neptune, ] ``` We will impose the final figure also to show a dashed red line which represents $R_{p} = R_{a}$, meaning that orbit is perfectly circular: ```{code-cell} :tags: [nbsphinx-thumbnail] # Prellocate Tisserand figure fig, ax = plt.subplots(1, 1, figsize=(15, 7)) ax.set_title("Apsis Tisserand for Solar System bodies") ax.set_xlabel("$R_{a} [AU]$") ax.set_ylabel("$R_{p} [AU]$") ax.set_xscale("log") ax.set_yscale("log") # Build tisserand tp = TisserandPlotter(axes=ax, kind=TisserandKind.APSIS) # Show perfect circular orbits r = np.linspace(0, 10**2) * u.AU tp.ax.plot(r, r, linestyle="--", color="red") # Generate lines for inner planets for planet in SS_BODIES_INNER: tp.plot(planet, (1, 12) * u.km / u.s, num_contours=12) # Generate lines for outter planets for planet in SS_BODIES_OUTTER: if planet == Jupiter or planet == Saturn: tp.plot(planet, (1, 7) * u.km / u.s, num_contours=7) else: tp.plot(planet, (1, 5) * u.km / u.s, num_contours=10) ```