feat(parser_ros): FrameTransforms, OccupancyGrid, RobotDescription & Marker→SceneEntities producers#122
Merged
Merged
Conversation
tf2_msgs/TFMessage now produces BOTH a canonical sdk::FrameTransforms object (objectstore — for the 3D scene's per-dataset TF buffer) AND its existing flattened scalar fields (datastore — for plotting transforms as time series). This is dual registration in the schema catalog: object_type + parse_object added alongside the existing parse_scalars, the same pattern Image/PointCloud2 already use. parseFrameTransforms decodes the CDR TFMessage into one FrameTransform per TransformStamped, each carrying its OWN Header.stamp — the per-sample time the TF buffer needs for zero-order-hold scrub lookups — independent of the message receive time. Test: TFMessageProducesFrameTransformsObject verifies classifySchema reports kFrameTransforms and that parseObject decodes a 2-transform message with the correct per-transform timestamps, parent/child frames, translation, and rotation. 29/29 parser_ros tests pass against plotjuggler_core 0.3.1. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…on producers Extends the dual datastore+objectstore producer set with three more unambiguous, self-contained canonical types (all present in core 0.3.1): - nav_msgs/OccupancyGrid -> kOccupancyGrid: byte-backed, cells zero-copied as a Span over the payload; dual-registered with discard-large-array scalars. - geometry_msgs/TransformStamped -> kFrameTransforms: single-element, sharing the new readStampedTransform helper with the TFMessage producer. - std_msgs/String on a robot_description topic -> kRobotDescription, with a best-effort urdf/sdf/mjcf format hint sniffed from the root element. Topic-gated in bindSchema (a generic String stays a scalar), resolving the dispatch ambiguity by topic name. Deferred (ambiguous / stateful, or not in 0.3.1): Markers (type switch + action/lifetime/identity), DepthImage (encoding dispatch + CameraInfo), CameraInfo / OccupancyGridUpdate. Tests: object-route decode for each, plus a negative test that a String on a non-robot_description topic is NOT classified as RobotDescription. 33/33 parser_ros tests pass against plotjuggler_core 0.3.1. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…atch namespaced robot_description
Routing per design: only TFMessage and TransformStamped are dual
datastore+objectstore (their transforms are useful plotted as time series).
OccupancyGrid and RobotDescription are object-store only — a map/costmap and a
URDF/SDF/MJCF document aren't useful as scalar columns — so their parse_scalars
is dropped (SchemaHandler permits a null scalar route).
robot_description topic-gating already matched namespace-prefixed topics via
ends_with("/robot_description"); make that explicit in the comment and cover it
with a test for "/my_robot/robot_description" (which also exercises the SDF
format sniff).
34/34 parser_ros tests pass against plotjuggler_core 0.3.1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per-message, stateless conversion of Marker / MarkerArray into the canonical sdk::SceneEntities object (one SceneEntity per ADD/MODIFY marker, one SceneEntityDeletion per DELETE/DELETEALL). Decoders in a new ros_marker_handlers.cpp; catalog + bindSchema wiring; tests; MARKER_NOTES.md captures the design. - Type map: CUBE/SPHERE/CYLINDER/LINE_*/TRIANGLE_LIST/TEXT_VIEW_FACING -> matching primitives; MESH_RESOURCE -> ModelPrimitive; CUBE_LIST/SPHERE_LIST expand to N primitives; POINTS/ARROW_STRIP skipped (no canonical mapping). - (ns,id) -> length-prefixed entity id; lifetime/frame_locked carried through; ColorRGBA float->uint8; per-vertex colors only when sized to the points. - Positional CDR decode with a bindSchema sniff (uv_coordinates / mesh_file) so the humble+ texture/mesh_file tail is consumed correctly on every distro, keeping MarkerArray elements aligned. Statefulness (accumulation, lifetime expiry) is intentionally left to a future 3D scene consumer, not the parser; see MARKER_NOTES.md. Requires the SceneEntities ModelPrimitive + deletions[] additions in plotjuggler_core. Parser-side groundwork: no kSceneEntities renderer exists yet, so this is exercised by unit tests only (not yet built in this environment due to an unrelated plugin-dependency build issue). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 30, 2026
…id ingest fix, MCAP latched-stamp clamp parser_ros: object producers (FrameTransforms, TransformStamped, OccupancyGrid, RobotDescription, Marker, MarkerArray) now return ObjectRecord, threading the parser-controlled embedded timestamp (use_embedded_timestamp_) through the object route instead of returning a bare BuiltinObject. parser_ros: nav_msgs/OccupancyGrid keeps its parse_scalars route (parseScalarsDiscardingLargeArrays). An object-only entry (no parse_scalars) aborts the message push before the object route runs, so the scalar handler is required for the grid to reach the ObjectStore; metadata stays plottable while the large data[] array is discarded. data_load_mcap: clamp header (publishTime) stamps that fall outside the recording's log-time window to its first timestamp. Latched / long-running publishers (static TF, robot_description, pre-computed maps) would otherwise drag the playback range off the actual recording. useMcapLogTime() still forces the message's own logTime.
…Update Port the one unique producer from #119 (feat/occupancy-grid-parser): the incremental delta-patch counterpart to OccupancyGrid (e.g. costmap_updates). map_msgs/OccupancyGridUpdate -> kOccupancyGridUpdate, dual datastore+object route: x/y/width/height stay plottable while the large data[] patch is discarded by parseScalarsDiscardingLargeArrays. Byte-backed zero-copy cells (span pinned by the payload anchor) with a width*height bounds check. kOccupancyGridUpdate is available in core 0.5.x (builtin type id 15). #119's OccupancyGrid half is redundant with this branch and is dropped; its readPose/readF64 helpers were only needed there, so they are not ported. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
419ff90 to
538054e
Compare
Contributor
Author
|
@copilot fix CI build |
Contributor
Addressed in |
pabloinigoblasco
approved these changes
Jun 1, 2026
Contributor
pabloinigoblasco
left a comment
There was a problem hiding this comment.
I see this PR well.
I approve.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extends
parser_rosto emit canonical builtin objects (not just scalar columns) for several ROS types, feeding the 3D scene / object store:tf2_msgs/TFMessage→kFrameTransforms— keeps the existing scalar flattening and emits a FrameTransforms object for the TF buffer.geometry_msgs/TransformStamped→kFrameTransforms— single-element, sharing thereadStampedTransformhelper with the TFMessage producer.nav_msgs/OccupancyGrid→kOccupancyGrid— dual datastore+object route (metadata stays plottable; the largedata[]array is discarded byparseScalarsDiscardingLargeArrays).map_msgs/OccupancyGridUpdate→kOccupancyGridUpdate— the incremental delta-patch counterpart to OccupancyGrid (e.g. costmap updates); same dual route. Consolidated from feat(parser_ros): emit OccupancyGrid + OccupancyGridUpdate #119.std_msgs/Stringon arobot_descriptiontopic →kRobotDescription— topic-gated (a generic String stays a scalar), with a urdf/sdf/mjcf format sniff. Matches both the bare topic and any<ns>/robot_description.visualization_msgs/Marker(Array)→kSceneEntities— one SceneEntity per ADD/MODIFY, a SceneEntityDeletion for DELETE/DELETEALL. Wire-layout sniffing handles the humble+ texture/mesh tail vs. EOL foxy/galactic/ROS 1. Seeparser_ros/MARKER_NOTES.md.Also includes a small
data_load_mcap/mcap_source.cppchange.Rebase note
Rebased onto
main. The four redundant CI commits this branch originally carried were the unsquashed version of the already-merged cloudsmith/ensure_core.shwork (#120) — they were dropped during the rebase (verified byte-identical to / superseded bymain). The topic-conditional override and Marker layout sniffing were re-homed ontomain's refactoredcompileBoundSchema/registerBoundSchemaHandlerstructure (newselectCatalogEntryhelper).Tests
parser_rosbuilds clean under the full-Werrorwarning set; all 45ros_parser_testcases pass, includingRobotDescriptionTopicProducesObject,RobotDescriptionNamespacedTopicProducesObject,GenericStringTopicIsNotRobotDescription,OccupancyGridProducesObject,TextMarkerHumbleAndFoxyLayouts, and the TF/TransformStamped producers.Routing
robot_descriptionandMarker(Array)are intentionally object-only (no scalar route) — a URDF/SDF/MJCF document and 3D scene markers aren't useful as scalar columns.OccupancyGridkeeps a metadata scalar route (parseScalarsDiscardingLargeArrays) so resolution/size/origin stay plottable while the largedata[]array is discarded.TFMessage/TransformStampedare dual datastore+object.Core version
The
OccupancyGridUpdateproducer depends on thekOccupancyGridUpdatebuiltin object (occupancy_grid_update.hpp, builtin type id 15), available inplotjuggler_core≥ 0.5.0. This repo already pins 0.5.1 (SDK_VERSION+ theextern/plotjuggler_coresubmodule atv0.5.1), which ships the type — so no core bump is required; every producer in this PR builds against the already-pinned core.🤖 Generated with Claude Code