Skip to content
Snippets Groups Projects
Commit 774166c4 authored by Olivier Bertrand's avatar Olivier Bertrand
Browse files

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
parent d55ee4c3
No related branches found
No related tags found
No related merge requests found
...@@ -7,10 +7,10 @@ import numpy as np ...@@ -7,10 +7,10 @@ import numpy as np
import pandas as pd import pandas as pd
import sqlite3 import sqlite3
import io import io
import warnings
from navipy.scene import is_numeric_array, check_scene from navipy.scene import is_numeric_array, check_scene
import navipy.maths.constants as mconst import navipy.maths.constants as mconst
from navipy.tools.trajectory import Trajectory from navipy.tools.trajectory import Trajectory
from navipy.scene import __spherical_indeces__
import logging import logging
...@@ -151,12 +151,12 @@ class DataBase(): ...@@ -151,12 +151,12 @@ class DataBase():
self._logger.exception(msg) self._logger.exception(msg)
raise NameError(msg) raise NameError(msg)
azimuth = np.linspace(-180, 180, 360) azimuth = np.deg2rad(np.linspace(-180, 180, 360))
elevation = np.linspace(-90, 90, 180) elevation = np.deg2rad(np.linspace(-90, 90, 180))
[ma, me] = np.meshgrid(azimuth, elevation) [ma, me] = np.meshgrid(azimuth, elevation)
self.viewing_directions = np.zeros((ma.shape[0], ma.shape[1], 2)) self.viewing_directions = np.zeros((ma.shape[0], ma.shape[1], 2))
self.viewing_directions[..., 0] = me self.viewing_directions[..., __spherical_indeces__['elevation']] = me
self.viewing_directions[..., 1] = ma self.viewing_directions[..., __spherical_indeces__['azimuth']] = ma
def table_exist(self, tablename): def table_exist(self, tablename):
""" """
...@@ -465,6 +465,7 @@ class DataBaseLoad(DataBase): ...@@ -465,6 +465,7 @@ class DataBaseLoad(DataBase):
R,G,B or D (Distance)' R,G,B or D (Distance)'
self._logger.exception(msg) self._logger.exception(msg)
raise ValueError(msg) raise ValueError(msg)
self.__convention = None
@property @property
def create(self): def create(self):
...@@ -491,6 +492,35 @@ class DataBaseLoad(DataBase): ...@@ -491,6 +492,35 @@ class DataBaseLoad(DataBase):
toyield.drop('id', inplace=True) toyield.drop('id', inplace=True)
yield toyield 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 @property
def posorients(self): def posorients(self):
"""Return the position orientations of all points in the \ """Return the position orientations of all points in the \
...@@ -501,20 +531,9 @@ class DataBaseLoad(DataBase): ...@@ -501,20 +531,9 @@ class DataBaseLoad(DataBase):
posorient = pd.read_sql_query( posorient = pd.read_sql_query(
"select * from position_orientation;", self.db) "select * from position_orientation;", self.db)
posorient.set_index('id', inplace=True) posorient.set_index('id', inplace=True)
if 'rotconv_id' in posorient.columns: if self.rotation_convention is not None:
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")
posorients = Trajectory() posorients = Trajectory()
posorients.from_dataframe(posorient, rotconv='rxyz') posorients.from_dataframe(posorient, rotconv=self.__convention)
return posorients return posorients
@property @property
......
from navipy import Brain from navipy import Brain
from navipy.processing.pcode import apcv, skyline from navipy.processing.pcode import apcv, skyline
import pandas as pd import pandas as pd
import numpy as np
from navipy.scene import __spherical_indeces__
# 0) Define a class heriting from Brain # 0) Define a class heriting from Brain
...@@ -24,8 +26,10 @@ def processing(scene, viewing_directions, channel): ...@@ -24,8 +26,10 @@ def processing(scene, viewing_directions, channel):
scene[..., 3, :] = 1/scene[..., 3, :] scene[..., 3, :] = 1/scene[..., 3, :]
# Calculate the skyline # Calculate the skyline
scene = skyline(scene) scene = skyline(scene)
# skyline viewing direction
comanv = apcv(scene, viewing_directions) viewdir = viewing_directions[1, ...][np.newaxis, ...]
viewdir[..., __spherical_indeces__['elevation']] = 0
comanv = apcv(scene, viewdir)
return comanv[..., channel, :] return comanv[..., channel, :]
...@@ -34,6 +38,7 @@ def comparing(current, memory): ...@@ -34,6 +38,7 @@ def comparing(current, memory):
homing vector = current vector - memory vector homing vector = current vector - memory vector
""" """
return current-memory
class ASVBrain(Brain): class ASVBrain(Brain):
...@@ -53,9 +58,10 @@ class ASVBrain(Brain): ...@@ -53,9 +58,10 @@ class ASVBrain(Brain):
self.vision.viewing_directions, self.vision.viewing_directions,
self.channel) self.channel)
homing_vector = comparing(current, self.memory) homing_vector = comparing(current, self.memory)
homing_vector = np.squeeze(homing_vector)
indeces = [('location', 'dx'), ('location', 'dy'), indeces = [('location', 'dx'), ('location', 'dy'),
('location', 'dz'), (convention, 'dalpha_0'), ('location', 'dz'), (convention, 'dalpha_0'),
(convention, 'dalpha_1'), (convention, 'dalpha_2')] (convention, 'dalpha_1'), (convention, 'dalpha_2')]
velocity = pd.Series(data=0, index=pd.MultiIndex.from_tuples(indeces)) velocity = pd.Series(data=0, index=pd.MultiIndex.from_tuples(indeces))
velocity['location'] = homing_vector velocity.loc['location'] = homing_vector
return velocity return velocity
...@@ -28,6 +28,7 @@ import multiprocessing ...@@ -28,6 +28,7 @@ import multiprocessing
from multiprocessing import Queue, JoinableQueue, Process from multiprocessing import Queue, JoinableQueue, Process
import inspect import inspect
import navipy.moving.maths as navimomath import navipy.moving.maths as navimomath
from navipy.database import DataBaseLoad
version = float(nx.__version__) version = float(nx.__version__)
...@@ -52,25 +53,33 @@ class AbstractAgent(): ...@@ -52,25 +53,33 @@ class AbstractAgent():
def __init__(self, convention='rzyx'): def __init__(self, convention='rzyx'):
self._brain = DefaultBrain() self._brain = DefaultBrain()
self._alter_posorientvel = defaultcallback self._alter_posorientvel = defaultcallback
tuples = [('location', 'x'), ('location', 'y'), tuples = [('location', 'x'),
('location', 'z'), (convention, 'alpha_0'), ('location', 'y'),
(convention, 'alpha_1'), (convention, 'alpha_2')] ('location', 'z'),
(convention, 'alpha_0'),
(convention, 'alpha_1'),
(convention, 'alpha_2')]
index = pd.MultiIndex.from_tuples(tuples, index = pd.MultiIndex.from_tuples(tuples,
names=['position', names=['position',
'orientation']) 'orientation'])
self._posorient_col = index self._posorient_col = index
tuples_vel = [('location', 'x'), ('location', 'y'), tuples_vel = [('location', 'dx'),
('location', 'z'), (convention, 'alpha_0'), ('location', 'dy'),
(convention, 'alpha_1'), (convention, 'alpha_2'), ('location', 'dz'),
('location', 'dx'), ('location', 'dy'), (convention, 'dalpha_0'),
('location', 'dz'), (convention, 'dalpha_0'), (convention, 'dalpha_1'),
(convention, 'dalpha_1'), (convention, 'dalpha_2')] (convention, 'dalpha_2')]
index_vel = pd.MultiIndex.from_tuples(tuples_vel, index_vel = pd.MultiIndex.from_tuples(tuples_vel,
names=['position', names=['position',
'orientation']) '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._velocity_col = index_vel
self._posorient_vel_col = self._velocity_col.copy() self._posorient_vel_col = index_posvel
self._posorient_vel = pd.Series( self._posorient_vel = pd.Series(
index=self._posorient_vel_col, index=self._posorient_vel_col,
data=np.nan) data=np.nan)
...@@ -105,6 +114,15 @@ class AbstractAgent(): ...@@ -105,6 +114,15 @@ class AbstractAgent():
self._posorient_vel.loc[self._velocity_col] = \ self._posorient_vel.loc[self._velocity_col] = \
velocity.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 @property
def brain(self): def brain(self):
return inspect.getsourcelines(self._brain) return inspect.getsourcelines(self._brain)
...@@ -176,11 +194,14 @@ GridAgent is a close loop agent here its position is snap to a grid. ...@@ -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, posorients_queue=None,
results_queue=None): results_queue=None):
if convention is None: if not isinstance(brain.renderer, DataBaseLoad):
raise Exception("convention must be set") 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): if (posorients_queue is not None) and (results_queue is not None):
multiprocessing.Process.__init__(self) multiprocessing.Process.__init__(self)
AbstractAgent.__init__(self, convention) AbstractAgent.__init__(self, convention)
...@@ -283,14 +304,19 @@ the agent motion, or ...@@ -283,14 +304,19 @@ the agent motion, or
""" """
def __init__(self, brain): def __init__(self, brain, mode_of_motion):
self._brain = copy.copy(brain) self._brain = copy.copy(brain)
# Init the graph # Init the graph
self._graph = nx.DiGraph() 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(): for row_id, posor in self._brain.posorients.iterrows():
posor.name = row_id posor.name = row_id
self._graph.add_node(row_id, self._graph.add_node(row_id,
posorient=posor) posorient=posor)
self.mode_of_motion = mode_of_motion
@property @property
def graph(self): def graph(self):
......
...@@ -49,7 +49,7 @@ def next_pos(motion_vec, move_mode, move_param=None): ...@@ -49,7 +49,7 @@ def next_pos(motion_vec, move_mode, move_param=None):
# speed in spherical coord # speed in spherical coord
epsilon = np.arctan2(speed['location']['dz'], epsilon = np.arctan2(speed['location']['dz'],
np.sqrt(speed['location']['dx']**2 + np.sqrt(speed['location']['dx']**2 +
speed['location']['dy']**2)) speed['location']['dy']**2))
phi = np.arctan2(speed['location']['dy'], speed['location']['dx']) phi = np.arctan2(speed['location']['dy'], speed['location']['dx'])
radius = np.sqrt(np.sum(speed**2)) radius = np.sqrt(np.sum(speed**2))
if np.isclose(radius, 0): if np.isclose(radius, 0):
...@@ -88,15 +88,9 @@ def next_pos(motion_vec, move_mode, move_param=None): ...@@ -88,15 +88,9 @@ def next_pos(motion_vec, move_mode, move_param=None):
else: else:
raise ValueError('grid_mode is not supported') raise ValueError('grid_mode is not supported')
toreturn = motion_vec toreturn = motion_vec
toreturn['location']['x'] = (toreturn['location']['x'] + toreturn.loc[('location', 'x')] += speed['location']['dx']
speed['location']['dx']) toreturn.loc[('location', 'y')] += speed['location']['dy']
toreturn['location']['y'] = (toreturn['location']['y'] + toreturn.loc[('location', 'z')] += speed['location']['dz']
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
return toreturn return toreturn
...@@ -110,9 +104,9 @@ def closest_pos(pos, positions): ...@@ -110,9 +104,9 @@ def closest_pos(pos, positions):
""" """
euclidian_dist = np.sqrt( euclidian_dist = np.sqrt(
(pos['location']['x'] - positions['location']['x'])**2 (pos['location']['x'] - positions['location']['x'])**2
+ (pos['location']['y'] - positions['location']['y'])**2 + (pos['location']['y'] - positions['location']['y'])**2
+ (pos['location']['z'] - positions['location']['z'])**2) + (pos['location']['z'] - positions['location']['z'])**2)
return positions.loc[euclidian_dist.idxmin()] return positions.loc[euclidian_dist.idxmin()]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment