Source code for ed.shape

from typing import List

from ed_msgs.msg import EntityInfo
import PyKDL as kdl

from .util.equal_hash_mixin import EqualHashMixin


[docs]class Shape(EqualHashMixin): """Represents shape properties""" def __init__(self): pass @property def convex_hull(self) -> List[kdl.Vector]: return self._calc_convex_hull()
[docs] def _calc_convex_hull(self): raise NotImplementedError( "_calc_convex_hull must be implemented by subclasses. " "Class {cls} has no implementation".format(cls=self.__class__.__name__) )
@property def size(self) -> float: return self._calc_size()
[docs] def _calc_size(self) -> float: raise NotImplementedError( "_calc_size must be implemented by subclasses. " "Class {cls} has no implementation".format(cls=self.__class__.__name__) )
@property def x_min(self) -> float: return self._calc_x_min()
[docs] def _calc_x_min(self) -> float: raise NotImplementedError( "_calc_x_min must be implemented by subclasses. " "Class {cls} has no implementation".format(cls=self.__class__.__name__) )
@property def x_max(self) -> float: return self._calc_x_max()
[docs] def _calc_x_max(self) -> float: raise NotImplementedError( "_calc_x_max must be implemented by subclasses. " "Class {cls} has no implementation".format(cls=self.__class__.__name__) )
@property def y_min(self) -> float: return self._calc_y_min()
[docs] def _calc_y_min(self) -> float: raise NotImplementedError( "_calc_y_min must be implemented by subclasses. " "Class {cls} has no implementation".format(cls=self.__class__.__name__) )
@property def y_max(self) -> float: return self._calc_y_max()
[docs] def _calc_y_max(self) -> float: raise NotImplementedError( "_calc_y_max must be implemented by subclasses. " "Class {cls} has no implementation".format(cls=self.__class__.__name__) )
@property def z_min(self) -> float: return self._calc_z_min()
[docs] def _calc_z_min(self) -> float: raise NotImplementedError( "_calc_z_min must be implemented by subclasses. " "Class {cls} has no implementation".format(cls=self.__class__.__name__) )
@property def z_max(self) -> float: return self._calc_z_max()
[docs] def _calc_z_max(self) -> float: raise NotImplementedError( "_calc_z_max must be implemented by subclasses. " "Class {cls} has no implementation".format(cls=self.__class__.__name__) )
[docs]class RightPrism(Shape): """ Represents a right prism, i.e., a prism in which the joining edges and faces are perpendicular to the base faces. This is typical for the shapes resulting from the convex hull, z min and z max of EntityInfo """ def __init__(self, convex_hull: List[kdl.Vector], z_min: float, z_max: float): """ Constructor :param convex_hull: list with vectors representing the vertices of the convex hull. N.B.: these should only contain x and y values, the z-values are not relevant (the height information is contained in the z_min and z_max parameters). :param z_min: Minimum height [m] w.r.t. the center of the corresponding Entity :param z_max: Maximum height [m] w.r.t. the center of the corresponding Entity """ super(RightPrism, self).__init__() self._convex_hull = convex_hull self._z_min = z_min self._z_max = z_max
[docs] def _calc_x_max(self) -> float: return max(ch.x() for ch in self._convex_hull)
[docs] def _calc_x_min(self) -> float: return min(ch.x() for ch in self._convex_hull)
[docs] def _calc_y_max(self) -> float: return max(ch.y() for ch in self._convex_hull)
[docs] def _calc_y_min(self) -> float: return min(ch.y() for ch in self._convex_hull)
[docs] def _calc_z_max(self) -> float: return self._z_max
[docs] def _calc_z_min(self) -> float: return self._z_min
[docs] def _calc_convex_hull(self) -> List[kdl.Vector]: return self._convex_hull
[docs] def _calc_size(self) -> float: """ Calculate the rough size of a shape >>> RightPrism([kdl.Vector(0, 0, 0), kdl.Vector(0, 1, 0), kdl.Vector(1, 1, 0), kdl.Vector(1, 0, 0)], z_min=0, z_max=1).size 1.0 >>> RightPrism([kdl.Vector(0, 0, 0), kdl.Vector(0, 2, 0), kdl.Vector(2, 2, 0), kdl.Vector(2, 0, 0)], z_min=0, z_max=2).size 8.0 """ # TODO: this only uses the bounding box's size, which might not be accurate size_x = abs(self.x_max - self.x_min) size_y = abs(self.y_max - self.y_min) size_z = abs(self.z_max - self.z_min) return size_x * size_y * size_z
[docs]def shape_from_entity_info(e: EntityInfo) -> Shape: """ Creates a shape from the convex_hull, z_min and z_max of the EntityInfo object. If no convex hull is present, an empty Shape object is returned :param e: ed_msgs.msg.EntityInfo :return: Shape """ # Check if we have a convex hull if not e.convex_hull: return Shape() return RightPrism(convex_hull=[kdl.Vector(p.x, p.y, p.z) for p in e.convex_hull], z_min=e.z_min, z_max=e.z_max)
if __name__ == "__main__": import doctest doctest.testmod()