Motor
Creating a Motor Instance
A motor instance is created by subclassing MultiMotorInterface, which provides essential features for a generic multi-axis motor.
For real hardware, you should implement device-specific communication methods in your subclass as follows:
from lys_instr import MultiMotorInterface
class YourMotor(MultiMotorInterface): # Give a name to your subclass, e.g., ``YourMotor``
def __init__(self, *axisNamesAll, **kwargs):
super().__init__(*axisNamesAll, **kwargs)
... your code to establish connection and initialize the instruments ...
self.start()
def _set(self, **target):
# target (dict): Axis names as keys and target positions as values.
... your code to tell the instruments to move to the target positions for specified axes ...
def _get(self):
... your code to read the current positions of all axes from the instruments ...
return ... a dictionary with axis names as keys and current positions (float) as values ...
def _stop(self):
... your code to tell the instruments to stop all axes ...
def _isBusy(self):
... your code to check if each axis is moving ...
return ... a dictionary with axis names as keys and busy states (bool) as values (True if busy, False if not) ...
def _isAlive(self):
... your code to check if each axis is connected and functioning ...
return ... a dictionary with axis names as keys and alive states (bool) as values (True if alive, False if not) ...
Step-by-Step Demonstration
Here we illustrate step-by-step construction of YourMotor for a dummy device with axes “x” and “y”.
Subclass MultiMotorInterface to create YourMotor, and attach a simulator instance to each axis to supply position values.
(The _ValueInfo helper in lys_instr.dummy provides such a simulator.)
The constructor accepts positional axis names via *axisNamesAll, for example, YourMotor("x", "y").
from lys_instr import MultiMotorInterface
class YourMotor(MultiMotorInterface):
def __init__(self, *axisNamesAll, **kwargs):
super().__init__(*axisNamesAll, **kwargs)
from lys_instr.dummy.MultiMotor import _ValueInfo
self._simulator = {name: _ValueInfo(10) for name in axisNamesAll} # motor speed: 10 units/s
self.start()
Alternatively, you can use a constructor that explicitly accepts two axis name parameters, for example, axisName_x and axisName_y.
from lys_instr import MultiMotorInterface
class YourMotor(MultiMotorInterface):
def __init__(self, axisName_x, axisName_y, **kwargs):
super().__init__(axisName_x, axisName_y, **kwargs)
from lys_instr.dummy.MultiMotor import _ValueInfo
self._simulator = {axisName_x: _ValueInfo(10), axisName_y: _ValueInfo(10)} # motor speed: 10 units/s
self.start()
Implement _set() to assign target positions for specified axes (this starts movement in the simulator).
_set() accepts keyword arguments mapping axis names to numeric targets.
def _set(self, **target):
for name, d in self._simulator.items():
if name in target:
d.set(target[name])
Implement _get() to read the position of each simulator axis and return a dictionary mapping axis names to their current positions.
def _get(self):
return {name: d.position for name, d in self._simulator.items()}
Implement _stop() to halt all axis motion by calling each axis’s stop() method.
def _stop(self):
for d in self._simulator.values():
d.stop()
Implement _isBusy() to check the simulator and return a dictionary mapping axis names to booleans indicating whether each axis is currently moving.
def _isBusy(self):
return {name: d.busy for name, d in self._simulator.items()}
Implement _isAlive() to check the simulator and return a dictionary mapping axis names to booleans indicating whether each axis is connected and functioning.
def _isAlive(self):
return {name: not d.error for name, d in self._simulator.items()}
Optionally, implement settingsWidget to return a QWidget for later use by GUI.
The _OptionalPanel class in the lys_instr.dummy.MultiMotor module can readily be used.
def settingsWidget(self):
from lys_instr.dummy.MultiMotor import _OptionalPanel
return _OptionalPanel(self)
The class constructed above is actually the MultiMotorDummy class provided in the lys_instr.dummy module.
Checking Operations
To verify functionality, instantiate your motor class, for example, YourMotor.
(Import it if defined in a separate module.)
motor = YourMotor(... your parameters ...)
For demonstration, we use the YourMotor class defined above with two axes, “x” and “y”:
motor = YourMotor("x", "y")
This is functionally equivalent to instantiating the provided MultiMotorDummy class:
from lys_instr import dummy
motor = dummy.MultiMotorDummy("x", "y")
Now, you can use the set(), get(), stop(), isBusy(), and isAlive() methods provided by MultiMotorInterface to confirm that the motor is functioning correctly.
For example:
motor.set(x=1.0, y=2.0) # You can also set a single axis: motor.set(x=1.0)
print(motor.get()) # Returns current positions, e.g. {'x': 0.18, 'y': 0.18}