S- and P-Kernel Files =========================================================================== Revisions December 15, 1994 This December 1994 version of the document differs from the previous version of July 1994 in that it documents the addition of new routines to the SPK suite of software. The new SPK data type (type 15) has been included. As a result four new routines have been included: SPKR15, SPKE15, SPKS15, and SPKW15. These routines provide the capabilities of reading, evaluating, subsetting and writing type 15 SPK data. Purpose The purpose of this document is to describe SPK--the common file format for NAIF's S-kernel and ephemeris portion of the P-kernel. It also describes the NAIF Toolkit SPICELIB (SPICE LIBrary) software provided to users of SPK files for accessing the data within. Intended Audience This document is required reading for all users of SPK (ephemeris) kernel files. References All references are to NAIF documents. The notation [Dn] refers to NAIF document number. 1. [163] JPL Internal Memorandum on Modified Difference Array polynomials; F. Krogh 2. [164] Precession Matrix Based on IAU (1976) System of Astronomical Constants; E. M. Standish; Astronomy and Astrophysics 73, 282-284 (1979) 3. [165] Orientation of the JPL Ephemerides, DE200/LE200, to the Dynamical Equinox of J2000; E. M. Standish; Astronomy and Astrophysics 114, 297-302 (1982) 4. [166] The JPL Asteroid and Comet Database (as Implemented by NAIF); a collection of papers and memos; assembled by I. Underwood; 11 Dec 1989 5. [167] Double Precision Array Files (DAF) - Required Reading; latest version Introduction -------------------------------------------------------- To help fully understand the science data returned from a spacecraft's instruments it is necessary to know, at any given epoch, the positions of the spacecraft and all the target bodies of interest. The purpose of the SPK---which stands for S(pacecraft) and P(lanet) Kernel---file is to allow ephemerides for any collection of solar system bodies to be combined under a common file format, and accessed by a common set of subroutines. Historically, ephemerides for spacecraft have been considered separately from those for planets and satellites. In fact, they are generated through different processes, using different representations. However, there is no essential reason for keeping them separate: a spacecraft---like any planet, satellite, comet, or asteroid---has a position and velocity given relative to some center of mass. So these two types of data may be combined in the SPICE SPK file. The SPK format is supported by a collection of subroutines that are part of the SPICELIB library, the major component of the NAIF Toolkit. This family of SPK subroutines support the following functions: 1. Make the ephemeris data in one or more SPK files available to a user's program. 2. Return the apparent, true, or geometric state (position and velocity) of one solar system body as seen from another. The SPK file format is one of the SPICE kernel formats included under the DAF (Double precision Array File) architecture. Readers who are not familiar with that architecture are referred to [167], which describes the common aspects of all DAF formats, as well as a collection of SPICELIB subroutines that support the DAF architecture. Those users who only intend to read existing SPK files need to use only the SPK family of subroutines. They do not need to read [167]. The DAF routines in SPICELIB may be used to create, write, and manipulate SPK files. The values of ND and NI for the SPK format of a DAF file are ND=2 and NI=6. SPK files are binary files. A NAIF Toolkit utility program (SPACIT) is used to convert SPK files to SPICE transfer format for porting to another type of computer; on the new host the SPACIT utility is used to convert the SPICE transfer format file to the native binary format. Segments--The Fundamental SPK Building Blocks An SPK file contains several `segments'. Each segment contains ephemeris data sufficient to compute the geometric state (position and velocity) of one solar system body (the `target') with respect to another (the `center'), at any epoch throughout some finite interval of time. Either body may be a spacecraft, a planet or planet barycenter, a satellite, a comet, an asteroid, or an arbitrary point for which an ephemeris has been calculated. Each body in the solar system is associated with a unique integer code. A list of names and codes for the planets, the major satellites, and several spacecraft can be found at the end of this document. The states computed from the ephemeris data in a segment must be referenced to a single, recognized inertial reference frame. A list of recognized frames can be found at the end of this document. The data in each segment are stored as a single array. The summary for the array, called a `descriptor', has two double precision components: 1. The initial epoch of the interval for which ephemeris data are contained in the segment, in ephemeris seconds past Julian year 2000. 2. The final epoch of the interval for which ephemeris data are contained in the segment, in ephemeris seconds past Julian year 2000. The descriptor has six integer components: 1. The NAIF integer code for the target. 2. The NAIF integer code for the center. 3. The NAIF integer code for the inertial reference frame. 4. The integer code for the representation (type of ephemeris data). 5. The initial address of the array. 6. The final address of the array. The name of each array may contain up to 40 characters. This space must be used to store a `pedigree' for the data in the array. The pedigree of a segment should allow a user to determine the conditions under which the data in the segment were generated. For example, given the pedigree of a segment containing an ephemeris for the Magellan spacecraft relative to Venus, a user should be able to contact the appropriate party (named in the pedigree) to determine the values of the various harmonic coefficients used by the Magellan NAV Team to integrate that particular ephemeris. The Comment Area Preceding the `segments', the Comment Area provides space in the SPK file for storing additional textual information besides what is written in the array names. Ideally, each SPK file would contain internal documentation that describes the origin, recommended use, and any other pertinent information about the data in that file. For example, the beginning and ending epochs for the file, the names and NAIF integer codes of the bodies included, an accuracy estimate, the date the file was produced, and the names of the source files used in making the SPK file could be included in the Comment Area. SPICELIB provides a family of subroutines for handling this Comment Area. The name of each routine in this family begins with the letters `SPC' which stand for `SPk and Ck' because this feature is common to both types of files. The SPC software provides the ability to add, extract, read, and delete comments and convert commented files from binary format to SPICE transfer format and back to binary again. The SPC routines and their functions are described in detail in the SPC Required Reading. SPK Data Types The fourth integer component of the descriptor---the code for the representation, or `data type'---is the key to the SPK format. For purposes of determining the segment best suited to fulfill a particular request, all segments are treated equally. It is only when the data in a segment are to be evaluated---when a state vector is to be computed---that the type of data used to represent the ephemeris becomes important. Because this step is isolated within a single low-level reader, SPKPV, new data types can be added to the SPK format without affecting application programs that use the higher level readers. SPKPV is designed so that the changes required to implement a new data type are minimal. There are no real limits on the possible representations that can be used for ephemeris data. Users with access to data suitable for creating an ephemeris may choose to invent their own representations, adapting SPKPV accordingly. The data types currently supported by SPICELIB software are listed under ``Supported Data Types'' later in this document. The SPK Family of Subroutines SPICELIB contains a family of subroutines that are designed specifically for use with SPK files. The name of each routine begins with the letters `SPK', followed by a two- or three-character mnemonic. For example, the routine that returns the state of one body with respect to another is named SPKEZ, pronounced `S-P-K-E-Z'. A complete list of mnemonics, translations, and calling sequences can be found at the end of this document. Each subroutine is prefaced by a complete SPICELIB module header, which describes inputs, outputs, restrictions, and exceptions, discusses the context in which the subroutine should be used, and shows typical examples of its use. Any discussion of the subroutines in this document is intended as an introduction: the final documentation for any subroutine is its module header. Whenever an SPK subroutine appears in an example, the translation of the mnemonic part of its name will appear to the right of the reference, in braces. For example, CALL SPKLEF ( FNAME, HANDLE ) { Load ephemeris file } All subroutines and functions, including those whose names do not begin with `SPK', are from SPICELIB. Code examples will make use of the structured DO ... END DO and DO WHILE ... END DO statements supported by the VAX/VMS Fortran compiler. These statements are easily converted to the standard equivalents DO label var = e1, e2, e3 stmt label CONTINUE and label IF ( expr ) .THEN stmt GO TO label END IF SPK readers are available to perform the following functions. 1. Determine the apparent, true, or geometric state of any body with respect to any other body. 2. Determine the apparent, true, or geometric state of any body with respect to an observer with an arbitrary (user-supplied) state. 3. Determine the geometric state of any body with respect to the solar system barycenter. 4. Determine the geometric state of a target body with respect to the center of motion for a particular segment. 5. Determine, from a list of SPK files supplied by the calling program, the files and segments best suited to fulfill a request for the state of a particular body. These subroutines form a hierarchy: (1) uses (2) and (3); (2) uses (3); and (3) uses (4) and (5). Thus, routines (1), (2), and (3) can serve as starting points for more specialized routines that users may wish to write for themselves. Computing States SPKEZ is the most powerful of the SPK readers. It determines the apparent, true, or geometric state of one body (the target) as seen by a second body (the observer), provided that ephemeris data are available for both bodies. CALL SPKEZ ( TARG, ET, FRAME, ABERR, OBS, STATE, LT ) { Easy state } The subroutine accepts five inputs (target body, epoch, reference frame, aberration correction type, and observing body) and returns two outputs (state of the target body as seen from the observing body, and one-way light-time from the target body to the observing body). The target and observing bodies are identified by integer codes rather than names. For example, to determine the state of Triton (body 801) as seen from the Voyager-2 spacecraft (body -32), CALL SPKEZ ( 801, ET, FRAME, ABERR, -32, STATE, LT ) { Easy state } By definition, the ephemerides in SPK files are continuous: the user can obtain states at any epoch within the interval of coverage. Epochs are always specified in ephemeris seconds past Julian year 2000. For example, to determine the state of Triton as seen from Voyager-2 at Julian Ephemeris Date 2447751.8293, ET = ( 2447751.8293D0 - J2000() ) * SPD() CALL SPKEZ ( 801, ET, FRAME, ABERR, -32, STATE, LT ) { Easy state } where the function J2000 returns Julian year 2000 (Julian Ephemeris Date 2451545.0) and the function SPD returns the number of seconds per Julian day (86400.0). The ephemeris data in a single SPK file may be referenced to a number of different inertial reference frames. Because any two inertial frames differ by a simple rotation, states returned by SPKEZ do not have to be referenced to their native frames. The user can specify that states are to be returned in any of the recognized frames listed at the end of this document. For example, to determine the state of Triton as seen from Voyager-2, referenced to the IAU standard J2000 frame, CALL SPKEZ ( 801, ET, 'J2000', ABERR, -32, STATE, LT ) { Easy state } SPKEZ returns apparent, true, or geometric states depending on the value of the aberration correction type flag, ABERR. Apparent states are corrected for planetary aberration, which is the composite of the apparent angular displacement produced by motion of the observer (stellar aberration) and the actual motion of the target body (correction for light-time). True states are corrected for light-time only. Geometric states are uncorrected. Instead of using the potentially confusing terms terms `true' and `geometric' to specify the type of state to be returned, SPKEZ requires the specific corrections to be named. To compute apparent states, specify correction for both light-time and stellar aberration: `LT+S'. To compute true states, specify correction for light-time only: `LT'. To compute geometric states, specify no correction: `NONE'. In all cases, the one-way light-time from the target to the observer is returned along with the state. This is useful when determining the apparent orientation of the target body. For example, the following code fragment computes the sub-spacecraft latitude and longitude on Triton: CALL SPKEZ ( 801, ET, 'J2000', 'LT', -32, STATE, LT ) { Easy state } CALL BODMAT ( 801, ET - LT, TIPM ) CALL VMINUS ( STATE, STATE ) CALL MXV ( TIPM, STATE, STATE ) CALL RECLAT ( STATE, RADIUS, LONG, LAT ) Subroutine BODMAT uses coefficients from the NAIF Planetary Constants kernel to compute the transformation from J2000 coordinates to pole and prime meridian coordinates for a specified body at a specified epoch; VMINUS changes the direction of an arbitrary 3-vector; MXV multiplies a 3x3 matrix and a 3-vector; and RECLAT converts an arbitrary 3-vector into latitudinal coordinates. Loading Files Note that SPKEZ does not require the name of an SPK file as input. SPKEZ relies on a second routine, SPKLEF, to maintain a database of ephemeris files. The calling program indicates which files are to be used by passing their names to SPKLEF. DO I = 1, N CALL SPKLEF ( EPHEM(I), HANDLE(I) ) { Load ephemeris file } END DO SPKLEF returns a DAF file handle for each file, which may be used to access the file directly using DAF subroutines. Once an SPK file has been loaded, it may be accessed by SPKEZ. In general, a state returned by SPKEZ is built from several more primitive states. Consider the following diagram, which shows some of the states that might be needed to determine the state of the Galileo spacecraft as seen from Earth: Jupiter --- Europa / \ / \ / Spacecraft / / / / SSB \ \ \ EMB --- Earth (SSB and EMB are the solar system and Earth-Moon barycenters.) Each state is computed from a distinct segment. The segments may reside in a single SPK file, or may be contained in as many as five separate files. For example, the segments needed to compute the Earth-spacecraft state shown above might come from the following set of files: CALL SPKLEF ( 'barycenters.bsp', H(1) ) { Load ephemeris file } CALL SPKLEF ( 'planet-centers.bsp', H(2) ) { Load ephemeris file } CALL SPKLEF ( 'satellites.bsp', H(3) ) { Load ephemeris file } CALL SPKLEF ( 'spacecraft.bsp', H(4) ) { Load ephemeris file } Or from the following set: CALL SPKLEF ( 'earth.bsp', H(1) ) { Load ephemeris file } CALL SPKLEF ( 'jupiter.bsp', H(2) ) { Load ephemeris file } CALL SPKLEF ( 'spacecraft.bsp', H(3) ) { Load ephemeris file } An SPK file may contain any number of segments. In fact, the same file may contain overlapping segments: segments containing data for the same body over a common interval. When this happens, the latest segment in a file supersedes any competing segments earlier in the file. Similarly, the latest file loaded supersedes any earlier files. In effect, several loaded files become equivalent to one large file. Unloading Files Sophisticated programs may need to open many files in the course of a single execution. A general-purpose `solar system calculator', for example, may have to provide information about any body in the entire solar system; its usefulness is enhanced if users do not have to specify which files should be used. On the other hand, the number of SPK files that may be open at any one time is limited. Such a program may need to unload some SPK files to make room for others. An SPK file may be unloaded by supplying its handle to subroutine SPKUEF. The sequence of statements shown below, CALL SPKLEF ( 'file.a', HA ) { Load ephemeris file } CALL SPKLEF ( 'file.b', HB ) { Load ephemeris file } CALL SPKLEF ( 'file.c', HC ) { Load ephemeris file } CALL SPKUEF ( HB ) { Unload ephemeris file } CALL SPKLEF ( 'file.d', HD ) { Load ephemeris file } CALL SPKUEF ( HC ) { Unload ephemeris file } is equivalent to the following (shorter) sequence: CALL SPKLEF ( 'file.a', HA ) { Load ephemeris file } CALL SPKLEF ( 'file.d', HD ) { Load ephemeris file } Lower-level Readers SPKEZ should be sufficient to handle the needs of most users. However, it is possible to exercise more direct control over the way states are computed. SPKEZ computes apparent and true states using two readers of slightly less power. The first, SPKSSB, returns the state of a body with respect to the solar system barycenter. SPKEZ uses it to compute the state of the observer. The second, SPKAPP, returns the state of a target body as seen from an observer. Where SPKEZ requires the integer code for an observer, SPKAPP requires the actual state of the observer with respect to the solar system barycenter. A single call to SPKEZ, CALL SPKEZ ( 801, ET, 'J2000', 'LT+S', -32, STARG, LT ) { Easy state } is equivalent to a pair of calls to SPKSSB and SPKAPP: CALL SPKSSB ( -32, ET, 'J2000', STOBS ) { Solar system barycenter } CALL SPKAPP ( 801, ET, 'J2000', STOBS, 'LT+S', STARG, LT ) { Apparent state } One possible advantage of using SPKAPP directly is the ability to place an observer somewhere other than at the center of a body (for example, at a specified location on the surface of the Earth). When computing uncorrected, that is, geometric states, SPKEZ does not need to compute the state of the target and observer relative to the solar system barycenter, but only relative to the first common center of motion of those two bodies. SPKEZ calls SPKGEO to compute geometric states. Using SPKGEO instead of the combination SPKSSB and SPKAPP as above prevents possible round-off error, may reduce the number of file reads, and may require less data. For example, if SPK ephemeris data for a spacecraft relative to a planet has been loaded, but the ephemeris data for that planet relative to the solar system barycenter is not available, SPKGEO can still compute the state of the spacecraft relative to the planet, whereas the combination SPKSSB and SPKAPP would be unsuccessful at computing that state. The calling sequence of SPKGEO is the same as SPKEZ, but with no correction flag. CALL SPKEZ ( 801, ET, 'J2000', 'NONE', -32, STARG, LT ) { Easy state } is equivalent to CALL SPKGEO ( 801, ET, 'J2000', -32, STARG, LT ) { Geometric state } Primitive States At the lowest level, it is possible to compute states without combining them at all. Given the handle and descriptor for a particular segment, subroutine SPKPV returns a state from that segment directly. CALL SPKPV ( HANDLE, DESCR, ET, REF, STATE, CENTER ) { Position, velocity } SPKPV is the most basic SPK reader. It rotates states into a specified reference frame, but does not combine them: it returns a state relative to the center whose integer code is stored in the descriptor for the segment. The user is responsible for using that state in the proper context. The user is also responsible for using the DAF subroutines to determine the particular file and segment from which each state is to be computed. If files have been loaded by previous calls to SPKLEF, it is possible to use the same choices that would normally be made by SPKEZ, SPKSSB, SPKAPP, and SPKGEO. Subroutine SPKSFS selects, from the database of loaded files, the file handle and segment descriptor for the segment best suited to the request. If two segments from different files are suitable, SPKSFS selects the one from the file that was loaded later. If two segments from the same file are suitable, SPKSFS selects the one that is stored later in the file. The call CALL SPKSFS ( 801, ET, HANDLE, DESCR, PDGREE, FOUND ) { Select file and segment } returns the handle, descriptor, and pedigree for the latest segment containing data for Triton at the specified epoch. SPKSFS maintains a buffer of segment descriptors and pedigrees, so it doesn't waste time searching the database for bodies it already knows about. Example 1: Computing Latitude and Longitude The next several sections present sample programs to show how the SPK readers can be used to compute state vectors, and how those vectors can be used to compute derived quantities. All subroutines and functions used in the examples are from SPICELIB. The convention of expanding SPK subroutine names will be dropped for these examples. The first program is a program to compute the planetocentric latitude and longitude of the sub-observer point on a target body for any combination of observer, target, and epoch. (Note that planetocentric coordinates differ from planetographic and cartographic coordinates in that they are always right-handed, regardless of the rotation of the body.) PROGRAM LATLON C C SPICELIB functions C DOUBLE PRECISION DPR C C Variables C CHARACTER*(32) UTC DOUBLE PRECISION ET DOUBLE PRECISION LAT DOUBLE PRECISION LON DOUBLE PRECISION LT DOUBLE PRECISION RADIUS DOUBLE PRECISION STATE ( 6 ) DOUBLE PRECISION TIBF ( 3,3 ) INTEGER OBS INTEGER TARG INTEGER H ( 13 ) C C Load constants into the kernel pool. Two files are C needed. The first (`time.ker') contains the dates C of leap seconds and values for constants needed to C compute the difference between UTC and ET at any C epoch. The second (`trans.ker') contains IAU values C needed to compute transformations from inertial C (J2000) coordinates to body-fixed (pole and prime C meridian) coordinates for the major bodies of the C solar system. (These files, or their equivalents, C are normally distributed along with SPICELIB.) C CALL CLPOOL CALL LDPOOL ( 'TIME.KER' ) CALL LDPOOL ( 'TRANS.KER' ) C C Several ephemeris files are needed. Most contain data for C a single planetary system (`jupiter.ker', `saturn.ker', C and so on). Some contain data for spacecraft (`vgr1.ker', C `mgn.ker'). C CALL SPKLEF ( 'MERCURY.BSP', H(1) ) CALL SPKLEF ( 'VENUS.BSP', H(2) ) CALL SPKLEF ( 'EARTH.BSP', H(3) ) CALL SPKLEF ( 'MARS.BSP', H(4) ) CALL SPKLEF ( 'JUPITER.BSP', H(5) ) CALL SPKLEF ( 'SATURN.BSP', H(6) ) CALL SPKLEF ( 'URANUS.BSP', H(7) ) CALL SPKLEF ( 'NEPTUNE.BSP', H(8) ) CALL SPKLEF ( 'PLUTO.BSP', H(9) ) CALL SPKLEF ( 'VGR1.BSP', H(10) ) CALL SPKLEF ( 'VGR2.BSP', H(11) ) CALL SPKLEF ( 'MGN.BSP', H(12) ) CALL SPKLEF ( 'GLL.BSP', H(13) ) C C Inputs are entered interactively. The user enters three C items: the code for the observer (an integer), the code C for the target (an integer), and the epoch at which the C sub-observer point is to be computed (a free-format string). C C The epoch must be converted to ephemeris time (ET). C DO WHILE ( .TRUE. ) WRITE (*,*) WRITE (*,*) 'Observer?' READ (*,*) OBS WRITE (*,*) WRITE (*,*) 'Target?' READ (*,*) TARG WRITE (*,*) WRITE (*,*) 'Epoch (UTC)?' READ (*,FMT='(A)') UTC CALL UTC2ET ( UTC, ET ) C C Compute the true state (corrected for light-time) C of the target as seen from the observer at the C specified epoch. Do all computations in standard C (J2000) coordinates. C CALL SPKEZ ( TARG, ET, 'J2000', 'LT', OBS, STATE, LT ) C C Compute the transformation from inertial to body-fixed C coordinates (TIBF) at the specified epoch minus the one- C way light-time from the target to the observer. (The C target continues to rotate as light reflected from it C races toward the observer.) BODMAT retrieves the necessary C coefficients from the kernel pool. C CALL BODMAT ( TARG, ET - LT, TIBF ) C C Rotate the state into the body-fixed frame. Although we C computed the vector FROM the observer TO the target in C order to get the proper light-time correction, we need C the vector FROM the target TO the observer in order to C compute latitude and longitude. So reverse it. C CALL VMINUS ( STATE, STATE ) CALL MXV ( TIBF, STATE, STATE ) C C Convert from rectangular coordinates to latitude and C longitude, then from radians to degrees for output. C CALL RECLAT ( STATE, RADIUS, LON, LAT ) WRITE (*,*) WRITE (*,*) 'Sub-observer latitude (deg): ', LAT * DPR() WRITE (*,*) ' longitude : ', LON * DPR() WRITE (*,*) WRITE (*,*) 'Range to target (km) : ', RADIUS WRITE (*,*) 'Light-time (sec) : ', LT WRITE (*,*) C C Get the next set of inputs. C END DO END Example 2: Faster Latitude and Longitude The second program computes the same quantities as the first. However, this program assumes that the observer is always the Magellan spacecraft and the target is always Venus. It also ignores light-time from the planet to the spacecraft. These restrictions allow a more primitive reader, SPKPV, to be substituted for the more general reader, SPKEZ. SPKEZ would compute the state of the spacecraft with respect to the planet by computing the states of both bodies with respect to the solar system barycenter. SPKPV returns this same state, but does it directly---making the second program much faster than the first. But the second program is much less flexible. For example, if the spacecraft ephemeris contains cruise data (describing the motion of the spacecraft relative to the solar system barycenter instead of the planet center), the program would produce incorrect results. Furthermore, the program cannot easily be generalized to work for other orbiters. The motion of the Galileo spacecraft, for instance, would normally be known relative to the Jupiter barycenter, not to the planet itself. PROGRAM FASTER C C SPICELIB functions C DOUBLE PRECISION DPR C C Definitions C INTEGER MGN PARAMETER ( MGN = -18 ) INTEGER VENUS PARAMETER ( VENUS = 299 ) C C Variables C CHARACTER*(40) PDGREE CHARACTER*(32) UTC DOUBLE PRECISION DESCR ( 5 ) DOUBLE PRECISION ET DOUBLE PRECISION LAT DOUBLE PRECISION LON DOUBLE PRECISION RADIUS DOUBLE PRECISION STATE ( 6 ) DOUBLE PRECISION TIBF ( 3,3 ) INTEGER CENTER INTEGER HANDLE LOGICAL FOUND C C Load constants into the kernel pool. Two files are C needed. The first (`time.ker') contains the dates C of leap seconds and values for constants needed to C compute the difference between UTC and ET at any C epoch. The second (`venus.ker') contains IAU values C needed to compute the transformation from inertial C (J2000) coordinates to body-fixed (pole and prime C meridian) coordinates for Venus. C CALL CLPOOL CALL LDPOOL ( 'TIME.KER' ) CALL LDPOOL ( 'VENUS.KER' ) C Only one ephemeris file is needed. This contains data for C the Magellan spacecraft relative to Venus. The states of C other bodies are not needed. C CALL SPKLEF ( 'MGN.BSP', HANDLE ) C C Inputs are entered interactively. The user enters only the C epoch at which the sub-spacecraft point is to be computed C (a free-format string). C C C The epoch must be converted to ephemeris time (ET). C DO WHILE ( .TRUE. ) WRITE (*,*) WRITE (*,*) 'Epoch (UTC)?' READ (*,FMT='(A)') UTC CALL UTC2ET ( UTC, ET ) C C Because the ephemeris file might contain many segments C for the spacecraft, we need to select the proper segment C each time a state is computed. C C For now, we will assume that a segment is found. A more C careful program would check this each time. (If FOUND is C ever false, the data needed to respond to the user's C request are not available, and the program should take C appropriate action.) C CALL SPKSFS ( MGN, ET, HANDLE, DESCR, PDGREE, FOUND ) C C Compute the geometric state (uncorrected for light-time) C of the spacecraft as seen from the planet. We can compute C this directly because light-time is being ignored. C Do all computations in standard (J2000) coordinates, C C For now, we will assume that CENTER is always Venus C (2 or 299). A more careful program would check this C each time. C CALL SPKPV ( HANDLE, DESCR, ET, 'J2000', STATE, CENTER ) C C Compute the transformation from inertial to body-fixed C coordinates (TIBF) at the specified epoch, ignoring C light-time. C CALL BODMAT ( VENUS, ET, TIBF ) C C Rotate the state into the body-fixed frame. C CALL MXV ( TIBF, STATE, STATE ) C C Convert from rectangular coordinates to latitude and C longitude, then from radians to degrees for output. C CALL RECLAT ( STATE, RADIUS, LON, LAT ) WRITE (*,*) WRITE (*,*) 'Sub-spacecraft latitude (deg): ', LAT * DPR() WRITE (*,*) ' longitude : ', LON * DPR() WRITE (*,*) C C Get the next input epoch. C END DO END Example 3: Occultation or Transit The third program determines epochs when one target body (spacecraft, planet, or satellite) is occulted by or in transit across another target body as seen from an arbitrary observer. It is similar in both form and generality to the first program. PROGRAM OCCTRN C C SPICELIB functions C DOUBLE PRECISION SUMAD DOUBLE PRECISION VNORM DOUBLE PRECISION VSEP C C Variables C CHARACTER*(32) UTC DOUBLE PRECISION AVG DOUBLE PRECISION D ( 2 ) DOUBLE PRECISION ET DOUBLE PRECISION R ( 2 ) DOUBLE PRECISION RADII ( 3 ) DOUBLE PRECISION S ( 6,2 ) DOUBLE PRECISION SEP INTEGER I INTEGER OBS INTEGER T ( 2 ) INTEGER H ( 13 ) C C Load constants into the kernel pool. Two files are C needed. The first (`time.ker') contains the dates C of leap seconds and values for constants needed to C compute the difference between UTC and ET at any C epoch. The second (`radii.ker') contains values C for the tri-axial ellipsoids used to model the major C major bodies of the solar system. C CALL CLPOOL CALL LDPOOL ( 'TIME.KER' ) CALL LDPOOL ( 'RADII.KER' ) C C Several ephemeris files are needed. Most contain data for C a single planetary system (`jupiter.ker', `saturn.ker', C and so on). Some contain data for spacecraft (`vgr1.ker', C `mgn.ker'). C CALL SPKLEF ( 'MERCURY.BSP', H(1) ) . . CALL SPKLEF ( 'GLL.BSP', H(13) ) C C Inputs are entered interactively. The user enters four C items: the code for the observer (an integer), the codes C for two target bodies (integers), and the epoch at which the C sub-observer point is to be computed (a free-format string). C C The epoch must be converted to ephemeris time (ET). C DO WHILE ( .TRUE. ) WRITE (*,*) WRITE (*,*) 'Observer?' READ (*,*) OBS WRITE (*,*) WRITE (*,*) 'Targets?' READ (*,*) T(1), T(2) WRITE (*,*) WRITE (*,*) 'Epoch (UTC)?' READ (*,FMT='(A)') UTC CALL UTC2ET ( UTC, ET ) C C Get the apparent states of the target objects as seen from C the observer. Also get the apparent radius of each object C from the kernel pool. (Use zero radius for any spacecraft; C use average radius for anything else.) C C T(i) is the ID code of the i'th target. C S(1-6,i) is the apparent state of the i'th target. C D(i) is the apparent distance to the i'th target. C R(i) is the apparent radius of the i'th target. C C Function VNORM returns the Euclidean norm (magnitude) of C a three-vector. C C Function SUMAD returns the sum of the elements in a C double precision array. C DO I = 1, 2 CALL SPKEZ (T(I), ET, 'J2000', 'LT+S', OBS, S(1,I), LT) D(I) = VNORM ( S(I) ) IF ( T(I) .LT. 0 ) THEN R(I) = 0.D0 ELSE CALL BODVAR ( T(I), 'RADII', DIM, RADII ) AVG = SUMAD ( RADII, 3 ) / 3.D0 R(I) = ASIN ( AVG / D(I) ) END IF END DO C C Determine the separation between the two bodies. If the C separation between the centers is greater than the sum of C the apparent radii, then the target bodies are clear of C each other. C C Function VSEP returns the angle of separation between C two three-vectors. C SEP = VSEP ( S(1,1), S(1,2) ) - ( R(1) + R(2) ) IF ( SEP .GT. 0 ) THEN WRITE (*,*) WRITE (*,*) 'Clear.' C C Otherwise, the smaller body is either occulted or C in transit. C ELSE IF ( R(1) .LT. R(2) ) THEN IF ( D(1) .LT. D(2) ) THEN WRITE (*,*) WRITE (*,*) T(1), ' in transit across ', T(2) ELSE WRITE (*,*) WRITE (*,*) T(1), ' occulted by ', T(2) END IF ELSE IF ( D(1) .LT. D(2) ) THEN WRITE (*,*) WRITE (*,*) T(2), ' occulted by ', T(1) ELSE WRITE (*,*) WRITE (*,*) T(2), ' in transit across ', T(1) END IF END IF END IF C C Get the next set of inputs. C END DO END Additional, working examples of using the principal SPK subroutines may be found in the ``Cookbook'' programs distributed with the NAIF Toolkit. Supported Data Types -------------------------------------------------------- The following representations, or data types, are currently supported by the SPK routines in SPICELIB. 1. Modified Difference Arrays. Created by the JPL Orbit Determination Program (ODP), these are used primarily for spacecraft ephemerides. 2. Chebyshev polynomials (position only). These are sets of coefficients for the x, y, and z components of the body position. The velocity of the body is obtained by differentiation. This data type is normally used for planet barycenters, and for satellites whose orbits are integrated. 3. Chebyshev polynomials (position and velocity). These are sets of coefficients for the x, y, and z components of the body position, and for the corresponding components of the velocity. This data type is normally used for satellites whose orbits are computed directly from theories. 4. Reserved for future use. 5. Discrete states (two body propagation). This data type contains discrete state vectors. A state is obtained for a specified epoch by propagating the state vectors to that epoch according to the laws of two body motion and then taking a weighted average of the resulting states. Normally, this data type is used for comets and asteroids, whose ephemerides are integrated from an initial state or set of osculating elements. 6. Reserved for future use. 7. Reserved for future use. 8. Equally spaced discrete states (Lagrange interpolation) This data type contains discrete state vectors whose time tags are separated by a constant step size. A state is obtained for a specified epoch by finding a set of states `centered' at that epoch and using Lagrange interpolation on each component of the states. 9. Unequally spaced discrete states (Lagrange interpolation) This data type contains discrete state vectors whose time tags may be unequally spaced. A state is obtained for a specified epoch by finding a set of states `centered' at that epoch and using Lagrange interpolation on each component of the states. 10. Reserved for future use. 11. Reserved for future use. 12. Reserved for future use. 13. Reserved for future use. 14. Reserved for future use. 15. Precessing conic propagation. This data type allows for first order precession of the line of apsides and regression of the line of nodes due to the effects of the J2 coefficient in the harmonic expansion of the gravitational potential of an oblate spheroid. Because SPK files are (DAF) array files, each segment is stored as an array. Each array corresponding to a particular data type has a particular internal structure. These structures are described below. Type 1: Modified Difference Arrays The first SPK data type contains Modified Difference Arrays (MDA), sometimes called `difference lines'. Normally, this data type is used only for spacecraft whose ephemerides are produced by JPL. Difference lines are extracted from the spacecraft trajectory file (`P-files' and `PV-files') created by the DPTRAJ program. Each segment containing Modified Difference Arrays contains an arbitrary number of logical records. Each record contains difference line coefficients valid up to some final epoch, along with the state at that epoch. The contents of the records themselves are described in [163]. The subroutine SPKE01 contains the algorithm used to construct a state from a particular record and epoch. The records within a segment are ordered by increasing final epoch. A segment of this type is structured as follows: +-----------------------------------------+ | Record 1 (difference line coefficients) | +-----------------------------------------+ | Record 2 (difference line coefficients) | +-----------------------------------------+ . . . +-----------------------------------------+ | Record N (difference line coefficients) | +-----------------------------------------+ | Epoch 1 | +------------------------------+ | Epoch 2 | +------------------------------+ . . . +------------------------------+ | Epoch N | +------------------------------+ | Directory epoch 1 | (First directory epoch) +------------------------------+ | Directory epoch 2 | +------------------------------+ . . . +------------------------------+ | Directory epoch (N/100)*100 | (Final directory epoch) +------------------------------+ | N | +------------------------------+ The number of records in a segment, N, can be arbitrarily large. Records 1 through N contain the difference line coefficients and other constants needed to compute state data. Each one of these records contains 71 double precision numbers. The list of final epochs for the records is stored immediately after the last record. Following the list of epochs is a second list, the `directory', containing every 100th epoch from the previous list. If there are N epochs, there will be N/100 directory epochs. If there are fewer than 100 epochs, then the segment will not contain any directory epochs. Directory epochs are used to speed up access to desired records. The final element in the segment is the number of records contained in the segment, N. The index of the record corresponding to a particular epoch is the index of the first epoch not less than the target epoch. Type 2: Chebyshev (position only) The second SPK data type contains Chebyshev polynomial coefficients for the position of the body as a function of time. Normally, this data type is used for planet barycenters, and for satellites whose ephemerides are integrated. (The velocity of the body is obtained by differentiating the position.) Each segment contains an arbitrary number of logical records. Each record contains a set of Chebyshev coefficients valid throughout an interval of fixed length. The subroutine SPKE02 contains the algorithm used to construct a state from a particular record and epoch. The records within a segment are ordered by increasing initial epoch. All records contain the same number of coefficients. A segment of this type is structured as follows: +---------------+ | Record 1 | +---------------+ | Record 2 | +---------------+ . . . +---------------+ | Record N | +---------------+ | INIT | +---------------+ | INTLEN | +---------------+ | RSIZE | +---------------+ | N | +---------------+ A four-number `directory' at the end of the segment contains the information needed to determine the location of the record corresponding to a particular epoch. 1. INIT is the initial epoch of the first record, given in ephemeris seconds past 2000 Jan 01 12:00:00, also known as J2000. 2. INTLEN is the length of the interval covered by each record, in seconds. 3. RSIZE is the total size of (number of array elements in) each record. 4. N is the number of records contained in the segment. Each record is structured as follows: +------------------+ | MID | +------------------+ | RADIUS | +------------------+ | X coefficients | +------------------+ | Y coefficients | +------------------+ | Z coefficients | +------------------+ The first two elements in the record, MID and RADIUS, are the midpoint and radius of the time interval covered by coefficients in the record. These are used as parameters to perform transformations between the domain of the record (from MID - RADIUS to MID + RADIUS) and the domain of Chebyshev polynomials (from -1 to 1 ). The same number of coefficients is always used for each component, and all records are the same size (RSIZE), so the degree of each polynomial is ( RSIZE - 2 ) / 3 - 1 To facilitate the creation of type 2 segments, a segment writing routine called SPKW02 has been provided. This routine takes as input arguments the handle of an SPK file that is open for writing, the information needed to construct the segment descriptor, and the data to be stored in the segment. The header of the subroutine provides a complete description of the input arguments and an example of its usage. Type 3: Chebyshev (position and velocity) The third SPK data type contains Chebyshev polynomial coefficients for the position and velocity of the body as a function of time. Normally, this data type is used for satellites for which the ephemerides are computed from analytical theories. The structure of the segment is nearly identical to that of the SPK data type 2 (Chebyshev polynomials for position only). The only difference is that each logical record contains six sets of coefficients instead of three. The subroutine SPKE03 contains the algorithm used to construct a state from a particular record and epoch. Each record is structured as follows: +------------------+ | MID | +------------------+ | RADIUS | +------------------+ | X coefficients | +------------------+ | Y coefficients | +------------------+ | Z coefficients | +------------------+ | X' coefficients | +------------------+ | Y' coefficients | +------------------+ | Z' coefficients | +------------------+ The same number of coefficients is always used for each component, and all records are the same size (RSIZE), so the degree of each polynomial is ( RSIZE - 2 ) / 6 - 1 To facilitate the creation of type 3 segments, a segment writing routine called SPKW03 has been provided. This routine takes as input arguments the handle of an SPK file that is open for writing, the information needed to construct the segment descriptor, and the data to be stored in the segment. The header of the subroutine provides a complete description of the input arguments and an example of its usage. Type 5: Discrete states (two body propagation). The fifth standard SPK data type contains discrete state vectors. A state is obtained from a type 5 segment for any epoch that is within the bounds of that segment by propagating the discrete states to the specified epoch according to the laws of two body motion. Normally, this data type is used for comets and asteroids, whose ephemerides are integrated from an initial state or set of osculating elements. Each segment contains of a number of logical records. Each record consists of an epoch (ephemeris seconds past J2000) and the geometric state of the body at that epoch (x, y, z, dx/dt, dy/dt, dz/dt, in kilometers and kilometers per second). Records are ordered with respect to time. The records that correspond to an epoch for which a state is desired are the ones whose associated epochs bracket that epoch. The state in each record is used as the initial state in a two-body propagation; a weighted average of the propagated states gives the position of the body at the specified epoch. The velocity is given by the derivative of the position. Thus the position and velocity at the specified epoch are given by: P = W(t) * P1(t) + (1-W(t)) * P2(t) V = W(t) * V1(t) + (1-W(t)) * V2(t) + W'(t) * ( P1(t) - P2(t) ) where P1, V1, P2, and V2 are the position and velocity components of the propagated states and W is the weighting function. The weighting function used is: W(t) = 0.5 + 0.5 * cos [ PI * ( t - t1 ) / ( t2 - t1 ) ] where t1 and t2 are the epochs that bracket the specified epoch t. Physically, the epochs and states are stored separately, so that the epochs can be searched as an ordered array. Thus, the initial part of each segment looks like this: +--------------------+ | State 1 | +--------------------+ . . . +--------------------+ | State N | +--------------------+ | Epoch 1 | +--------------------+ . . . +--------------------+ | Epoch N | +--------------------+ The number of records in a segment can be arbitrarily large. In order to avoid the file reads required to search through a large array of epochs, each segment contains a simple directory immediately after the final epoch. This directory contains every 100th epoch in the epoch array. If there are N epochs, there will be N/100 directory epochs. (If there are fewer than 100 epochs, no directory epochs are stored.) The final items in the segment are GM, the gravitational parameter of the central body (kilometers and seconds), and N, the number of states in the segment. Thus, the complete segment looks like this: +--------------------+ | State 1 | +--------------------+ . . . +--------------------+ | Epoch 1 | +--------------------+ . . . +--------------------+ | Epoch N | +--------------------+ | Epoch 100 | (First directory epoch) +--------------------+ | Epoch 200 | +--------------------+ . . . +--------------------+ | Epoch (N/100)*100 | (Final directory epoch) +--------------------+ | GM | +--------------------+ | N | +--------------------+ To facilitate the creation of type 5 segments, a segment writing routine called SPKW05 has been provided. This routine takes as input arguments the handle of an SPK file that is open for writing, the information needed to construct the segment descriptor, and the data to be stored in the segment. The header of the subroutine provides a complete description of the input arguments and an example of its usage. Type 8: Equally Spaced Discrete States (Lagrange Interpolation) The eighth SPK data type represents a continuous ephemeris using a discrete set of states and a Lagrange interpolation method. The epochs (also called `time tags') associated with the states must be evenly spaced: there must be some positive constant STEP such that each time tag differs from its predecessor and successor by STEP seconds. For a request epoch not corresponding to the time tag of some state, the data type defines a state by interpolating each component of a set of states whose epochs are `centered' near the request epoch. Details of how these states are selected and interpolated are given below. The SPK system can also represent an ephemeris using unequally spaced discrete states and Lagrange interpolation; SPK type 9 does this. SPK type 9 sacrifices some run-time speed and economy of storage in order to achieve greater flexibility. The states in a type 8 segment are geometric: they do not take into account aberration corrections. The six components of each state vector represent the position and velocity (x, y, z, dx/dt, dy/dt, dz/dt, in kilometers and kilometers per second) of the body to which the ephemeris applies, relative to the center specified by the segment's descriptor. The epochs corresponding to the states are barycentric dynamical times (TDB), expressed as seconds past J2000. Each segment also has a polynomial degree associated with it; this is the degree of the interpolating polynomials to be used in evaluating states based on the data in the segment. The identical degree is used for interpolation of each state component. Type 8 SPK segments have the structure shown below: +--------+ | x(1) | / +--------+ / | y(1) | / +--------+ / | z(1) | +-----------------------+ / +--------+ | State 1 | < |dx(1)/dt| +-----------------------+ \ +--------+ | State 2 | \ |dy(1)/dt| +-----------------------+ \ +--------+ . \ |dz(1)/dt| . +--------+ . +-----------------------+ | State N | +-----------------------+ | Epoch of state 1 (TDB)| +-----------------------+ | Step size | +-----------------------+ | Polynomial degree | +-----------------------+ | Number of states | +-----------------------+ In the diagram, each box representing a state vector corresponds to six double precision numbers; the other boxes represent individual double precision numbers. Since the epochs of the states are evenly spaced, they are represented by a start epoch and a step size. The number of states must be greater than the interpolating polynomial degree. The type 8 interpolation method works as follows: given an epoch at which a state is requested and a segment having coverage for that epoch, the type 8 reader finds a group of states whose epochs are `centered' about the epoch. The size of the group is one greater than the polynomial degree associated with the segment. If the group size N is even, then the group will consist of N consecutive states such that the request time is between the epochs of the members of the group having indices, relative to the start of the group, of N/2 and (N/2 + 1), inclusive. When N is odd, the group will contain a central state whose epoch is closest to the request time, and will also contain (N-1)/2 neighboring states on either side of the central one. The type 8 evaluator will then use Lagrange interpolation on each component of the states to produce a state corresponding to the request time. For the jth state component, the interpolation algorithm is mathematically equivalent to finding the unique polynomial of degree N-1 that interpolates the ordered pairs ( epoch(i), state(j,i) ), i = k , k , ... , k 1 2 N and evaluating the polynomial at the request epoch. Here k , k , ... , k 1 2 N are the indices of the states in the interpolation group, epoch(i) is the epoch of the ith state and state(j,i) is the jth component of the ith state. There is an exception to the state selection algorithm described above: the request time may be too near the first or last state of the segment to be properly bracketed. In this case, the set of states selected for interpolation still has size N, and includes either the first or last state of the segment. To facilitate the creation of type 8 segments, a segment writing routine called SPKW08 has been provided. This routine takes as input arguments the handle of an SPK file that is open for writing, the information needed to construct the segment descriptor, and the data to be stored in the segment. The header of the subroutine provides a complete description of the input arguments and an example of its usage. Type 9: Unequally Spaced Discrete States (Lagrange Interpolation) The ninth SPK data type represents a continuous ephemeris using a discrete set of states and a Lagrange interpolation method. The epochs (also called `time tags') associated with the states need not be evenly spaced. For a request epoch not corresponding to the time tag of some state, the data type defines a state by interpolating each component of a set of states whose epochs are `centered' near the request epoch. Details of how these states are selected and interpolated are given below. The states in a type 9 segment are geometric: they do not take into account aberration corrections. The six components of each state vector represent the position and velocity (x, y, z, dx/dt, dy/dt, dz/dt, in kilometers and kilometers per second) of the body to which the ephemeris applies, relative to the center specified by the segment's descriptor. The epochs corresponding to the states are barycentric dynamical times (TDB), expressed as seconds past J2000. Each segment also has a polynomial degree associated with it; this is the degree of the interpolating polynomials to be used in evaluating states based on the data in the segment. The identical degree is used for interpolation of each state component. Type 9 SPK segments have the structure shown below: +--------+ | x(1) | / +--------+ / | y(1) | / +--------+ / | z(1) | +-----------------------+ / +--------+ | State 1 | < |dx(1)/dt| +-----------------------+ \ +--------+ | State 2 | \ |dy(1)/dt| +-----------------------+ \ +--------+ . \ |dz(1)/dt| . +--------+ . +-----------------------+ | State N | +-----------------------+ | Epoch 1 | +-----------------------+ | Epoch 2 | +-----------------------+ . . . +-----------------------+ | Epoch N | +-----------------------+ | Epoch 100 | (First directory) +-----------------------+ . . . +-----------------------+ | Epoch ((N-1)/100)*100 | (Last directory) +-----------------------+ | Polynomial degree | +-----------------------+ | Number of states | +-----------------------+ In the diagram, each box representing a state vector corresponds to six double precision numbers; the other boxes represent individual double precision numbers. The number of states must be greater than the interpolating polynomial degree. The set of time tags is augmented by a series of directory entries; these entries allow the type 9 reader to search for states more efficiently. The directory entries contain time tags whose indices are multiples of 100. The set of indices of time tags stored in the directories ranges from 100 to ( (N-1) / 100 ) * 100 where N is the total number of time tags. Note that if N is Q * 100 then only Q - 1 directory entries are stored, and in particular, if there are only 100 states in the segment, there are no directories. The type 9 interpolation algorithm is virtually identical to the type 8 algorithm; see the discussion of SPK type 8 for details. However, the type 9 algorithm executes more slowly than the type 8 algorithm, since the type 9 reader must search through tables of time tags to find appropriates states to interpolate, while the type 8 reader can locate the correct set of states to interpolate by a direct computation. To facilitate the creation of type 9 segments, a segment writing routine called SPKW09 has been provided. This routine takes as input arguments the handle of an SPK file that is open for writing, the information needed to construct the segment descriptor, and the data to be stored in the segment. The header of the subroutine provides a complete description of the input arguments and an example of its usage. Type 15: Precessing Conic Propagation. The SPK data type 15 represents a continuous ephemeris using a compact analytic model. The object is modelled as orbiting a central body under the influence of a central mass plus first order secular effects of the J2 term in harmonic expansion of the the central body gravitational potential. Type 15 SPK segments have the structure shown below: +--------------------------------+ | Epoch of Periapsis | +--------------------------------+ | Trajectory pole_x | +--------------------------------+ | Trajectory pole_y | +--------------------------------+ | Trajectory pole_z | +--------------------------------+ | Periapsis Unit Vector_x | +--------------------------------+ | Periapsis Unit Vector_y | +--------------------------------+ | Periapsis Unit Vector_z | +--------------------------------+ | Semi-Latus Rectum | +--------------------------------+ | Eccentricity | +--------------------------------+ | J2 Processing Flag | +--------------------------------+ | Central Body Pole_x | +--------------------------------+ | Central Body Pole_y | +--------------------------------+ | Central Body Pole_z | +--------------------------------+ | Central Body GM | +--------------------------------+ | Central Body J2 | +--------------------------------+ | Central Body Equatorial Radius | +--------------------------------+ It is important to note that the epoch must be that of periapsis passage. Precession of the line of apsides and regression of the line of nodes is computed relative to this epoch. The effects of the J2 term are not applied if the eccentricity is greater than or equal to 1. To facilitate the creation of type 15 segments, a segment writing routine called SPKW15 has been provided. This routine takes as input arguments the handle of an SPK file that is open for writing, the information needed to construct the segment descriptor, and the data to be stored in the segment. The header of the subroutine provides a complete description of the input arguments and an example of its usage. Codes Used in SPK Subroutine Calls -------------------------------------------------------- Body Codes A unique integer can be assigned to each body in the solar system, including interplanetary spacecraft. The SPK routines in SPICELIB use such integer codes instead of names to refer to ephemeris bodies for three reasons. 1. Space Integers code are smaller than alphanumeric names. 2. Uniqueness The names of some satellites conflict with the names of some asteroids and comets. Also, some satellites are commonly referred to by names other than those approved by the IAU. 3. Context The type of a body (barycenter, planet, satellite, comet, asteroid, or spacecraft) and the system to which it belongs (Earth, Mars, Jupiter, Saturn, Uranus, Neptune, or Pluto) can be recovered algorithmically from the integer code assigned to a body. This is not generally true for names. These integer codes are used for the arguments named TARGET and CENTER found in the Summary of Calling Sequences section of this document. Consult the NAIF IDS Required Reading file for the current list of body codes recognized by the NAIF Toolkit software. Reference Frames Every state vector returned from an ephemeris must be referenced to a recognized inertial reference frame. This requirement ensures that primitive states from different ephemerides can be combined to create more general states. (By forbidding states referenced to dynamically defined frames, this requirement also ensures that the ephemeris data stored in a file cannot be modified by definitions stored outside the file.) The inertial reference frames to which states may be referenced fall into three general categories. 1. New New frames are identical or nearly identical to the frame defined by the Earth mean equator and dynamical equinox of Julian year 2000, adopted by the IAU as the standard reference frame for all publications. The frame defined by the (as yet unreleased) FK5 star catalog will be in this category. 2. Old Old frames are close to the frame defined by the Earth mean equator and dynamical equinox of Besselian year 1950. The frames in this category are often referred to collectively by the name `EME50', although individual frames may be offset from each other by as much as half a second of arc. The name `B1950' is reserved for the frame defined by applying the J2000 precession model [164] to the J2000 frame. The frame defined by the FK4 star catalog is offset from the B1950 frame by about half a second of arc. Several of the frames in this category are defined by one of the Developmental Ephemeris (DE) files created by Standish at JPL. These may be offset from the FK4 frame by anywhere from a tenth to a hundredth of a second of arc [165]. 3. Other Other frames may be defined as needed. Currently, only one frame does not fit into either of the previous categories: the Galactic (System II) reference frame. The rotation between any two recognized frames can be obtained from subroutine IRFROT in SPICELIB by supplying the indexes of the frames. The module header for IRFROT contains the definitive list of recognized frames. For example, to rotate a position vector from FK4 coordinates to J2000 coordinates, CALL IRFROT ( 3, 1, ROT ) CALL MXV ( ROT, OLD, NEW ) (ROT is a 3-by-3 matrix, OLD and NEW are 3-vectors; subroutine MXV multiplies a matrix and a vector to produce a vector.) Two additional subroutines can be used to convert names to numbers (indexes) and vice versa. To find the index of the DE-125 frame, CALL IRFNUM ( 'DE-125', NUMBER ) To find the name corresponding to index 6, CALL IRFNAM ( 6, NAME ) These codes (here called indexes) are used for the argument named REF found in the Summary of Calling Sequences section of this document. Appendix A --- Summary of SP-kernel Subroutines =========================================================================== Summary of Mnemonics -------------------------------------------------------- SPICELIB contains a family of subroutines that are designed specifically for use with SPK files. The name of each routine begins with the letters `SPK', followed by a two- or three-character mnemonic. For example, the routine that returns the state of one body with respect to another is named SPKEZ, pronounced `S-P-K-E-Z'. Many of the routines listed are entry points of another subroutine. If a routine is an entry point, the parent routine's name will be listed inside brackets preceding the mnemonic translation. The following is a complete list of mnemonics and translations, in alphabetical order. SPKAPP ( SP-kernel, Apparent state ) SPKE01 ( SP-kernel, Evaluate record, type 01 ) SPKE02 ( SP-kernel, Evaluate record, type 02 ) SPKE03 ( SP-kernel, Evaluate record, type 03 ) SPKE05 ( SP-kernel, Evaluate record, type 05 ) SPKE08 ( SP-kernel, Evaluate record, type 08 ) SPKE09 ( SP-kernel, Evaluate record, type 09 ) SPKE15 ( SP-kernel, Evaluate record, type 15 ) SPKEZ ( SP-kernel, Easy state ) SPKGEO ( SP-kernel, Geometric state ) SPKLEF [SPKBSR] ( SP-kernel, Load ephemeris file ) SPKPDS ( SP-kernel, pack descriptor ) SPKPV ( SP-kernel, Position, velocity ) SPKR01 ( SP-kernel, Read record, type 01 ) SPKR02 ( SP-kernel, Read record, type 02 ) SPKR03 ( SP-kernel, Read record, type 03 ) SPKR05 ( SP-kernel, Read record, type 05 ) SPKR08 ( SP-kernel, Read record, type 08 ) SPKR09 ( SP-kernel, Read record, type 09 ) SPKR15 ( SP-kernel, Read record, type 15 ) SPKS01 ( SP-kernel, Subset data, type 01 ) SPKS02 ( SP-kernel, Subset data, type 02 ) SPKS03 ( SP-kernel, Subset data, type 03 ) SPKS05 ( SP-kernel, Subset data, type 05 ) SPKS08 ( SP-kernel, Subset data, type 08 ) SPKS09 ( SP-kernel, Subset data, type 09 ) SPKS15 ( SP-kernel, Subset data, type 15 ) SPKSFS [SPKBSR] ( SP-kernel, file and segment ) SPKSSB ( SP-kernel, Solar system barycenter ) SPKUEF [SPKBSR] ( SP-kernel, Unload ephemeris file ) SPKSUB ( SP-kernel, Subset a segment ) SPKW02 ( SP-kernel, Write segment, type 02 ) SPKW03 ( SP-kernel, Write segment, type 03 ) SPKW05 ( SP-kernel, Write segment, type 05 ) SPKW08 ( SP-kernel, Write segment, type 08 ) SPKW09 ( SP-kernel, Write segment, type 09 ) SPKW15 ( SP-kernel, Write segment, type 15 ) Summary of Calling Sequences -------------------------------------------------------- The calling sequences for the SPK subroutines are summarized below. The subroutines are grouped by function. Loading, unloading files: SPKLEF ( FNAME, HANDLE ) SPKUEF ( HANDLE ) Computing states: SPKEZ ( TARGET, ET, REF, ABERR, OBS, STATE, LT ) SPKAPP ( TARGET, ET, REF, STOBS, ABERR, STATE, LT ) SPKSSB ( TARGET, ET, REF, STATE ) SPKGEO ( TARGET, ET, REF, OBS, STATE, LT ) SPKPV ( HANDLE, DESCR, ET, REF, STATE, CENTER ) Selecting files, segments: SPKSFS ( TARGET, ET, HANDLE, DESCR, PDGREE, FOUND ) Reading, evaluating records: SPKRO1 ( HANDLE, DESCR, ET, RECORD ) SPKE01 ( ET, RECORD, STATE ) SPKRO2 ( HANDLE, DESCR, ET, RECORD ) SPKE02 ( ET, RECORD, STATE ) SPKRO3 ( HANDLE, DESCR, ET, RECORD ) SPKE03 ( ET, RECORD, STATE ) SPKRO5 ( HANDLE, DESCR, ET, RECORD ) SPKE05 ( ET, RECORD, STATE ) SPKRO8 ( HANDLE, DESCR, ET, RECORD ) SPKE08 ( ET, RECORD, STATE ) SPKRO9 ( HANDLE, DESCR, ET, RECORD ) SPKE09 ( ET, RECORD, STATE ) SPKR15 ( HANDLE, DESCR, ET, RECORD ) SPKE15 ( ET, RECORD, STATE ) Writing segments to files. SPKPDS ( BODY, CENTER, FRAME, TYPE, FIRST, LAST, DESCR ) SPKW02 ( HANDLE, BODY, CENTER, FRAME, FIRST, LAST, SEGID, INTLEN, N, POLYDG, CDATA, BTIME ) SPKW03 ( HANDLE, BODY, CENTER, FRAME, FIRST, LAST, SEGID, INTLEN, N, POLYDG, CDATA, BTIME ) SPKW05 ( HANDLE, BODY, CENTER, FRAME, FIRST, LAST, SEGID, GM, N, STATES, EPOCHS ) SPKW08 ( HANDLE, BODY, CENTER, FRAME, FIRST, LAST, SEGID, DEGREE, N, STATES, EPOCH1, STEP ) SPKW09 ( HANDLE, BODY, CENTER, FRAME, FIRST, LAST, SEGID, DEGREE, N, STATES, EPOCHS ) SPKW15 ( HANDLE, BODY, CENTER, FRAME, FIRST, LAST, SEGID, EPOCH, TPOLE, PERI, P, ECC, J2FLG, CPOLE, GM, J2, RADIUS ) Extracting subsets of data from a segment: SPKS01 ( HANDLE, BADDR, EADDR, BEGIN, END ) SPKS02 ( HANDLE, BADDR, EADDR, BEGIN, END ) SPKS03 ( HANDLE, BADDR, EADDR, BEGIN, END ) SPKS05 ( HANDLE, BADDR, EADDR, BEGIN, END ) SPKS08 ( HANDLE, BADDR, EADDR, BEGIN, END ) SPKS09 ( HANDLE, BADDR, EADDR, BEGIN, END ) SPKS15 ( HANDLE, BADDR, EADDR, BEGIN, END ) SPKSUB ( HANDLE, DESCR, IDENT, BEGIN, END, NEWH ) For converting SPK files and opening new SPK files, see the SPC Required Reading and the DAF Required Reading. Appendix B --- SPTEST, the NAIF Toolkit SPK Test Program =========================================================================== A standard test program, SPTEST, is included in the NAIF Toolkit so users can verify that the SPK readers have been installed correctly in any new environment. The program computes a series of state vectors, using data from a standard test ephemeris file, and compares the results with state vectors computed and recorded earlier in the NAIF development environment. If the states agree to within some specified tolerance (which can be changed by the user), the program simply reports that the SPK readers are working correctly. Otherwise, it prints out diagnostic information that should be forwarded to NAIF for evaluation.