Skip to content

feat(transport): integrate shared CDR codecs and native SDK - #4722

Open
TomCC7 wants to merge 5 commits into
cc/feat/cdr-unit-external-messagesfrom
cc/feat/cdr-unit-transports
Open

TomCC7 wants to merge 5 commits into
cc/feat/cdr-unit-external-messagesfrom
cc/feat/cdr-unit-transports

Conversation

@TomCC7

@TomCC7 TomCC7 commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Bind CDR and legacy codecs from the declared message type in existing LCM, Zenoh and WebRTC transports. Native SDK output callbacks return encoding errors instead of panicking, and the SDK uses the external CDR library for complete messages.

The SDK consumes the same generated ROS messages as its callers. Remove custom public TF types and handwritten TF storage/query algorithms. The external transforms library owns tree storage, interpolation and common-time lookup; standard TFMessage streams bind tf and tf_static. SDK time and geometry adapters preserve integer ROS timestamps. The backend pins each child's parent and static/dynamic kind. LCM/Zenoh do not implement DDS transient-local durability; existing Python mount publishers still use dynamic tf for compatibility.

Base: #4721. The SDK changes previously separated into #4774 are included here because they are part of this unmerged transport feature. Business callers migrate in their original feature PRs. The CI workflow at this layer runs SDK/macros checks against this layer's sources; full consumer interoperability checks are added at the stack tip.

Shared CDR foundation

Standard ROS definitions are fetched and verified through the existing source lock and generation pipeline in #4366. Native SDK support is included in #4722. Shared Python value implementations and regressions are reviewed in #4800–#4803 before the #4734 caller migration. SDK and consumers use the same generated Rust message crate, including Time, TransformStamped and TFMessage; there is no separate TF schema package or generation command. Camera/depth callers migrate in #4734 and mapping/navigation callers in #4737.

The external CDR and transforms library pins remain unchanged. Local verification passed 122 SDK tests, all existing native consumer suites, and all 24 real native/DimSim/port acceptance tests without skips. Seven staged Nix source layouts resolve exactly one message crate with locked Cargo metadata. This is not a full Nix build or hardware validation. Fresh CI runs verify #4722 independently and the combined stack tip.

Stack #4804 contains the 12 original feature PRs and four separately reviewed adapter/buffer PRs (#4800–#4803). The redundant #4774 is superseded by #4722. No feature PR has been merged into main; existing conflicts with main and the WIP cutover failures in #4739 remain.

@github-actions github-actions Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go2 replay realtime (arm64)

Details
Benchmark suite Current: deecf9a Previous: ecc2b8f Ratio
peak memory 1602.242 MB 1570.996 MB 1.02
peak threads 357 threads 355 threads 1.01
network (transport) 2722.06 MB 2730.387 MB 1.00
disk write 1.719 MB 1.496 MB 1.15
instructions 115.629 G 115 G 1.01

This comment was automatically generated by workflow using github-action-benchmark.

@codecov

codecov Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
7279 1 7278 61
View the top 1 failed test(s) by shortest run time
dimos.perception.detection.type.test_detection3d::test_guess_projection
Stack Traces | 0.725s run time
get_moment_2d = <functools._lru_cache_wrapper object at 0x7a5813a70040>
publish_moment = <function publish_moment.<locals>.publisher at 0x7a5813ca14e0>

    def test_guess_projection(get_moment_2d, publish_moment) -> None:
        moment = get_moment_2d()
        for key, value in moment.items():
            print(key, "====================================")
            print(value)
    
        moment.get("camera_info")
        detection2d = moment.get("detections2d")[0]
        tf = moment.get("tf")
        tf.get("camera_optical", "world", detection2d.ts, 5.0)
    
        # for stash
        # detection3d = Detection3D.from_2d(detection2d, 1.5, camera_info, transform)
        # print(detection3d)
    
>       publish_moment(moment)

