Coordinate System

Open in Claude

Coordinate Frames and XYZ Calculation

Ouster uses two coordinate frames:

The Lidar Coordinate Frame follows the Right Hand Rule convention and is a point cloud-centric frame of reference that is the simplest frame in which to calculate and manipulate point clouds. The X-axis points backwards towards the external connector, which is an unintuitive orientation that was deliberately chosen to meet the following criteria:

  • Data frames split at the back of the sensor i.e. the external connector

  • Data frames start with the azimuth angle equal to 0°

All point cloud features including setting an azimuth window and phase locking are defined in the Lidar Coordinate Frame.

The Sensor Coordinate Frame follows the Right Hand Rule convention and is a mechanical housing-centric frame of reference that follows robotics convention with X-axis pointing forward. Ouster-provided drivers and visualizers represent data in the Sensor Coordinate Frame.

Note: All Ouster coordinate frames follow the Right Hand Rule, allowing for standard 3D transformation matrix math to convert between them. For multi-sensor systems that require calibration, this Linear Algebra-based approach can be convenient. However, customers with single-sensor systems may find it more intuitive to stay in the Lidar Coordinate Frame and take arithmetic shortcuts.

Lidar Coordinate Frame

The Lidar Coordinate Frame is defined at the intersection of the lidar axis of rotation and the lidar optical midplane (a plane parallel to Sensor Coordinate Frame XY plane and coincident with the 0° elevation beam angle of the sensor).

The Lidar Coordinate Frame axes are arranged with:

  • positive X-axis pointed at encoder angle 0° and the external connector
  • positive Y-axis pointed towards encoder angle 90°
  • positive Z-axis pointed towards the top of the sensor

The Lidar Coordinate Frame is marked in both diagrams below with X_L, Y_L, and Z_L.

Lidar coordinate frame top-down view

Lidar Range to XYZ

Given the following information, range data may be transformed into 3D cartesian XYZ coordinates in the Lidar Coordinate Frame:

From a measurement block from the UDP packet:

  • Measurement ID value can be found on the lidar data packet
  • scan_width value of the horizontal resolution
  • r or range_mm value of the data block of the i-th channel
  • r' or range_to_beam_origin_mm

From the beam-intrinsics HTTP Command:

  • beam_to_lidar_transform value
  • beam_altitude_angles array
  • beam_azimuth_angles array

The corresponding 3D point can be computed by

r=range_mmn=(beam_to_lidar[0,3])2+(beam_to_lidar[2,3])2r=r+nθencoder=2π(1measurementIDscan_width)θazimuth=2πbeam_azimuth_angles[i]360ϕ=2πbeam_altitude_angles[i]360x=(rn)cos(θencoder+θazimuth)cos(ϕ)+beam_to_lidar[0,3]cos(θencoder)y=(rn)sin(θencoder+θazimuth)cos(ϕ)+beam_to_lidar[0,3]sin(θencoder)z=(rn)sin(ϕ)+beam_to_lidar[2,3]\begin{align} r &= \texttt{range\_mm} \\ |\vec{n}| &= \sqrt{(beam\_to\_lidar[0,3])^2 + (beam\_to\_lidar[2,3])^2} \\ r &= |\vec{r'}| + |\vec{n}| \\ \theta_{encoder} &= 2\pi \cdot \left( 1 - \frac{\texttt{measurement\,ID}}{\texttt{scan\_width}}\right) \\ \theta_{azimuth} &= -2\pi \frac{\texttt{beam\_azimuth\_angles[i]}}{360} \\ \phi &= 2\pi \frac{\texttt{beam\_altitude\_angles[i]}}{360} \\[6pt] x &= (r-|\vec{n}|) \cos(\theta_{encoder} + \theta_{azimuth}) \cos(\phi) + beam\_to\_lidar[0,3] \cdot \cos(\theta_{encoder}) \\ y &= (r-|\vec{n}|) \sin(\theta_{encoder} + \theta_{azimuth}) \cos(\phi) + beam\_to\_lidar[0,3] \cdot \sin(\theta_{encoder}) \\ z &= (r-|\vec{n}|) \sin(\phi) + beam\_to\_lidar[2,3] \end{align} Lidar coordinate frame side view

Sensor Coordinate Frame

The Sensor Coordinate Frame is defined at the center of the sensor housing on the bottom, with the X-axis pointed forward, Y-axis pointed to the left and Z-axis pointed towards the top of the sensor. The external connector is located in the negative x direction. The Sensor Coordinate Frame is marked in the diagram below with X_S, Y_S, Z_S.

Sensor coordinate frame top-down view Sensor coordinate frame side view

Combining Lidar and Sensor Coordinate Frame

The Lidar Coordinate Frame’s positive X-axis (0 encoder value) is opposite the Sensor Coordinate Frame’s positive X-axis to center lidar data about the Sensor Coordinate Frame’s positive X-axis. A single measurement frame starts at the Lidar Coordinate Frame’s 0° position and ends at the 360° position. This is convenient when viewing a “range image” of the Ouster Sensor measurements, allowing the “range image” to be centered in the Sensor Coordinate Frame’s positive X-axis, which is generally forward facing in most robotic systems.

The Ouster Sensor scans in the clockwise direction when viewed from the top, which is a negative rotational velocity about the Z-axis. Thus, as encoder ticks increase from 0 to 90,111, the actual angle about the Z-axis in the Lidar Coordinate Frame will decrease.

Lidar Intrinsic Beam Angles

The intrinsic beam angles for each beam may be queried with a HTTP command beam-intrinsics to provide an azimuth and elevation adjustment offset to each beam. The azimuth adjustment is referenced off of the current encoder angle and the elevation adjustment is referenced from the XY plane in the Sensor and Lidar Coordinate Frames. OS1-MAX sensors (256 channels) return beam angle arrays with one entry per channel.

Lidar Range Data To Sensor XYZ Coordinate Frame

Applications that calibrate against a precision mount or fuse IMU and lidar data must transform XYZ points into the Sensor Coordinate Frame. This requires a Z translation (the lidar aperture height above the sensor origin, which varies by model) and a 180° rotation about the Z-axis. Query this transform over HTTP as a homogeneous transformation matrix in row-major order.

Example JSON formatted query using the HTTP command lidar-intrinsics:

1{
2 "lidar_to_sensor_transform": [-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 38.195, 0, 0, 0, 1]
3 }

Which corresponds to the following matrix

M_lidar_to_sensor=[1000010000138.1950001]\texttt{M\_lidar\_to\_sensor} = \begin{bmatrix} -1 & 0 & 0 & 0\\ 0 & -1 & 0 & 0\\ 0 & 0 & 1 & 38.195\\ 0 & 0 & 0 & 1 \end{bmatrix}

IMU Data To Sensor XYZ Coordinate Frame

The IMU is slightly offset within the Sensor Coordinate Frame for mechanical reasons. Query the IMU-to-sensor transform over HTTP as a homogeneous transformation matrix in row-major order.

Example 1- Expected response for HTTP command imu-intrinsics when using Gen1 OS1 (all revisions), Gen2 OS01 (all revisions) and Gen2 OS2 (top-level revisions A, B, C)

1{
2 "imu_to_sensor_transform": [1, 0, 0, 6.253, 0, 1, 0, -11.775, 0, 0, 1, 7.645, 0, 0, 0, 1]
3}

Which corresponds to the following matrix

M_imu_to_sensor=[1006.25301011.7750017.6450001]\texttt{M\_imu\_to\_sensor} = \begin{bmatrix} 1 & 0 & 0 & 6.253\\ 0 & 1 & 0 & -11.775\\ 0 & 0 & 1 & 7.645\\ 0 & 0 & 0 & 1 \end{bmatrix}

Example 2 — Expected response for HTTP command imu-intrinsics when using Gen2 OS2 (top-level revisions D and higher):

1{
2 "imu_to_sensor_transform": [1, 0, 0, 6.253, 0, 1, 0, -11.775, 0, 0, 1, 11.645, 0, 0, 0, 1]
3}

Which corresponds to the following matrix:

M_imu_to_sensor=[1006.25301011.77500111.6450001]\texttt{M\_imu\_to\_sensor} = \begin{bmatrix} 1 & 0 & 0 & 6.253\\ 0 & 1 & 0 & -11.775\\ 0 & 0 & 1 & 11.645\\ 0 & 0 & 0 & 1 \end{bmatrix}

Configurable IMU Scale

The full-scale range (fsr) of the accelerometer and gyroscope is configurable. Toggle each between the default NORMAL and the wider EXTENDED range via the Web UI or by issuing POST /api/v1/sensor/config with accel_fsr and/or gyro_fsr in the body. Query the current value with GET /api/v1/sensor/metadata/imu_data_format. See the API reference for full schemas.

  • accel_fsr — accelerometer scale.

    • NORMAL (default): X/Y/Z fixed at ± 2 g.
    • EXTENDED: X/Y/Z extended to ± 16 g.
  • gyro_fsr — gyroscope scale.

    • NORMAL (default): X/Y/Z fixed at ± 250 dps (°/sec).
    • EXTENDED: X/Y/Z programmable to ± 2000 dps (°/sec).

Note: Switching to EXTENDED updates the values reported in IMU packets accordingly, but can result in a slight loss of precision due to truncation of the least significant bits (LSB). Full IMU specifications are in the Sensor Datasheet.