Analysis of Euclid frames

In a previous post I looked at the modulation and coding of Euclid, the recently launched ESA space telescope. I processed a 4.5 hour recording that I did with two dishes from the Allen Telescope Array. This post is an analysis of the telemetry frames. As we will see, Euclid uses CCSDS TM Space Data Link frames and the PUS protocol version 1. The telemetry structure is quite similar to that of JUICE, which I described in an earlier post. I have re-used most of my analysis code for JUICE. However, it is interesting to look at the few differences between the two spacecraft.

TM frames

Euclid transmits CCSDS TM Space Data Link frames with spacecraft ID 0x2A8. This ID is assigned to Euclid in the SANA registry, both for the forward and return directions (and for X and K-band). Unlike in the case of JUICE, there is no secondary header (JUICE frames contained a secondary header which gave an extension to the virtual channel frame count). There is an Operational Control Field carrying a CLCW, and a Frame Error Control Field. Virtual channels 0, 4, and 7 are in use during the recording.

I have timestamped the decoded frames by using the baudrates that I have measured in the GNU Radio decoder, by considering that the first low rate frame happens at 10715.1 seconds (which is when the modulation starts in the waterfall), and by correcting for missed frames using the jumps in the master channel frame count. The figure below shows a check of the continuity of the timestamps during the modulation change. In the waterfall we can see that there are 3 seconds without modulation. Given that the duration of low rate frames is 4.44 seconds, the plot looks more or less correct, give or take one second. We will come back to this plot when we compare these timestamps with the spacecraft time source packets.

The following plot shows the frame loss throughout all the recording. There are very few lost frames, since the signal was quite strong. The lost frames near the beginning are probably related to a mistake I made with the antenna pointing. The frames slightly before 10:00 UTC correspond to the modulation change, and the frames lost after 10:00 UTC are caused by the high frequency drift during the uplink sweep.

The next figure shows the usage of each virtual channel. We see that virtual channel 4 is used very sparingly. Most of the bandwidth is occupied by virtual channel 0, which has a steady rate (that changes somewhat as a consequence of the modulation change) with some higher usage peaks, possibly caused by responses to telecommands.

Virtual channel 0

Virtual channel 0 contains CCSDS Space Packets with real-time telemetry. The packets use PUS version number 1, described in ECSS-E-70-41A. As specified in this document, all the packets except those in APID 0 (which correspond to spacecraft time source packets) have a PUS header as secondary header. In the PUS header, the packet sub-counter field is not present. The destination ID field is 8 bits wide, and usually has the value 0x00, but sometimes it has the value 0x01.

The time field is 48 bits wide and contains \(2^{-16}\) second units. However, unlike in the case of JUICE, which used 2000-01-01 00:00:00 UTC (the J2000 epoch) as the epoch for this field, Euclid’s epoch seems to be at a rather unspecial timestamp on the day of launch. Subtracting the timestamp of the first decoded packet from the timestamp of the start of the recording gives 2023-07-01 08:07:02. UTC. As of writing this post there are now SPICE kernels for Euclid in ESA’s repository, including SPK trajectory kernels (and this information is also in HORIZONS), but there are no SCLK kernels describing the spacecraft clock, so we cannot confirm the correct exact value of the epoch.

Regarding the destination ID field in the PUS header, there are 59301 packets with a destination of 0x00 and only 370 packets with a destination of 0x01. There seems to be a direct relation between the PUS services and the destination. PUS services 3 (housekeeping and diagnostic data reporting service) and 5 (event reporting service) use destination 0x00, while PUS services 1 (telecommand verification service), 8 (function management service), and 11 (on-board operations scheduling service) use destination 0x01, yet there are two packets APID 550 PUS (3, 25) that use destination 0x01 for no apparent reason (they seem very similar to other PUS (3, 25) packets in the same APID).

The following figure shows when packets are transmitted in each APID. The x-axis shows the space packet timestamp value as seconds since the epoch. As we will see below in more detail, APID 0 is the spacecraft time source packet and is transmitted periodically. APID 550 is real-time telemetry and is always active. APID 771 and 1312 seem to be more verbose real-time telemetry only active in the high speed mode. APID 769 is a periodic event report. The other APIDs transmit packets as a response to telecommands. Something which is of interest is that Euclid doesn’t seem to use idle Space Packets (APID 2047), unlike JUICE.

The next two figures show the usage of each APID in packets per second and bytes per second, using a logarithmic scale.

The Space Packets in all the APIDs except APID 0 contain a CRC-16, and all the CRCs in the decoded packets are valid (as would be expected, since we have already discarded frames with wrong CRC). Interestingly, JUICE had a valid CRC-16 in all the Space Packets, including APID 0.

Next we describe the contents of each APID in Virtual channel 0.


APID 0 contains the spacecraft time source packets as specified by the PUS standard. The time code uses 7 bytes and a resolution of \(2^{-24}\) seconds. The first two bytes of each packet always contain 0x062f. These indicate the format of the time code and that the time code is reported every 64 frames. This means that the spacecraft clock is latched at the beginning of the transmission of each virtual channel 0 frame whose virtual channel frame count is divisible by 64. A Space Packet with this time code is generated and transmitted subsequently.

Since we know to which frame each time source packet corresponds, we can compare the values of the receiver timestamps that we have generated by using the measured symbol rate with the timestamps in APID 0 packets. To do this, we subtract a constant offset to make the difference zero at the beginning of the recording, since we do not know the epoch of the spacecraft clock. The difference is shown here. We can see two effects. First, there is a jump of about one second when the modulation change happens. This is caused by an error in our timestamping of the first decoded frame after the modulation change.

