Cassini Position Example

Below is an example that uses spiceypy to plot the position of the Cassini spacecraft relative to the barycenter of Saturn.

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

First import spiceypy and test it out.

import spiceypy as spice
# Print out the toolkit version

We will need to load some kernels. You will need to download the following kernels from the NAIF servers via the links provided. After the kernels have been downloaded to a common directory write a metakernel containing the file names for each downloaded kernel (provided after the links). I named the metakernel ‘cassMetaK.txt’ for this example. For more on defining meta kernels in spice, please consult the Kernel Required Reading.

# The meta kernel file contains entries pointing to the following SPICE kernels, which the user needs to download.
#   The following is the contents of a metakernel that was saved with
#   the name 'cassMetaK.txt'.
#   \begindata
#   'naif0009.tls',
#   'cas00084.tsc',
#   'cpck05Mar2004.tpc',
#   '020514_SE_SAT105.bsp',
#   '981005_PLTEPH-DE405S.bsp',
#   '030201AP_SK_SM546_T45.bsp',
#   '04135_04171pc_psiv2.bc',
#   '',
#   'cas_iss_v09.ti')
#   \begintext

step = 4000
# we are going to get positions between these two dates
utc = ['Jun 20, 2004', 'Dec 1, 2005']

# get et values one and two, we could vectorize str2et
etOne = spice.str2et(utc[0])
etTwo = spice.str2et(utc[1])
print("ET One: {}, ET Two: {}".format(etOne, etTwo))
ET One: 140961664.18440723, ET Two: 186667264.18308285
# get times
times = [x*(etTwo-etOne)/step + etOne for x in range(step)]

# check first few times:
[140961664.18440723, 140973090.5844069, 140984516.98440656]
# check the documentation on spkpos before continueing
Help on function spkpos in module spiceypy.spiceypy:

spkpos(targ, et, ref, abcorr, obs)
    Return the position of a target body relative to an observing
    body, optionally corrected for light time (planetary aberration)
    and stellar aberration.

    :param targ: Target body name.
    :type targ: str
    :param et: Observer epoch.
    :type et: float or List of Floats
    :param ref: Reference frame of output position vector.
    :type ref: str
    :param abcorr: Aberration correction flag.
    :type abcorr: str
    :param obs: Observing body name.
    :type obs: str
            Position of target,
            One way light time between observer and target.
    :rtype: tuple
#Run spkpos as a vectorized function
positions, lightTimes = spice.spkpos('Cassini', times, 'J2000', 'NONE', 'SATURN BARYCENTER')

# Positions is a 3xN vector of XYZ positions
print("Positions: ")

# Light times is a N vector of time
print("Light Times: ")
[-5461446.61080924 -4434793.40785864 -1200385.93315424]
Light Times:
# Clean up the kernels

We will use matplotlib’s 3D plotting to visualize Cassini’s coordinates. We first convert the positions list to a 2D numpy array for easier indexing in the plot.

positions = np.asarray(positions).T # positions is a list, make it an ndarray for easier indexing
fig = plt.figure(figsize=(9, 9))
ax  = fig.add_subplot(111, projection='3d')
ax.plot(positions[0], positions[1], positions[2])
plt.title('SpiceyPy Cassini Position Example from Jun 20, 2004 to Dec 1, 2005')
plot of cassini positions over time using matplotlib