Commit b15fa35
feat: add 7 new canonical builtin object types (#90)
* feat(proto): add canonical builtin object wire schemas
Wire-format contracts for the byte-backed builtin object types that
PlotJuggler plugins emit and renderers consume:
- Image, DepthImage, PointCloud: pair with existing SDK structs
- CompressedPointCloud, OccupancyGrid: new byte-backed types
- SceneEntities + 8 scene primitives (Arrow, Cube, Sphere, Cylinder,
Line, Triangle, Text, Axes) for marker-style 3D visualization
- Mesh3D, VideoFrame: opaque-asset family (binary payload + format
identifier)
Schema cleanup:
- Add Pose to Geometry.proto (shared by scene primitives, OccupancyGrid,
Mesh3D)
- Merge FrameTransform.proto into FrameTransforms.proto to match the
single-file-per-family pattern
- Add pj/README.md describing the purpose of each schema
Tooling:
- Extend .clang-format with a Proto language section (Google base,
120-col limit) and enable the existing clang-format pre-commit hook
on .proto files.
- Pass --allow-multiple-documents to the check-yaml hook so it accepts
the multi-doc .clang-format file.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(builtin): add SDK structs for new canonical object types
Catalog additions matching the proto contracts landed in f37b7e4.
This is the "top-level" change: BuiltinObjectType enum + SDK struct
headers. Codecs follow in subsequent commits.
New SDK structs:
- sdk::OccupancyGrid: 2D metric grid (maps, costmaps)
- sdk::CompressedPointCloud: opaque compressed cloud (Draco, ...)
- sdk::Mesh3D: binary mesh asset (GLTF/STL/PLY/OBJ/USD/DAE)
- sdk::VideoFrame: single frame of h264/h265/vp9/av1 stream
- sdk::SceneEntities + 8 primitives (Arrow, Cube, Sphere, Cylinder,
Line, Triangle, Text, Axes) for marker-style 3D visualization
Also adds sdk::Pose to FrameTransforms.hpp (consumed by Mesh3D,
OccupancyGrid, and the scene primitives). Long-term it belongs in
a dedicated Geometry.hpp alongside Vector3/Quaternion/Point2/Point3
- separate refactor.
BuiltinObject.hpp:
- Enum gains 5 entries (kOccupancyGrid through kSceneEntities at
numeric values 7..11; preserves the historical gap at 2).
- name(), parseBuiltinObjectType(), and typeOf() extended to cover
every new entry.
Tests: builtin_object_test.cpp gains a round-trip test that iterates
every enum value through name() / parseBuiltinObjectType() to catch
future drift between the three helpers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(builtin): add codecs for 5 new canonical object types
Hand-rolled protobuf codecs implementing the wire contracts landed
in f37b7e4 for the SDK structs landed in 620f3da. Round-trip tests
follow in a separate commit.
New codecs (each with serialize / deserialize / kSchema constant):
- video_frame_codec
- compressed_point_cloud_codec
- occupancy_grid_codec
- mesh3d_codec
- scene_entities_codec (also covers the 8 scene primitives:
Arrow, Cube, Sphere, Cylinder, Line, Triangle, Text, Axes)
Codec infrastructure:
- protobuf_wire.hpp gains a parseFields(reader, handler) helper that
drains the standard tag-read / switch / skip-unknown decode loop —
cuts ~10 lines of boilerplate per nested message.
- protobuf_wire.hpp gains fixed32 / packedFixed32 / readFixed32 /
readPackedFixed32 for LinePrimitive.indices and similar.
- Reader.readBytes is promoted from private to public so byte-backed
codecs can copy bytes into their owned vector + BufferAnchor.
- New internal geometry_codec.hpp consolidates the shared
writeTimestamp / writeVector3 / writeQuaternion / writePose /
writeColor / writePoint3 + decode counterparts. Pulled out of
frame_transforms_codec.cpp; frame_transforms now includes it.
Pure code move — wire format unchanged, existing tests pass.
Existing image_annotations_codec.cpp is NOT refactored in this PR
(it has its own writeColor / decodeColor that match byte-identically).
That refactor is left for a follow-up to keep this PR scoped.
Build wire-up: 5 new .cpp files added to pj_base library sources.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(builtin): add codecs for Image, DepthImage, PointCloud
The SDK structs predate the catalog rework; their wire contracts
landed in f37b7e4. This commit closes the codec gap so all
byte-backed builtin types have round-trippable serialization.
New codecs (each with serialize / deserialize / kSchema):
- image_codec — kSchemaImage = "PJ.Image"
- depth_image_codec — kSchemaDepthImage = "PJ.DepthImage"
- point_cloud_codec — kSchemaPointCloud = "PJ.PointCloud"
Codec infrastructure additions to protobuf_wire.hpp:
- Writer.floatField + Reader.readFloat for `optional float`
(used by Image.compressed_depth_min / _max).
- Writer.packedDouble (range-based) for `repeated double` fields
(DepthImage.K, DepthImage.D).
- readPackedDouble / readPackedDoubleArray<N> free helpers for the
decode side. The fixed-size-array variant guards DepthImage.K's
9-entry contract at the wire boundary.
Misc: media_metadata_test.cpp uses "PJ.VideoFrame" in its example
metadata payload instead of the now-renamed "PJ.CompressedVideo".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(builtin): add AssetVideo type for file-backed video assets
AssetVideo carries no pixel data — it references a video file by path
and surfaces decode-routing metadata (MIME type, dimensions, frame
rate) so consumers can size playback windows and route to a decoder
without opening the file. Producers (LeRobot dataset loaders, MP4
loaders) push exactly one AssetVideo per topic; the ObjectStore
timestamp of that entry equals `time_origin_ns` so timeline UIs see
the asset's start instant.
Distinct from VideoFrame (which carries a single coded frame as
opaque bytes) — AssetVideo is the file-reference family alongside
Mesh3D, not the streamed-payload family.
Adds:
- pj_base/proto/pj/AssetVideo.proto
- pj_base/include/pj_base/builtin/AssetVideo.hpp (SDK struct)
- pj_base/include/pj_base/builtin/asset_video_codec.hpp
- pj_base/src/builtin/asset_video_codec.cpp
- kAssetVideo = 12 in BuiltinObjectType + name/parse/typeOf entries
- Tests extended to cover round-trip through the catalog helpers
SDK-side `time_origin_ns` and `duration_ns` are std::optional —
absent means "not aligned to wall clock" / "probe the file"
respectively. The codec emits these fields only when set, and on
decode leaves them as nullopt when the field is absent on the wire.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor: rename builtin SDK headers to snake_case
The 12 SDK builtin headers under `pj_base/include/pj_base/builtin/`
were the only CamelCase filenames in a codebase that is otherwise
snake_case throughout. Rename them to match (e.g. `Image.hpp` →
`image.hpp`, `SceneEntities.hpp` → `scene_entities.hpp`); update all
`#include` directives, `@file` Doxygen tags, and the include snippet
in `docs/builtin_type.md`. Proto files keep their CamelCase names —
they mirror the contained message name (e.g. `Image.proto` →
`message Image`), a separate convention scope.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test: add round-trip tests for all 9 new builtin codecs
Each new codec gets a small gtest file covering its schema-name
constant, the empty-buffer error path, and a realistic round-trip
through serialize/deserialize. SceneEntities additionally exercises
one entity carrying every primitive kind plus per-vertex colors and
indices on a LinePrimitive; Image/DepthImage/Mesh3D cover their two
mutually-exclusive shapes (compressed-depth vs raw, plumb_bob vs
rectified, embedded asset vs URL).
Hand-rolled protobuf builders (varint/tag/double/fixed32/length-
delimited/string/bytes) plus geometry encoders (Timestamp, Vector3,
Quaternion, Pose) are extracted into a shared
`pj_base/tests/protobuf_wire_test_helpers.hpp`. The existing
frame_transforms_codec_test.cpp and image_annotations_codec_test.cpp
adopt it; their golden-byte assertions remain unchanged so they keep
guarding the on-wire format.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs: extend builtin_type.md with the new canonical types
Document the 6 new builtin types (OccupancyGrid, CompressedPointCloud,
Mesh3D, VideoFrame, AssetVideo, SceneEntities) added on this branch:
update the public-headers include block, extend the serialization-
families table (the byte-backed views family grew from 3 to 7; the
owned-values family gained SceneEntities and AssetVideo), add the new
kEnum rows to the classification table, and write a brief per-type
section in the same shape as the existing Image/DepthImage/PointCloud
sections.
Also expand the Conversion Examples table with the new source-side
inputs each type covers (Draco clouds, nav_msgs/OccupancyGrid, URDF
mesh resources, marker arrays, raw codec frames, MP4 dataset files).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(pj_base): add RobotDescription builtin object type
Stage B of the pj_scene3D PJ4-integration plan. Adds a canonical SDK
type for URDF / SDF / MJCF robot descriptions so the upcoming 3D widget
can consume them through the same ObjectStore path as other builtin
objects (PointCloud, FrameTransforms, Image, etc.).
- New PJ::sdk::RobotDescription owned struct: timestamp_ns, topic,
format (open-ended hint string, mirrors Image::encoding), text (raw
source markup). Header lives at pj_base/builtin/robot_description.hpp
(snake_case to match the rest of this branch).
- BuiltinObjectType::kRobotDescription = 13, appended after kAssetVideo.
The original branch assigned slot 7, which collided with the
kOccupancyGrid = 7 assignment landing in this PR; renumbered up to
preserve stable IDs for all already-assigned values.
- New cases in name(), parseBuiltinObjectType(), typeOf() — symmetric
with kFrameTransforms.
- builtin_object_test gains typeOf coverage, the round-trip loop entry,
ParsesRobotDescriptionTypeName, and RobotDescriptionRoundtripPreservesFields.
57/57 tests pass.
- docs/builtin_type.md: new section explaining raw-text + format-hint
rationale (open format space, no canonical codec, no embedded mesh
bytes — mesh resolution is consumer-side), enum table row, conversion
example for std_msgs/String on /robot_description.
The producer (ParserROS in stage D) validates the text matches the
declared format before emission so generic std_msgs/String topics on
unrelated channels don't surface as phantom robot descriptions.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(pj_base): add frame_id to sdk::PointCloud
3D consumers (pj_scene3D's Scene3DDockWidget, RViz/Foxglove-style viewers)
need the source coordinate frame to TF-transform points to a fixed render
frame. Without this, a cloud emitted in the sensor frame cannot be
positioned in world space when multiple frames coexist.
The field is purely additive — defaulted to empty string, so existing
2D-only consumers and scalar emission are unaffected. The proto schema
gets `string frame_id = 10;` at the next free wire tag; the codec round-
trips it; the C++ struct picks it up in stable position.
Ports commit 1a38059 from feat/robot-description-builtin onto the
snake_case + codec layout of feat/builtin-protos.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(pj_base): sync C ABI builtin object enum with C++ enum
PJ_builtin_object_type_t (the C ABI enum that pure-C plugins compile
against for classify_schema) was stuck at the original 5 typed values
plus a single commented-out reservation for OccupancyGrid. The C++
enum has since grown to 13 entries with the snake_case + AssetVideo +
RobotDescription work. Without this sync, a pure-C plugin trying to
declare any of OccupancyGrid / CompressedPointCloud / Mesh3D /
VideoFrame / SceneEntities / AssetVideo / RobotDescription via
classify_schema has no way to name the value — it would silently map
to PJ_BUILTIN_OBJECT_TYPE_NONE.
Adds all 7 missing typed values at their stable numeric slots (matching
BuiltinObjectType in builtin_object.hpp exactly) and pins each value
with a static_assert in abi_layout_sentinels_test so a future renumber
breaks the build. Also drops the obsolete 5-type list from the
docstring in favor of pointing readers at the C++ enum as the source
of truth.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Davide Faconti <dfaconti@aurynrobotics.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 2e958e1 commit b15fa35
75 files changed
Lines changed: 4870 additions & 415 deletions
File tree
- docs
- pj_base
- include/pj_base
- builtin
- proto/pj
- src/builtin
- tests
- pj_plugins/include/pj_plugins
- host
- sdk
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
20 | 21 | | |
21 | 22 | | |
22 | 23 | | |
| |||
30 | 31 | | |
31 | 32 | | |
32 | 33 | | |
33 | | - | |
| 34 | + | |
34 | 35 | | |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
6 | 9 | | |
7 | 10 | | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
8 | 17 | | |
9 | 18 | | |
10 | 19 | | |
| |||
63 | 72 | | |
64 | 73 | | |
65 | 74 | | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
66 | 84 | | |
67 | 85 | | |
68 | 86 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
Lines changed: 81 additions & 13 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
34 | 41 | | |
35 | 42 | | |
36 | 43 | | |
37 | 44 | | |
38 | 45 | | |
39 | 46 | | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
47 | 59 | | |
48 | 60 | | |
49 | 61 | | |
| |||
68 | 80 | | |
69 | 81 | | |
70 | 82 | | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
71 | 97 | | |
72 | 98 | | |
73 | 99 | | |
| |||
93 | 119 | | |
94 | 120 | | |
95 | 121 | | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
96 | 143 | | |
97 | 144 | | |
98 | 145 | | |
| |||
121 | 168 | | |
122 | 169 | | |
123 | 170 | | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
124 | 192 | | |
125 | 193 | | |
126 | 194 | | |
| |||
Lines changed: 41 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
Lines changed: 25 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| |||
0 commit comments