Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions dimos/core/test_lcmmsg_gen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#!/usr/bin/env python3

# Copyright 2025 Dimensional Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from lcm_msgs.geometry_msgs import Orientation, Pose, PoseStamped, Vector3
from lcm_msgs.std_msgs import Header


# None of the tests actually pass apart from the first two.
# The rest of the tests are a proposal for functionality to be added.
#
# Below mutable init is how current lcmgen can only be used,
# This is not very ergonomical, and these are the most common objects we use,
# so we need a way to both have a better init for them by default, coming
# out of lcmgen,
# as well as to have a better way to modify individual types by hand for
# type specific convinience methods.
#
# Some examples:
# header taking datetime or float, instead of a weird ros timestamp dictionary format,
# Quaternion having .yaw() pitch() or to_euler() -> Vector3 methods,etc
# Vector taking a list or tuple as init, not just kwargs
#
def test_vector_current_init():
vector = Vector3()
vector.x = 1.0
vector.y = 2.0
vector.z = 3.0


def test_vector_defaults():
vector = Vector3()
assert vector.x == 0.0
assert vector.y == 0.0
assert vector.z == 0.0


def test_vector_init():
vector = Vector3(x=1.0, y=2.0, z=3.0)
assert vector.x == 1.0
assert vector.y == 2.0
assert vector.z == 3.0


# I'm not sure if easily achievable,
# but this is a much better interface
def test_vector_args_init():
vector = Vector3(1.0, 2.0, 3.0)
assert vector.x == 1.0
assert vector.y == 2.0
assert vector.z == 3.0


# if we are using these types across the platform, they are the most common
# objects used, we have to be able to subclass and implement convinience
# methods (like above positional arg init)
#
# how can we hand- add to a specific autogenerated lcm_msg type?
# while also keeping the new class within the original dep structure
# (so Pose would refer to the new convinient Vector3 subclass,
# without recoding the Pose itself?)


def test_vector_partial_defaults():
vector = Vector3(x=1.0)
assert vector.x == 1.0
assert vector.y == 0.0
assert vector.z == 0.0


def test_vector_encode_decode():
msg = Vector3(x=1.0, y=2.0, z=3.0).encode()
assert isinstance(msg, bytes)
vector = Vector3.decode(msg)
assert vector.x == 1.0
assert vector.y == 2.0
assert vector.z == 3.0


def test_pose_stamped_init():
pose = PoseStamped(
pose=Pose(
position=Vector3(1.0, 2.0, 3.0),
orientation=Orientation(1.0, 2.0, 3.0, 4.0),
),
header=Header(stamp=1234567890, frame_id="test_frame"),
)


# not sure if we can achieve this automatically easily, but this is
# a much better interface
def test_pose_fancy_init():
pose = PoseStamped(
# depeer init implicit
position=Vector3(1.0, 2.0, 3.0),
orientation=Orientation(1.0, 2.0, 3.0, 4.0),
stamp=1234567890,
frame_id="test_frame",
)

assert pose.pose.position.x == 1.0


def test_pose_partial_fancy_init():
# partially implicit init
pose = PoseStamped(
# pose explicit
pose=Pose(
# I'm hoping for positional argument support here
position=Vector3(1.0, 2.0, 3.0),
orientation=Orientation(1.0, 2.0, 3.0, 4.0),
),
# header implicit
stamp=1234567890,
frame_id="test_frame",
)

assert pose.pose.position.x == 1.0

# can Stamped modules provide access to the underlying data
# directly? Maybe manual Stamped subclass?
assert pose.position.y == 2.0
Loading