Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

...

This wiki describes why and how one subclasses the class Dabsdabs.Devicesinterfaces.Interfaces.LinearStageController. From now on we will refer to this class or an instance of it as (an) "LSC".

...

  • It has properties for the current stage position (.positionAbsolute, .positionRelative) and whether the stage is currently moving (.isMoving).
  • It performs unit conversion, and can map the stage coordinate system onto an a differing external coordinate system.
  • It has methods for nonblocking and blocking stage moves (see below).
  • It maintains an origin to enable zeroing the position coordinate system (within software).
  • It has properties for device metadata, such as resolution, velocity, positionUnits, and so on.

Blocking vs nonblocking moves
The LSC interface provides two types of moves: blocking, and nonblocking. When started, a blocking move blocks MATLAB execution until the move is complete. When a nonblocking move is started, control is returned to MATLAB immediately after the move is initiated, so that MATLAB execution can continue. For nonblocking moves, the LSC interface allows a callback to be supplied, which fires when the move is complete.

How LSC works

LSC properties and methods are roughly split into two groups: those intended for the subclass writer (you), and those intended for the LSC user (whoever or whatever interacts with the class; most often, this will be the ScanImage application).

The properties you should focus on are the abstract properties, many of which have "Raw" in their names: positionAbsoluteRaw, velocityRaw, etc. You will implement these properties appropriately for your device, within a coordinate and unit system of your choosing.

On the other hand, users of your LSC class will interact with the "non-Raw" properties: postionAbsolute, velocity, and so on. These properties provide access to the Raw properties, but with an additional layer of code that performs unit conversion and coordinate transformations. In general, LSC users do not interact with the Raw properties.

The situation with methods is the same. As an LSC class author, you should focus on the abstract methods which have "Hook" in their names, such as moveStartHook. Meanwhile, users of your class will use the corresponding "non-Hook" methods, such as moveStartAbsolute. The code for moveStartAbsolute calls your moveStartHook method, but has an additional layer of code.

Your Device

We will assume you have a particular stage controller device you wish to control from MATLAB. To be controlled by MATLAB, the device must have an interface to your computer, such as a serial port interface. You will need the documentation for this interface (the available commands and their responses, etc). Note that your stage will often have manual input/control in addition to control via its computer interface.

...

If so, you may want to subclass from Dabsdabs.Devices.Interfacesinterfaces.LSCSerial rather than LinearStageController. LSCSerial is itself a subclass of LSC and provides initialization of the MATLAB serial port, along with an instance of an RS232DeviceBasic object which is a serial port interface with some built-in convenience functionality.

...

The LSC interface currently uses three dimensions (X, Y, and Z) for input and output of position values. Some However, some devices may only control one or two physical dimensions. In this case, your subclass will need to initialize the properties numDeviceDimensions and lsc2DeviceDims, which specify a nondefault value of numDeviceDimensions when calling the LSC constructor. This value specifies the number of dimensions controlled by your device and the mapping between those dimensions and the three-dimensional space used by LSC.

Which dimensions of my stage are 'active'?

Depending on your application, you may want to "turn off" certain dimensions in your stage controller. For example, you might have a device that can move in three dimensions, but an experimental setup where you only want scanning in a fixed 2-D plane.

In this case, you will need to initialize the property activeDimensions to specify which dimensions are "on" and which are "off". (This property is specified with respect to the three-dimensional LSC coordinate system.)

.

Note that the users of your LSC class may set the property lsc2DeviceDims to specify how the device coordinate system is mapped to the external, three-dimensional coordinate system. This functionality is built in to LSC; you, the subclass writer, do not have to do anything to make this workBy default activeDimensions is "all on", so if you just want to use all the dimensions available for your device, you don't have to do anything.

What units of measurement does my device operate in?

...

The second unit system is intended for the class user, who is interacting with an instance of your class to control a particular stage. This set of units is represented by the properties positionUnits, velocityUnits, and accelerationUnits. The user can set these units as is convenient for his or her application. For example, ScanImage works in units of microns; when ScanImage uses LSC objects, it makes sure to have positionUnits set to be 1e-6, and so on.

...

Some devices have various move-related modes. For example, the Sutter sutter.MP285 has a "coarse" resolution for faster, less accurate moves, and a "fine" resolution for slower, more accurate moves.

...

If your device responds when a move is complete, then you should probably set nonblockingMoveCompletedDetectionStrategy to 'callback'. Otherwise, set it to 'poll'. Specification of this property is necessary for LSC to implement its move interface, which supports both blocking and nonblocking moves (see above).

Implementing Abstract Properties

Example: MP285

We use Dabsdabs.Devices.Suttersutter.MP285 as an example of a concrete LSC subclass. Since the Sutter MP285 device is controlled by serial port, MP285 subclasses Dabsdabs.Devices.Interfacesinterfaces.LSCSerial.

MP285 implements LSC abstract properties in a typical way:

  • Some properties are known in advance and will not change at run-time. Examples are : positionUnits or velocityUnits, or resolutionBestfor example. These properties are implemented as regular (non-Dependent) properties, and are given default values directly in the properties block. In some cases, it may make sense to allow these properties to be optionally constructor-initialized, eg if their value depends on a firmware version which can vary from device to device. For the MP285, the positionUnits falls into this "set-it-and-forget-it" category.
  • Some properties do change at runtime, and involve read-only queries to the hardware. An example is positionAbsoluteRaw. These properties are implemented as Dependent properties, with get-methods that send the appropriate query commands to the hardware.
  • Some properties not only change at runtime, but can be set to new values, as well as queried. An example of such a property is velocity, implemented as a Dependent property with both a set-method and a get-method. The set-method sends the appropriate set-command (and value-to-be-set) to the hardware to set the value on the device.

Other

...

notes:

  • In some cases, a property "does not apply" to a device. In the same vein, ScanImage does not utilize all available LSC properties. At the current time, the abstract properties required for ScanImage operation are:
  1. nonblockingMoveCompletedDetectionStrategy
  2. positionAbsoluteRaw (get only)
  3. isMoving (get only)
  4. positionUnits (get only)
  5. resolution (get only)

...

  • accelerationRaw, for example, does not apply to the MP285. To make MP285 a concrete class, accelerationRaw must be defined somewhere in a properties block; however, this property doesn't do anything (its get-method always returns NaN, and there is no set-method). Your LSC subclass may similarly "omit" inapplicable properties. Note however that ScanImage will expect certain properties to be present and working. See #Minimal LSC Implementation for ScanImage below.
  • The MP285 has two "resolutionModes", 'fine' and 'coarse'. Each mode has its own velocity setting, so that the resolutionMode is queried when setting/getting the velocity property. The details related to resolutionMode are specific to MP285 and may not apply to your device; however they do illustrate the general pattern of having more than one mode.
  • The MP285 is a serial port device, and the MP285 class subclasses from LSCSerial. To implement its send/receive commands, it uses the LSCSerial property , which holds an hRS232 object. This object adds some convenience functionality to the MATLAB serial object. See the documentation for Dabsdabs.Devicesinterfaces.Interfaces.RS232DeviceBasic for details.

...

LSC has a number of other methods with Hook in their names, such as moveCompleteHook, interruptMoveHook, etc. Concrete subclasses are encouraged to override these methods whenever possible. The default implementation of interruptMoveHook, for example, simply throws an error indicating that move-interruption is not supported. LSC subclasses representing stages that can be interrupted during moves should implement an override for this method to enable such interruption.

Minimal LSC Implementation for ScanImage

The LSC interface includes more than is absolutely required by ScanImage, because it was designed to be generally useful, independent of any single application.

That said, you are probably reading this page because you are a ScanImage user with a custom stage. At the moment, ScanImage requires the following properties and methods of LSC to be implemented/functional:

Properties

  1. nonblockingMoveCompletedDetectionStrategy
  2. isMoving (get only)
  3. positionAbsoluteRaw (get only)
  4. positionDeviceUnits (get only)

Methods

  1. moveStartHook
  2. getResolutionBestHook (This method has a default implementation in LSC, but if the default method doesn't apply to your device then you should provide an override.)

Testing

When your subclass is complete, it is critical to test its operation with real hardware in a "safe" setting before live use. Implementing an LSC subclass involves a fair amount of complexity and some amount of testing/debugging time will likely be necessary to ensure reliable operation. Using an LSC without proper testing could lead to wild stage moves and damage to your rig.