Skip to content

feat(pj_base): add GridMap canonical builtin object (SDK 0.26.0) - #185

Merged
facontidavide merged 2 commits into
mainfrom
feat/gridmap-builtin
Sep 2, 2026
Merged

feat(pj_base): add GridMap canonical builtin object (SDK 0.26.0)#185
facontidavide merged 2 commits into
mainfrom
feat/gridmap-builtin

Conversation

@facontidavide

Copy link
Copy Markdown
Contributor

Summary

Adds sdk::GridMap, a 2D grid whose cells carry named channels: the layered, generic-valued sibling of OccupancyGrid for elevation maps and multi-layer costmaps (grid_map_msgs/GridMap, foxglove.Grid). First of three PRs for rendering grid maps as a lit, colormapped heightfield in PlotJuggler 4's 3D view; the PJ4 renderer and the parser mappings follow once this is released.

Design: row-major fixed-size cell records described by the shared PointField channel model, mirroring foxglove.Grid plus an explicit row_count, so Foxglove producers hand data over zero-copy and only ROS grid_map needs a one-time transcode. A NaN in a float channel means "no data". Which channel is height, which drives color, and the colormap are viewer-side; the type carries no styling. Conventional channel names documented: elevation, and red/green/blue/alpha for RGBA.

Changes

  • pj_base/builtin/grid_map.hpp and GridMap.proto (data = field 10)
  • grid_map_codec.{hpp,cpp}: decode rejects a layout the cell math could not index safely (zero stride with cells declared, row shorter than its columns, data shorter than row_count * row_stride, a field reaching past cell_stride)
  • BuiltinObjectType::kGridMap = 20, PJ_BUILTIN_OBJECT_TYPE_GRID_MAP = 20, splice-table entry, type-erased dispatcher cases
  • sdk::Vector2 in the geometry vocabulary with wire helpers (PJ.Vector2 already existed on the wire)
  • Docs: builtin_type.md section plus classification and conversion rows, proto README, builtin counts in both CLAUDE.md files
  • VERSION 0.26.0 and CHANGELOG entry. MINOR per the release policy: additions only, no existing struct, slot, or wire format changes.

Test plan

  • Tests written first: 7 new GridMapCodecTest cases (round trip with NaN preserved, ownership, empty grid, four rejections) plus the enum, ABI-sentinel, metadata and splice-table tests extended; they failed on kGridMap undeclared before the implementation
  • Release build + ctest: 84/84
  • ./build.sh --debug && ./test.sh (ASAN): 84/84
  • pre-commit clean
  • CI abi_check (abigail not installed locally; additions only)

After merge

Release 0.26.0. Not included, deliberately: a GridMapBuilder in the WASM parser-module kit and a validity-mask (basic_fields) extension; both are additive if wanted later.

🤖 Generated with Claude Code

facontidavide and others added 2 commits September 2, 2026 21:38
sdk::GridMap is a 2D grid whose cells carry named channels: the layered,
generic-valued sibling of OccupancyGrid for elevation maps and multi-layer
costmaps (grid_map_msgs/GridMap, foxglove.Grid). Row-major fixed-size cell
records described by the shared PointField channel model, mirroring
foxglove.Grid plus an explicit row_count so producers with that layout hand
`data` over zero-copy; a NaN in a float channel means "no data".

- grid_map.hpp + PJ.GridMap wire format (data = field 10) + grid_map_codec:
  decode rejects a layout the cell math could not index safely (zero stride
  with cells, row shorter than its columns, data shorter than
  row_count * row_stride, field past cell_stride)
- kGridMap = 20 / PJ_BUILTIN_OBJECT_TYPE_GRID_MAP, splice-table entry,
  type-erased dispatcher cases
- sdk::Vector2 in the geometry vocabulary (PJ.Vector2 already on the wire)
- docs: builtin_type.md section, proto README, builtin counts; CHANGELOG;
  VERSION 0.26.0 (MINOR: additions only)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…d ObjectWriter builder

Review follow-up for the GridMap builtin:

- The functional-v2 splice path decodes the canonical wire before the bulk
  bytes are attached, so a decode-time data-length check rejected every
  spliced GridMap. A wire without `data` now decodes with an empty span and
  the full layout check lives in validateGridMap(), run once bytes are in
  place. Field validation is unconditional and rejects unknown datatypes and
  zero counts (bytesPerElement instead of a local size table).
- Both host splice-attachment switches gain the kGridMap case, and the
  parser-module ObjectWriter gains GridMapBuilder / gridMap() (object type 20,
  data field 10), with builder, splice and host-path tests for each.
- PointField wire helpers shared by the PointCloud, VoxelGrid and GridMap
  codecs move to one private header (point_field_codec.hpp).
- Docs: the packed cell layout matches foxglove.Grid, not the wire format or
  field descriptors (PackedElementField datatype numbering differs, count is
  always 1); cell_stride bound is the largest field end; pose composition
  wording; dispatcher invariant tests and the plugin guide count 18 builtins.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@facontidavide
facontidavide merged commit 704ac48 into main Sep 2, 2026
7 checks passed
@facontidavide
facontidavide deleted the feat/gridmap-builtin branch September 2, 2026 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant