From 50ed9322e390faf44f9012df0dd855679e4dbb3c Mon Sep 17 00:00:00 2001 From: "Olivier J.N. Bertrand" <olivier.bertrand@uni-bielefeld.de> Date: Tue, 6 Feb 2018 14:02:56 +0100 Subject: [PATCH] Change agent to use a brain instead of renderer --- navipy/__init__.py | 60 ++++++++++++++++++++++++++++++++++++ navipy/moving/agent.py | 70 ++++++++++-------------------------------- 2 files changed, 77 insertions(+), 53 deletions(-) diff --git a/navipy/__init__.py b/navipy/__init__.py index e69de29..99e6fe8 100644 --- a/navipy/__init__.py +++ b/navipy/__init__.py @@ -0,0 +1,60 @@ +""" +Every agent comes with a battery of a brain processing the about of \ +senses or sensors for biological or technical agent, respectively. + +The senses of agents in navipy are limited +to: + +* 4d vision (brighness + depth) + +The 4d vision sense is controlled by rendering module, either an \ +online rendering or loaded from a database containing pre-rendered images. + +For example to use pre-rendered images from a database: + +.. literalinclude:: example/processing/apcv.py + :lines: 10-11 + +Then the senses can be updated at a new position orientation: + +.. literalinclude:: example/processing/apcv.py + :lines: 15 + +Renderer +-------- +.. automodule:: navipy.sensors.renderer + +""" +from database import DataBaseLoad + +class Bunch: + def __init__(self, **kwds): + self.__dict__.update(kwds) + + +class Brain(): + def __init__(self, + renderer=None): + self.vision = Bunch(scene=None, + viewing_directions=None, + channels=None) + self.renderer = renderer + if self.renderer is not None: + self.vision.scene = None + self.vision.viewing_directions = renderer.viewing_directions + self.vision.channels = renderer.channels + + def velocity(self): + raise NotImplementedError("Subclasses should implement this") + + def update(self, posorient): + if self.renderer is not None: + self.vision.scene = self.renderer.scene(posorient) + + @property + def posorients(self): + if isinstance(self.renderer, DataBaseLoad): + return self.renderer.posorients + else: + raise NotImplementedError("Subclasses should implement this, "+ + "when renderer is not DataBaseLoad") diff --git a/navipy/moving/agent.py b/navipy/moving/agent.py index 0415985..6a8acb5 100644 --- a/navipy/moving/agent.py +++ b/navipy/moving/agent.py @@ -37,8 +37,7 @@ class DefaultSensors(): class AbstractAgent(): def __init__(self): - self._sensors = DefaultSensors() - self._motion = defaultcallback + self._brian = DefaultSensors() self._motion_param = None self._alter_posorientvel = defaultcallback self._posorient_col = ['x', 'y', 'z', @@ -81,37 +80,20 @@ class AbstractAgent(): velocity.loc[self._velocity_col] @property - def motion(self): - return inspect.getsourcelines(self._motion) + def brain(self): + return inspect.getsourcelines(self._brain) - @property - def motion_param(self): - return self._motion_param.copy() - - @motion_param.setter - def motion_param(self, param): - if isinstance(param, dict): - self._motion_param = param - else: - raise TypeError('motion param should be a dictionary') - - @property - def sensors(self): - return inspect.getsourcelines(self._sensors) + @brain.setter + def brain(self, brain): + self._brain = brain @property def alter_posorientvel(self): return inspect.getsourcelines(self._alter_posorientvel) def move(self): - self._sensors.update(self.posorient) - if self._motion_param is None: - self.velocity = self._motion(self._posorient_vel, - self._sensors) - else: - self.velocity = self._motion(self._posorient_vel, - self._sensors, - **self._motion_param) + self._brain.update(self.posorient) + self.velocity = self._brian.velocity() alteredpos = self._alter_posorientvel(self._posorient_vel) self.posorient = alteredpos self.velocity = alteredpos @@ -142,20 +124,12 @@ CyberBeeAgent is a close loop agent and need to be run within blender \ bla """ - def __init__(self, renderer): + def __init__(self, brain): AbstractAgent.__init__(self) AbstractAgent._alter_posorientvel = \ lambda motion_vec: navimomath.next_pos(motion_vec, move_mode='free_run') - self.sensors = renderer - - @AbstractAgent.sensors.setter - def sensors(self, renderer): - self._sensors = Senses(renderer) - - @AbstractAgent.motion.setter - def motion(self, motion): - self._motion = motion + self.brain = brain class GridAgent(AbstractAgent, Process): @@ -173,25 +147,15 @@ GridAgent is a close loop agent here its position is snap to a grid. library. Thus, several GridAgents can safely be run in parallel. """ - def __init__(self, database_filename, + def __init__(self, brain, posorients_queue=None, results_queue=None): if (posorients_queue is not None) and (results_queue is not None): multiprocessing.Process.__init__(self) AbstractAgent.__init__(self) self._alter_posorientvel = self.snap_to_grid - self.sensors = database_filename - - @AbstractAgent.sensors.setter - def sensors(self, database_filename): - self.db = DataBaseLoad(database_filename) - self._posorients = self.db.posorients - self._sensors = Senses(renderer=self.db) - - @AbstractAgent.motion.setter - def motion(self, motion): - self._motion = motion - + self.brain = brain + @property def mode_of_motion(self): """ @@ -284,11 +248,11 @@ the agent motion, or 2. pre-computed agent-motion """ - def __init__(self, database_filename): - self.db = DataBaseLoad(database_filename) + def __init__(self, brian): + self._brain = copy.deepcopy(brain) # Init the graph self._graph = nx.DiGraph() - for row_id, posor in self.db.posorients.iterrows(): + for row_id, posor in self._brain.posorients.iterrows(): posor.name = row_id self._graph.add_node(row_id, posorient=posor) @@ -320,7 +284,7 @@ the agent motion, or # Start ndatabase loader num_agents = ncpu - agents = [GridAgent(self.dbname, + agents = [GridAgent(copy.deepcopy(self._brain), posorients_queue=posorients_queue, results_queue=results_queue) for _ in range(num_agents)] -- GitLab