lidar_scan.h

LidarScan

class LidarScan

Data structure for efficient operations on aggregated lidar data.

Stores each field (range, intensity, etc.) contiguously as a H x W block of 4-byte unsigned integers, where H is the number of beams and W is the horizontal resolution (e.g. 512, 1024, 2048).

Note: this is the “staggered” representation where each column corresponds to a single measurement in time. Use the destagger() function to create an image where columns correspond to a single azimuth angle.

Public Types

template<typename T>
using Header = Eigen::Array<T, Eigen::Dynamic, 1>

Header typedef.

using Points = Eigen::Array<double, Eigen::Dynamic, 3>

XYZ coordinates with dimensions arranged contiguously in columns.

Public Functions

LidarScan()

The default constructor creates an invalid 0 x 0 scan.

LidarScan(size_t w, size_t h)

Initialize a scan with fields configured for the LEGACY udp profile.

Note, the number of columns per packet is set to the default (DEFAULT_COLUMNS_PER_PACKET).

Parameters:
  • w[in] horizontal resolution, i.e. the number of measurements per scan.

  • h[in] vertical resolution, i.e. the number of channels.

LidarScan(size_t w, size_t h, sensor::UDPProfileLidar profile, size_t columns_per_packet = DEFAULT_COLUMNS_PER_PACKET)

Initialize a scan with the default fields for a particular udp profile.

Parameters:
  • w[in] horizontal resolution, i.e. the number of measurements per scan.

  • h[in] vertical resolution, i.e. the number of channels.

  • profile[in] udp profile.

  • columns_per_packet[in] The number of columns per packet, this argument is optional.

template<typename Iterator>
inline LidarScan(size_t w, size_t h, Iterator begin, Iterator end, size_t columns_per_packet = DEFAULT_COLUMNS_PER_PACKET)

Initialize a scan with a custom set of fields.

Template Parameters:

Iterator – A standard template iterator for the custom fields.

Parameters:
  • w[in] horizontal resoulution, i.e. the number of measurements per scan.

  • h[in] vertical resolution, i.e. the number of channels.

  • begin[in] begin iterator of pairs of channel fields and types.

  • end[in] end iterator of pairs of channel fields and types.

  • columns_per_packet[in] The number of columns per packet, this argument is optional.

LidarScan(const LidarScan &other)

Initialize a lidar scan from another lidar scan.

Parameters:

other[in] The other lidar scan to initialize from.

LidarScan(const LidarScan &other, const LidarScanFieldTypes &fields)

Initialize a lidar scan from another with only the indicated fields. Casts, zero pads or removes fields from the original scan if necessary.

Throws:

std::invalid_argument – if field dimensions are incompatible

Parameters:
  • other[in] The other lidar scan to initialize from.

  • fields[in] Fields to have in new lidar scan.

LidarScan(LidarScan &&other)

Initialize a lidar scan from another lidar scan.

Parameters:

other[in] The other lidar scan to initialize from.

LidarScan &operator=(const LidarScan &other)

Copy.

Parameters:

other[in] The lidar scan to copy from.

LidarScan &operator=(LidarScan &&other)

Copy via Move semantic.

Parameters:

other[in] The lidar scan to copy from.

~LidarScan()

Lidar scan destructor.

sensor::ShotLimitingStatus shot_limiting() const

Get frame shot limiting status

sensor::ThermalShutdownStatus thermal_shutdown() const

Get frame thermal shutdown status

template<typename T>
Eigen::Ref<img_t<T>> field(const std::string &f)

Access a lidar data field.

Throws:

std::invalid_argument – if T does not match the runtime field type.

Template Parameters:

T – The type parameter T must match the dynamic type of the field. See the constructor documentation for expected field types or query dynamically for generic operations.

Parameters:

f[in] the field to view.

Returns:

a view of the field data.

template<typename T>
Eigen::Ref<const img_t<T>> field(const std::string &f) const

Access a lidar data field.

Throws:

std::invalid_argument – if T does not match the runtime field type.

Template Parameters:

T – The type parameter T must match the dynamic type of the field. See the constructor documentation for expected field types or query dynamically for generic operations.

Parameters:

f[in] the field to view.

Returns:

a view of the field data.

Field &field(const std::string &name)

Access a lidar data field.

Parameters:

name[in] string key of the field to access

Returns:

Field reference of the requested field

const Field &field(const std::string &name) const

Access a lidar data field.

Parameters:

name[in] string key of the field to access

Returns:

Field reference of the requested field

bool has_field(const std::string &name) const

Check if a field exists

Parameters:

name[in] string key of the field to check

Returns:

true if the lidar scan has the field, else false

Field &add_field(const std::string &name, FieldDescriptor d, FieldClass field_class = FieldClass::PIXEL_FIELD)

Add a new zero-filled field to lidar scan.

Throws:

std::invalid_argument – if key duplicates a preexisting field, or if flags dimensional requirements are not met

