Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
941e02c
lcm Vector3
leshy Jun 18, 2025
7f1e0c6
stricter vector tests
leshy Jun 18, 2025
2a974b1
typing fixes for vector init
leshy Jun 18, 2025
ce81d85
multiple dispatch beartype version of Vector3
leshy Jun 18, 2025
2b6cf21
pep 585 type hints
leshy Jun 18, 2025
f0db57e
correct typing for Vector3
leshy Jun 18, 2025
3699f00
removed Vector3 typevar
leshy Jun 18, 2025
34b3b52
cleaning up typing for mypy
leshy Jun 18, 2025
aebbf2c
resolved all typing issues
leshy Jun 18, 2025
f7ca202
workflow fix
leshy Jun 18, 2025
dba6a39
rebuild py trigger
leshy Jun 18, 2025
edb3b38
added quaternion type
leshy Jun 18, 2025
f01b7ca
euler conversion
leshy Jun 18, 2025
e0d32a1
pitch/yaw/roll accessors for vector3
leshy Jun 18, 2025
4f9b6de
quaternion <-> euler conversions
leshy Jun 18, 2025
719b6e2
mypy check within dev repo
leshy Jun 18, 2025
1402cdc
Merge branch 'lcm_unitree_client' of github.com:dimensionalOS/dimos i…
leshy Jun 18, 2025
0e1bb2f
small vector fixes
leshy Jun 18, 2025
cc77e70
Pose message implemented
leshy Jun 18, 2025
b94477f
vector dimensionality set to 3
leshy Jun 18, 2025
7bc5f69
vector3 simple data storage
leshy Jun 18, 2025
3258d5e
lcm msgs are now installable
leshy Jun 18, 2025
70b534e
vector lcm encode/decode
leshy Jun 19, 2025
c55cda1
mypy precommit is problematic for now
leshy Jun 19, 2025
69027bf
testing LCM encode/decode
leshy Jun 19, 2025
70d08ed
attempt to fix install
leshy Jun 19, 2025
4eb83ad
type check in commit hooks
leshy Jun 19, 2025
51072b8
small msg cleanup
leshy Jun 19, 2025
954df92
protocol spec work, pubsub, rpc, service
leshy Jun 19, 2025
ef71385
new service default config implementation, redis recode
leshy Jun 19, 2025
59e81ba
generic message encoder/decoder sketch
leshy Jun 20, 2025
2dc9a3d
encoder/decoder mixin tests
leshy Jun 20, 2025
ecccef6
better encoder spec
leshy Jun 20, 2025
0517ae1
tests fixed
leshy Jun 20, 2025
d4a7b25
LCM encoder work
leshy Jun 20, 2025
a6e337b
tests fix
leshy Jun 20, 2025
056dfcb
added type validation to test workflow
leshy Jun 20, 2025
4eaaf59
mypy -v
leshy Jun 20, 2025
d0f3238
mypy should check protocol/ dir
leshy Jun 20, 2025
d3f728a
no verbose mypy
leshy Jun 20, 2025
5117d39
mypy ignore import-not-found
leshy Jun 20, 2025
d5eff21
encode/deode mixin updates
leshy Jun 24, 2025
9aea67c
environment modification for in-image lcm
leshy Jun 24, 2025
2f023a5
unifying pubsub spec
leshy Jun 24, 2025
c7c5c28
pubsub tests passing
leshy Jun 24, 2025
fe8838c
functional unsubscribe for pubsub
leshy Jun 24, 2025
1bd413a
tests/types fixes
leshy Jun 24, 2025
2800312
geometry_msgs updated for new lcm encode/decode API
leshy Jun 24, 2025
861f73e
passing geometry types through LCM in tests
leshy Jun 24, 2025
e829ccc
Merge branch 'dev' into lcm_unitree_client
leshy Jun 28, 2025
b280e61
Merge branch 'dev' into lcm_unitree_client
leshy Jun 28, 2025
c167ce7
image type implemented
leshy Jun 28, 2025
55b2c3c
image and data bugfixes, encoding tests
leshy Jun 28, 2025
fc2b543
starting lidar message conversion
leshy Jun 29, 2025
5c6eebe
removed dataclass from msgs, lidar msg compatible with pointcloud2
leshy Jun 29, 2025
4f05fa2
lidar replay
leshy Jun 29, 2025
99ec461
pointcloud encode/decode test, sensor reply fix, timeseries fix
leshy Jun 29, 2025
9196996
mini changes to sensor replay
leshy Jun 29, 2025
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
5 changes: 4 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,8 @@
},
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true
}
},
"runArgs": [
"--cap-add=NET_ADMIN"
]
}
5 changes: 5 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,13 @@ jobs:
exit 0

- uses: actions/checkout@v4

- name: Validate typing
run: |
/entrypoint.sh bash -c "mypy"

- name: Run tests
run: |
git config --global --add safe.directory '*'
/entrypoint.sh bash -c "${{ inputs.cmd }}"

13 changes: 13 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ repos:
name: format json
args: [ --autofix, --no-sort-keys ]

# - repo: local
# hooks:
# - id: mypy
# name: Type check
# # possible to also run within the dev image
# #entry: "./bin/dev mypy"
# entry: "./bin/mypy"
# language: python
# additional_dependencies: ["mypy==1.15.0", "numpy>=1.26.4,<2.0.0"]
# types: [python]

