Skip to content

3D Trajectory Visualization

plot_trajectory_3d

plot_trajectory_3d(trajectories, *, time_range=None, units='km', normalize=False, view_azimuth=45.0, view_elevation=30.0, view_distance=None, central_body='earth', show_body=True, texture=None, additional_bodies=None, sphere_resolution_lon=360, sphere_resolution_lat=180, backend='matplotlib', width=None, height=None) -> object

Plot 3D trajectories about a central body.

Trajectories are plotted in the central body's centered-inertial frame. A trajectory declared in any other frame is converted to it via to_frame(). Custom bodies without a NAIF ID are plotted using the trajectory's raw Cartesian position, unconverted.

Parameters:

Name Type Description Default
trajectories list of dict

List of trajectory groups, each with: - trajectory: OrbitTrajectory - color (str, optional): Line color - line_width (float, optional): Line width - label (str, optional): Legend label

required
time_range tuple

(start_epoch, end_epoch) to filter data

None
units str

'm' or 'km'. Default: 'km'

'km'
normalize bool

Normalize distances by the central body's radius. Default: False

False
view_azimuth float

Camera azimuth angle (degrees). Default: 45.0

45.0
view_elevation float

Camera elevation angle (degrees). Default: 30.0

30.0
view_distance float

Camera distance multiplier. Default: 2.5 (larger = further out)

None
central_body str or dict

Central body to plot trajectories around. Either a brahe.plots.bodies.BODY_VISUALS registry key (e.g. 'earth', 'moon', 'mars') or a custom dict {name, radius, texture} (radius in meters). Default: 'earth'

'earth'
show_body bool

Show the central body sphere at the origin. Default: True

True
texture str

Texture to use for the central body sphere (plotly only). Options: - 'simple': Solid lightblue sphere (fast rendering) - 'blue_marble': NASA Blue Marble texture (packaged with brahe, Earth only) - 'natural_earth_50m': Natural Earth 50m shaded relief (auto-downloads ~20MB, Earth only) - 'natural_earth_10m': Natural Earth 10m shaded relief (auto-downloads ~180MB, Earth only) - Any other brahe.plots.texture_utils.PLANET_TEXTURES key (auto-downloads, CC BY 4.0, Solar System Scope: https://www.solarsystemscope.com/textures/) - A path to an image file Note: matplotlib always uses a simple solid sphere regardless of this setting. Default: 'simple' for matplotlib; the central body's registry texture (or 'simple' for custom bodies without one) for plotly

None
additional_bodies list of dict

Extra textured spheres to draw alongside the central body, each with: - position (array-like, length 3): Position in meters, in the same frame as the plotted trajectories - radius (float): Radius in meters - texture (str, Path, or None, optional): Texture, as for texture above - name (str): Label used in the legend/hover text

None
sphere_resolution_lon int

Longitude resolution for textured sphere (plotly only). Higher values = better quality but slower rendering, with a larger output file (the textured sphere is encoded as a per-face-colored Mesh3d). Default: 360

360
sphere_resolution_lat int

Latitude resolution for textured sphere (plotly only). Higher values = better quality but slower rendering, with a larger output file (the textured sphere is encoded as a per-face-colored Mesh3d). Default: 180

180
backend str

'matplotlib' or 'plotly'. Default: 'matplotlib'

'matplotlib'
width int

Figure width in pixels (plotly only). Default: None (responsive)

None
height int

Figure height in pixels (plotly only). Default: None (responsive)

None

Returns:

Name Type Description
object object

Generated figure (matplotlib.figure.Figure or plotly.graph_objects.Figure)

Raises:

Type Description
ValueError

If central_body is not recognized, if a trajectory cannot be converted to the central body's centered-inertial frame, or if a non-Cartesian trajectory is plotted about a custom central body that has no NAIF ID.

TypeError

If a trajectory is not an OrbitTrajectory object.

Example
import brahe as bh
import numpy as np

# Create trajectory
eop = bh.FileEOPProvider.from_default_standard(bh.EarthOrientationFileType.STANDARD, True)
bh.set_global_eop_provider(eop)

epoch = bh.Epoch.from_datetime(2024, 1, 1, 0, 0, 0.0, 0.0, bh.TimeSystem.UTC)
oe = np.array([bh.R_EARTH + 500e3, 0.01, np.radians(97.8), 0.0, 0.0, 0.0])
state = bh.state_koe_to_eci(oe, bh.AngleFormat.RADIANS)

prop = bh.KeplerianPropagator.from_eci(epoch, state, 60.0)
prop.propagate_to(epoch + bh.orbital_period(oe[0]))
traj = prop.trajectory

# Plot 3D trajectory around Earth with matplotlib (simple sphere)
fig = bh.plot_trajectory_3d(
    [{"trajectory": traj, "color": "red", "label": "LEO Orbit"}],
    units='km',
    backend='matplotlib'
)

# Plot 3D trajectory with plotly (Blue Marble texture)
fig = bh.plot_trajectory_3d(
    [{"trajectory": traj, "color": "red", "label": "LEO Orbit"}],
    units='km',
    texture='blue_marble',
    backend='plotly'
)

# Create a small lunar orbit
epoch = bh.Epoch.from_datetime(2024, 1, 1, 0, 0, 0.0, 0.0, bh.TimeSystem.UTC)
angles = np.linspace(0, 2*np.pi, 20, endpoint=False)
radius, speed = bh.R_MOON + 100e3, 1600.0
states = np.column_stack([
    radius*np.cos(angles), radius*np.sin(angles), np.zeros(20),
    -speed*np.sin(angles), speed*np.cos(angles), np.zeros(20)
])
lunar_traj = bh.OrbitTrajectory.from_orbital_data(
    [epoch + i*60 for i in range(20)], states,
    bh.CelestialFrame.LCI,
    bh.OrbitRepresentation.CARTESIAN, None, None
)

# Plot a Moon-centered trajectory with an Earth sphere shown for scale
fig = bh.plot_trajectory_3d(
    [{"trajectory": lunar_traj, "label": "LLO"}],
    central_body='moon',
    additional_bodies=[
        {"position": [-384.4e6, 0.0, 0.0], "radius": bh.R_EARTH,
         "texture": "blue_marble", "name": "Earth"}
    ],
    backend='plotly'
)