Expand description
§cloudini
A point cloud compression library implementing the Cloudini format.
Cloudini uses a two-stage pipeline:
- Field encoding — each point field is encoded with a type-appropriate scheme:
- Integers → delta + zigzag varint
Float32/Float64with resolution → quantization + delta + varint (lossy)Float64without resolution → XOR with previous value (lossless)
- Block compression — the encoded byte stream is compressed with LZ4 or ZSTD.
Typical results on Lidar geometry (XYZ @ 1 mm + intensity): ~34% compressed size with Lossy + ZSTD.
§Quickstart
use cloudini::ros::{CompressExt, CompressionConfig, PointCloud2Msg};
use ros_pointcloud2::points::PointXYZI;
let resolution = 0.001_f32; // 1 mm
// Build a PointCloud2Msg from a vec of typed points (simulated Lidar scan)
let points: Vec<PointXYZI> = (0..200)
.map(|i| {
let t = i as f32 * 0.05;
PointXYZI::new(t.sin() * 5.0, t.cos() * 5.0, t * 0.1, i as f32)
})
.collect();
let cloud = PointCloud2Msg::try_from_vec(points.clone()).unwrap();
let raw_size = cloud.data.len();
// Compress — 1 mm lossy + ZSTD
let compressed = cloud.compress(CompressionConfig::lossy_zstd(resolution)).unwrap();
assert_eq!(compressed.format, "cloudini/lossy/zstd");
assert!(
compressed.compressed_data.len() < raw_size,
"compressed ({} B) should be smaller than raw ({} B)",
compressed.compressed_data.len(), raw_size,
);
// Decompress — no metadata needed, it is all in the header
let restored = compressed.decompress().unwrap();
assert_eq!(restored.dimensions.width, 200);
// Each float component is within resolution / 2 of the original
let tol = resolution / 2.0 + 1e-6;
let restored_points: Vec<PointXYZI> = restored.try_into_iter().unwrap().collect();
for (orig, rest) in points.iter().zip(restored_points.iter()) {
assert!((orig.x - rest.x ).abs() <= tol);
assert!((orig.y - rest.y ).abs() <= tol);
assert!((orig.z - rest.z ).abs() <= tol);
assert!((orig.intensity - rest.intensity).abs() <= tol);
}§Compression presets
| Constructor | Encoding | Compression | Max float error |
|---|---|---|---|
ros::CompressionConfig::lossy_zstd | Lossy | ZSTD | res / 2 |
ros::CompressionConfig::lossy_lz4 | Lossy | LZ4 | res / 2 |
ros::CompressionConfig::lossless_zstd | Lossless XOR | ZSTD | 0 |
ros::CompressionConfig::lossless_lz4 | Lossless XOR | LZ4 | 0 |
ros::CompressionConfig::default is lossy_zstd(0.001) — suitable for most Lidar workloads.
§Raw API
Disable the default feature and drive the encoder/decoder directly:
cloudini = { version = "0.1.0", default-features = false }use cloudini::{
CompressionOption, EncodingInfo, EncodingOptions, FieldType, PointField,
PointcloudDecoder, PointcloudEncoder,
};
// Describe the point layout: x, y, z (f32) + intensity (u8) = 13 bytes/point
let info = EncodingInfo {
fields: vec![
PointField { name: "x".into(), offset: 0, field_type: FieldType::Float32, resolution: Some(0.001) },
PointField { name: "y".into(), offset: 4, field_type: FieldType::Float32, resolution: Some(0.001) },
PointField { name: "z".into(), offset: 8, field_type: FieldType::Float32, resolution: Some(0.001) },
PointField { name: "intensity".into(), offset: 12, field_type: FieldType::Uint8, resolution: None },
],
width: 1000,
height: 1,
point_step: 13,
encoding_opt: EncodingOptions::Lossy,
compression_opt: CompressionOption::Zstd,
..EncodingInfo::default()
};
// raw_cloud: width * height * point_step bytes of packed point data
let raw_cloud: Vec<u8> = vec![0u8; 1000 * 13];
let compressed = PointcloudEncoder::new(info).encode(&raw_cloud).unwrap();
let (_info, decoded) = PointcloudDecoder::new().decode(&compressed).unwrap();
assert_eq!(decoded.len(), raw_cloud.len());§Encoding modes
| Mode | Float32/64 with resolution | Float64 without resolution | Integers |
|---|---|---|---|
EncodingOptions::None | raw copy | raw copy | raw copy |
EncodingOptions::Lossy | quantise → delta → varint | raw copy | delta → varint |
EncodingOptions::Lossless | raw copy (f32) / XOR (f64) | XOR with prev bits | delta → varint |
§Compression backends
CompressionOption | Notes |
|---|---|
None | field encoding only, no block compression |
Lz4 | fast, moderate ratio |
Zstd | higher ratio, higher CPU cost |
Re-exports§
pub use decoder::PointcloudDecoder;pub use encoder::PointcloudEncoder;pub use error::Error;pub use error::Result;pub use header::decode_header;pub use header::encode_header;pub use header::encoding_info_from_yaml;pub use header::encoding_info_to_yaml;pub use types::CompressionOption;pub use types::ENCODING_VERSION;pub use types::EncodingInfo;pub use types::EncodingOptions;pub use types::FieldType;pub use types::MAGIC_HEADER;pub use types::POINTS_PER_CHUNK;pub use types::PointField;
Modules§
- decoder
- Pointcloud decoder — reconstructs raw point data from a Cloudini buffer.
- encoder
- Pointcloud encoder — converts raw point data to a self-contained Cloudini buffer.
- error
- field_
decoder - Per-field decoding logic for the Cloudini format.
- field_
encoder - Per-field encoding logic for the Cloudini format.
- header
- Cloudini header encode/decode.
- ros
- ROS integration — compress and decompress
PointCloud2Msgusing the Cloudini format. - types
- Core types shared across the cloudini encoder and decoder.
- varint
- Zigzag varint encoding matching the Cloudini wire format.