Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,39 @@
Changelog
=========

[0.16.1]
=========

* [BUGFIX] Add ``--coord-frame`` (``SENSOR|BODY|WORLD``) to ``ouster-cli source ... filter`` for XYZ filtering. ``WORLD`` now applies ``dewarp(points, scan.pose)`` before thresholding, ``BODY`` remains the default for backward compatibility, and ``SENSOR`` uses XYZ without extrinsics.
* [BUGFIX] Fix crash in ``LidarScan.__str__`` when scans contain non-pixel fields (IMU, GNSS, ZONE, or CHAR fields). The ``to_string()`` function now properly handles these field types, with special formatting for CHAR fields to display NMEA sentences.
* [BUGFIX] Avoid divide-by-zero in IMU visualization when IMU magnitudes are zero.
* [BUGFIX] Fix AOI picker showing normalized values for unknown fields in the viz.
* [BREAKING] Renamed ``-F`` flag to ``-f`` in ``ouster-cli source`` command (short for ``--filter`` flag), which drops scans with missing data.
* [BUGFIX] PLY maker minor change (e.g. support for no valid key field, ``--field NONE``).
* [BUGFIX] Use stderr instead of stdout for logging in ouster-cli.
* [BUGFIX] Fix ``filter``, ``clip``, and ``mask`` bugs: correct filter_xyz semantics (points inside bounds zeroed), restrict operations to PIXEL_FIELD only to avoid crashes with IMU/GNSS fields, and use RANGE2 coordinates for second-return fields.
* [BUGFIX] Handle unsupported ChanFieldTypes when reading OSF files: skip unsupported fields with a warning instead of crashing (forward compatibility with newer OSF files).
* Add ``--legacy`` flag for OSF export (PNG compression + drop CHAR/ZONE_STATE for SDK 0.12–0.15 compatibility), separate from ``--png`` (PNG compression only).
* [BUGFIX] Update TUM format in trajectory saving as per official specification.
* [BUGFIX] Fix viz GL buffer cleanup leaks: add missing ``glDeleteBuffers()`` for GLCuboid, GLRings, and GLImage to prevent GPU memory growth on repeated create/destroy.
* [BUGFIX] Fix ValueError in viz when resizing before scans received.
* [BUGFIX] Fix crash when saving a GIF when frame duration is negative (e.g. source has looped); fix viz deadlock when saving image recording.
* [BUGFIX] Fix improper handling of sensors with lidar data disabled.
* [BUGFIX] SLAM crashes when at least one sensor doesn't have imu data in a multi-sensor setup with the Synchronous IMU feature enabled.
* [BUGFIX] SLAM uses un-corrected timestamps when using the the inertial integration deskew method with multi-sensor unsynchronized setups.
* Pose Optimizer: constraint ID counter moved to constraint base class; constraint IDs are now logged when adding/processing constraints, and reassign constraint id when conflict instead of throwing.
* [BUGFIX] Remove the skipping on single scans in SLAM and localize pipelines for multi-sensor datasets.
* [BUGFIX] PNGs from the viz now embed the Display P3 profile so their colors match the viz window.
* Add ``--http-addr`` option to ``sensor_replay`` plugin (e.g. for use with Ouster Detect).
* Update README with community forum and support info.
* Normalize license files for GitHub detection.

Important Notes
---------------

* This will be the last release that supports macOS 11.x, 12.x and 13.x.


[0.16.0]
=========

Expand All @@ -10,7 +43,7 @@ Changelog
* Clear AOI selection in the viz when right click is pressed and there is a preexisting selection.
* Extend AOI selection to show 3 axis fields properly when right click in viz images.
* Add support for low bandwidth dual returns lidar profile (PROFILE_RNG15_RFL8_NIR8_DUAL).
* [BREAKING] renamed ``data_format::packets_per_frame()`` to ``lidar_packets_per_frame()``
* [BREAKING] Renamed ``data_format::packets_per_frame()`` to ``lidar_packets_per_frame()``
* Add support for saving and reading new ZPNG based OSF files which are several times faster and have better compression ratios.
* [BREAKING] Make ZPNG the default format for saved OSF files. This format cannot be opened by older SDK versions.
* [BREAKING] Change ``ouster-cli source <osf> dump`` JSON output to return the OSF version as a semver-style string instead of an integer.
Expand Down Expand Up @@ -85,7 +118,7 @@ Changelog
* Changed all core sdk enums to enum classes and removed the prefixes from enum values. The C++ enums naming is now consistent with the Python enums naming.
- e.g. ``OPERATING_NORMAL`` is now ``OperatingMode::UNSPECIFIED``
- The older enum identiers are still available for use but are deprecated.
* Utilize imu data when compensating for lidar data distortion during motion in SLAM and Localization.
* Utilize imu data when compensating for lidar data distortion during motion in SLAM and Localization.
* Add Zone Monitor:
- Add support for reading and writing Zone Monitor configurations for sensors running firmware 3.2 and above.
- Add zone state data to LidarScans when Zone Monitor is enabled on the sensor.
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)