Parameters:
  • name[in] string key of the field to add

  • d[in] descriptor of the field to add

  • field_class[in] class to be assigned to the field, e.g. PIXEL_FIELD

Returns:

field

Field &add_field(const FieldType &type)

Add a new zero-filled field to lidar scan.

Throws:

std::invalid_argument – if key duplicates a preexisting field

Parameters:

type[in] descriptor of the field to add

Returns:

field

Field del_field(const std::string &name)

Release the field and remove it from lidar scan

Throws:

std::invalid_argument – if field under key does not exist

Parameters:

name[in] string key of the field to remove

FieldType field_type(const std::string &name) const

Get the type of the specified field.

Parameters:

name[in] the string key of the field to query.

Returns:

the type associated with the field.

LidarScanFieldTypes field_types() const

Get the FieldType of all fields in the scan

Returns:

the type associated with every field in the scan

std::unordered_map<std::string, Field> &fields()

Reference to the internal fields map

const std::unordered_map<std::string, Field> &fields() const

Reference to the internal fields map

Eigen::Ref<Header<uint64_t>> timestamp()

Access the measurement timestamp headers.

Returns:

a view of timestamp as a w-element vector.

Eigen::Ref<const Header<uint64_t>> timestamp() const

Access the measurement timestamp headers.

Returns:

a view of timestamp as a w-element vector.

Eigen::Ref<Header<uint64_t>> packet_timestamp()

Access the packet timestamp headers (usually host time).

Returns:

a view of timestamp as a w-element vector.

Eigen::Ref<const Header<uint64_t>> packet_timestamp() const

Access the host timestamp headers (usually host time).

Returns:

a view of timestamp as a w-element vector.

uint64_t get_first_valid_packet_timestamp() const

Return the first valid packet timestamp

Returns:

the first valid packet timestamp, 0 if none available

Eigen::Ref<Header<uint16_t>> measurement_id()

Access the measurement id headers.

Returns:

a view of measurement ids as a w-element vector.

Eigen::Ref<const Header<uint16_t>> measurement_id() const

Access the measurement id headers.

Returns:

a view of measurement ids as a w-element vector.

Eigen::Ref<Header<uint32_t>> status()

Access the measurement status headers.

Returns:

a view of measurement statuses as a w-element vector.

Eigen::Ref<const Header<uint32_t>> status() const

Access the measurement status headers.

Returns:

a view of measurement statuses as a w-element vector.

Field &pose()

Access the array of poses (per each timestamp). Cast to ArrayView3<double> in order to access as 3d

Returns:

3d field of homogenous pose matrices, shaped (w, 4, 4).

const Field &pose() const

Access the array of poses (per each timestamp). Cast to ArrayView3<double> in order to access as 3d

Returns:

3d field of homogenous pose matrices, shaped (w, 4, 4).

bool complete(sensor::ColumnWindow window) const

Assess completeness of scan.

Parameters:

window[in] The column window to use for validity assessment

Returns:

whether all columns within given column window were valid

Public Members

size_t w = {0}

Pointer offsets to deal with strides.

Warning

Members variables: use with caution, some of these will become private.

size_t h = {0}

Pointer offsets to deal with strides.

Warning

Members variables: use with caution, some of these will become private.

size_t columns_per_packet_ = {DEFAULT_COLUMNS_PER_PACKET}

Number of columns contained in each packet making up the scan.

uint64_t frame_status = {0}

Frame status - information from the packet header which corresponds to a frame

Warning

Member variables: use with caution, some of these will become private.

int64_t frame_id = {-1}

The current frame ID.

Warning

Members variables: use with caution, some of these will become private.

Friends

friend bool operator==(const LidarScan &a, const LidarScan &b)

Equality for scans.

Parameters:
  • a[in] The first scan to compare.

  • b[in] The second scan to compare.

Returns:

if a == b.

LidarScan::Points cartesian(const LidarScan &scan, const XYZLut &lut)

Convert LidarScan to Cartesian points.

Parameters:
  • scan[in] a LidarScan.

  • lut[in] lookup tables generated by make_xyz_lut.

Returns:

Cartesian points where ith row is a 3D point which corresponds to ith pixel in LidarScan where i = row * w + col.

LidarScan::Points cartesian(const Eigen::Ref<const img_t<uint32_t>> &range, const XYZLut &lut)

Convert a staggered range image to Cartesian points.

Parameters:
  • range[in] a range image in the same format as the RANGE field of a LidarScan.

  • lut[in] lookup tables generated by make_xyz_lut.

Returns:

Cartesian points where ith row is a 3D point which corresponds to ith pixel in LidarScan where i = row * w + col.

bool operator==(const LidarScan &a, const LidarScan &b)

Equality for scans.

Parameters:
  • a[in] The first scan to compare.

  • b[in] The second scan to compare.

Returns:

if a == b.

inline bool operator!=(const LidarScan &a, const LidarScan &b)

NOT Equality for scans.

