This guide covers the public replay workflow and how to adapt a new bag to the input contract.
At minimum, a replayed dataset should provide:
- a point-cloud topic compatible with
sensor_msgs/msg/PointCloud2 - a pose source that can be normalized by
pose_provider
Depending on the selected regime, the pose source may be:
- odometry
- pose stamped
- pose with covariance stamped
- TF-derived pose information
- inspect the bag
- choose the cloud and pose sources
- choose the closest example profile
- replay through
scripts/replay_example.sh - export the map if needed
- compute proxy metrics if needed
Use:
python3 scripts/rosbag_info.py /absolute/path/to/bagor native ROS tooling when available.
When inspecting a new bag, identify:
- the cloud topic to be mapped
- the usable pose source
- the cloud frame id
- the pose frame id
- whether
tfandtf_staticare present - the approximate rates of cloud and pose streams
Choose by cloud-pose relationship, not by robot name.
| If the bag looks like... | Starting example | Main consequence |
|---|---|---|
| Cloud is already in the backend integration frame | examples/spot_identity.yaml |
use backend_pose_mode=identity |
| Pose already describes the mapping sensor frame | examples/generic_template.yaml |
use backend_pose_mode=odometry |
| Pose must be normalized from TF | examples/dynablox_tf_normalized.yaml |
configure pose_provider from TF |
| Pose describes a body frame and the lidar is offset from it | examples/anymal_body_plus_extrinsic.yaml |
configure the static extrinsic |
The most important public parameters are:
| Parameter | Role |
|---|---|
pose_provider_input_mode |
upstream pose-message interpretation |
backend_pose_mode |
backend-facing pose interpretation |
backend_sensor_frame_id |
backend-facing sensor frame identifier |
backend_sensor_offset_x/y/z |
static translation from pose frame to sensor frame |
backend_sensor_roll/pitch/yaw |
static rotation from pose frame to sensor frame |
max_pose_cloud_skew_sec |
cloud-pose admissibility threshold |
max_pose_age_sec |
maximum pose age retained for pairing |
allow_future_pose_match |
whether future-pose fallback is allowed |
./scripts/replay_example.sh \
--bag-path /absolute/path/to/bag \
--db-tsdf-config /absolute/path/to/db_tsdf_profile.yaml \
--points-topic /your/points \
--odometry-topic /your/odometry \
--backend-pose-mode odometryThe main example launch used by this script is:
ros2_ws/src/dense_mapping_tsdf/launch/input_contract_mapping.launch.py
./scripts/replay_example.sh \
--bag-path /absolute/path/to/bag \
--db-tsdf-config /absolute/path/to/db_tsdf_profile.yaml \
--points-topic /your/points \
--odometry-topic /your/odometry \
--backend-pose-mode odometry \
--keep-alive-after-playback
./scripts/export_map.sh \
--output-dir /absolute/path/to/output \
--compute-metricsThe proxy metrics are comparative summaries under fixed replay conditions. They should not be interpreted as ground-truth reconstruction accuracy.
Before replaying the full bag, run a short test and confirm that:
- the pose stream is received
- the cloud stream is received
- accepted observations begin to appear
- the wrapper is not rejecting every cloud for missing pose
- the wrapper is not rejecting every cloud for timing skew
Likely causes:
- wrong pose topic
- wrong pose input mode
- no usable pose in the bag
- a timing mismatch so severe that pairing never occurs
Likely causes:
max_pose_cloud_skew_secis too strict- timestamps are misaligned
- replay timing is inconsistent with the selected regime
Likely causes:
- wrong
backend_pose_mode - missing or incorrect static extrinsic
- wrong frame interpretation