Skip to content
Merged
Show file tree
Hide file tree
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
6 changes: 6 additions & 0 deletions dimos/core/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ def _close_module(self) -> None:
if hasattr(self, "_disposables"):
self._disposables.dispose()

# Break the In/Out -> owner -> self reference cycle so the instance
# can be freed by refcount instead of waiting for GC.
for attr in list(vars(self).values()):
if isinstance(attr, (In, Out)):
attr.owner = None

def _close_rpc(self) -> None:
if self.rpc:
self.rpc.stop() # type: ignore[attr-defined]
Expand Down
5 changes: 5 additions & 0 deletions dimos/mapping/voxels.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ def start(self) -> None:
@rpc
def stop(self) -> None:
super().stop()
# Free tensor-tracked objects eagerly so Open3D does not report them as leaks.
self.get_global_pointcloud.invalidate_cache(self)
self.get_global_pointcloud2.invalidate_cache(self)
self.vbg = None
self._voxel_hashmap = None

def _on_frame(self, frame: PointCloud2) -> None:
self.add_frame(frame)
Expand Down
18 changes: 9 additions & 9 deletions dimos/msgs/sensor_msgs/PointCloud2.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,27 +363,27 @@ def as_numpy(
colors = np.asarray(self.pointcloud.colors) if self.pointcloud.has_colors() else None
return points, colors

@functools.cache
def get_axis_aligned_bounding_box(self) -> o3d.geometry.AxisAlignedBoundingBox:
@functools.cached_property
def axis_aligned_bounding_box(self) -> o3d.geometry.AxisAlignedBoundingBox:
"""Get axis-aligned bounding box of the point cloud."""
return self.pointcloud.get_axis_aligned_bounding_box()

@functools.cache
def get_oriented_bounding_box(self) -> o3d.geometry.OrientedBoundingBox:
@functools.cached_property
def oriented_bounding_box(self) -> o3d.geometry.OrientedBoundingBox:
"""Get oriented bounding box of the point cloud."""
return self.pointcloud.get_oriented_bounding_box()

@functools.cache
def get_bounding_box_dimensions(self) -> tuple[float, float, float]:
@functools.cached_property
def bounding_box_dimensions(self) -> tuple[float, float, float]:
"""Get dimensions (width, height, depth) of axis-aligned bounding box."""
bbox = self.get_axis_aligned_bounding_box()
bbox = self.axis_aligned_bounding_box
extent = bbox.get_extent()
return tuple(extent)

def bounding_box_intersects(self, other: PointCloud2) -> bool:
# Get axis-aligned bounding boxes
bbox1 = self.get_axis_aligned_bounding_box()
bbox2 = other.get_axis_aligned_bounding_box()
bbox1 = self.axis_aligned_bounding_box
bbox2 = other.axis_aligned_bounding_box

# Get min and max bounds
min1 = bbox1.get_min_bound()
Expand Down
5 changes: 4 additions & 1 deletion dimos/perception/detection/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ def moment_provider(**kwargs) -> Moment:
"tf": tf,
}

return moment_provider
yield moment_provider
moment_provider.cache_clear()


@pytest.fixture(scope="session")
Expand Down Expand Up @@ -217,6 +218,7 @@ def moment_provider(**kwargs) -> Moment2D:

yield moment_provider

moment_provider.cache_clear()
module._close_module()


Expand Down Expand Up @@ -250,6 +252,7 @@ def moment_provider(**kwargs) -> Moment3D:
}

yield moment_provider
moment_provider.cache_clear()
if module is not None:
module._close_module()

Expand Down
2 changes: 1 addition & 1 deletion dimos/perception/detection/type/detection3d/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def update_object(self, other: Object) -> None:

def get_oriented_bounding_box(self) -> Any:
"""Get oriented bounding box of the pointcloud."""
return self.pointcloud.get_oriented_bounding_box()
return self.pointcloud.oriented_bounding_box

def scene_entity_label(self) -> str:
"""Get label for scene visualization."""
Expand Down
6 changes: 3 additions & 3 deletions dimos/perception/detection/type/detection3d/pointcloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ def pose(self) -> PoseStamped:

def get_bounding_box(self): # type: ignore[no-untyped-def]
"""Get axis-aligned bounding box of the detection's pointcloud."""
return self.pointcloud.get_axis_aligned_bounding_box()
return self.pointcloud.axis_aligned_bounding_box

def get_oriented_bounding_box(self): # type: ignore[no-untyped-def]
"""Get oriented bounding box of the detection's pointcloud."""
return self.pointcloud.get_oriented_bounding_box()
return self.pointcloud.oriented_bounding_box

def get_bounding_box_dimensions(self) -> tuple[float, float, float]:
"""Get dimensions (width, height, depth) of the detection's bounding box."""
return self.pointcloud.get_bounding_box_dimensions()
return self.pointcloud.bounding_box_dimensions

def bounding_box_intersects(self, other: Detection3DPC) -> bool:
"""Check if this detection's bounding box intersects with another's."""
Expand Down
6 changes: 3 additions & 3 deletions dimos/utils/decorators/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from functools import wraps
import threading
import time
from typing import Any, Protocol, TypeVar
from typing import Any, Protocol, TypeVar, cast

from .accumulators import Accumulator, LatestAccumulator

Expand Down Expand Up @@ -113,7 +113,7 @@ def wrapper(*args, **kwargs): # type: ignore[no-untyped-def]
return decorator


def simple_mcache(method: Callable) -> Callable: # type: ignore[type-arg]
def simple_mcache(method: Callable[..., _CacheReturn]) -> CachedMethod[_CacheReturn]:
"""
Decorator to cache the result of a method call on the instance.

Expand Down Expand Up @@ -163,7 +163,7 @@ def invalidate_cache(instance: Any) -> None:

getter.invalidate_cache = invalidate_cache # type: ignore[attr-defined]

return getter
return cast("CachedMethod[_CacheReturn]", getter)


def retry(max_retries: int = 3, on_exception: type[Exception] = Exception, delay: float = 0.0): # type: ignore[no-untyped-def]
Expand Down
2 changes: 2 additions & 0 deletions dimos/utils/testing/moment.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def start(self) -> None:
pass

def stop(self) -> None:
self.value = None
self.transport.stop()


Expand All @@ -65,6 +66,7 @@ def start(self) -> None:
pass

def stop(self) -> None:
self.value = None
self.transport.stop()


Expand Down
Loading