# cartographer/sensor/range_data.h ## Overview `RangeData` is the core sensor data structure for lidar/rangefinder measurements. It represents a single scan as an origin point plus two point clouds: returns (obstacle hits) and misses (free space along rays). ## Struct: `cartographer::sensor::RangeData` ```cpp struct RangeData { Eigen::Vector3f origin; // Sensor origin in sensor frame PointCloud returns; // Points where rays hit obstacles PointCloud misses; // Points along rays with no return }; ``` ### Semantics - **Origin** — Sensor position at measurement time (typically 0,0,0 in sensor frame) - **Returns** — 3D points where laser/radar detected an obstruction - **Misses** — Points at configured max range along rays with no return; represents free space ### Assumptions - Space between `origin` and `misses` is free (unoccupied) - `returns` and `misses` have the same number of points (one per ray) - Points are in the sensor's local frame ## Functions ### `TransformRangeData` ```cpp RangeData TransformRangeData(const RangeData& range_data, const transform::Rigid3f& transform); ``` Applies a rigid transform (rotation + translation) to all points. ### `CropRangeData` ```cpp RangeData CropRangeData(const RangeData& range_data, float min_z, float max_z); ``` Filters points by Z coordinate. Useful for removing ground/ceiling returns. ### `ToProto` / `FromProto` ```cpp proto::RangeData ToProto(const RangeData& range_data); RangeData FromProto(const proto::RangeData& proto); ``` Serialization to/from protobuf for storage and RPC. ## PointCloud ```cpp using PointCloud = std::vector; ``` Simple vector of 3D points. For large point clouds, consider `CompressedPointCloud`. ## Usage ```cpp // Create from raw sensor data sensor::RangeData range_data; range_data.origin = Eigen::Vector3f(0, 0, 0); range_data.returns = {Eigen::Vector3f(1, 0, 0), Eigen::Vector3f(0, 1, 0), ...}; range_data.misses = {Eigen::Vector3f(30, 0, 0), Eigen::Vector3f(0, 30, 0), ...}; // Transform to tracking frame auto transformed = sensor::TransformRangeData(range_data, sensor_to_tracking); // Crop to 2D slice auto cropped = sensor::CropRangeData(range_data, -0.5, 2.0); // Serialize proto::RangeData proto = sensor::ToProto(range_data); ``` ## Integration with TrajectoryBuilder ```cpp // Wrap in Dispatchable for sensor collator auto dispatchable = sensor::MakeDispatchable( "laser", // sensor ID common::FromUniversal(timestamp), range_data); // Add to trajectory builder trajectory_builder->AddSensorData("laser", std::move(dispatchable)); ``` ## Configuration Range data processing configured in trajectory builder options: ```lua TRAJECTORY_BUILDER_2D = { min_range = 0.1, -- Ignore returns closer than this max_range = 30.0, -- Max range for returns and misses missing_data_ray_length = 5.0, -- Length of miss rays voxel_filter_size = 0.025, -- Downsample before insertion } ``` ## See Also - [PointCloud](point_cloud.md) — Point cloud representation - [CompressedPointCloud](compressed_point_cloud.md) — Compressed storage - [RangeDataInserter](../mapping/submaps.md) — Insertion into submaps - [Dispatchable](data.md) — Sensor data wrapper - [SensorBridge (cartographer_ros)](../../cartographer_ros/cartographer_ros/include/cartographer_ros/sensor_bridge.h.md) — ROS message to RangeData conversion