from abc import ABC
from ..platform.base import FixedPlatform
from .base import BaseSensor
from ..types.array import StateVector
from ..types.state import State
[docs]class Sensor(BaseSensor, ABC):
"""Sensor Base class for general use.
Most properties and methods are inherited from :class:`~.BaseSensor`, but this class includes
crucial functionality and so should be used in preference.
All sensors must be mounted on a platform to calculate their position and orientation. To
make this easier, if the sensor has a position and/or orientation specified in the constructor,
and no :attr:`platform_system`, then the default is to create an internally held "private"
platform for the Sensor. This restricts the later setting of the :attr:`platform_system` but
does allow the Sensor to control (and set) its own position and orientation.
"""
# this functionality requires knowledge of FixedPlatform so cannot go in the BaseSensor
# class
def __init__(self, *args, **kwargs):
position = kwargs.pop('position', None)
orientation = kwargs.pop('orientation', None)
self._internal_platform = None
super().__init__(*args, **kwargs)
if position is not None or orientation is not None:
if position is None:
# assuming 3d for a default platform
position = StateVector([0, 0, 0])
if orientation is None:
orientation = StateVector([0, 0, 0])
self._internal_platform = FixedPlatform(
states=State(state_vector=position),
position_mapping=list(range(len(position))),
orientation=orientation,
sensors=[self])
@property
def _has_internal_platform(self):
return self._internal_platform is not None
def _set_platform_system(self, value):
if self._has_internal_platform:
raise AttributeError('Platform system cannot be set on sensors that were created with '
'a default platform')
super()._set_platform_system(value)