Cepton
Cepton

Cepton Sensor Communication Specifications

1. Revision History

Current version:

Version Date Changes
0.9.1 01/19/2024 Update INFO and PANIC packet format
0.9 07/19/2023 Define frame aggregation behavior
0.8.3 08/27/2022 Define blooming and blocked bits
0.8.2 03/02/2022 Functional safety clarifications
0.8.1 01/27/2022 Add noise bit in point flag
0.8 01/11/2022 Clarify SDK reserved bits
0.7.1 01/10/2022 Draft document, add v2 point header
0.7 08/21/2021 Draft document, add v1 point data
0.6 07/14/2021 Draft document, not finalized

2. Overview

This document outlines the data communication protocol for Vista-X and Nova series of lidars produced by Cepton.

There are three general type of communications supported by Cepton's lidar sensors:

  1. Data being sent out by sensor on a regular basis:
    • Point Data: UDP packet.
    • INFO data: UDP packet sent out twice per second.
  2. Data being sent out by sensor under specific conditions:
    • Fault data: UDP packet sent out when a fault occurs.
    • ARP lookup: If configured with destination IP but no destination MAC, sensor will send ARP query to resolve destination MAC address.
  3. Other protocols sensor supports:
    • ARP query: sensor will respond to ARP query to report its own MAC address to the local network.
    • PTP 802.1AS: Sensor supports Level 2 PTP protocol, aka gPTP.
    • PTP over UDP: Sensor supports PTP over UDP as defined in IEEE1588-2008
    • Configuration: UDP packet containing configuration request (this is not covered by this document)

3. Point Data Packet

Point data is accumulated as the lidar measurements happen. Once a full packet is filled the data will be sent out.

  • Protocol: UDP packet on IPv4
  • Destination IP: 255.255.255.255 (Configurable)
  • Destination port: 8808 (Configurable)

Point data is a stream of measurements following strict order:

  • All data follow the firing sequence.
  • In the case of two lasers fired at the same time, the point data sequence between the two are predetermined. E.g. in Vista-X90 sensors channel 0 and channel 37 fires together, the point data will always be channel 0 first then channel 37, even if the laser return of 37 comes back first. The second laser that is fired at the same time always has relative timestamp value of 0.
  • A no-return condition happens when laser shot out doesn't hit a valid target. No return points are not present in the point stream. (Note: This can be changed if desirable )
  • A maximum time lapse value is defined based on minimum allowed data rate (20ms ). When time approaches maximum time lapse and the point data buffer is still not filled, the shorter packet will be sent out.
  • When double return is enabled, the second return will only be present in the point data stream if it is valid. When present, it will be placed right after the first return and before any other laser channels. The SecondReturn flag will be set and relative timestamp is always 0.
  • For double returns, first return is always the strongest. If the farthest return is not also the strongest, it will be the second return. Otherwise the second return will be second strongest signal.

3.1. Point Data Packet Structure

In the payload of the UDP packet, after the 20 bytes header, each point is contiguously placed based on the point size. In V0 of point data, there are up to 143 points of 10 bytes each. In V1, there are up to 120 points of 12 bytes each.

Offset Block Size Description
0 Header 20/24 Point Data Packet Header
20 Point0 Point #0
Point1 Point #1
... ... ... ...
PointN Point #N
Offset Field Size Value Description
0 Signature 4 STDV 4 byte signature to identify packet type
4 Header Version 1 1/2 Header type
5 Header Size 1 Header size
6 Flags 2 0 Flags
8 Timestamp 8 Reference timestamp
16 Point Version 1 0/1 Point structure type
17 PointSize 1 Point structure size
18 PointCount 2 144/120* Number of points in this packet
20 Sequence ID 4 Version 2+: Sequencing ID for packet stream

(*When there aren't enough points to fill all 144 or 120 possible points in the UDP Packet, this number can be smaller, and the remaining space is filled with empty points (all values equal to 0). )

Corresponding C structure:

struct CeptonPointDataHeader {
  uint32_t signature;
  uint8_t header_version;
  uint8_t header_size;
  uint16_t flags;
  uint64_t timestamp_usec;
  uint8_t point_version;
  uint8_t point_size;
  uint16_t point_count;
  uint32_t sequence_id;
};

Reference timestamp holds the reference time for the first point. This is the number of microseconds (us) since the sensor boot up time. To convert this timestamp to universal time, please reference INFO packet description.

Flags: There is no packet level flags defined. This byte has to be 0 at all time.

3.2. Point Data Structure

Offset Field Size Unit Range Description
0 X 2 0.5cm -163.840m to 163.835m X coordinate
2 Y 2 0.5cm 0 to 327.68m Y coordinate
4 Z 2 0.5cm -163.840m to 163.835m Z coordinate
6 Reflectivity 1 % 0 to 255 Reflectivity
7 Timestamp 1 us 0 to 255 Time difference from the point before
8 Channel 1 0 to 63 Channel ID
9 Flags 1 Flags
10+ Internal When PointSize > 10, these are internal data

Corresponding C structure:

struct CeptonPointData {
  int16_t x;
  uint16_t y;
  int16_t z;
  uint8_t reflectivity;
  uint8_t relative_timestamp;
  uint8_t channel_id;
  uint8_t flags;
};

Coordinates: Looking from the sensor bore-sight,

  • X represents left to right (negative to positive)
  • Y represents near to far (0 and up)
  • Z represents bottom to top (negative to positive)

Coordinates X and Z are signed short, while Y is unsigned. The reference point (0,0,0) is located at the geometric center of the sensor, which is at the mid-point of all 3 primary dimensions of the sensor enclosure.

Reflectivity: 0-100% reflectivity are measured by assuming Lambertian reflection model. Non-Lambertian materials, such as retro-reflective surfaces commonly found in road signs and warning cones, can produce higher than 100% reflectivity. For reflectivity less than 127%, intensity is equal to reflectivity. For reflectivity greater than or equal to 127%, we convert to intensity exponentially using quantize_table[reflectivity-127]:

private static float[] quantize_table = {
  127.0f,  130.7f,  134.5f,  138.4f,  142.4f,  146.6f,  150.9f,  155.3f,
  159.8f,  164.4f,  169.2f,  174.1f,  179.2f,  184.4f,  189.8f,  195.3f,
  201.0f,  206.9f,  212.9f,  219.1f,  225.4f,  232.0f,  238.8f,  245.7f,
  252.9f,  260.2f,  267.8f,  275.6f,  283.6f,  291.9f,  300.4f,  309.1f,
  318.1f,  327.4f,  336.9f,  346.7f,  356.8f,  367.2f,  377.9f,  388.9f,
  400.2f,  411.9f,  423.9f,  436.2f,  448.9f,  462.0f,  475.4f,  489.2f,
  503.5f,  518.1f,  533.2f,  548.8f,  564.7f,  581.2f,  598.1f,  615.5f,
  633.4f,  651.9f,  670.8f,  690.4f,  710.5f,  731.1f,  752.4f,  774.3f,
  796.9f,  820.1f,  843.9f,  868.5f,  893.8f,  919.8f,  946.6f,  974.1f,
  1002.5f, 1031.7f, 1061.7f, 1092.6f, 1124.4f, 1157.2f, 1190.9f, 1225.5f,
  1261.2f, 1297.9f, 1335.7f, 1374.6f, 1414.6f, 1455.8f, 1498.2f, 1541.8f,
  1586.6f, 1632.8f, 1680.4f, 1729.3f, 1779.6f, 1831.4f, 1884.8f, 1939.6f,
  1996.1f, 2054.2f, 2114.0f, 2175.5f, 2238.9f, 2304.0f, 2371.1f, 2440.1f,
  2511.2f, 2584.3f, 2659.5f, 2736.9f, 2816.6f, 2898.6f, 2983.0f, 3069.8f,
  3159.2f, 3251.1f, 3345.8f, 3443.2f, 3543.4f, 3646.6f, 3752.7f, 3862.0f,
  3974.4f, 4090.1f, 4209.2f, 4331.7f, 4457.8f, 4587.6f, 4721.1f, 4858.6f,
  5000.0f};

Timestamp: This value is the relative value from the time since last point in the packet. For the very first point, it is time since the packet header's reference time. Notice that 0 value is possible for dual firing mode or dual return's second return. The timestamp represents the time of firing, for the time accuracy afforded (> 1us, ~300m traveled), it is OK to use directly as target point time (time when target is hit by laser).

Channel ID: Reports the channel ID, which usually indicate a distinct laser->APD pathway. Each channel correspond to a unique set of laser/APD pair.

Flags: per-point flags are defined in the table below

Bit Value Name Description
0 1 Saturated Set if the point is saturated
1 2 Reserved Reserved for SDK use
2 4 FrameParity Frame parity bit
3 8 Reserved* Reserved for SDK use
4 16 SecondReturn Set for second return
5 32 NoReturn Set if this point has no return
6 64 Noise Set if this point is a noise
7 128 Blocked Set if this point is blocked

(*The reserved bit#3 is defined in SDK as frame boundary. This is a software flag created by SDK and is not part of the communication protocol. Refer to Cepton SDK documentation for details)

Corresponding flags and enumerations

enum {
  CEPTON_POINT_SATURATED = 1 << 0,
  CEPTON_POINT_FRAME_PARITY = 1 << 2,
  CEPTON_POINT_SECOND_RETURN = 1 << 4,
  CEPTON_POINT_NO_RETURN = 1 << 5,
  CEPTON_POINT_NOISE = 1 << 6,
  CEPTON_POINT_BLOCKED = 1 << 7,
};

Saturated flag: Set if the signal received is too strong to be correctly measured. This usually happen when measuring retro-reflective targets. When this flag is set, the reflectivity is not trust worthy, and the distance accuracy is slightly reduced.

There are also some unspecified conditions that can be derived from the data stream itself:

FrameParity: Cleared for even frames and set for odd frames. This ensures the frame boundary as identified by the sensor is always communicated even when one of the data packet is lost.

Dual return case: If two consecutive points have same ChannelID and second point has Timestamp set to 0. The second point is the second return of the same laser firing. Second return signifies that the fired laser was somehow split up (e.g. hitting a corner of a near wall, then hitting a wall farther down). In this case, the strongest is always the first and farthest return can be determined by comparing Y value.

Blocked points: Some Cepton lidar products can detect blockage and report them. When blockage happens, there might still be a valid return. The distance of the return can be trusted but the reflectivity should be considered incorrect.

3.3. Point Data Configuration

Point data packets can be turned off completely.

For sensors that support turning on or off the second return feature, point data structure will not change. The second return, when present, will just be a repeat of the same laser channel, with time offset 0 and SecondReturn flag set.

4. INFO Packet

Offset Block Size Description
0 Header 76 / 96 INFO packet header
76 / 96 Diagnosis Signals Variable Sensor specific diagnosis data

4.1. INFO Packet Header Structure

INFO packet header is universal data for all Cepton sensors

Offset Field Size Value Description
0 Signature 4 INFZ 4 byte signature to identify packet type
4 HeaderMagic 4 4 bytes for future compatibility
8 Model 4 Model number
12 SerialNumber 4 Sensor serial number
16 FirmwareVersion 4 Firmware version number
20 ModelName 28 UTF-8 string for model name
48 PartNumber 4 Part Number

For V0 info block: HeaderMagic has value of 0x004C, the total header size is 76 bytes, with the second half look like this:

Offset Field Size Value Description
52 PowerUpTime 8 Microseconds since power up
60 TimeSyncOffset 8 Power up epoch time in microseconds
68 TimeRateCorrection 4 Clock drift correction
72 TimeSyncStatus 1 Time synchronization details
73 3 Reserved for future use

Corresponding c structure:

struct CeptonInfoHeader_V0 {
  uint32_t signature;
  uint32_t header_magic;
  uint32_t model;
  uint32_t serial_number;
  uint32_t firmware_version;
  char model_name[28];
  uint32_t part_number;

  uint64_t power_up_time;
  uint64_t time_sync_offset;
  uint32_t time_rate_correction;
  uint8_t time_sync_status;
  uint8_t reserved[3];
};

For V1 info block: HeaderMagic has value of 0x0860, the total header size is 96 bytes, with the second half look like this:

Offset Field Size Value Description
52 FirmwareVersionAPM 4 Internal APM firmware version
56 FirmwareVersionIOX 4 Internal IOX firmware version
60 FirmwareVersionIguana 4 Internal Iguana firmware version
64 PowerUpTime 8 Microseconds since power up
72 TimeSyncOffset 8 PTP master time offset in microseconds
80 TimeRateCorrection 4 Clock drift correction
84 TimeSyncStatus 1 Time synchronization status
85 ReturnMode 1 Duel return mode enum
86 ThermalDerateState 1 Thermal derating enum
87 reserved 1
88 Temperature 2 Sensor temperature
90 ChannelCount 2 Channel count number
92 FaultSummary 4 Fault cases summarization

Corresponding c structure:

struct CeptonInfoHeader_V1 {
  uint32_t signature;
  uint32_t serial_number;
  uint32_t firmware_version;
  uint16_t model;
  uint16_t model_reserved;
  char model_name[28];
  uint32_t part_number;

  uint32_t firmware_version_apm;
  uint32_t firmware_version_iox;
  uint32_t firmware_version_iguana;
  uint64_t power_up_time;
  uint64_t time_sync_offset;
  uint8_t padding[4];
  uint8_t time_sync_status;
  uint8_t return_mode;
  uint8_t thermal_derate_state;
  uint8_t reserved;
  uint16_t temperature;
  uint16_t channel_count;
  uint32_t fault_summary;
};

5. Frame Aggregation Logic

SDK provides a few methods to aggregate points such that the point cloud creates a frame. Two types of aggregation are available:

5.1 Natural Frame Aggretation

The lidar has a built-in notion of when a frame starts and ends. This is signified by the parity on points (shown in the CEPTON_POINT_FRAME_PARITY bit from the point flag). When the parity changes, the frame aggregator would then note to finish off the frame and start a new one. Frame aggregation utilizes this mode as the default.

When point packets are dropped, this mode will robustly still detect a frame change. In the unlikely event that a whole frame of the opposite parity is dropped, the aggregator will produce two frames of the same parity with variable results on what the frame looks like visually, but then resume normal operation.

5.2 Fixed Frame Aggregation

Users of the SDK can specify the period of time a frame should last before switching to a new frame by specifying it in microseconds (minimum 1000). This should be passed when listening to frames via the CeptonListenFrames function call.

At a given start timestamp, the internal frame aggregator would increment its time by adding on each point's relative timestamp value. When the starting timestamp reaches the fixed frame duration (or reach an internal buffer limit), it then takes the most recent point cloud packet's start time, adds on the aggregate time elapsed from the points taken in the packet, and restarts the time and frame aggregation from that point.

Note that based on this implementation, if any point packets get lost, the next incoming points will assume a timestamp earlier compared to its presumed ground truth timestamp until the current frame finishes. When the frame is complete, then the next frame will adjust accordingly to the current timestamp again.

6. Functional Safety Considerations

There are several built-in mechanisms to ensure the data sanity of the point cloud stream coming out of the lidar:

  1. Both the ethernet MAC layer and UDP header has checksum that is populated and enforced. This guarantees there is no bit flip in the data arriving at the host PC.
  2. Starting in header version 2, we have introduced a "sequence id" which can be used to detect any missing UDP packet.
  3. Starting in header version 2, when the sequence IDs are contiguous, the timestamp starting point in header will match exactly the timestamp of last measurement in the previous point data packet. This ensures no gap in measurement occurs.

In addition, when any faults happen inside the sensor, the sensor will send out a "panic message" to inform the host as soon as possible.

Panic packet format:

Offset Field Size Description
0 Header 16 PANIC packet header
16 Active Fault 24 Active fault detailed information

Panic packet header format:

Offset Field Size Value Description
0 Magic 8 !PANIC!! 8 bytes header magic signature
8 Serial Number 4 Sensor serial number
12 Sequence Id 2 Continuous increasing sequence id
14 Reserved 2 Reserve for future use

Panic packet active fault format:

Offset Field Size Value Description
0 Fault Identity 4 4 bytes field for unique fault case identification
8 Life Counter Timestamp 4 Sensor life age counter timestamp
12 PTP Timestamp 8 PTP timestamp
14 Reserved 8 Reserve for future use

packet structure:

struct panic_packet {
  uint64_t magic;
  uint32_t serial_number;
  uint16_t sequence_id;
  uint16_t reserved;
  struct {
    uint32_t fault_identity;
    uint32_t life_counter;
    uint64_t ptp_timestamp;
    uint64_t reserved;
  } active_fault;
};