SCLK Required Reading =========================================================================== Last revised on 2004 DEC 21 by B. V. Semenov. Abstract -------------------------------------------------------- The SCLK system is the component of SPICE concerned with spacecraft clock correlation data. Introduction -------------------------------------------------------- The spacecraft clock is the onboard time-keeping mechanism that triggers most spacecraft events, such as shuttering of a camera. Since telemetry data are downlinked with this clock's time attached to it, spacecraft clock time (SCLK--pronounced ``s-clock'') is the fundamental time measurement for referencing many spacecraft activities. It is natural, then, that SCLK have an important role in the CSPICE system. In fact, all C-kernel pointing data are referenced to SCLK. CSPICE contains functions to convert between SCLK and other standard time systems, such as Ephemeris Time (ET) and Universal Time Coordinated (UTC). References 1. SFOC SIS ``SFOC-2-SYS-Any-TimeForms,'' 02/06/90. Supported Missions The set of missions for which NAIF currently supports SCLK time conversions includes, but is not limited to, the following: -- Cassini -- Galileo -- Mars Climate Orbiter -- Mars Global Surveyor -- Mars Polar Lander -- Near Earth Asteroid Rendezvous -- Stardust -- Voyager I and II The suite of SCLK functions has been designed to easily accommodate future missions. A later section describes how the system might be easily expanded to incorporate new spacecraft clocks. Detection of Non-native Text Files Starting with the N0057 release of the SPICE Toolkit (March, 2004) the SPICE data loading mechanism detects and prohibits loading text kernel files containing lines terminated with EOF character(s) non-native to the platform on which the Toolkit was compiled. If a non-native EOL terminator is detected in the first 132 characters of a text kernel, the execution is stopped and an error message is displayed. This feature does not work with files that are smaller that 132 bytes or have the first line longer that 132 characters. The Basics -------------------------------------------------------- In this section, we present a minimal subset of facts about the CSPICE SCLK system that you can get by with and still use the system successfully. SCLK rates Most of the complexity of dealing with SCLK time values arises from the fact that the rate at which any spacecraft clock runs varies over time. As a consequence, the relationship between SCLK and ET or UTC is not accurately described by a linear function; usually, a piecewise linear function is used to model this relationship. The mapping that models the relationship between SCLK and other time systems is updated as a mission progresses. While the change in the relationship between SCLK and other systems will usually be small, you should be aware that it exists; it may be a cause of discrepancies between results produced by different sets of software. SCLK kernels To use any of the SCLK conversion functions, your program must first load a SCLK kernel file. The code fragment furnsh_c ( ); accomplishes this. You must supply the actual name of the kernel file you want to load. In addition, you will usually need to load a leapseconds kernel. For some missions, conversions between SCLK and ET will require that both an SCLK and a leapseconds kernel be loaded. The code fragment furnsh_c ( ); loads a leapseconds kernel. Leapseconds kernels are described in the TIME required reading document, time.req. Normally, you will load these kernels at just one point in your application program, prior to using any time conversion functions. Details concerning the kernel pool are covered in the KERNEL required reading document, kernel.req. Partitions, briefly The lifetime of each mission is divided into intervals called ``partitions.'' Partitions are time intervals during which the spacecraft clock advances continuously. Every time that a discontinuity in a spacecraft clock's readout values occurs, a new partition is started. Discontinuities may consist of positive jumps, in which the spacecraft clock's readout ``skips'' ahead, or negative jumps, in which the spacecraft clock regresses. The fact that a spacecraft clock may regress raises the possibility that the clock may give the same reading at two or more different times. For this reason, SCLK strings in CSPICE are prefaced with partition numbers. The partition number is a positive integer followed by a forward slash, for example 4 / Any number of blanks are allowed on either side of the slash. An example of a Galileo SCLK string with a partition number is 1/100007:76:1 Partition numbers serve to ensure that spacecraft clock readings can be interpreted unambiguously. Converting between SCLK strings and ET or UTC The time known as ``spacecraft event time'' (SCET) is usually UTC. You must verify that this is the case for your spacecraft. To convert a SCLK string to a double precision ET value, you can use the function call scs2e_c ( sc, clkstr, &et ); To convert a SCLK string to a UTC string, you can use the code fragment scs2e_c ( sc, clkstr, &et ); timout_c ( et, pictur, lenout, utc ); where sc is the NAIF spacecraft ID code for your spacecraft. clkstr is a SCLK string. et is an ET time. pictur is a format picture for timout_c. lenout is the output string length. utc is the UTC time equivalent to SCLK. See these functions for details concerning their arguments. The inverse conversion is performed by the code fragment str2et_c ( utc, &et ); sce2s_c ( sc, et, lenout, clkstr ); Using encoded SCLK The CSPICE C kernel (CK) system tags CK data with SCLK times. Within the CK system, these time tags are encoded as double precision numbers. To look up CK data, you will need to supply encoded SCLK time tags to the CK reader functions. You can obtain encoded SCLK values from SCLK strings via the function scencd_c. The code fragment scencd_c ( sc, clkstr, &sclkdp ); encodes the SCLK string clkstr as the double precision value sclkdp. Encoded SCLK values can be converted to strings using the code fragment scdecd_c ( sc, sclkdp, lenout, clkstr ); You can obtain continuous encoded SCLK values from ET via the function sce2c_c. The code fragment sce2c_c ( sc, et, &sclkdp ); encodes the ephemeris time ET as the double precision value sclkdp. SCLKDP need not be integral; even though non-integral tick values do not represent SCLK readings, they are permitted to avoid truncation error when representing ET as encoded SCLK. A parallel routine sce2t_c converts ET to encoded SCLK, rounding the result to the nearest integral tick. The inverse conversion is provided by the routine sct2e_c, which is called as follows: sct2e_c ( sc, sclkdp, &et ); SCT2E handles integral or continuous tick values as inputs. There is a special function that is used for encoding ``tolerance'' values for the CK readers. (See the CK Required Reading, ck.req, document for a discussion of the CK readers.) The code fragment sctiks_c ( sc, clkstr, &ticks ); produces an encoded tolerance value. sctiks_c takes SCLK strings WITHOUT partition numbers as inputs; this is because the strings indicate a delta time rather than an absolute time. All of the concepts used in this section are discussed in greater detail in the following sections of this document. Encoded SCLK -------------------------------------------------------- The fundamental representation of SCLK in the CSPICE system is a double precision numeric encoding of each multi-component count. Encoding SCLK provides the following advantages: -- Encoding makes for a more compact representation. Direct (un-encoded) representation of spacecraft clock counts usually requires multiple numbers for the separate components making up the SCLK count. -- Having a single numeric equivalent for each count makes it much easier to compare SCLK times (Is time t1 greater than time t2? Is time t1 closer to time t2 than time t3? And so on.) For these reasons, encoded SCLK is the time representation that is associated with pointing data in the C-kernel. Encoded SCLK is the basis by which conversions are made from SCLK to other time systems. To convert a character representation of an SCLK count sclkch to its double precision encoding sclkdp, use the function scencd_c (Encode SCLK): scencd_c ( sc, sclkch, &sclkdp ); The function scdecd_c (Decode SCLK) recovers the character representation of spacecraft clock from its double precision encoding. scdecd_c ( sc, sclkdp, lenout, sclkch ); The first argument to both functions, sc, is the NAIF integer ID for the spacecraft whose clock count is being encoded or decoded (for example, --32 for Voyager 2). Each spacecraft may have a different format for its clock counts, so the encoding scheme may be different for each. Later chapters describing clock types give complete details on clock string formats for spacecraft clocks supported by the CSPICE Toolkit. Ticks The units of encoded SCLK are ``ticks since spacecraft clock start,'' where a ``tick'' is defined to be the shortest time increment expressible by a particular spacecraft's clock. An analogy can be drawn with a standard wall clock, showing hours, minutes, and seconds. One tick for a wall clock would be one second. And a wall clock time of 10:05:50 would represent 10(3600) + 5(60) + 50 = 36350 ticks. As in the case of the wall clock, the length of time associated with a tick varies as the clock rate varies. Since not all spacecraft clocks are the same, the particular time value for one tick varies from spacecraft to spacecraft. For Mars Global Surveyor, for instance, one tick is equivalent to approximately four milliseconds. For Galileo, it's about 8 1/3 milliseconds. In addition to representing spacecraft clock readings, ticks can be used to represent arbitrary epochs. In order to minimize discretization error, ``continuous'' (non-integral) tick values are supported: ephemeris times may be converted to non-integral ticks via the function sce2c_c. Conversion of spacecraft clock strings to ticks always produces integral tick values. Partitions One desirable feature of encoded SCLK is that it increases continuously throughout the course of the mission. Unfortunately, real spacecraft clocks do not always behave so nicely. A clock may reset to a lower value, rendering certain counts ambiguous. This might happen if the clock has reached its maximum expression, or because of a power surge. A clock may also jump ahead. Any time one of these discontinuities occurs, we say that SCLK time has entered a new partition. The partitions must be accounted for when encoding and decoding SCLK. To continue our analogy, say our wall clock was being used to keep time throughout an entire day. Then 10:05:50 is ambiguous, because we don't know if it falls in the morning or evening ``partition.'' So we append the indicators ``a.m.''\ or ``p.m.''\ to be clear. We handle SCLK similarly. Instead of just converting a clock count to ticks (10:05:50 to 36350), we take into account the partition that the count falls in, and compute the number of ticks since clock start (10:05:50 a.m. to 36350; 10:05:50 p.m. to 36350 + 12(60)(60) = 79550). When you pass a SCLK string to scencd_c, it is normally prefixed with a number indicating the partition in which the count falls. Sample SCLK strings for Voyager 2, including partition numbers, are given in an example program later in this document. The presence of the partition number is not always required. If it is missing, scencd_c will assume the partition to be the earliest one possible that contains the clock string being encoded. It's good practice to always include the partition number in SCLK strings. To convert to ticks since clock start, scencd_c processes the partition number. It has to know how many ticks were in all preceding partitions, and what the start and stop clock values were for each. This information is stored in a SCLK kernel file for that spacecraft. The SCLK kernel file is described in detail in a later section. New partitions may occur at any time throughout the course of active missions. The responsible mission operations team must update the SCLK kernel file to include new partitions as they occur. In converting encoded SCLK back to an equivalent clock string, scdecd_c must also use the SCLK kernel file. Note, however, that you only have to load the SCLK kernel file once in your program, no matter how many calls to scencd_c and scdecd_c are made afterwards. See the KERNEL required reading file, kernel.req, for information about ``loading'' miscellaneous kernel files into the kernel pool. scdecd_c always returns a clock string prefixed by a partition number and the '/' character, for example 2/2000:83:12 If you want to read partition start and stop times for yourself, use the function scpart_c: scpart_c ( sc, nparts, pstart, pstop ); SCLK Conversion Functions -------------------------------------------------------- In order to correlate data obtained from different components of the CSPICE system, for example pointing and ephemeris data, it is necessary to be able to convert between SCLK time and representations of time in other systems, such as UTC and ephemeris time (also referred to as ``ET,'' ``barycentric dynamical time,'' and ``TDB''). CSPICE contains the following functions to convert between encoded and character SCLK, ET and UTC. Note that the names of the the functions involving SCLK are all prefixed with sc, for Spacecraft Clock. et2utc_c (et, format, prec, lenout, utc) (Convert ET to a utc string) utc2et_c (utc, et) (Convert a utc string to ET) scencd_c (sc, sclkch, sclkdp) (Encode SCLK) scdecd_c (sc, sclkdp, lenout, sclkch) (Decode SCLK) sct2e_c (sc, sclkdp, et) (Convert encoded SCLK ticks to ET) scs2e_c (sc, sclkch, et) (Convert SCLK string to ET) sce2c_c (sc, et, sclkdp) (Convert ET to continuous ticks) sce2t_c (sc, et, sclkdp) (Convert ET to encoded SCLK ticks) sce2s_c (sc, et, lenout, sclkch) (Convert ET to SCLK string) It takes at most two function calls to convert between any two of the four representations. CSPICE also contains two functions that can encode and decode relative, or ``delta'' SCLK times. These are SCLK strings without partition numbers that represent time increments rather than total time since clock start. Such strings are encoded as tick counts. The functions are: sctiks_c ( sc, clkstr, ticks ) (Convert delta SCLK to ticks ) scfmt_c (sc, ticks, lenout, clkstr) (Convert ticks to delta SCLK) Distinguishing Between Different Clocks -------------------------------------------------------- The algorithms used to encode and decode SCLK, and convert between SCLK and other time systems are not necessarily the same for each spacecraft. The differences are handled by the SCLK software at two levels: High-level differences are managed in the code itself through ``clock types.'' More detailed spacecraft-specific differences are handled using parameters in a SCLK kernel. Clock Types A clock type is a general clock description that may encompass several separate spacecraft clocks. Each clock type is identified in the SCLK functions by an integer code. At the release date of the current revision of this document, all supported missions use spacecraft clock type 1. A spacecraft clock data type has two components: a format defining the set of acceptable spacecraft clock (SCLK) strings, and a method of converting SCLK strings to a standard time representation, such as ephemeris or UTC seconds past J2000. For example, a type 1 clock consists of some number of cascading integer counters. An individual counter can increment only when the immediately preceding counter reaches its maximum expression and ``rolls over.'' Our wall clock is an example: the counters are hours, minutes and seconds. One tick for a type 1 clock is defined to be the value of the least-significant component increment. Clock type 1 uses a piecewise-linear interpolation process to convert between SCLK and other time systems. The chapter ``SLCK01'' describes clock type 1 in detail. It includes the specific SCLK string formats for each of the type 1 spacecraft clocks supported by the CSPICE Toolkit. SCLK functions determine the clock type for a particular spacecraft from the SCLK kernel file (described in the next section). Clock type-specific functions Each clock type is supported in the encoding and decoding process by the function sccc_c, where cc is the number of the clock type. sccc_c contains two entry points: sctkcc_ (sc, clkstr, ticks, len_clkstr ) (SCLK string to ticks, type cc) scfmcc_ (sc, ticks, clkstr, len_clkstr) (Ticks to SCLK string, type cc) sctkcc_ and scfmcc_ do not process any partition information; that work is handled at a higher level by scencd_c and scdecd_c, and is the same for all spacecraft clocks. sctkcc_ and scfmcc_ are called by sctiks_c and scfmt_c, respectively. Each clock type is supported in the time conversion process by two functions: sctecc_ (sc, sclkdp, et) (Encoded SCLK ticks to ET, type cc) sceccc_ (sc, et, sclkdp) (ET to continuous ticks, type cc) Spacecraft-Specific Parameters Once the clock type has been determined, SCLK functions need parameters that uniquely distinguish each spacecraft within the same SCLK type. For instance, for type 1, they need to know: How many components make up this particular clock? What are the modulus values for each of the components? What are the coefficients defining the mapping from SCLK to a ``parallel'' time system, such as ET? Spacecraft-specific parameters such as these are read from the SCLK kernel file at run-time (see below). The SCLK Kernel File -------------------------------------------------------- NAIF SCLK kernel files supply CSPICE SCLK conversion functions with information required to convert between SCLK values and other representations of time. Typically, a NAIF SCLK kernel will describe the clock of a single spacecraft. Before calling any of the functions to encode or decode SCLK, or convert between SCLK and other time systems, an application program must load the contents of the SCLK kernel file into the kernel pool, using the function furnsh_c (load pool): furnsh_c ( "name_of_SCLK_kernel_file" ); An application must also load the leapseconds kernel file if there are any conversions to be performed between ET and UTC. This is typically done in the initialization section of your program. The SCLK kernel file you use should contain values for the particular spacecraft you are dealing with. The variables expected to be found in the file are all prefixed with the string SCLK_ These variables include partition boundaries, clock type, and several other parameters associated with the clock type. These are described below. Partition boundaries The tick values for the beginning and end of each partition are given by: SCLK_PARTITION_START_ss = ( ..... ..... ..... ..... ) SCLK_PARTITION_END_ss = ( ..... ..... ..... ..... ) where --ss is the spacecraft ID code. These variables are arrays containing one element per partition. The nth element of SCLK_PARTITITION_END_ss is considered to be the ``first tick'' of the (n+1)st partition. Mathematically speaking, partitions may be thought of as intervals that are closed on the left and open on the right. Clock type assignment If --ss is the NAIF ID code of a spacecraft, the associated clock type for that spacecraft is given by the assignment SCLK_DATA_TYPE_ss = ( cc ) where cc is the clock type. New clock types will be developed as needed. Note that multiple spacecraft ID codes can be associated with the type 1 SCLK data type at one time. Since the spacecraft codes are included in the SCLK variable names, there will be no naming conflicts. (We don't expect this feature to be used much, if at all, but it's there should you need it.) Clock type-specific parameters Each spacecraft clock type has its own set of parameters that the CSPICE SCLK functions require in order to convert SCLK values of that type. A complete list and description of these parameters, and their variable names for the kernel pool, is given for type 1 in the chapter ``SCLK01.'' Expanding the system: What NAIF must do -------------------------------------------------------- Accommodating new spacecraft clocks may involve no code changes to the SCLK subroutines whatsoever. If a new clock fits into the framework of clock type 1, then the clock can be accommodated simply by producing a new kernel file for that spacecraft clock. For the new clock, a new set of kernel variables corresponding to those described above, and those in the chapter ``SCLK01,'' could be added to an existing SCLK kernel file. Alternatively, an entirely new SCLK kernel file containing the new parameters could be created --- this is the more likely approach. Once this is done, all existing SCLK functions will function, without modification, using the spacecraft ID. If a new clock does not fit into the clock type 1 framework, then NAIF will design a new clock type. This will involve writing new versions of the four clock type-specific functions described earlier: sctkcc_ scfmcc_ sctecc_ sceccc_ where cc is the new clock type number. New cases will have to be added to the code of the following higher-level SCxxx conversion functions to call the new, type-specific functions: scfmt_c sctiks_c sct2e_c scs2e_c sce2c_c sce2t_c sce2s_c It will probably be necessary to design new SCLK kernel file variables to accommodate the new type, and augment the standard variables described above. Adding a new clock type does not change the calling sequence of any of the high-level conversion functions. Thus, once you've learned how to use the SCLK conversion functions, you won't have to re-learn just because a new spacecraft clock has been introduced. An Example Using SCLK Functions -------------------------------------------------------- The following example shows how some of the SCLK functions might be used in a typical application program. This one reads pointing data from a C-kernel file. In this example, a set of four input clock times are hard-coded in the program for the purpose of demonstration: A real application written by you would likely get input times from some external source, such as a file or through interactive user input. /* Request pointing from a C-kernel file for a sequence of pictures obtained from the Voyager 2 narrow angle camera. Use an array of character spacecraft clock counts as input. Decode the output clock counts and print the input and output clock strings. Also print the equivalent UTC time for each output clock time. Note that the SCLK kernel file must contain VGR 2 clock information. */ #include #include "SpiceUsr.h" void main() { /* Local constants: */ #define NPICS 4 #define TIMLEN 25 #define LINLEN 80 /* Names of C kernel and SCLK kernels: */ #define CK "VGR2NA.BC" #define SCLKKER "SCLK.KER" #define LSK "LSK.KER" /* The instrument we want pointing for is the Voyager 2 narrow angle camera. The reference frame we want is J2000. The spacecraft is Voyager 2. */ #define INST -32001 #define REF "J2000" #define SC -32 /* Local static variables: */ static SpiceChar clktol [ TIMLEN ] = "0:01:001"; static SpiceChar sclkin [ NPICS ] [ TIMLEN ] = { "2/20538:39:768", "2/20543:21:768", "2/20550:37", "2/20564:19" }; /* Local automatic variables: */ SpiceBoolean found; SpiceChar sclkout [ TIMLEN ]; SpiceChar utc [ TIMLEN ]; SpiceDouble cmat [3][3]; SpiceDouble et; SpiceDouble timein; SpiceDouble timeout; SpiceDouble tol; SpiceInt i; SpiceInt sc; /* Load the appropriate files. We need 1) A CK file containing pointing data. 2) The SCLK kernel file, for the SCLK conversion functions. 3) A leapseconds kernel, for ET-UTC conversions. */ furnsh_c ( CK, ); furnsh_c ( SCLKKER ); furnsh_c ( LSK ); /* Convert the tolerance string to ticks. */ sctiks_c ( SC, clktol, &tol ); for ( i = 0; i < NPICS; i++ ) { scencd_c ( SC, sclkin[i], &timein ); ckgp_c ( INST, timein, tol, REF, cmat, &timeout, &found ); scdecd_c ( SC, timeout, TIMLEN, sclkout ); sct2e_c ( SC, timeout, &et ); et2utc_c ( et, "D", 3, TIMLEN, utc ); if ( found ) { printf ( "\n" "Input s/c clock count: %s\n" "Output s/c clock count: %s\n" "Output UTC: %s\n" "Output C-Matrix: \n" "\n" "%f\t %f\t %f\t\n" "%f\t %f\t %f\t\n" "%f\t %f\t %f\t\n" "\n", sclkin[i], sclkout, utc, cmat[0][0], cmat[0][1], cmat[0][2], cmat[1][0], cmat[1][1], cmat[1][2], cmat[2][0], cmat[2][1], cmat[2][2] ); } else { printf ( "\n" "Input s/c clock count: %s\n" "No pointing found.\n", sclkin[i] ); } } } The output from this program looks like this: Input s/c clock count: 2 / 20538:39:768 Output s/c clock count: 2/20538.39.768 Output UTC: 79-186/21:50:23.000 Output C-Matrix: Input s/c clock count: 2 / 20543:21:768 Output s/c clock count: 2/20543.22.768 Output UTC: 79-187/01:35:57.774 Output C-Matrix: Input s/c clock count: 2 / 20550:37 Output s/c clock count: 2/20550.36.768 Output UTC: 79-187/07:23:57.774 Output C-Matrix: Input s/c clock count: 2 / 20564:19 Output s/c clock count: 2/20564.19.768 Output UTC: 79-187/18:22:21.774 Output C-Matrix: SCLK01 =========================================================================== This chapter describes the type 1 SCLK format and conversion algorithms in detail. Also, the SCLK formats for supported spacecraft whose clocks conform to the type 1 specification are described. Conforming spacecraft clocks -------------------------------------------------------- The following spacecraft have SCLK formats that conform to the type 1 specification: -- Cassini -- Galileo Orbiter -- Mars Global Surveyor -- Mars Climate Orbiter -- Mars Polar Lander -- NEAR -- Stardust -- Voyager 1 -- Voyager 2 The spacecraft clock encoding and conversion functionality described in this document is fully supported by the CSPICE Toolkit for these spacecraft. Type 1 SCLK format -------------------------------------------------------- The first standard NAIF spacecraft clock data type has two components: a format defining the set of acceptable spacecraft clock (SCLK) strings, and a method of converting SCLK strings to any of a set of standard time systems such as UTC or ET. Type 1 SCLK strings have the form pp/