if(MSVC)
add_compile_options(/W2 /bigobj /Zf)
add_compile_definitions(NOMINMAX _USE_MATH_DEFINES WIN32_LEAN_AND_MEAN)
add_compile_definitions(NOMINMAX _USE_MATH_DEFINES WIN32_LEAN_AND_MEAN _ENABLE_EXTENDED_ALIGNED_STORAGE)
else()
add_compile_options(-Wall -Wextra)
endif()
Expand Down
4 changes: 2 additions & 2 deletions VERSION
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__version__ = '0.16.0'
__cpp_version__ = '0.16.0'
__version__ = '0.16.1'
__cpp_version__ = '0.16.1'
13 changes: 11 additions & 2 deletions docs/cli/filter-sessions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ Where:
- ``--invalid-value``: The value to replace the pixels that match the predicate. Default is zero.
- ``--filtered-fields``: A comma-separated list of fields to apply the filter to. If not specified, the filter will
be applied to all fields of the scan.
- ``--coord-frame``: Coordinate frame for XYZ filtering only. Options are ``SENSOR`` (no extrinsics),
``BODY`` (extrinsics, default), and ``WORLD`` (dewarp with poses).

Example Usage
-------------
Expand All @@ -55,7 +57,7 @@ command predicate, we can highlight points in the low cloud with higher reflecti
:align: center
:width: 800px


2) Filter based on cartesian coordinates:

Another way to filter the point cloud is to use the cartesian coordinates of the points. For example, imagine we want to
Expand All @@ -66,6 +68,13 @@ follows:

ouster-cli source <source_url> filter Z :-1m filter Z 1m: viz

If you need the XYZ filter in a different coordinate frame, use ``--coord-frame``. For example, dewarp
into WORLD coordinates before filtering:

.. code:: bash

ouster-cli source <source_url> filter --coord-frame WORLD Z :-1m viz

After applying this filter the resulting point cloud will look like this:

.. image:: /images/filter-example-z.png
Expand All @@ -92,7 +101,7 @@ resulting point cloud will look like this:
:align: center
:width: 800px

This can be useful to mask out certain columns (``V``) or certain beams (``U``) of the LidarScan.
This can be useful to mask out certain columns (``V``) or certain beams (``U``) of the LidarScan.

.. note::

Expand Down
24 changes: 14 additions & 10 deletions docs/cli/pose-optimizer-sessions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ Optional Config Parameters

The constraint JSON file may also include the following optional parameters to fine-tune the optimization process:

- ``traj_rotation_weight`` (float): The weight for rotational constraints during trajectory optimization (default: ``10.0``). Higher values enforce stronger rotation consistency.
- ``traj_translation_weight`` (float): The weight for translational constraints during trajectory optimization (default: ``10.0``). Higher values enforce stronger position consistency.
- ``traj_rotation_weight`` (float): The weight for rotational constraints during trajectory optimization (default: ``10.0``). Higher values enforce stronger rotation consistency. Must be a float ``> 0``.
- ``traj_translation_weight`` (float): The weight for translational constraints during trajectory optimization (default: ``10.0``). Higher values enforce stronger position consistency. Must be a float ``> 0``.
- ``max_num_iterations`` (int): The maximum number of iterations the solver will perform before terminating.
- ``loss_function`` (str): The name of the robust loss function to use (e.g., ``HUBER_LOSS``, ``CAUCHY_LOSS``, ``SOFT_L_ONE_LOSS``, ``ARCTAN_LOSS``, ``TRIVIAL_LOSS``).
- ``loss_scale`` (float): The scaling parameter for the chosen loss function. Higher values make the loss less sensitive to outliers.
Expand All @@ -67,6 +67,7 @@ Several constraint types (explained later) support optional weight fields that e
**rotation weight**

