Source code for mxcubecore.HardwareObjects.mockup.MotorMockup
# encoding: utf-8
#
# Project name: MXCuBE
# https://github.com/mxcube
#
# This file is part of MXCuBE software.
#
# MXCuBE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# MXCuBE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with MXCuBE. If not, see <http://www.gnu.org/licenses/>.
"""
Example of xml config file
<object class="MotorMockup">
<username>Mock motor</username>
<actuator_name>mock_motor</actuator_name>
<!-- for the mockup only -->
<default_value>500</default_value>
<velocity>100</velocity>
<wrap_range>None</wrap_range>
<default_limits>[-360, 360]</default_limits>
</object>
"""
import time
from mxcubecore.HardwareObjects.abstract.AbstractMotor import AbstractMotor, MotorStates
from mxcubecore.HardwareObjects.mockup.ActuatorMockup import ActuatorMockup
__copyright__ = """ Copyright © 2010-2020 by the MXCuBE collaboration """
__license__ = "LGPLv3+"
DEFAULT_VELOCITY = 100
DEFAULT_LIMITS = (-10000, 10000)
DEFAULT_VALUE = 10.124
DEFAULT_WRAP_RANGE = None
[docs]class MotorMockup(ActuatorMockup, AbstractMotor):
"""Mock Motor implementation"""
SPECIFIC_STATES = MotorStates
def __init__(self, name):
AbstractMotor.__init__(self, name)
self._wrap_range = None
[docs] def init(self):
"""Initialisation method"""
# get username, actuator_name and tolerance
super().init()
# local properties
if not self.get_velocity():
self.set_velocity(DEFAULT_VELOCITY)
if None in self.get_limits():
self.update_limits(DEFAULT_LIMITS)
try:
self._wrap_range = float(self.get_property("wrap_range"))
except (TypeError, ValueError):
self._wrap_range = DEFAULT_WRAP_RANGE
if self.default_value is None:
self.default_value = DEFAULT_VALUE
self.update_value(self.default_value)
self.update_state(self.STATES.READY)
def _move(self, value):
"""Simulated motor movement.
Args:
value (float): target position
Returns:
(float): The reached position.
"""
self.update_specific_state(self.SPECIFIC_STATES.MOVING)
start_pos = self.get_value()
if value is not None and start_pos is not None:
delta = abs(value - start_pos)
direction = -1 if value < self.get_value() else 1
start_time = time.time()
while (time.time() - start_time) < (delta / self.get_velocity()):
time.sleep(0.02)
val = start_pos + direction * self.get_velocity() * (
time.time() - start_time
)
val = val if not self._wrap_range else val % self._wrap_range
self.update_value(val)
time.sleep(0.02)
_low, _high = self.get_limits()
if value == self.default_value:
self.update_specific_state(self.SPECIFIC_STATES.HOME)
elif value == _low:
self.update_specific_state(self.SPECIFIC_STATES.LOWLIMIT)
elif value == _high:
self.update_specific_state(self.SPECIFIC_STATES.HIGHLIMIT)
else:
self.update_specific_state(None)
return value
def is_moving(self):
return (self.get_state() == self.STATES.BUSY) or (
self.get_state() == self.SPECIFIC_STATES.MOVING
)