detection2d = Detection2DBBox(bbox=(503.43731689453125, 249.89385986328125, 655.9505004882812, 469.82879638671875), track_id=1, clas...70.490248, image=Image(shape=(720, 1280, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=1757960670.490248))
get_moment_2d = <functools._lru_cache_wrapper object at 0x7a5813a70040>
key        = 'detections2d'
moment     = {'camera_info': CameraInfo(height=720, width=1280, distortion_model='equidistant', frame_id='camera_optical', ts=17926...optical', ts=1757960670.490248), 'lidar_frame': PointCloud(points=31284, frame_id='world', ts=1757960670.4755309), ...}
publish_moment = <function publish_moment.<locals>.publisher at 0x7a5813ca14e0>
tf         = <dimos.protocol.tf.tf.TF object at 0x7a5813176ed0>
value      = <dimos.perception.detection.type.detection2d.imageDetections2D.ImageDetections2D object at 0x7a5813d089e0>

.../detection/type/test_detection3d.py:37: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../perception/detection/conftest.py:126: in publisher
    detections.publish(detections2d_val.to_ros_detection2d_array())
        detections = <dimos.core.transport.LCMTransport object at 0x7a5867a7ebd0>
        detections2d_val = <dimos.perception.detection.type.detection2d.imageDetections2D.ImageDetections2D object at 0x7a5813d089e0>
        moment     = {'camera_info': CameraInfo(height=720, width=1280, distortion_model='equidistant', frame_id='camera_optical', ts=17926...optical', ts=1757960670.490248), 'lidar_frame': PointCloud(points=31284, frame_id='world', ts=1757960670.4755309), ...}
dimos/core/stream.py:107: in publish
    self.broadcast(None, msg)
        msg        = <dimos_lcm.vision_msgs.Detection2DArray.Detection2DArray object at 0x7a589777a500>
        self       = <dimos.core.transport.LCMTransport object at 0x7a5867a7ebd0>
dimos/core/transport.py:164: in broadcast
    self.lcm.publish(self.topic, msg)
        _          = None
        msg        = <dimos_lcm.vision_msgs.Detection2DArray.Detection2DArray object at 0x7a589777a500>
        self       = <dimos.core.transport.LCMTransport object at 0x7a5867a7ebd0>
.../protocol/pubsub/encoders.py:68: in publish
    encoded_message = self.encode(message, topic)
        __class__  = <class 'dimos.protocol.pubsub.encoders.PubSubEncoderMixin'>
        message    = <dimos_lcm.vision_msgs.Detection2DArray.Detection2DArray object at 0x7a589777a500>
        self       = <dimos.protocol.pubsub.impl.lcmpubsub.LCM object at 0x7a5867a7ec30>
        topic      = Topic(topic='/detections', lcm_type=<class 'dimos.msgs.vision_msgs.Detection2DArray.Detection2DArray'>, message_type=<class 'dimos.msgs.vision_msgs.Detection2DArray.Detection2DArray'>)
.../protocol/pubsub/encoders.py:149: in encode
    return descriptor.codec.encode(msg)
        descriptor = MessageDescriptor(message_type=<class 'dimos.msgs.vision_msgs.Detection2DArray.Detection2DArray'>, encoding='lcm', nam...sgs.Detection2DArray', codec=LCMCodec(message_type=<class 'dimos.msgs.vision_msgs.Detection2DArray.Detection2DArray'>))
        msg        = <dimos_lcm.vision_msgs.Detection2DArray.Detection2DArray object at 0x7a589777a500>
        self       = <dimos.protocol.pubsub.impl.lcmpubsub.LCM object at 0x7a5867a7ec30>
        topic      = Topic(topic='/detections', lcm_type=<class 'dimos.msgs.vision_msgs.Detection2DArray.Detection2DArray'>, message_type=<class 'dimos.msgs.vision_msgs.Detection2DArray.Detection2DArray'>)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = LCMCodec(message_type=<class 'dimos.msgs.vision_msgs.Detection2DArray.Detection2DArray'>)
message = <dimos_lcm.vision_msgs.Detection2DArray.Detection2DArray object at 0x7a589777a500>

    def encode(self, message: T) -> bytes:
        if not isinstance(message, self.message_type):
>           raise TypeError("Message does not match the declared type")
E           TypeError: Message does not match the declared type

message    = <dimos_lcm.vision_msgs.Detection2DArray.Detection2DArray object at 0x7a589777a500>
self       = LCMCodec(message_type=<class 'dimos.msgs.vision_msgs.Detection2DArray.Detection2DArray'>)

.../protocol/pubsub/codec.py:41: TypeError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@TomCC7
TomCC7 added this pull request to stack #4743 October 20, 2026 22:26
Comment thread dimos/core/cdr_transport.py Outdated
@TomCC7
TomCC7 force-pushed the cc/feat/cdr-unit-transports branch from 254cb8b to 2b46518 Compare October 21, 2026 01:05
@TomCC7 TomCC7 changed the title feat(transport): support CDR across Python and native SDK transports feat(transport): share CDR and legacy codecs across existing transports Oct 21, 2026
Comment thread dimos/core/transport.py Outdated
@greptile-apps

greptile-apps Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] No outstanding findings block merging this PR.

Summary

This PR shares message codecs across LCM, Zenoh, and WebRTC. Generated messages use CDR; legacy messages keep their LCM format.

  • Typed LCM and Zenoh topics now choose CDR or legacy LCM encoding.
  • Typed WebRTC streams now encode generated messages with CDR.
  • ROS and DDS transports now require adapters for generated CDR messages.
  • Message setup docs use working links and current import paths.

Reviews (2) · Last reviewed commit: "fix(transport): preserve native DDS type..." · Reviewed by Greptile

Comment thread dimos/core/transport_factory.py Outdated
Comment thread dimos/core/transport.py Outdated
@TomCC7

TomCC7 commented Oct 21, 2026

Copy link
Copy Markdown
Member Author

@greptile review

@TomCC7
TomCC7 force-pushed the cc/feat/cdr-unit-transports branch from 23a3480 to 42b9f1f Compare October 21, 2026 04:39
@TomCC7
TomCC7 force-pushed the cc/feat/cdr-unit-transports branch from 42b9f1f to deecf9a Compare October 21, 2026 18:43
@TomCC7
TomCC7 removed this pull request from stack #4743 October 22, 2026 18:51
@TomCC7
TomCC7 added this pull request to stack #4776 October 22, 2026 18:52
@TomCC7
TomCC7 removed this pull request from stack #4776 October 23, 2026 08:47
@TomCC7
TomCC7 added this pull request to stack #4799 October 23, 2026 08:47
@TomCC7 TomCC7 changed the title feat(transport): share CDR and legacy codecs across existing transports feat(transport): integrate shared CDR codecs and native SDK Oct 23, 2026
@TomCC7
TomCC7 removed this pull request from stack #4799 October 23, 2026 09:19
@TomCC7
TomCC7 added this pull request to stack #4804 October 23, 2026 09:19

This branch was successfully deployed

1 active (outdated) deployment
cachix — 42b9f1f5 Deployed Oct 21, 2026 by TomCC7 via cachix-build-macos #13733
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