Commit 6b74d34b authored by Matias Guijarro's avatar Matias Guijarro
Browse files

controllers/motor: refactoring of AxisRef, remove global ENCODER_AXIS dict

Use common utility function
parent d4d22dbe
......@@ -560,12 +560,12 @@ class Axis(AliasMixin, LogMixin):
self.__move_done_callback = gevent.event.Event()
self.__move_done.set()
self.__move_done_callback.set()
self.__motion_hooks = config.get("motion_hooks", [])
hooks = []
for hook in self.__motion_hooks:
self.__motion_hooks = []
for hook in config.get("motion_hooks", []):
hook = hook()
hook.add_axis(self)
hooks.append(hook.name)
config["motion_hooks"] = hooks
self.__motion_hooks.append(hook)
self.__encoder = config.get("encoder")
self.__config = StaticConfig(config)
self._group_move = GroupMove()
self._beacon_channels = dict()
......@@ -671,14 +671,13 @@ class Axis(AliasMixin, LogMixin):
Reference to :class:`~bliss.common.encoder.Encoder` or None if no
encoder is defined
"""
try:
encoder_name = self.config.get("encoder")
except KeyError:
return None
if isinstance(self.__encoder, Encoder):
return self.__encoder
else:
enc = get_encoder(encoder_name)
enc.controller._initialize_encoder(enc)
return enc
if self.__encoder:
self.__encoder = self.__encoder()
self.__encoder.controller._initialize_encoder(self.__encoder)
return self.__encoder
@property
def motion_hooks(self):
......@@ -1117,13 +1116,13 @@ class Axis(AliasMixin, LogMixin):
return (position - self.offset) / self.sign
def __execute_pre_move_hook(self, motion):
for hook in self.__motion_hooks:
for hook in self.motion_hooks:
hook.pre_move([motion])
self._check_ready()
def __execute_post_move_hook(self, motions):
for hook in self.__motion_hooks:
for hook in self.motion_hooks:
try:
hook.post_move(motions)
except:
......@@ -1564,25 +1563,6 @@ class Axis(AliasMixin, LogMixin):
return dial_positions / self.steps_per_unit
class AxisRef(object):
"""Object representing a named reference to an :class:`Axis`."""
def __init__(self, name, _, config):
self.__name = name
self.__config = config
self.settings = AxisSettings(None)
@property
def name(self):
"""Axis reference name"""
return self.__name
@property
def config(self):
"""Reference to the :class:`~bliss.common.motor_config.StaticConfig`"""
return self.__config
class AxisState(object):
"""
Standard states:
......
......@@ -9,14 +9,13 @@
import os
import sys
import pkgutil
import weakref
from bliss.common import axis as axis_module
from bliss.common.axis import Axis, AxisRef
from bliss.common.axis import Axis
from bliss.common.encoder import Encoder
from bliss.config.static import Config, get_config
from bliss.common.tango import DeviceProxy
from bliss.config.plugins.utils import find_class
from bliss.config.plugins.utils import find_class, replace_reference_by_object
import bliss.controllers.motors
import gevent
......@@ -314,6 +313,21 @@ def add_axis(cfg, request):
)
class Reference:
def __init__(self, name, *args, **kwargs):
self.__name = name.lstrip("$")
@property
def name(self):
return self.__name
def __call__(self, *args, **kwargs):
return get_config().get(self.name)
def __str__(self):
return f"${self.name}"
def create_objects_from_config_node(config, node):
if "axes" in node or "encoders" in node:
# asking for a controller
......@@ -341,52 +355,36 @@ def create_objects_from_config_node(config, node):
switches_names = list()
shutters = list()
shutters_names = list()
for axis_config in node.get("axes"):
axis_name = axis_config.get("name")
if axis_name.startswith("$"):
axis_class = AxisRef
axis_name = axis_name.lstrip("$")
else:
axis_class_name = axis_config.get("class")
if axis_class_name is None:
axis_class = Axis
else:
try:
axis_class = getattr(axis_module, axis_class_name)
except AttributeError:
axis_class = getattr(controller_module, axis_class_name)
axes_names.append(axis_name)
hooks = []
for hook in axis_config.get("motion_hooks", ()):
if hook.startswith("$"):
hooks.append(get_config().get(hook.lstrip("$")))
axis_config["motion_hooks"] = hooks
associated_encoder = axis_config.get("encoder")
if associated_encoder:
if associated_encoder.startswith("$"):
axis_config["encoder"] = get_config().get(
associated_encoder.lstrip("$")
)
axes.append((axis_name, axis_class, axis_config))
for objects, objects_names, default_class, default_class_name, objects_config in (
(axes, axes_names, Axis, "", node.get("axes", [])),
(encoders, encoders_names, Encoder, "", node.get("encoders", [])),
(shutters, shutters_names, None, "Shutter", node.get("shutters", [])),
(switches, switches_names, None, "Switch", node.get("switches", [])),
):
for object_config in objects_config:
object_name = object_config.get("name")
object_class_name = object_config.get("class")
object_config = _checkref(config, object_config)
if object_class_name is None:
object_class = default_class
if object_class is None:
replace_reference_by_object(config, object_config, placeholder=Reference)
if not isinstance(object_config.get("name"), str):
# reference
object_class = object_config.get("name")
object_name = object_class.name
else:
object_name = object_config.get("name")
object_class_name = object_config.get("class")
if object_class_name is None:
object_class = default_class
if object_class is None:
try:
object_class = getattr(
controller_module, default_class_name
)
except AttributeError:
pass
else:
try:
object_class = getattr(controller_module, default_class_name)
object_class = getattr(controller_module, object_class_name)
except AttributeError:
pass
else:
object_class = getattr(controller_module, object_class_name)
object_class = getattr(axis_module, object_class_name)
objects_names.append(object_name)
objects.append((object_name, object_class, object_config))
......@@ -417,13 +415,3 @@ def create_object_from_cache(config, name, controller):
except KeyError:
pass
raise KeyError(name)
def _checkref(config, cfg):
obj_cfg = cfg.deep_copy()
for key, value in obj_cfg.items():
if isinstance(value, str) and value.startswith("$"):
# convert reference to item from config
obj = weakref.proxy(config.get(value))
obj_cfg[key] = obj
return obj_cfg
......@@ -32,10 +32,14 @@ def find_class_and_node(cfg_node, base_path="bliss.controllers"):
return klass, node
def _checkref(config, item_cfg_node, referenced_objects, name, value):
def _checkref(config, item_cfg_node, referenced_objects, name, value, placeholder):
if isinstance(value, str) and value.startswith("$"):
# convert reference to item from config
obj = config.get(value)
value = value.lstrip("$")
if placeholder:
obj = placeholder(value)
else:
obj = config.get(value)
item_cfg_node[name] = obj
referenced_objects[name] = obj
return True
......@@ -43,39 +47,43 @@ def _checkref(config, item_cfg_node, referenced_objects, name, value):
return False
def _parse_dict(config, item_cfg_node, referenced_objects, subdict):
for name, node in subdict.items():
if _checkref(config, subdict, referenced_objects, name, node):
def _parse_dict(config, item_cfg_node, referenced_objects, subdict, placeholder):
for name, value in subdict.items():
if _checkref(config, subdict, referenced_objects, name, value, placeholder):
continue
elif isinstance(node, dict):
elif isinstance(value, dict):
childdict = dict()
childref = dict()
_parse_dict(config, childdict, childref, node)
_parse_dict(config, childdict, childref, value, placeholder)
if childref:
node.update(childref)
referenced_objects[name] = node
value.update(childref)
referenced_objects[name] = value
subdict.update(childdict)
elif isinstance(node, list):
return_list = _parse_list(config, node)
elif isinstance(value, list):
return_list = _parse_list(config, value, placeholder)
if return_list:
referenced_objects[name] = return_list
item_cfg_node[name] = return_list
def _parse_list(config, value):
def _parse_list(config, value, placeholder):
object_list = list()
for node in value:
if isinstance(node, str) and node.startswith("$"):
object_list.append(config.get(node))
node = node.lstrip("$")
if placeholder:
object_list.append(placeholder(node))
else:
object_list.append(config.get(node))
elif isinstance(node, dict):
subdict = dict()
subref = dict()
_parse_dict(config, subdict, subref, node)
_parse_dict(config, subdict, subref, node, placeholder)
if subdict:
node.update(subdict)
object_list.append(node)
elif isinstance(node, list):
return_list = _parse_list(config, node)
return_list = _parse_list(config, node, placeholder)
if return_list:
object_list.append(return_list)
else:
......@@ -83,21 +91,25 @@ def _parse_list(config, value):
return object_list
def replace_reference_by_object(config, item_cfg_node, ref_objects=None):
def replace_reference_by_object(
config, item_cfg_node, ref_objects=None, placeholder=None
):
referenced_objects = ref_objects if ref_objects is not None else dict()
for name, value in item_cfg_node.items():
if _checkref(config, item_cfg_node, referenced_objects, name, value):
if _checkref(
config, item_cfg_node, referenced_objects, name, value, placeholder
):
continue
if isinstance(value, list):
return_list = _parse_list(config, value)
return_list = _parse_list(config, value, placeholder)
if return_list:
referenced_objects[name] = return_list
item_cfg_node[name] = return_list
elif isinstance(value, dict):
subdict = dict()
subref = dict()
_parse_dict(config, subdict, subref, value)
_parse_dict(config, subdict, subref, value, placeholder)
if subref:
referenced_objects[name] = subref
item_cfg_node.update(subdict)
......@@ -14,7 +14,7 @@ from bliss.common.motor_settings import (
setting_update_from_channel,
floatOrNone,
)
from bliss.common.axis import Axis, NoSettingsAxis, AxisRef, Trajectory
from bliss.common.axis import Axis, NoSettingsAxis, Trajectory
from bliss.common.motor_group import Group, TrajectoryGroup
from bliss.common import event
from bliss.physics import trajectory
......@@ -22,12 +22,11 @@ from bliss.common.utils import set_custom_members, object_method
from bliss.common import mapping
from bliss.common.logtools import LogMixin
from bliss.config.channels import Cache, Channel
from bliss.config import static, settings
from bliss.config import settings
from gevent import lock
# make the link between encoder and axis, if axis uses an encoder
# (only 1 encoder per axis of course)
ENCODER_AXIS = dict()
# apply settings or config parameters
def get_setting_or_config_value(axis, name):
......@@ -73,10 +72,8 @@ class Controller(LogMixin):
for tag in axis_tags.split():
self._tagged.setdefault(tag, []).append(axis)
# For custom attributes and commands.
# NB : AxisRef has no controller.
if not isinstance(axis, AxisRef):
set_custom_members(self, axis, axis.controller._initialize_axis)
if axis.controller is self:
set_custom_members(self, axis, self._initialize_axis)
for encoder_name, encoder_class, encoder_config in encoders:
encoder = encoder_class(encoder_name, self, encoder_config)
......@@ -93,13 +90,6 @@ class Controller(LogMixin):
mapping.register(self)
def _init(self):
controller_axes = [
(axis_name, axis)
for axis_name, axis in self.axes.items()
if not isinstance(axis, AxisRef)
]
self._update_refs()
for axis in self.axes.values():
axis._beacon_channels.clear()
hash_setting = settings.HashSetting("axis.%s" % axis.name)
......@@ -123,14 +113,12 @@ class Controller(LogMixin):
self.initialize()
for axis_name, axis in controller_axes:
for axis_name, axis in self.axes.items():
if axis.controller is not self:
continue
axis_initialized = Cache(axis, "initialized", default_value=0)
self.__initialized_hw_axis[axis] = axis_initialized
self.__initialized_axis[axis] = False
encoder = axis.config.get("encoder", str, "")
if encoder:
encoder_name = encoder.lstrip("$")
ENCODER_AXIS[encoder_name] = axis.name
@property
def axes(self):
......@@ -162,20 +150,6 @@ class Controller(LogMixin):
def config(self):
return self.__config
def _update_refs(self):
config = static.get_config()
for tag, axis_list in self._tagged.items():
for i, axis in enumerate(axis_list):
if not isinstance(axis, AxisRef):
continue
referenced_axis = config.get(axis.name)
if not isinstance(referenced_axis, Axis):
raise TypeError(
"%s: invalid axis '%s`, not an Axis" % (self.name, axis.name)
)
self.axes[axis.name] = referenced_axis
axis_list[i] = referenced_axis
def _check_limits(self, axis, user_positions):
min_pos = user_positions.min()
max_pos = user_positions.max()
......
......@@ -10,7 +10,7 @@ import random
import gevent
from bliss.physics.trajectory import LinearTrajectory
from bliss.controllers.motor import Controller, ENCODER_AXIS, CalcController
from bliss.controllers.motor import Controller, CalcController
from bliss.common.axis import Axis, AxisState
from bliss.common import event
from bliss.config.static import get_config
......@@ -46,6 +46,8 @@ class Motion:
class Mockup(Controller):
ENCODER_AXIS = dict()
def __init__(self, *args, **kwargs):
Controller.__init__(self, *args, **kwargs)
......@@ -84,6 +86,9 @@ class Mockup(Controller):
def initialize(self):
for axis_name, axis in self.axes.items():
axis.settings.set("init_count", 0)
encoder_name = axis.config.get("encoder", str, "").lstrip("$")
if encoder_name:
self.ENCODER_AXIS[encoder_name] = axis_name
"""
Axes initialization actions.
......@@ -107,11 +112,11 @@ class Mockup(Controller):
def initialize_encoder(self, encoder):
self.__encoders.setdefault(encoder, {})["measured_noise"] = None
self.__encoders[encoder]["steps"] = None
axis_name = ENCODER_AXIS[encoder.name]
self.__encoders[encoder]["axis"] = axis_name
axis = get_config().get(axis_name)
if not axis in self._axis_moves:
self.initialize_axis(axis)
axis_name = self.ENCODER_AXIS.get(encoder.name)
if axis_name:
self.__encoders[encoder]["axis"] = axis_name
axis = get_config().get(axis_name)
axis.controller._initialize_axis(axis)
"""
Actions to perform at controller closing.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment