Skip to main content

auki-mappers

Synced from the repository

This page mirrors crates/auki-mappers/README.md in the auki-sdk repo (branch develop). The repository is the source of truth.

auki-mappers contains SDK-native Map producers. Its first Mapper is a voxel Mapper which consumes SDK point-cloud and pose logs and writes sparse, mergeable MapUpdates. It has no robot or ROS API surface.

Live voxel Mapper flow

  1. Merge Resource Catalog rows obtained through the SDK.
  2. Fetch the selected Map Registry body with ClusterManager::fetch_map_entry.
  3. Use VoxelMapperSources::select to choose the unique live point-cloud and pose pair connecting the sensor frame to the selected Map frame. If the Map publisher needs to own that frame identity, construct a ValidatedFrameAlias from both exact Frame Registry entries and call select_with_frame_alias; this permits only an identity-preserving rebind, never an implicit coordinate conversion.
  4. Open point_cloud_request and pose_request against each row's writer peer through Domain/ClusterManager.
  5. Pass the accepted subscriptions, the Rangefinder Registry body, the Voxel Map Registry body, and a MapUpdateSink to run_sdk_voxel_mapper.

Selection and stream binding require exact content-addressed frames (or an explicit alias whose handedness, axes, and units match exactly) and one shared SDK clock. Accept-time resource/clock mismatches, timestamp regressions, and sequence gaps fail closed. Point-cloud and pose source peers and the Map Log destination peer are independent.

LocalMapLogSink::new preserves aligned input timestamps and therefore fails closed unless the input logs and destination Map Log declare the same exact clock. LocalMapLogSink::retimestamped samples the destination clock when it appends each update, allowing a Mapper hosted by Park (or any other peer) to consume a remote peer's aligned point-cloud/pose pair while publishing a correctly-clocked local Map Log. Other peers, explicit time-transform sinks, or materializers can implement MapUpdateSink without changing the Mapper.

Point-cloud and pose inputs must still share one exact clock so interpolation is meaningful. The output Map Log clock is independent: the sink owns the conversion or restamping boundary and the run report exposes both alignment_clock and map_clock.

A restamped update's Map Log timestamp is its production/append time, not the original sensor observation time. Applications that need observation-time provenance should provide a sink backed by an explicit SDK time transform.

The live runner separates stream alignment from voxel computation. Point-cloud and pose subscriptions remain responsive on the async runtime; once a point cloud has a bracketing pose, the aligned job enters a bounded blocking-worker queue. The queue is latest-wins, so a newer aligned cloud replaces stale pending work while one cloud is being voxelized. The run report distinguishes these worker-overload drops from point clouds dropped while waiting for poses.

MapUpdateSink::append_from is part of the async boundary: implementations must not perform expensive synchronous compaction, encoding, or I/O before returning their future. Applications also control runner lifetime. A UI such as Park should start the voxel Mapper only while an output consumer is active and stop it when demand disappears.

Pure voxelization

Voxelizer decodes the canonical XYZ fields from an SDK Rangefinder payload, interpolates the SDK-supplied sensor-to-Map pose, traces free-space rays, and emits additive occupied/free evidence grouped into sparse chunks.

Stable occupancy

run_sdk_voxel_mapper enables VoxelPersistenceConfig::default() unless its service configuration explicitly sets persistence: None. The filter first normalizes a point-cloud frame to at most one occupied or free observation per voxel, so point density does not count as repeated evidence. A candidate voxel is published only after six observations spanning three seconds with no gap over 500 ms. Once confirmed, it remains in the Map until continuous free-space observations span one second. Missing or occluded observations do not clear it.

All four thresholds are configurable. The low-level VoxelMapperRunner retains its immediate raw-evidence behavior unless the application calls with_persistence, which keeps existing algorithm and test uses explicit.

Camera calibration for metric Mappers

effective_camera_calibration applies the shared camera contract used by PnP and future Portal Mappers. A CameraFrame.dynamic_intrinsics value replaces the complete Camera Registry calibration for that frame. Otherwise the static, content-addressed registry calibration is used. Resolution fails closed when neither source exists or when the selected calibration is invalid.