Commits

German Larrain committed 13740d3

robot.sensors: added class 'SignalSensor'

Comments (0)

Files changed (1)

ars/model/robot/sensors.py

 from abc import ABCMeta, abstractmethod
 
+from ars.lib.pydispatch import dispatcher
 import ars.model.collision.adapters as coll
 import ars.utils.containers
 from ars.utils.generic import get_current_epoch_time
 		return self._source
 
 
+class SignalSensor:
+	__metaclass__ = ABCMeta
+	
+	any_sender = dispatcher.Any
+
+	@abstractmethod
+	def __init__(self, signal, sender=any_sender, autotime=False):
+		""" 
+		:param signal: signal to subscribe to
+		:param sender: object that will send the signal; if it is
+			:attr:`any_sender`, subscription will be to any object
+		:param autotime: if True and :meth:`_get_time` is not overriden, every
+			measurement's time will set to the computer time in that instant
+		
+		"""
+		self._signal = signal
+		self._sender = sender
+		self._autotime = autotime
+		
+		# subscribe :meth:`on_send` handler to the signal sent by ``sender``
+		dispatcher.connect(self.on_send, signal=self._signal,
+			sender=self._sender)
+		self.data_queue = SensorDataQueue()
+
+	def on_send(self, sender, *args, **kwargs):
+		"""Handle signal sent/fired by ``sender`` through the dispatcher. Take
+		care of building a data object, set time to it and save it in the
+		``data_queue``.
+		
+		:param sender: signal sender
+		:param args: signal arguments
+		:param kwargs: signal keyword arguments
+		
+		"""
+		data = self._build_data(sender, *args, **kwargs)
+		time = self._get_time()
+		if time is not None:
+			data.set_time(time)
+		self.data_queue.put(data)
+
+	@abstractmethod
+	def _build_data(self, sender, *args, **kwargs):
+		"""Build and return a SensorData object with current data.
+		
+		:return: object containing data based on the state of the sender
+		:rtype: :class:`SensorData`
+		
+		"""
+		raise NotImplementedError()
+	
+	def _get_time(self):
+		"""Return the time to set to the :class`SensorData` instance. Override
+		to define it based on some object's state or property.
+
+		:return: time value for the data
+		:rtype: :class:`float` or None
+
+		"""
+		time = None
+		if self._autotime:
+			time = get_current_epoch_time()
+		return time
+
+	@property
+	def sender(self):
+		return self._sender
+
+
 class BodySensor(Sensor):
 	__metaclass__ = ABCMeta