From d495c3629b43b6b6ba171102d2573820d46698c6 Mon Sep 17 00:00:00 2001 From: "Olivier J.N. Bertrand" <bolirev@hotmail.com> Date: Sat, 9 Dec 2017 12:11:52 +0100 Subject: [PATCH] Wrote Simple and AbstractAgent, Multi is in progress --- navipy/moving/agent.py | 126 +++++++++++++++++++++++++++++++---------- navipy/moving/maths.py | 36 +++++++++--- todo | 21 +++++++ 3 files changed, 146 insertions(+), 37 deletions(-) diff --git a/navipy/moving/agent.py b/navipy/moving/agent.py index 9e18901..ced17a7 100644 --- a/navipy/moving/agent.py +++ b/navipy/moving/agent.py @@ -4,24 +4,97 @@ import numpy as np import pandas as pd from pandas.api.types import is_numeric_dtype +from navipy.database import DataBaseLoad +from .maths import next_pos, \ + closest_pos, \ + closest_pos_memory_friendly, \ + __mode_moves_supported -class Single(): +class AbstractAgent(): + # Define a default mode_of_motion + __mode_move = {'mode': 'on_cubic_grid', + 'param': {'grid_spacing': 1}} + + def __init__(self, + database, + memory_friendly=False): + + if isinstance(database, DataBaseLoad): + self.__db = database + else: + raise TypeError('database should be of type DataBaseLoad') + + if memory_friendly: + self.__posorients = None + else: + self.__posorients = self.__db.get_posorients() + + @property + def mode_of_motion(self): + """ + """ + toreturn = self.__mode_move + toreturn['describe'] = \ + __mode_moves_supported[self.__mode_move['mode']]['describe'] + return toreturn + + @mode_of_motion.setter + def mode_of_motion(self, mode): + """ + + """ + if not isinstance(mode, dict): + raise TypeError('Mode is not a dictionary') + if 'mode' not in mode: + raise KeyError("'mode' is not a key of mode") + if 'param' not in mode: + raise KeyError("'param' is not a key of mode") + if mode['mode'] in __mode_moves_supported.keys: + for param in __mode_moves_supported[mode['mode']]['param']: + if param not in mode['param']: + raise KeyError( + "'{}' is not in mode['param']".format(param)) + self.__mode_move = mode + else: + raise ValueError('mode is not supported') + + def abstractmove(self, posorients_vel): + + # NEED TO CHECK posorients_vel + + # Compute the next position + posorients_vel = next_pos(posorients_vel, + move_mode=self.__mode_move['mode'], + move_param=self.__mode_move['param']) + + # Compute the closest possible position + if posorients_vel is None: + posorients_vel[['x', 'y', 'z', + 'yaw', 'pitch', 'roll']] = \ + closest_pos_memory_friendly(posorients_vel, self.__db) + else: + posorients_vel[['x', 'y', 'z', + 'yaw', 'pitch', 'roll']] = \ + closest_pos(posorients_vel, self.__posorients) + return posorients_vel + + +class Single(AbstractAgent): __posorientvel = pd.Series(['x', 'y', 'z', 'yaw', 'pitch', 'roll', 'dx', 'dy', 'dy', 'dyaw', 'dpitch', 'droll'], dtype=np.float, data=np.nan) - __mode_move = 'on_graph' - - __mode_moves_supported = { - 'on_grid': - "Agent restricted to move on a grid", - 'on_grid_memoryfriendly': - "same as on_grid without loading grid to memory"} - - def __init__(self, database, initial_condition): + # Define a list of supported mode in a dictionary + # key mode, val is list of required parameters + + def __init__(self, + database, + initial_condition, + memory_friendly=False): + super().__init__(database, memory_friendly) if isinstance(initial_condition, pd.Series): if is_numeric_dtype(initial_condition): for key in self.__posorientvel.index: @@ -32,19 +105,9 @@ class Single(): else: raise TypeError('vel should be a pandas Series') - raise NameError('NOT FINISHED, NEED TO CHECK DATABASE') - self.__db = database - def move(self): - pass - - @property - def mode_of_motion(self, mode): - if mode in self.__mode_moves_supported: - self.__mode_move = mode - else: - raise ValueError('mode is not supported') - raise NameError("NOT FINISHED, NEED TO UPDATE STUFF") + # Compute the next position + self.__posorientvel = self.abstractmove(self.__posorientvel) @property def position(self): @@ -91,20 +154,25 @@ class Single(): raise TypeError('vel should be a pandas Series') -def Multi(): +def Multi(AbstractAgent): - __graph = None - - def __init__(self, database): - pass + def __init__(self, database, + memory_friendly=False): + super().__init__(database, memory_friendly) + # Init the graph + self.__graph = None @property def graph(self): return self.__graph @graph.setter - def graph(self, positions_velocities): - # Use Luise Graph builder :) + def graph(self, graph): + # Check that graph is properly formatted + pass + + def build_graph(self, callback_function): + # Build a graph with luises code pass def reach_goals(): diff --git a/navipy/moving/maths.py b/navipy/moving/maths.py index 4265045..4487a37 100644 --- a/navipy/moving/maths.py +++ b/navipy/moving/maths.py @@ -5,8 +5,19 @@ geometry, and predefined grids shapes import numpy as np import pandas as pd +__mode_moves_supported = { + 'on_cubic_grid': { + 'param': + ['grid_spacing'], + 'describe': + "Agent restricted to move on a grid"}, + 'free_run': { + 'param': [], + 'describe': + "Freely moving agent, pos(t+dt)=pos+speed (dt=1)"}} -def next_pos(motion_vec, grid_spacing=1, grid_mode='cubic'): + +def next_pos(motion_vec, move_mode, move_param=None): """return the future position knowing speed and current position :param motion_vec: the position and speed of the agent @@ -17,20 +28,19 @@ def next_pos(motion_vec, grid_spacing=1, grid_mode='cubic'): ..todo: add literal include for supported_grid_mode """ - supported_grid_mode = ['cubic', - None] assert isinstance(motion_vec, pd.Series),\ 'motion vector must be a pandas Series' - assert grid_mode in supported_grid_mode,\ - 'grid mode must is not supported {}'.format(grid_mode) + assert move_mode in __mode_moves_supported,\ + 'move mode must is not supported {}'.format(move_mode) speed = motion_vec.loc[['dx', 'dy', 'dz']] position = motion_vec.loc[['x', 'y', 'z']] - if grid_mode == 'cubic': + if move_mode == 'on_cubic_grid': + grid_spacing = move_param['grid_spacing'] speed /= np.linalg.norm(speed) scaling = grid_spacing / (2 * np.sin(np.pi / 8)) - elif grid_mode is None: - scaling = 1 + elif move_mode is 'free_run': + scaling = 1 # <=> dt = 1, user need to scale speed in dt units else: raise ValueError('grid_mode is not supported') @@ -49,3 +59,13 @@ def closest_pos(pos, positions): + (pos.y - positions.y)**2 + (pos.z - positions.z)**2) return positions.loc[euclidian_dist.idxmin(), :] + + +def closest_pos_memory_friendly(pos, database): + """Return the closest position from a list of positions + + :param pos: the position to find (a pandas Series with ['x','y','z'] + :param database: the possible closest positions + (a pandas dataframe with ['x','y','z']) + """ + raise NameError('Not implemated') diff --git a/todo b/todo index 612f232..a22ec71 100644 --- a/todo +++ b/todo @@ -1,2 +1,23 @@ +Remove DUPLICATE: is_numeric_array is in: + processing.__init__ + and comparing.__init__ + + use the one it processing.__init__ + +Remove DUPLICATE: check_scene is in: + processing.__init__ + and comparing.__init__ + +Move check_scene, is_numeric_array to: + processing.__init__ + +Move function in processing/__init__ to processing/place_code.py +Move function optic_flow in processing/place_code.py to processing/motion_code.py + + - Fix db in test function such that it work from any location. (probably need to add a module resources and function to load them) - Test are failing WHY??? + +- Adapt GraphManager from Downlowd/clusterstuff for moving/agent/Multi + - Change init so that no need to rebuild grid + - Use Charlotte next pos -- GitLab