Moving the Stage

Demonstrates and discusses methods on how to move the stage.

Simple stage move

In the following example the :doc:`Hardware Controller </nodes/HardwareController> is used to control the stage:

import litho.core as lc

# Get the stage position:
spos = lc.hwCtrl().currentStagePosition(True)
# True: Refetch the position from the SEM
 
# print the current position
print(spos)

# add 4 and 2 mm to the curent xy position
spos.position += lc.vec2(4,2)
print(spos.position)

lc.hwCtrl().setStagePos(spos.position) # moves only xy

# move it back
lc.hwCtrl().moveStagePos(lc.vec2(-4,-2))
# .. this moves it relative to the current position

# the "stage calibration matrix" is a property of the sem controller.
# to use it:
cmat = lc.hwCtrl().sem().stageCalibMatrix # get it ..
clib_delta = cmat*lc.vec2(4, -1) # apply it to your 'move' ...
abs_pos = lc.hwCtrl().currentStagePosition(True).position+clib_delta
print(abs_pos)
lc.hwCtrl().setStagePos(xy=abs_pos) # .. and set it

Note

All stage position calls (e.g. set../move..) are synchronous. This can have the consequence that the smile2 user interface might partially “freeze” during the stage move.

Using the SEM Controller

The same can also be done by calling the SEM control component directly:

import litho.core as lc

# the "low level" way:

# get a handle of the sem controller
sem = lc.hwCtrl().sem()

# this call starts the stage movement, and returns
sem.setStagePos(xyz_position=lc.vec3(20,20,0), rot=10, opts=lc.StageMoveOpts.Backlashed)

# .. depending on the SEM, one can ask if the stage is busy:
if sem.stageFeatures() & lc.Feature.StageAutoPositionContol:
	while sem.isStageBusy == True:
		print("Oha! still moving!")
else:
	print("No clue. Better to move stage with hwCtrl()")
# note: not all sems/stages support 'StageAutoPositionContol'

One difference between this and the example above is that, the direct call is asynchronous (meaning it returns after the command as been sent to the SEM)