- repo: local
hooks:
- id: lfs_check
Expand All @@ -48,3 +59,5 @@ repos:
pass_filenames: false
entry: bin/lfs_check
language: script


Empty file added dimos/msgs/__init__.py
Empty file.
185 changes: 185 additions & 0 deletions dimos/msgs/geometry_msgs/Pose.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# 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 __future__ import annotations

import struct
from io import BytesIO
from typing import BinaryIO, TypeAlias

from lcm_msgs.geometry_msgs import Pose as LCMPose
from plum import dispatch

from dimos.msgs.geometry_msgs.Quaternion import Quaternion, QuaternionConvertable
from dimos.msgs.geometry_msgs.Vector3 import Vector3, VectorConvertable

# Types that can be converted to/from Pose
PoseConvertable: TypeAlias = (
tuple[VectorConvertable, QuaternionConvertable]
| LCMPose
| dict[str, VectorConvertable | QuaternionConvertable]
)


class Pose(LCMPose):
position: Vector3
orientation: Quaternion
name = "geometry_msgs.Pose"

@classmethod
def lcm_decode(cls, data: bytes | BinaryIO):
if not hasattr(data, "read"):
data = BytesIO(data)
if data.read(8) != cls._get_packed_fingerprint():
raise ValueError("Decode error")
return cls._lcm_decode_one(data)

@classmethod
def _lcm_decode_one(cls, buf):
return cls(Vector3._decode_one(buf), Quaternion._decode_one(buf))

def lcm_encode(self) -> bytes:
return super().encode()

@dispatch
def __init__(self) -> None:
"""Initialize a pose at origin with identity orientation."""
self.position = Vector3(0.0, 0.0, 0.0)
self.orientation = Quaternion(0.0, 0.0, 0.0, 1.0)

@dispatch
def __init__(self, x: int | float, y: int | float, z: int | float) -> None:
"""Initialize a pose with position and identity orientation."""
self.position = Vector3(x, y, z)
self.orientation = Quaternion(0.0, 0.0, 0.0, 1.0)

@dispatch
def __init__(
self,
x: int | float,
y: int | float,
z: int | float,
qx: int | float,
qy: int | float,
qz: int | float,
qw: int | float,
) -> None:
"""Initialize a pose with position and orientation."""
self.position = Vector3(x, y, z)
self.orientation = Quaternion(qx, qy, qz, qw)

@dispatch
def __init__(self, position: VectorConvertable) -> None:
self.position = Vector3(position)
self.orientation = Quaternion()

@dispatch
def __init__(self, orientation: QuaternionConvertable) -> None:
self.position = Vector3()
self.orientation = Quaternion(orientation)

@dispatch
def __init__(self, position: VectorConvertable, orientation: QuaternionConvertable) -> None:
"""Initialize a pose with position and orientation."""
self.position = Vector3(position)
self.orientation = Quaternion(orientation)

@dispatch
def __init__(self, pose_tuple: tuple[VectorConvertable, QuaternionConvertable]) -> None:
"""Initialize from a tuple of (position, orientation)."""
self.position = Vector3(pose_tuple[0])
self.orientation = Quaternion(pose_tuple[1])

@dispatch
def __init__(self, pose_dict: dict[str, VectorConvertable | QuaternionConvertable]) -> None:
"""Initialize from a dictionary with 'position' and 'orientation' keys."""
self.position = Vector3(pose_dict["position"])
self.orientation = Quaternion(pose_dict["orientation"])

@dispatch
def __init__(self, pose: "Pose") -> None:
"""Initialize from another Pose (copy constructor)."""
self.position = Vector3(pose.position)
self.orientation = Quaternion(pose.orientation)

@dispatch
def __init__(self, lcm_pose: LCMPose) -> None:
"""Initialize from an LCM Pose."""
self.position = Vector3(lcm_pose.position.x, lcm_pose.position.y, lcm_pose.position.z)
self.orientation = Quaternion(
lcm_pose.orientation.x,
lcm_pose.orientation.y,
lcm_pose.orientation.z,
lcm_pose.orientation.w,
)

@property
def x(self) -> float:
"""X coordinate of position."""
return self.position.x

@property
def y(self) -> float:
"""Y coordinate of position."""
return self.position.y

@property
def z(self) -> float:
"""Z coordinate of position."""
return self.position.z

@property
def roll(self) -> float:
"""Roll angle in radians."""
return self.orientation.to_euler().roll

@property
def pitch(self) -> float:
"""Pitch angle in radians."""
return self.orientation.to_euler().pitch

@property
def yaw(self) -> float:
"""Yaw angle in radians."""
return self.orientation.to_euler().yaw

def __repr__(self) -> str:
return f"Pose(position={self.position!r}, orientation={self.orientation!r})"

def __str__(self) -> str:
return (
f"Pose(pos=[{self.x:.3f}, {self.y:.3f}, {self.z:.3f}], "
f"euler=[{self.roll:.3f}, {self.pitch:.3f}, {self.yaw:.3f}])"
)

def __eq__(self, other) -> bool:
"""Check if two poses are equal."""
if not isinstance(other, Pose):
return False
return self.position == other.position and self.orientation == other.orientation


@dispatch
def to_pose(value: "Pose") -> Pose:
"""Pass through Pose objects."""
return value


@dispatch
def to_pose(value: PoseConvertable | Pose) -> Pose:
"""Convert a pose-compatible value to a Pose object."""
return Pose(value)


PoseLike: TypeAlias = PoseConvertable | Pose
Loading
Loading