From 774166c453f8e4d88f07cde0210f3518d99ec20b Mon Sep 17 00:00:00 2001 From: "Olivier J.N. Bertrand" <olivier.bertrand@uni-bielefeld.de> Date: Fri, 8 Jun 2018 18:25:42 +0200 Subject: [PATCH] Bug correction Agent was not using convention in a safe manner. For example for database the convention should be return by the database itself if unique. The speed update in moving was not done with .loc and therefore lead to unchanged values the model of hafner have been updated to correct a mistakes in the viewing direction --- navipy/database/__init__.py | 55 ++++++++++++++++++++++++------------ navipy/models/hafner_2000.py | 12 ++++++-- navipy/moving/agent.py | 54 ++++++++++++++++++++++++++--------- navipy/moving/maths.py | 20 +++++-------- 4 files changed, 93 insertions(+), 48 deletions(-) diff --git a/navipy/database/__init__.py b/navipy/database/__init__.py index abeb5ad..431b525 100644 --- a/navipy/database/__init__.py +++ b/navipy/database/__init__.py @@ -7,10 +7,10 @@ import numpy as np import pandas as pd import sqlite3 import io -import warnings from navipy.scene import is_numeric_array, check_scene import navipy.maths.constants as mconst from navipy.tools.trajectory import Trajectory +from navipy.scene import __spherical_indeces__ import logging @@ -151,12 +151,12 @@ class DataBase(): self._logger.exception(msg) raise NameError(msg) - azimuth = np.linspace(-180, 180, 360) - elevation = np.linspace(-90, 90, 180) + azimuth = np.deg2rad(np.linspace(-180, 180, 360)) + elevation = np.deg2rad(np.linspace(-90, 90, 180)) [ma, me] = np.meshgrid(azimuth, elevation) self.viewing_directions = np.zeros((ma.shape[0], ma.shape[1], 2)) - self.viewing_directions[..., 0] = me - self.viewing_directions[..., 1] = ma + self.viewing_directions[..., __spherical_indeces__['elevation']] = me + self.viewing_directions[..., __spherical_indeces__['azimuth']] = ma def table_exist(self, tablename): """ @@ -465,6 +465,7 @@ class DataBaseLoad(DataBase): R,G,B or D (Distance)' self._logger.exception(msg) raise ValueError(msg) + self.__convention = None @property def create(self): @@ -491,6 +492,35 @@ class DataBaseLoad(DataBase): toyield.drop('id', inplace=True) yield toyield + @property + def rotation_convention(self): + """ Return the convention in the database + + The database can technically contains more than one convention. + Although it is discourage to do so, it is not forbidden. + + If more than one convention is found in the database, this function + will issue awarning when more than one convention is present in the database. + """ + posorient = pd.read_sql_query( + "select * from position_orientation;", self.db) + posorient.set_index('id', inplace=True) + if self.__convention is None: + if 'rotconv_id' in posorient.columns: + rotconv = posorient.loc[:, 'rotconv_id'] + if np.all(rotconv == rotconv.iloc[0]): + self.__convention = rotconv + else: + self._logger.warning( + 'More than one convention have been found in database') + self.__convention = None + else: + self._logger.warning("you are loading a database with old\ + conventions, it will be transformed\ + automatically into the new one") + self.__convention = 'rxyz' + return self.__convention + @property def posorients(self): """Return the position orientations of all points in the \ @@ -501,20 +531,9 @@ class DataBaseLoad(DataBase): posorient = pd.read_sql_query( "select * from position_orientation;", self.db) posorient.set_index('id', inplace=True) - if 'rotconv_id' in posorient.columns: - rotconv = posorient.loc[:, 'rotconv_id'] - if np.all(rotconv == rotconv.iloc[0]): - posorients = Trajectory( - rotconv.iloc[0], indeces=posorient.index) - posorients.from_dataframe(posorient) - else: - posorients = posorient - else: - warnings.warn("you are loading a database with old\ - conventions, it will be transformed\ - automatically into the new one") + if self.rotation_convention is not None: posorients = Trajectory() - posorients.from_dataframe(posorient, rotconv='rxyz') + posorients.from_dataframe(posorient, rotconv=self.__convention) return posorients @property diff --git a/navipy/models/hafner_2000.py b/navipy/models/hafner_2000.py index 4e72a80..3c94b92 100644 --- a/navipy/models/hafner_2000.py +++ b/navipy/models/hafner_2000.py @@ -1,6 +1,8 @@ from navipy import Brain from navipy.processing.pcode import apcv, skyline import pandas as pd +import numpy as np +from navipy.scene import __spherical_indeces__ # 0) Define a class heriting from Brain @@ -24,8 +26,10 @@ def processing(scene, viewing_directions, channel): scene[..., 3, :] = 1/scene[..., 3, :] # Calculate the skyline scene = skyline(scene) - - comanv = apcv(scene, viewing_directions) + # skyline viewing direction + viewdir = viewing_directions[1, ...][np.newaxis, ...] + viewdir[..., __spherical_indeces__['elevation']] = 0 + comanv = apcv(scene, viewdir) return comanv[..., channel, :] @@ -34,6 +38,7 @@ def comparing(current, memory): homing vector = current vector - memory vector """ + return current-memory class ASVBrain(Brain): @@ -53,9 +58,10 @@ class ASVBrain(Brain): self.vision.viewing_directions, self.channel) homing_vector = comparing(current, self.memory) + homing_vector = np.squeeze(homing_vector) indeces = [('location', 'dx'), ('location', 'dy'), ('location', 'dz'), (convention, 'dalpha_0'), (convention, 'dalpha_1'), (convention, 'dalpha_2')] velocity = pd.Series(data=0, index=pd.MultiIndex.from_tuples(indeces)) - velocity['location'] = homing_vector + velocity.loc['location'] = homing_vector return velocity diff --git a/navipy/moving/agent.py b/navipy/moving/agent.py index baa501a..0c4775c 100644 --- a/navipy/moving/agent.py +++ b/navipy/moving/agent.py @@ -28,6 +28,7 @@ import multiprocessing from multiprocessing import Queue, JoinableQueue, Process import inspect import navipy.moving.maths as navimomath +from navipy.database import DataBaseLoad version = float(nx.__version__) @@ -52,25 +53,33 @@ class AbstractAgent(): def __init__(self, convention='rzyx'): self._brain = DefaultBrain() self._alter_posorientvel = defaultcallback - tuples = [('location', 'x'), ('location', 'y'), - ('location', 'z'), (convention, 'alpha_0'), - (convention, 'alpha_1'), (convention, 'alpha_2')] + tuples = [('location', 'x'), + ('location', 'y'), + ('location', 'z'), + (convention, 'alpha_0'), + (convention, 'alpha_1'), + (convention, 'alpha_2')] index = pd.MultiIndex.from_tuples(tuples, names=['position', 'orientation']) self._posorient_col = index - tuples_vel = [('location', 'x'), ('location', 'y'), - ('location', 'z'), (convention, 'alpha_0'), - (convention, 'alpha_1'), (convention, 'alpha_2'), - ('location', 'dx'), ('location', 'dy'), - ('location', 'dz'), (convention, 'dalpha_0'), - (convention, 'dalpha_1'), (convention, 'dalpha_2')] + tuples_vel = [('location', 'dx'), + ('location', 'dy'), + ('location', 'dz'), + (convention, 'dalpha_0'), + (convention, 'dalpha_1'), + (convention, 'dalpha_2')] index_vel = pd.MultiIndex.from_tuples(tuples_vel, names=['position', 'orientation']) + tuples_posvel = tuples + tuples_posvel.extend(tuples_vel) + index_posvel = pd.MultiIndex.from_tuples(tuples_posvel, + names=['position', + 'orientation']) self._velocity_col = index_vel - self._posorient_vel_col = self._velocity_col.copy() + self._posorient_vel_col = index_posvel self._posorient_vel = pd.Series( index=self._posorient_vel_col, data=np.nan) @@ -105,6 +114,15 @@ class AbstractAgent(): self._posorient_vel.loc[self._velocity_col] = \ velocity.loc[self._velocity_col] + @property + def posorient_vel(self): + return self._posorient_vel.copy() + + @posorient_vel.setter + def posorient_vel(self, posorient_vel): + self.posorient = posorient_vel + self.velocity = posorient_vel + @property def brain(self): return inspect.getsourcelines(self._brain) @@ -176,11 +194,14 @@ GridAgent is a close loop agent here its position is snap to a grid. """ - def __init__(self, brain, convention, + def __init__(self, brain, posorients_queue=None, results_queue=None): - if convention is None: - raise Exception("convention must be set") + if not isinstance(brain.renderer, DataBaseLoad): + msg = 'GridAgent only works with a brain having ' + msg += 'a renderer of type DataBaseLoad' + raise TypeError(msg) + convention = brain.renderer.rotation_convention if (posorients_queue is not None) and (results_queue is not None): multiprocessing.Process.__init__(self) AbstractAgent.__init__(self, convention) @@ -283,14 +304,19 @@ the agent motion, or """ - def __init__(self, brain): + def __init__(self, brain, mode_of_motion): self._brain = copy.copy(brain) # Init the graph self._graph = nx.DiGraph() + if not isinstance(self._brain.renderer, DataBaseLoad): + msg = 'GraphAgent only works with a brain having ' + msg += 'a renderer of type DataBaseLoad' + raise TypeError(msg) for row_id, posor in self._brain.posorients.iterrows(): posor.name = row_id self._graph.add_node(row_id, posorient=posor) + self.mode_of_motion = mode_of_motion @property def graph(self): diff --git a/navipy/moving/maths.py b/navipy/moving/maths.py index 55389c7..d2d14da 100644 --- a/navipy/moving/maths.py +++ b/navipy/moving/maths.py @@ -49,7 +49,7 @@ def next_pos(motion_vec, move_mode, move_param=None): # speed in spherical coord epsilon = np.arctan2(speed['location']['dz'], np.sqrt(speed['location']['dx']**2 + - speed['location']['dy']**2)) + speed['location']['dy']**2)) phi = np.arctan2(speed['location']['dy'], speed['location']['dx']) radius = np.sqrt(np.sum(speed**2)) if np.isclose(radius, 0): @@ -88,15 +88,9 @@ def next_pos(motion_vec, move_mode, move_param=None): else: raise ValueError('grid_mode is not supported') toreturn = motion_vec - toreturn['location']['x'] = (toreturn['location']['x'] + - speed['location']['dx']) - toreturn['location']['y'] = (toreturn['location']['y'] + - speed['location']['dy']) - toreturn['location']['z'] = (toreturn['location']['z'] + - speed['location']['dz']) - # toreturn.loc[['x', 'y', 'z']] += speed.rename({'dx': 'x', - # 'dy': 'y', - # 'dz': 'z'}) * scaling + toreturn.loc[('location', 'x')] += speed['location']['dx'] + toreturn.loc[('location', 'y')] += speed['location']['dy'] + toreturn.loc[('location', 'z')] += speed['location']['dz'] return toreturn @@ -110,9 +104,9 @@ def closest_pos(pos, positions): """ euclidian_dist = np.sqrt( - (pos['location']['x'] - positions['location']['x'])**2 - + (pos['location']['y'] - positions['location']['y'])**2 - + (pos['location']['z'] - positions['location']['z'])**2) + (pos['location']['x'] - positions['location']['x'])**2 + + (pos['location']['y'] - positions['location']['y'])**2 + + (pos['location']['z'] - positions['location']['z'])**2) return positions.loc[euclidian_dist.idxmin()] -- GitLab