Source code for contrast.motors.KukaMotor
"""
Provides a Motor interface to the `MAX IV Kuka robot Tango device`_.
.. _MAX IV Kuka robot Tango device: https://gitlab.maxiv.lu.se/nanomax/dev-maxiv-kuka_robot
"""
import PyTango
import time
from . import Motor
[docs]class KukaRobot(object):
"""
Managing class which coordinates movements of the robot in polar
coordinates. The manager's role is to avoid trying to move more than one
robot motor at a time, which would not be compatible with the controller.
This class owns three ``KukaMotor`` instances, which are returned on
iteration::
gamma, delta, radius = KukaRobot('path/to/device',
names=['gamma, 'delta', 'radius'])
"""
def __init__(self, tango_path, names=['gamma', 'delta', 'radius']):
"""
:param tango_path: Path to the underlying Tango device
:type tango_path: str
:param names: Names to assign to the three polar motors
:type names: list, tuple
"""
self.proxy = PyTango.DeviceProxy(tango_path)
self.proxy.set_source(PyTango.DevSource.DEV)
self.polar_motors = [
KukaMotor(manager=self, name=names[0]),
KukaMotor(manager=self, name=names[1]),
KukaMotor(manager=self, name=names[2])]
def __iter__(self):
return self.polar_motors.__iter__()
def motor2index(self, motor):
return self.polar_motors.index(motor)
def _safe_get_pos(self):
try:
return self.proxy.position
except PyTango.DevFailed:
msg = 'The robot device position is not available. State: %s'
raise Exception(msg % self.proxy.State())
[docs] def move_me(self, motor, pos):
"""
Method which makes sure that only one polar axis is moved at a time.
For now, this is done by blocking until the device is standing still.
Should perhaps be threaded or so, but works like this for scanning for
example the two polar angles in a mesh.
:param motor: Motor instance to move, typically ``self`` for the calling ``KukaMotor``.
:param pos: Target position
:type pos: float
"""
while self.busy():
time.sleep(.5)
target = self._safe_get_pos().copy()
target[self.motor2index(motor)] = pos
ok = False
while not ok:
try:
self.proxy.position = target
ok = True
except PyTango.DevFailed:
print('robot movement failed. reinizializing etc...')
self.proxy.Init()
time.sleep(1)
self.proxy.Connect()
time.sleep(1)
def where_am_i(self, motor):
current = self._safe_get_pos()
return current[self.motor2index(motor)]
def busy(self):
return not (self.proxy.State() == PyTango.DevState.ON)
[docs]class KukaMotor(Motor):
"""
Single motor as exposed by the ``KukaRobot`` class.
"""
def __init__(self, manager, **kwargs):
"""
:param manager: Managing ``KukaRobot`` instance
:param ``**kwargs``: Passed on to the base class constructor
"""
super(KukaMotor, self).__init__(**kwargs)
self.manager = manager
@property
def dial_position(self):
return self.manager.where_am_i(motor=self)
@dial_position.setter
def dial_position(self, pos):
self.manager.move_me(motor=self, pos=pos)
def busy(self):
return self.manager.busy()
def stop(self):
self.manager.proxy.Stop()
[docs] def move(self, pos):
"""
This motor needs to override the base class move, because move
commands must be accepted even if the motor is busy.
:param pos: Target position
:type pos: float
"""
dial = (pos - self._offset) / self._scaling
_lowlim, _uplim = self.dial_limits
try:
assert dial <= _uplim
assert dial >= _lowlim
except AssertionError:
print('Trying to move %s outside its limits!' % self.name)
return -1
except TypeError:
pass
self.dial_position = dial