- ``rotation_weight`` (single float) scales the quaternion axis-alignment residual for ``ABSOLUTE_POSE`` and ``POSE_TO_POSE`` constraints. Higher values enforce the orientation more strongly; set it to ``0`` to ignore the rotational component.
- Must be a single float value ``>= 0``.

**Example (rotation_weight for ABSOLUTE_POSE):**

Expand All @@ -78,7 +79,7 @@ This doubles the strength of the orientation penalty for that absolute pose.

**translation_weight**

- Must be a list of three numbers.
- Must be a list of three float values ``>= 0``.
- Applies to the positional components: **x**, **y**, and **z**.
- Higher values signal stronger confidence in the position, and lower values give the optimizer more freedom to adjust.
- Values are treated as relative weights for each axis.
Expand Down Expand Up @@ -132,9 +133,10 @@ Defines an absolute pose measurement relative to the world coordinate frame.

* Scales the quaternion axis-alignment residual applied to this pose.
* Higher values increase sensitivity to rotational deviations; setting it to ``0`` disables the rotational penalty.
* Must be a float value ``>= 0``.
- ``translation_weight``:

* A list of three values.
* A list of three float values ``>= 0``.
* Corresponds to confidence in the **x**, **y**, and **z** position.

See :ref:`weight-fields` for a detailed explanation.
Expand Down Expand Up @@ -178,13 +180,13 @@ Fixes a single point from a scan to known coordinates in the trajectory map fram
- ``type``: Must be exactly ``"ABSOLUTE_POINT"``.
- ``timestamp``: Lidar frame timestamp (first valid column timestamp).
- ``row``: Row index of the point (>= 0 && < scan.h).
- ``col``: Column index of the point (>= 0 && scan.w).
- ``col``: Column index of the point (>= 0 && < scan.w).
- ``return_idx``: Which range return to use (1 or 2).
- ``absolute_position``: Either an object with keys ``x``, ``y``, ``z`` or a list of three numbers ``[x, y, z]``.

**Optional fields:**

- ``translation_weight``: List of three values describing confidence along ``x``, ``y``, and ``z``.
- ``translation_weight``: List of three float values ``>= 0`` describing confidence along ``x``, ``y``, and ``z``.

.. note::

Expand Down Expand Up @@ -230,7 +232,7 @@ This constraint uses 2D image coordinates to select points from the lidar scans:

**Optional field:**

- ``translation_weight``: A list of three numbers.
- ``translation_weight``: A list of three float values ``>= 0``.

See :ref:`weight-fields` for a detailed explanation.

Expand Down Expand Up @@ -297,8 +299,8 @@ The ``POSE_TO_POSE`` constraint defines a constraint between two poses in the tr
* A dictionary (with ``rx``, ``ry``, ``rz``, ``x``, ``y``, ``z``), or
* A 16-element list (4x4 matrix)
* If omitted, transformation is auto-estimated using ICP matching.
- ``rotation_weight`` (float): Scales the quaternion axis-alignment residual for the relative pose. Setting it higher enforces the measured rotation more strongly; setting it to ``0`` disables the rotational penalty.
- ``translation_weight``: List of three values.
- ``rotation_weight`` (float): Scales the quaternion axis-alignment residual for the relative pose. Setting it higher enforces the measured rotation more strongly; setting it to ``0`` disables the rotational penalty. Must be a float value ``>= 0``.
- ``translation_weight``: List of three float values ``>= 0``.

See :ref:`weight-fields` for a detailed explanation.

Expand Down Expand Up @@ -457,11 +459,13 @@ addition to any constraints loaded from ``--config``). Remember the ``--config``
To record a dataset, connect your sensor to receive GPS data over a serial interface and set
the udp_profile_imu to ACCEL32_GYRO32_NMEA. Detailed instructions for configuring the sensor to accept
GPS input can be found in the `Sensor Time Sync`_ documentation:
Note: ``ACCEL32_GYRO32_NMEA`` is only available in firmware 3.2 or later.

- ``--auto-constraints``: Automatically generate and add GPS absolute pose constraints.
- ``--gps-constraints-every-m``: Approximate spacing in meters between constraints,
computed from distance traveled using lidar scan poses.
- ``--gps-constraints-weights``: Translation weights ``WX,WY,WZ``. ``WX`` and ``WY``
- ``--gps-constraints-weights``: Translation weights ``WX,WY,WZ`` (three
comma-separated numbers >= 0).
- ``--no-initial-align``: In ``--viz`` mode, disables the initial alignment step
using absolute constraints.

Expand Down
16 changes: 10 additions & 6 deletions ouster_client/include/ouster/impl/lidar_scan_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,11 @@ void visit_field_2d(FieldView& field, OP&& op, Args&&... args) {
std::forward<Args>(args)...);
break;
case ChanFieldType::ZONE_STATE:
// IMPORTANT: ZoneState is not an Eigen scalar type,
// so many of the operations provide as the template parameter OP
// will cause compilation errors if we try to apply them.
case ChanFieldType::CHAR:
case ChanFieldType::VOID:
case ChanFieldType::UNREGISTERED:
// These types are not Eigen scalar types or are not supported,
// so we silently skip them rather than crash.
break;
default:
throw std::invalid_argument("Invalid field for LidarScan");
Expand Down Expand Up @@ -140,9 +142,11 @@ void visit_field_2d(const FieldView& field, OP&& op, Args&&... args) {
std::forward<Args>(args)...);
break;
case ChanFieldType::ZONE_STATE:
// IMPORTANT: ZoneState is not an Eigen scalar type,
// so many of the operations provide as the template parameter OP
// will cause compilation errors if we try to apply them.
case ChanFieldType::CHAR:
case ChanFieldType::VOID:
case ChanFieldType::UNREGISTERED:
// These types are not Eigen scalar types or are not supported,
// so we silently skip them rather than crash.
break;
default:
throw std::invalid_argument("Invalid field for LidarScan");
Expand Down
2 changes: 2 additions & 0 deletions ouster_client/include/ouster/impl/logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class Logger {

bool configure_stdout_sink(const std::string& log_level);

bool configure_stderr_sink(const std::string& log_level);

bool configure_file_sink(const std::string& log_level,
const std::string& log_file_path, bool rotating,
int max_size_in_bytes, int max_files);
Expand Down
20 changes: 18 additions & 2 deletions ouster_client/include/ouster/lidar_scan.h
Original file line number Diff line number Diff line change
Expand Up @@ -552,21 +552,37 @@ class OUSTER_API_CLASS LidarScan {
ConstArrayView1<ZoneState> zones() const;

/**
* Return the first valid packet timestamp
* Return the first valid packet timestamp from any packet type.
*
* @return the first valid packet timestamp, 0 if none available
*/
OUSTER_API_FUNCTION
uint64_t get_first_valid_packet_timestamp() const;

/**
* Return the last valid packet timestamp
* Return the last valid packet timestamp from any packet type.
*
* @return the last valid packet timestamp, 0 if none available
*/
OUSTER_API_FUNCTION
uint64_t get_last_valid_packet_timestamp() const;

/**
* Return the first valid lidar packet timestamp
*
* @return the first valid lidar packet timestamp, 0 if none available
*/
OUSTER_API_FUNCTION
uint64_t get_first_valid_lidar_packet_timestamp() const;

/**
* Return the last valid lidar packet timestamp
*
* @return the last valid lidar packet timestamp, 0 if none available
*/
OUSTER_API_FUNCTION
uint64_t get_last_valid_lidar_packet_timestamp() const;

/**
* Return the first valid column timestamp
*
Expand Down
3 changes: 3 additions & 0 deletions ouster_client/include/ouster/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,9 @@ enum class UDPProfileLidar {
/** Single Return Zone Monitoring */
RNG19_RFL8_SIG16_NIR16_ZONE16,

/** Single Return Low Data Rate Window Status */
RNG15_RFL8_WIN8,

/** disabled */
OFF = 100,

Expand Down
2 changes: 1 addition & 1 deletion ouster_client/src/cloud_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ PointCloudXYZf read_pointcloud(const std::string& filename) {
input.seekg(0, std::ios::beg);

// field sizes
std::map<std::string, int> field_sizes{{"float", 4}};
std::map<std::string, int> field_sizes{{"float", 4}, {"uchar", 1}};
bool end_header_found = false;
bool is_binary = true;
int current_offset = 0;
Expand Down
Loading