From 021f3581b6303957b38352bb4ad27640dd4e4c14 Mon Sep 17 00:00:00 2001 From: diegoferigo Date: Thu, 12 Sep 2024 10:14:32 +0200 Subject: [PATCH 1/5] Update list of floats serialization/deserialization --- src/rod/sdf/element.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rod/sdf/element.py b/src/rod/sdf/element.py index da94df8..bfa11c5 100644 --- a/src/rod/sdf/element.py +++ b/src/rod/sdf/element.py @@ -47,7 +47,7 @@ def serialize_float(data: float) -> str: @staticmethod def serialize_list(data: list[float]) -> str: assert isinstance(data, list) - return " ".join(np.array(data, dtype=str)) + return " ".join(np.array(data, dtype=float).astype(str)) @staticmethod def deserialize_list(data: str, length: int | None = None) -> list[float]: @@ -57,4 +57,4 @@ def deserialize_list(data: str, length: int | None = None) -> list[float]: if length is not None: assert array.size == length - return list(array) + return array.tolist() From 1a82b30564662b7a9c23662e2b4af9b506d207c8 Mon Sep 17 00:00:00 2001 From: diegoferigo Date: Thu, 12 Sep 2024 10:15:39 +0200 Subject: [PATCH 2/5] Fix wrong typing of Geometry fields --- src/rod/sdf/geometry.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rod/sdf/geometry.py b/src/rod/sdf/geometry.py index 1df269d..4c12be9 100644 --- a/src/rod/sdf/geometry.py +++ b/src/rod/sdf/geometry.py @@ -114,9 +114,9 @@ class Sphere(Element): class Geometry(Element): box: Box | None = dataclasses.field(default=None) capsule: Capsule | None = dataclasses.field(default=None) - cylinder: Capsule | None = dataclasses.field(default=None) - ellipsoid: Capsule | None = dataclasses.field(default=None) + cylinder: Cylinder | None = dataclasses.field(default=None) + ellipsoid: Ellipsoid | None = dataclasses.field(default=None) heightmap: Heightmap | None = dataclasses.field(default=None) mesh: Mesh | None = dataclasses.field(default=None) - plane: Mesh | None = dataclasses.field(default=None) + plane: Plane | None = dataclasses.field(default=None) sphere: Sphere | None = dataclasses.field(default=None) From a57adac7ece5ff627c1a4eea2ea1e74717cdad08 Mon Sep 17 00:00:00 2001 From: diegoferigo Date: Thu, 12 Sep 2024 10:27:04 +0200 Subject: [PATCH 3/5] Add helper methods to Geometry to get the underlying shape --- src/rod/sdf/geometry.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/rod/sdf/geometry.py b/src/rod/sdf/geometry.py index 4c12be9..926f0e9 100644 --- a/src/rod/sdf/geometry.py +++ b/src/rod/sdf/geometry.py @@ -120,3 +120,28 @@ class Geometry(Element): mesh: Mesh | None = dataclasses.field(default=None) plane: Plane | None = dataclasses.field(default=None) sphere: Sphere | None = dataclasses.field(default=None) + + def geometries( + self, + ) -> list[Box | Capsule | Cylinder | Ellipsoid | Heightmap | Mesh | Plane | Sphere]: + + return [ + self.__getattribute__(field.name) + for field in dataclasses.fields(self) + if self.__getattribute__(field.name) is not None + ] + + def geometry( + self, + ) -> ( + Box | Capsule | Cylinder | Ellipsoid | Heightmap | Mesh | Plane | Sphere | None + ): + """Return the actual shape of the geometry object""" + + geometries = self.geometries() + + if len(geometries) > 1: + msg = "More than one geometry found, returning the first one" + logging.warning(msg) + + return geometries[0] if len(geometries) > 0 else None From 9ec33954ec6e2a20d46463960661493216a18700 Mon Sep 17 00:00:00 2001 From: diegoferigo Date: Thu, 12 Sep 2024 10:26:55 +0200 Subject: [PATCH 4/5] Add support for continuous joints with no lower and upper limits --- src/rod/sdf/joint.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/rod/sdf/joint.py b/src/rod/sdf/joint.py index 0d1b94c..eeae4c5 100644 --- a/src/rod/sdf/joint.py +++ b/src/rod/sdf/joint.py @@ -9,12 +9,15 @@ @dataclasses.dataclass class Limit(Element): - lower: float = dataclasses.field( - metadata=mashumaro.field_options(serialize=Element.serialize_float) + + lower: Optional[float] = dataclasses.field( + default=None, + metadata=mashumaro.field_options(serialize=Element.serialize_float), ) - upper: float = dataclasses.field( - metadata=mashumaro.field_options(serialize=Element.serialize_float) + upper: Optional[float] = dataclasses.field( + default=None, + metadata=mashumaro.field_options(serialize=Element.serialize_float), ) effort: Optional[float] = dataclasses.field( From cc68de03c831ab22492154063c2baf81a0fa5251 Mon Sep 17 00:00:00 2001 From: diegoferigo Date: Thu, 12 Sep 2024 13:34:27 +0200 Subject: [PATCH 5/5] Address review Co-authored-by: Filippo Luca Ferretti <102977828+flferretti@users.noreply.github.com> --- src/rod/sdf/element.py | 2 +- src/rod/sdf/geometry.py | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/rod/sdf/element.py b/src/rod/sdf/element.py index bfa11c5..06ba9fa 100644 --- a/src/rod/sdf/element.py +++ b/src/rod/sdf/element.py @@ -47,7 +47,7 @@ def serialize_float(data: float) -> str: @staticmethod def serialize_list(data: list[float]) -> str: assert isinstance(data, list) - return " ".join(np.array(data, dtype=float).astype(str)) + return " ".join(map(lambda element: str(float(element)), data)) @staticmethod def deserialize_list(data: str, length: int | None = None) -> list[float]: diff --git a/src/rod/sdf/geometry.py b/src/rod/sdf/geometry.py index 926f0e9..767b2a7 100644 --- a/src/rod/sdf/geometry.py +++ b/src/rod/sdf/geometry.py @@ -1,4 +1,7 @@ +from __future__ import annotations + import dataclasses +from typing import ClassVar import mashumaro @@ -112,6 +115,11 @@ class Sphere(Element): @dataclasses.dataclass class Geometry(Element): + + GeometryType: ClassVar = ( + Box | Capsule | Cylinder | Ellipsoid | Heightmap | Mesh | Plane | Sphere + ) + box: Box | None = dataclasses.field(default=None) capsule: Capsule | None = dataclasses.field(default=None) cylinder: Cylinder | None = dataclasses.field(default=None) @@ -121,9 +129,7 @@ class Geometry(Element): plane: Plane | None = dataclasses.field(default=None) sphere: Sphere | None = dataclasses.field(default=None) - def geometries( - self, - ) -> list[Box | Capsule | Cylinder | Ellipsoid | Heightmap | Mesh | Plane | Sphere]: + def geometries(self) -> list[Geometry.GeometryType]: return [ self.__getattribute__(field.name) @@ -131,12 +137,8 @@ def geometries( if self.__getattribute__(field.name) is not None ] - def geometry( - self, - ) -> ( - Box | Capsule | Cylinder | Ellipsoid | Heightmap | Mesh | Plane | Sphere | None - ): - """Return the actual shape of the geometry object""" + def geometry(self) -> Geometry.GeometryType | None: + """Return the actual geometry stored in the object""" geometries = self.geometries()