#%TITLE% KB_MIRROR.MAC
#%NAME%
# Define height and tilt pseudomotors for KB mirror
#
#%CATEGORY% Positioning
#
#%DESCRIPTION%
"""
A kb mirror is controlled typically by two rotation motors.
One, main rotation, is located at the middle of the mirror
while a second one is set in an eccentric point. The
combination of both allows to drive the mirror (the center
of it) to a certain 'tilt' angle and 'height' (for vertically
positioned mirrors, but we will use the 'height' term for
all mirrors).
This macro set supports both pseudo motor style definition
or macro motors directly in spec.
Rotation angles are in milli-radians, distance in millimeters
For pseudo motors:
------------------
Define tilt and height motors as controller NONE in spec config
In setup, for each mirror, add a line like:
mirrorsetup kbrot kbecrot kbtilt kbhgt 85
(in the example 85 is the distance between the two rotation points)
For macro motors:
-----------------
Add a MAC_MOT motor controller in spec config.
Device field = "kb"
Add motors tilt and height in config with controller pointing to
MAC_MOT "kb" controller
Set channels as:
channel 0 = tilt
channel 1 = height
Add !! manually !! in config files MOT_PAR lines to the
tilt (channel 0) motor. (Just add lines after MOTXXX line
correspoding to tilt motor
MOTPAR:distance = 85
MOTPAR:kbrot = kbrot
MOTPAR:kbecrot = kbecrot
(in the example kbrot and kbecrot are the mnemonics for
real motors (rotation and eccentric rotation). 85 is the
distance between the two rotation points )
Remember that one single kb motor controller is needed for
several mirrors. In that case it is necessary to define the
module field in the unit/mod/chan parameter in the motor
configuration in spec config.
"""
#%END%
global MIRROR_MNAME MIRROR_OLDPOS
global MIRROR_LEN
#%UU% <motor1> <motor2> <tilt> <offset> <distance>
#%MDESC%
# This macro allow to configure pseudo motors to control a KB-Mirror. %BR%
# A Kb_mirror is made with 2 motors mounted in leving-arm mode, one in the middle
# position of the mirror and one at the left side of the mirror: %BR%
# motor1 does a pure rotation of the mirror and motor2 does a kind of translation.%BR%
# So the mirror is rotated by moving m1 and tilt position = m2+m1.%BR%
# So the mirror is translated by moving first m1 of +delta and m2 of -delta and
# offset position = - m2 . %BR%
# %BR%
# m2 and m1 have to be configured in mradian unit and with a clokwise rotation.%BR%
#%PRE%
# X-Ray
# <--------------------------
# <- d ->
# o=========o==========
# | |
# | |
# | <== |<==
# | m2 m1
# ==== base
#%PRE%
#
# Note: with small mirror check how the motor m1 is mounted and its position motion direction.
# on BM05 m1 moves the mirror in the opposite direction of m2. So the SPEC sign into the config is -1.
# long mirror is "correctly" mounted.
def mirrorsetup '{
#
# Store motor mnemonics used
#
if ($# != 5){
print "Usage:mirrorsetup <motor1> <motor2> <tilt> <offset> <distance>"
exit
}
MIRROR_MNAME[0]="$1" # Motor1
MIRROR_MNAME[1]="$2" # Motor2
MIRROR_MNAME[2]="$3" # Tilt
MIRROR_MNAME[3]="$4" # Offset
MIRROR_LEN=$5 # Distance on mirror
#
# register hooks for SPEC
#
mirror_pdef
}'
#%UU% <tilt> <offset>
#%MDESC%
def mirrorunsetup '{
MIRROR_MNAME[2]="$1" # Tilt
MIRROR_MNAME[3]="$2" # Offset
cdef ("","",MIRROR_MNAME[2],"delete")
cdef ("","",MIRROR_MNAME[3],"delete")
}'
#%IU%
#%MDESC%
def mirror_getangle '{
local _position _sign
_position = A[$2] + A[$3]
_sign = user($1, 2) - user ($1, 1)
A[$1] = _position * _sign
MIRROR_OLDPOS[$1]=A[$1]
}'
#%IU%
#%MDESC%
def mirror_getheight '{
local _multi _position _sign
_multi = $4
_position = A[$3] * (-1.0) * _multi / 1000.0
_sign = user($1, 2) - user ($1, 1)
A[$1] = _position * _sign
MIRROR_OLDPOS[$1]=A[$1]
}'
#%IU%
#%MDESC%
def mirror_moveangle '{
local _sign
if (A[$1]!=MIRROR_OLDPOS[$1]) {
_sign = user($1, 2) - user ($1, 1)
A[$2] += (A[$1] - MIRROR_OLDPOS[$1]) * _sign
}
}'
#%IU%
#%MDESC%
def mirror_moveheight '{
local _multi _sign _pos
if (A[$1]!=MIRROR_OLDPOS[$1]) {
_multi = 1000.0 / $4
_sign = user($1, 2) - user ($1, 1)
#
# check first the limits of the second motor
# before moving the first one.
#
_pos = (A[$1] - MIRROR_OLDPOS[$1]) * _multi * _sign
_m2pos = A[$3] - _pos
_bad_lim=0
_chk_lim $3 _m2pos
if (_bad_lim) exit
A[$2] += _pos
move_all;waitmove;
A[$3] -= _pos
}
}'
#%IU%
#%MDESC%
def mirror_setuser '{
local delta _multi _sign _pos
delta = position2set - A[motor2set]
if (motor2set == $2) {
# height
_multi = 1 / $5
_multi = _multi * 1000.0
_sign = user($2, 2) - user ($2, 1)
chg_offset($3,A[$3]+ delta *_multi *_sign)
chg_offset($4,A[$4]- delta *_multi *_sign)
} else if (motor2set == $1) {
# angle
chg_offset($3,A[$3]+delta)
}
}'
#%IU%
#%MDESC%
def mirror_pdef '{
cdef("user_checkall",sprintf("mirror_moveheight %s %s %s %f;"\
,MIRROR_MNAME[3],MIRROR_MNAME[0],MIRROR_MNAME[1], MIRROR_LEN),MIRROR_MNAME[3],0x21)
cdef("user_getpangles",sprintf("mirror_getheight %s %s %s %f;"\
,MIRROR_MNAME[3],MIRROR_MNAME[0],MIRROR_MNAME[1], MIRROR_LEN),MIRROR_MNAME[3],0x11)
cdef("user_checkall",sprintf("mirror_moveangle %s %s %s ;"\
,MIRROR_MNAME[2],MIRROR_MNAME[0],MIRROR_MNAME[1]),MIRROR_MNAME[2],0x21)
cdef("user_getpangles",sprintf("mirror_getangle %s %s %s ;"\
,MIRROR_MNAME[2],MIRROR_MNAME[0],MIRROR_MNAME[1]),MIRROR_MNAME[2],0x11)
#LC 10/06/2004
cdef("user_set",sprintf("mirror_setuser %s %s %s %s %f;"\
,MIRROR_MNAME[2],MIRROR_MNAME[3],MIRROR_MNAME[0],MIRROR_MNAME[1], MIRROR_LEN)\
,MIRROR_MNAME[3],0x1)
}'
#
# Macros to support macro motor funcitonality
#
def kb_config(mne,type,unit,module,chan) '{
local _master, _kbrot, _kbecrot, _distance
if ( type == "ctrl") return
_master = motor_par(mne, "chan0")
_kbrot = motor_par(_master,"kbrot")
_kbecrot = motor_par(_master,"kbecrot")
_distance = motor_par(_master,"distance")
if (motor_num(_kbrot) == -1 || motor_num(_kbecrot) == -1) {
return ".error."
}
motor_par(mne, "master", _master, "add")
if (chan == 0) { # Tilt
# save my role and inform the master
motor_par(mne, "role", "tilt", "add")
motor_par(_master, "tilt", motor_mne(mne), "add")
#
# save interesting motor_par for real motors
# master, distance and role
# they will be needed later in kb_calc
#
motor_par(_kbrot, "master", mne, "add")
motor_par(_kbecrot, "master", mne, "add")
motor_par(_kbrot, "distance", distance, "add")
motor_par(_kbecrot, "distance", distance, "add")
motor_par(_kbrot, "role", "kbrot", "add")
motor_par(_kbecrot, "role", "kbecrot", "add")
} else if (chan == 1) { # Height
# save my role and inform the master
motor_par(mne, "role", "height", "add")
motor_par(_master, "height", motor_mne(mne), "add")
} else {
print "Wrong channel assignment for kb_mirror macro motors. Only 0 or 1"
return ".error."
}
# return dependency on real motors
return sprintf("%s %s", _kbrot, _kbecrot)
}'
def kb_calc(mne,mode) '{
local _motnum, _role, _master, _distance
local _kbrot, _kbecrot, _kbrotnum, _kbecrotnum
local _tilt, _hgt, _tiltnum, _hgtnum
_motnum = motor_num(mne)
if (mne == "..") return
#
# role and master have been set on kb_config for all motors,
# both real and macro motors
#
_role = motor_par(mne, "role")
_master = motor_par(mne, "master")
if ( mode == 0 ) { # getangles... calculate macro mot positions
_distance = motor_par(_master, "distance")
_kbrot = motor_par(_master,"kbrot")
_kbecrot = motor_par(_master,"kbecrot")
_kbrotnum = motor_num(_kbrot)
_kbecrotnum = motor_num(_kbecrot)
if ( _role == "tilt") {
A[_motnum] = A[_kbrotnum] + A[_kbecrotnum]
} else if ( _role == "height") {
A[_motnum] = - A[_kbecrotnum] * _distance / 1000.0
}
} else { # mode = 1. calculate real positions from macro motors
_tilt = motor_par(_master,"tilt")
_hgt = motor_par(_master,"height")
_distance = motor_par(_master, "distance")
_tiltnum = motor_num(_tilt)
_hgtnum = motor_num(_hgt)
if ( _role == "kbrot") {
A[_motnum] = A[_tiltnum] + A[_hgtnum] * 1000.0 / _distance
} else if ( _role == "kbecrot") {
A[_motnum] = - A[_hgtnum] * 1000.0 / _distance
}
}
}'
#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
# The file kb_mirror.mac has to be loaded ! done in idxxsetup.mac
# (This file needs pseudo.mac stlocal.mac)
#%AUTHOR%
# KB_MIRROR.MAC
#%TOC%
|