The second effect is that the difference increases slightly over time. This is best seen in the next two figures, which show the parts of the data before and after the modulation change. This increase is in in part caused by the error in our estimation of the received symbol rate, but it is also caused by Doppler. As Euclid is receding from Earth, Doppler makes the spacecraft clock appear to tick slower than the groundstation receiver clock if we do not factor in the increase in time of flight of the signal.

According to the ephemerides in HORIZONS, the range rate during the recording was around 2 km/s. This gives a Doppler effect of 6.66 ppm, which corresponds to a time difference of 24 ms over one hour. We see that the slope of the timestamp difference before the modulation change is close to this value, indicating that the baudrate estimate is quite accurate.

On the other hand, the slope after the modulation change is 37 ppm, which indicates that our estimate of the baudrate has a significant error.

APID 512

APID 512 contains the PUS (1, 1) (telecommand acceptance report) and PUS (1, 7) (telecommand execution completed report) packets for a single telecommand. The telecommand was sent using the same APID: 512. This seems a general rule in Euclid (unlike JUICE). The telecommand execution results are reported over the same APID that was used to send the telecommand.

APID 533

APID 533 contains the PUS (1, 1) and PUS (1, 7) packets for 32 telecommands, and 48 PUS (8, 2) packets that are sent as a result of executing these telecommands (they are sent between the PUS (1, 1) and PUS (1, 7)) packets. This is somewhat strange, because PUS service type 8 is the function management service, but there is no subtype 2 in the standard.

APID 534

APID 534 contains the PUS (1, 1) and PUS (1, 7) packets for 2 telecommands.

APID 550

APID 550 seems to be the main real-time telemetry APID. It contains many PUS (3, 25) (housekeeping parameter report) and PUS (3, 26) (diagnostic parameter report), as well as the PUS (1, 1) and PUS (1, 7) packets corresponding to two telecommands (which are probably related to the settings of the telemetry that is being transmitted in this APID).

There are a large number of SIDs active in PUS (3, 25). Unlike in the case of JUICE, in which SIDs were 4 bytes long, in Euclid they are 2 bytes long. The Jupyter notebook contains plots of all of them. In PUS (3, 26) only SID 0x003d is active. A raster map of the contents of this SID is shown here.

APID 555

APID 555 contains the PUS (1, 1) and PUS (1, 7) packets for 120 telecommands, plus 4 packets from PUS (11, 19), which are command schedule status reports. These can be parsed according to the format described in the standard.

PUS (11, 19) format (taken from ECSS-E-70-41A)

At the beginning of the packet data there is a byte with the value 1 which does not appear in this table. Then the 2-byte N1 field follows. Subschedule IDs and N2 are likewise 2 bytes. APIDs are also 2 bytes long. The status fields are 1 byte long.

The 4 schedule status report packets seem to come in pairs. The first of each pair lists sub-schedules 1 through 6, and the second one lists sub-schedules 7 through 10. The difference between the first two packets and the last two packets is that in the first two all the sub-schedules are enabled, while in the last two sub-schedule 8 becomes disabled. Within each sub-schedule, all the APIDs are enabled. The full contents of each schedule are in the Jupyter notebook.

APID 556

APID 556 contains a PUS (5, 1) packet (normal/progress report), and the PUS (1, 1) and PUS (1, 7) packets for a single telecommand. The report packet is rather short, and since there are no other reports to compare it with, it is not easy to tell what its contents mean, or even how long is the RID (report ID). The report is sent before the telecommand is received, so the telecommand does not cause the transmission of the report.

APID 769

APID 769 contains 32 PUS (5, 1) normal/progress report packets. The RIDs are 2 bytes long, and alternate between 0x025e and 0x025f. The reports are short, and mostly filled with zeros, except for one nibble which changes between 0x1 and 0x2.

APID 771

APID 771 contains PUS (3, 25) (housekeeping parameter report) packets from 10 different SIDs between 0x0002 and 0x000d. The packets from SIDs 0x000c and 0x000d only contain zeros. The Jupyter notebook contains raster map plots of each SID.

APID 1312

APID 1312 contains PUS (3, 25) packets from SID 0x0001. Here is a raster map of the contents of these packets.

Virtual channel 4

Virtual channel 4 contains Space Packets from APID 15 only. These packets do not use PUS. The packets have a fixed length. This is a raster map of these packets.

Virtual channel 7

Virtual channel 7 is the Only Idle Data virtual channel. As in the case of Juice, the contents of the frames are filled with a PN9 sequence that obeys the same description as in BepiColombo. An important remark that I have never made while speaking about this sequence is that since the contents of each frame depend only on its virtual channel frame count, the sequence can be recomputed on ground and used to measure the bit error rate. This would be harder to do with a sequence that does not reset when the virtual channel frame count wraps around to zero.


The CLCWs (Communications Link Control Words) alternate reporting between (telecommand) virtual channel 1 and 2. Frames with even master channel frame count contains CLCWs that report for virtual channel 1. This was also the case with JUICE.

In the no RF available and no bit lock fields we can see the groundstation handover.

The plot of the values of the report field shows that throughout all the recording many telecommands have been received in virtual channel 1. The large telecommand burst around 08:15 UTC is apparent. I already commented about it in the previous post.

Only one telecommand has been received in virtual channel 2. To see this, we need to plot the report for virtual channel 2 only, since otherwise the increase in the value is not visible due to the vertical scale.

The FARM-B counters stay with constant values throughout all the recording. This means that no expedited telecommand frames are received.

Code and data

The decoded frames can be found in this repository. The analysis has been done in this Jupyter notebook.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.