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