|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""A simple 6DOF pose container. |
|
""" |
|
|
|
import dataclasses |
|
import numpy as np |
|
from scipy.spatial import transform |
|
|
|
|
|
class NoCopyAsDict(object): |
|
"""Base class for dataclasses. Avoids a copy in the asdict() call.""" |
|
|
|
def asdict(self): |
|
"""Replacement for dataclasses.asdict. |
|
|
|
TF Dataset does not handle dataclasses.asdict, which uses copy.deepcopy when |
|
setting values in the output dict. This causes issues with tf.Dataset. |
|
Instead, shallow copy contents. |
|
|
|
Returns: |
|
dict containing contents of dataclass. |
|
""" |
|
return {k.name: getattr(self, k.name) for k in dataclasses.fields(self)} |
|
|
|
|
|
@dataclasses.dataclass |
|
class Pose3d(NoCopyAsDict): |
|
"""Simple container for translation and rotation.""" |
|
|
|
rotation: transform.Rotation |
|
translation: np.ndarray |
|
|
|
@property |
|
def vec7(self): |
|
return np.concatenate([self.translation, self.rotation.as_quat()]) |
|
|
|
def serialize(self): |
|
return { |
|
"rotation": self.rotation.as_quat().tolist(), |
|
"translation": self.translation.tolist(), |
|
} |
|
|
|
@staticmethod |
|
def deserialize(data): |
|
return Pose3d( |
|
rotation=transform.Rotation.from_quat(data["rotation"]), |
|
translation=np.array(data["translation"]), |
|
) |
|
|
|
def __eq__(self, other): |
|
return np.array_equal( |
|
self.rotation.as_quat(), other.rotation.as_quat() |
|
) and np.array_equal(self.translation, other.translation) |
|
|
|
def __ne__(self, other): |
|
return not self.__eq__(other) |
|
|