Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various optimizations #319

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
444e418
disable redundant centering of occupiedSpace
dfremont Apr 26, 2024
5f5f117
apply MeshRegion transformations simultaneously
dfremont Apr 26, 2024
ee6e0db
reduce redundant checks on occupiedSpace
dfremont Apr 27, 2024
0ec764d
improve backtrace for errors inside Point @properties
dfremont Apr 27, 2024
0a42892
PolygonalFootprintRegion.containsObject checks convex hull before exa…
dfremont Apr 27, 2024
3186598
speed up bounding box intersection check
dfremont Apr 27, 2024
13baa00
built-in mutators directly modify objects
dfremont Apr 27, 2024
46e1cfd
Merge branch 'main' into dfremont_optimizations
dfremont Apr 27, 2024
2555912
[WIP] precompute geometric data when shape/dimensions are fixed
dfremont Apr 29, 2024
6b451cb
Merge branch 'main' into dfremont_optimizations
dfremont Nov 26, 2024
7b4f06c
precompute geometric data when shape/dimensions are fixed
dfremont Dec 8, 2024
5a9105e
improve requirement sorting heuristic
dfremont Dec 8, 2024
0fb3f2a
fix collision detection benchmarking
dfremont Dec 8, 2024
8631c4f
precompute body count of MeshVolumeRegion
dfremont Dec 8, 2024
1f2d659
speed up copying trimeshes when creating MeshRegions
dfremont Dec 8, 2024
4bde5a5
avoid redundant scale computations for fixed shapes
dfremont Dec 9, 2024
e9a8e1e
reuse occupiedSpace for fixed objects
dfremont Dec 9, 2024
ca71a2e
compute MeshRegion.mesh lazily
dfremont Dec 9, 2024
3c51685
do circumradius check before computing bounding boxes; skip inradius …
dfremont Dec 9, 2024
93cc3ab
skip bounding box check if meshes are lazy
dfremont Dec 9, 2024
568a6e3
fix transforms of precomputed Shape data; cache MultiPoint of vertices
dfremont Dec 11, 2024
ca508ea
minor tweaks & extra tests to cover new lines
dfremont Dec 12, 2024
8ecc9bc
minor fix; more tests
dfremont Dec 13, 2024
d633f10
fix reproducibility issue
dfremont Jan 11, 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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ dependencies = [
"scikit-image ~= 0.21",
"scipy ~= 1.7",
"shapely ~= 2.0",
"trimesh >=4.0.9, <5",
"trimesh >=4.4.8, <5",
]

[project.optional-dependencies]
Expand Down
66 changes: 62 additions & 4 deletions src/scenic/core/object_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

from abc import ABC, abstractmethod
import collections
import functools
import inspect
import math
import random
import typing
Expand Down Expand Up @@ -77,7 +79,7 @@
toVector,
underlyingType,
)
from scenic.core.utils import DefaultIdentityDict, cached_method, cached_property
from scenic.core.utils import DefaultIdentityDict, cached, cached_method, cached_property
from scenic.core.vectors import (
Orientation,
Vector,
Expand Down Expand Up @@ -214,6 +216,7 @@ def __init__(self, properties, constProps=frozenset(), _internal=False):
self.properties = tuple(sorted(properties.keys()))
self._propertiesSet = set(self.properties)
self._constProps = constProps
self._sampleParent = None

@classmethod
def _withProperties(cls, properties, constProps=None):
Expand Down Expand Up @@ -544,7 +547,9 @@ def sampleGiven(self, value):
if not needsSampling(self):
return self
props = {prop: value[getattr(self, prop)] for prop in self.properties}
return type(self)(props, constProps=self._constProps, _internal=True)
obj = type(self)(props, constProps=self._constProps, _internal=True)
obj._sampleParent = self
return obj

def _allProperties(self):
return {prop: getattr(self, prop) for prop in self.properties}
Expand Down Expand Up @@ -599,6 +604,35 @@ def __repr__(self):
return f"{type(self).__name__}({allProps})"


def precomputed_property(func):
"""A @property which can be precomputed if its dependencies are not random.

Converts a function inside a subclass of `Constructible` into a method; the
function's arguments must correspond to the properties of the object needed
to compute this property. If any of those dependencies have random values,
this property will evaluate to `None`; otherwise it will be computed once
the first time it is needed and then reused across samples.
"""
deps = tuple(inspect.signature(func).parameters)

@cached
@functools.wraps(func)
def method(self):
args = [getattr(self, prop) for prop in deps]
if any(needsSampling(arg) for arg in args):
return None
return func(*args)

@functools.wraps(func)
def wrapper(self):
parent = self._sampleParent or self
return method(parent)

wrapper._scenic_cache_clearer = method._scenic_cache_clearer

return property(wrapper)


## Mutators


Expand Down Expand Up @@ -1297,14 +1331,38 @@ def _corners2D(self):
@cached_property
def occupiedSpace(self):
"""A region representing the space this object occupies"""
if self._sampleParent and self._sampleParent._hasStaticBounds:
return self._sampleParent.occupiedSpace

shape = self.shape
scaledShape = self._scaledShape
if scaledShape:
mesh = scaledShape.mesh
dimensions = None # mesh does not need to be scaled
convex = scaledShape.isConvex
else:
mesh = shape.mesh
dimensions = (self.width, self.length, self.height)
convex = shape.isConvex
return MeshVolumeRegion(
mesh=shape.mesh,
dimensions=(self.width, self.length, self.height),
mesh=mesh,
dimensions=dimensions,
position=self.position,
rotation=self.orientation,
centerMesh=False,
_internal=True,
_isConvex=convex,
_shape=shape,
_scaledShape=scaledShape,
)

@precomputed_property
def _scaledShape(shape, width, length, height):
return MeshVolumeRegion(
mesh=shape.mesh,
dimensions=(width, length, height),
centerMesh=False,
_internal=True,
_isConvex=shape.isConvex,
)

Expand Down
Loading
Loading