from pepper.framework.abstract import AbstractComponent, AbstractBackend, AbstractImage
from pepper.framework.component import ContextComponent
from pepper import logger
import numpy as np
from time import time
import random
[docs]class ExploreComponent(AbstractComponent):
"""
Explore Environment to keep up to date on the people/objects inhabiting it.
Parameters
----------
backend: AbstractBackend
Application Backend
"""
TIMEOUT = 15
LAST_MOVE = 0
SPEED = 0.05
def __init__(self, backend):
# type: (AbstractBackend) -> None
super(ExploreComponent, self).__init__(backend)
# Requires the ContextComponent to know which objects/people to look for
context = self.require(ExploreComponent, ContextComponent) # type: ContextComponent
log = logger.getChild(ExploreComponent.__name__)
def explore():
# type: () -> None
"""Explore Environment to keep up to date on the people/objects inhabiting it."""
# Get Observations, sorted (high to low) by last time seen
observations = sorted(context.context.objects, key=lambda obj: obj.time)
# If there are any observations and the odds are in this if statement's favour
if observations and random.random() > 0.33333:
# Look at least recently seen object's last known location
log.debug("Look at {}".format(observations[0]))
self.backend.motion.look(observations[0].direction, ExploreComponent.SPEED)
else:
# Look at random point (to keep exploring enviroment)
log.debug("Look at random point")
self.backend.motion.look((
float(np.clip(np.random.standard_normal() / 3 * np.pi/2, -np.pi, np.pi)),
float(np.clip(np.pi/2 + np.random.standard_normal() / 10 * np.pi, 0, np.pi))
), ExploreComponent.SPEED)
def on_image(image):
# type: (AbstractImage) -> None
"""
Private On Image Event. Simply used because it is called n times a second.
Parameters
----------
image: AbstractImage
"""
# When no chat is currently happening
if not context.context.chatting:
# At a certain interval
if time() - ExploreComponent.LAST_MOVE > ExploreComponent.TIMEOUT:
explore() # Explore!
ExploreComponent.LAST_MOVE = time()
# Subscribe private on_image event to backend camera (which will call it regularly)
self.backend.camera.callbacks += [on_image]