Parameters:
  • a[in] The first scan to compare.

  • b[in] The second scan to compare.

Returns:

if a != b.

Destagger

template<typename T>
inline img_t<T> destagger(const Eigen::Ref<const img_t<T>> &img, const std::vector<int> &pixel_shift_by_row, bool inverse)

Generate a destaggered version of a channel field.

In the default staggered representation, each column corresponds to a single timestamp. In the destaggered representation, each column corresponds to a single azimuth angle, compensating for the azimuth offset of each beam.

Destaggering is used for visualizing lidar data as an image or for algorithms that exploit the structure of the lidar data, such as beam_uniformity in ouster_viz, or computer vision algorithms.

Template Parameters:

T – the datatype of the channel field.

Parameters:
  • img[in] the channel field.

  • pixel_shift_by_row[in] offsets, usually queried from the sensor.

  • inverse[in] perform the inverse operation.

Returns:

destaggered version of the image.

template<typename T>
inline img_t<T> stagger(const Eigen::Ref<const img_t<T>> &img, const std::vector<int> &pixel_shift_by_row)

Generate a staggered version of a channel field.

Template Parameters:

T – the datatype of the channel field.

Parameters:
  • img[in] the channel field.

  • pixel_shift_by_row[in] offsets, usually queried from the sensor.

Returns:

staggered version of the image.

XYZLut

struct XYZLut

Lookup table of beam directions and offsets.

Public Members

LidarScan::Points direction

Lookup table of beam directions.

LidarScan::Points offset

Lookup table of beam offsets.

XYZLut ouster::make_xyz_lut(size_t w, size_t h, double range_unit, const mat4d &beam_to_lidar_transform, const mat4d &transform, const std::vector<double> &azimuth_angles_deg, const std::vector<double> &altitude_angles_deg)

Generate a set of lookup tables useful for computing Cartesian coordinates from ranges.

The lookup tables are:

  • direction: a matrix of unit vectors pointing radially outwards.

  • offset: a matrix of offsets dependent on beam origin distance from lidar origin.

Each table is an n x 3 array of doubles stored in column-major order where each row corresponds to the nth point in a lidar scan, with 0 <= n < h*w.

Projections to XYZ made with this XYZLut will be in the coordinate frame defined by transform*beam_to_lidar_transform.

Parameters:
  • w[in] number of columns in the lidar scan. e.g. 512, 1024, or 2048.

  • h[in] number of rows in the lidar scan.

  • range_unit[in] the unit, in meters, of the range, e.g. sensor::range_unit.

  • beam_to_lidar_transform[in] transform between beams and lidar origin. Translation portion is in millimeters.

  • transform[in] additional transformation to apply to resulting points.

  • azimuth_angles_deg[in] azimuth offsets in degrees for each of h beams.

  • altitude_angles_deg[in] altitude in degrees for each of h beams.

Returns:

xyz direction and offset vectors for each point in the lidar scan.

inline XYZLut ouster::make_xyz_lut(const sensor::sensor_info &sensor)

Convenient overload that uses parameters from the supplied sensor_info. Projections to XYZ made with this XYZLut will be in the sensor coordinate frame defined in the sensor documentation.

Parameters:

sensor[in] metadata returned from the client.

Returns:

xyz direction and offset vectors for each point in the lidar scan.

ScanBatcher

class ScanBatcher

Parse lidar packets into a LidarScan.

Make a function that batches a single scan (revolution) of data to a LidarScan.

Public Functions

ScanBatcher(size_t w, const sensor::packet_format &pf)

Create a batcher given information about the scan and packet format.

Parameters:
  • w[in] number of columns in the lidar scan. One of 512, 1024, or 2048.

  • pf[in] expected format of the incoming packets used for parsing.

ScanBatcher(const sensor::sensor_info &info)

Create a batcher given information about the scan and packet format.

Parameters:

info[in] sensor metadata returned from the client.

bool operator()(const uint8_t *packet_buf, LidarScan &ls)

Add a packet to the scan.

Deprecated:

this method is deprecated in favor of one that accepts a reference to a LidarPacket.

Parameters:
  • packet_buf[in] a buffer containing raw bytes from a lidar packet.

  • ls[in] lidar scan to populate.

Returns:

true when the provided lidar scan is ready to use.

bool operator()(const ouster::sensor::LidarPacket &packet, LidarScan &ls)

Add a packet to the scan.

Parameters:
  • packet[in] a LidarPacket.

  • ls[in] lidar scan to populate.

Returns:

true when the provided lidar scan is ready to use.

bool operator()(const uint8_t *packet_buf, uint64_t packet_ts, LidarScan &ls)

Add a packet to the scan.

Parameters:
  • packet_buf[in] a buffer containing raw bytes from a lidar packet.

  • packet_ts[in] timestamp of the packet (usually HOST time on receive).

  • ls[in] lidar scan to populate.

Returns:

true when the provided lidar scan is ready to use.

Public Members

sensor::packet_format pf

The packet format object used for decoding.