#%TITLE% TAB3.MAC
#%NAME%
# Macros to control three leg table(s) with logical motors
# xtilt, ytilt and height
#
#
#
#
# DOC : http://wikiserv.esrf.fr/bliss/index.php/Tab
#
#you must have :
#
# 3 real motors configured.
# 3 macro-motors
# 1 is considered as "master"
#
# ALL motors (real and macro) must have a 'master' field in their custom parameters to know which is the master.
#
# the master macmot has 9 or 10 supplementary custom parameters:
# lb1mne : real motor mnemonic for leg back 1
# lb2mne : real motor mnemonic for leg back 2
# lfmne : real motor mnemonic for leg front
# height : macro motor mnemonic for Z/Height
# xtilt : macro motor mnemonic for first tilt
# ytilt : macro motor mnemonic for second tilt
# d1 : custom distance 1
# d2 : custom distance 2
# (d3) : custom distance 3
# geometry : number 0..7
#
#
#
#
#%DESCRIPTION%
# A table with three legs in triangle. One in the front and two in the equilateral triangle ???
# back is a common positioning element in ESRF beamlines. This macros
# implement tilts and height for this kind of table as pseudomotors.
# This macros can use different geometries.
# More than one table can be defined in this way in the same spec
# application.%BR%
#
# For geometry 0 (standard):%BR%
# Xtilt is the angle defined by the two back legs.
# Fixed a middle point B between the two back legs. The height in the
# middle point between B and the front leg gives the value for the
# motor height. The motor Ytilt is defined as the angle existing
# between B and front leg.
#
# Two parameters must be input to the system: the distance between the
# two back legs and the distance between B and the front leg.
# In this geometry distances are given in mm. Angles in mrad.%BR%
#
# For geometry 1 (side front leg):%BR%
# The front leg is on the same side and aligned with the first motor. same side than what ???
# first motor ???
# The fixed point is in the middle of the mirror. For positive x tilt position of mirror ??
# is motor 1 higher up then motor 2. For positive y tilt is the
# front motor higher up then the two back motors.%BR%
#
# For geometry 2 (ID22 mirror):%BR%
# Xtilt is the angle defined by the two back legs, but only leg2 moves
# when a xtilt is requested.
# Ytilt and Height are defined in the line defined by leg1 and front.
# For the two movements leg2 follows leg1.%BR%
#
# For geometry 3 (ID21 mirror):%BR%
# Xtilt is the angle defined by the two back legs.
# Fixed a middle point B between the two back legs. The value of this diff with geo: position of Height
# point gives the value for the motor Height. The motor Ytilt is
# defined as the angle existing between B and front leg.
# Two parameters must be input to the system: the distance between the
# two back legs and the distance between B and the front leg.
# In this geometry distances are given in mm. Angles in mrad.%BR%
#
# For geometry 4 (ID20):%BR%
#
# For geometry 5 (ID29 mirror):%BR%
# Xtilt is the angle defined by the two back legs.
# B is the middle distance point between the two back legs. C is at
# fixed distance between B and the front leg, used to calculate the
# height. The Ytilt is defined as the angle between B and the front leg.
# Three parameters needed: the distance between the two back legs,
# between B and the front leg and between C and the front leg (all
# given in mm). Calculated angles in mrad.%BR%
#
# For geometry 6 (ID30):%BR%
#
#
# For geometry 7 (ID24 polychromator crystal tripod):%BR%
# 2 back legs (in front of mirror). let B the middle of b1 b2.
# 1 front leg (back of mirror).
# (front / back are counter-intuitive to reflect the symetrie of the tripod :
# 1 single leg in back and 2 legs in front of the mirror)
# 3 legs are placed as an equilateral triangle.
# let C the center of the triangle. [B;C] = 1/3 [B;leg2].
# Height is considered at the triangle center.
# Xtilt (PSI) is rotation along axis [B;leg2].
# Ytilt (CHI) is rotation along axis perpanducular to [Xtilt] passing by C.
# Height (Z) is considered in C.
# See pictur on bliss wiki.
#
# For geometry 8 (ID15A tripod lenses):
#
# t2 (front)
# (*)
# |
# -----------|---------> X
# |
# (*) | (*)
# t3 (leg2) | t1 (leg1)
# lens
#
# t1/t2/3 corresponds to motor labels
# d1= length(t1:t2) = length(t2:t3) = length(t3:t1)
# d2= length(middle(t1:t3):t2)
# d3= height of lens aperture from tripod base
#%IU% [parma]
#%MDESC%
#
def tab3_config(motornum, type, par1, par2) '{
__tab3_debug ">>> tab3_config: ",motornum, type, par1, par2
if (motornum == "..") {
}
else{
if (type == "mot") {
# Returns the list of all REAL motors involved in the macro motor(s).
return tab3_motconfig(motornum, par1, par2)
}
}
}'
#%IU% (<motnum>, <mode>, <unit>)
#%MDESC%
#
def tab3_calc(motnum, mode, unit) '{
__tab3_debug ">>> tab3_calc: ",motnum, mode, unit
local master_motnum
master_motnum = 0
# motor number
local lb1num lb2num lfnum
local hgtnum xtnum ytnum
local d1, d2, d3, geo
# lenghts/angles
local t3_bl1 t3_bl2 t3_fro
local t3_xti t3_yti t3_hgt
if (motnum == "..") {
return
}
# Get "master" motor.
if( (master_motnum = motor_num(motor_par(motnum, "master")) ) == -1){
__tab3_debug ">>> tab3_calc: master is: ", motor_mne(master_motnum)
printf("t3mh.mac--tab3_calc()--ERROR--cannot get \"master\" for motor %s(no %d)\n", \
motor_mne(motnum), motnum)
print " ---> exit"
exit
}
else{
__tab3_debug ">>> tab3_calc: master is: ", motor_mne(master_motnum)
}
# Get legs motor numbers.
if ((lb1num = motor_num(motor_par(master_motnum, "lb1mne"))) == -1){
__tab3_debug ">>> tab3_calc: lb1num: ", motor_mne(lb1num)
print "t3mh.mac--tab3_calc()--ERROR--cannot get \"lb1mne\" motor (all motors must have \"master\" field !!!)"
}
else{
__tab3_debug ">>> tab3_calc: lb1num: ", motor_mne(lb1num)
}
if ((lb2num = motor_num(motor_par(master_motnum, "lb2mne"))) == -1){
__tab3_debug ">>> tab3_calc: lb2num: ", motor_mne(lb2num)
print "t3mh.mac--tab3_calc()--ERROR--cannot get \"lb2mne\" motor"
print " ---> exit"
exit
}
else{
__tab3_debug ">>> tab3_calc: lb2num: ", motor_mne(lb2num)
}
if ((lfnum = motor_num(motor_par(master_motnum, "lfmne"))) == -1){
__tab3_debug ">>> tab3_calc: lb3num: ", motor_mne(lfnum)
print "t3mh.mac--tab3_calc()--ERROR--cannot get \"lfmne\" motor"
print " ---> exit"
exit
}
else{
__tab3_debug ">>> tab3_calc: lb3num: ", motor_mne(lfnum)
}
# Numbers of fake motors.
if ((hgtnum = motor_num(motor_par(master_motnum, "height"))) == -1){
print "t3mh.mac--tab3_calc()--ERROR--cannot get \"height\""
print " ---> exit"
exit
}
if ((xtnum = motor_num(motor_par(master_motnum, "xtilt"))) == -1){
print "t3mh.mac--tab3_calc()--ERROR--cannot get \"xtilt\""
print " ---> exit"
exit
}
if ((ytnum = motor_num(motor_par(master_motnum, "ytilt"))) == -1){
print "t3mh.mac--tab3_calc()--ERROR--cannot get \"ytilt\""
print " ---> exit"
exit
}
# Geometrical parameters.
if ((d1 = motor_par(master_motnum, "d1")) == -1){
print "t3mh.mac--tab3_calc()--ERROR--cannot get \"d1\""
print " ---> exit"
exit
}
if ((d2 = motor_par(master_motnum, "d2")) == -1){
print "t3mh.mac--tab3_calc()--ERROR--cannot get \"d2\""
print " ---> exit"
exit
}
if ((d3 = motor_par(master_motnum, "d3")) == -1){
print "t3mh.mac--tab3_calc()--ERROR--cannot get \"d3\""
print " ---> exit"
exit
}
if ((geo = motor_par(master_motnum, "geometry")) == -1){
print "t3mh.mac--tab3_calc()--ERROR--cannot get \"geometry\""
print " ---> exit"
exit
}
if ( mode == 0 ) {
# MACRO MOTORS CALCULATION
t3_bl1 = A[lb1num]
t3_bl2 = A[lb2num]
t3_fro = A[lfnum]
t3_xti = A[xtnum]
t3_yti = A[ytnum]
t3_hgt = A[hgtnum]
if (motnum == hgtnum) {
# height
A[motnum] = tab3_tf( 5, t3_bl1, t3_bl2, t3_fro, t3_xti, t3_yti, t3_hgt, geo, d1,d2,d3)
}
else if (motnum == xtnum) {
# xtilt
A[motnum] = tab3_tf( 3, t3_bl1, t3_bl2, t3_fro, t3_xti, t3_yti, t3_hgt, geo, d1,d2,d3)
}
else if (motnum == ytnum) {
# ytilt
A[motnum] = tab3_tf( 4, t3_bl1, t3_bl2, t3_fro, t3_xti, t3_yti, t3_hgt, geo, d1,d2,d3)
}
}
else {
# REAL MOTOR CALCULATION
t3_bl1 = A[lb1num]
t3_bl2 = A[lb2num]
t3_fro = A[lfnum]
t3_xti = A[xtnum]
t3_yti = A[ytnum]
t3_hgt = A[hgtnum]
__tab3_debug ">>> tab3_calc: -------------------------------- mode 1"
if ( motnum == -1 ) {
print "Mne " mne ".Motnum: " motnum
}
else if ( motnum == lb1num) {
# leg back 1
A[motnum] = tab3_tf( 0, t3_bl1, t3_bl2, t3_fro, t3_xti, t3_yti, t3_hgt, geo, d1,d2,d3)
}
else if ( motnum == lb2num) {
# leg back 2
A[motnum] = tab3_tf( 1, t3_bl1, t3_bl2, t3_fro, t3_xti, t3_yti, t3_hgt, geo, d1,d2,d3)
}
else if ( motnum == lfnum) {
# leg front
A[motnum] = tab3_tf( 2, t3_bl1, t3_bl2, t3_fro, t3_xti, t3_yti, t3_hgt, geo, d1,d2,d3)
}
}
#local myval mymne
#myval = A[motnum]
#mymne = motor_mne(motnum)
#__tab3_debug ">>> tab3_calc: motor ",mymne , " set to : ",myval
__tab3_debug ">>> tab3_calc: motor ", motor_mne(motnum), " is: ", A[motnum]
}'
#%IU% (<motnum>)
#%MDESC%
#
# -<motnum> :
# -<unit> :
# -<chan> :
def tab3_motconfig(motnum) '{
local _dependant_motors_list
local master_motnum
master_motnum = motor_num(motor_par(motnum, "master"))
if (master_motnum < 1){
print "tab3mh--ERROR--no master motor defined."
print " -> exit"
exit
}
# Finds 3 leg motors number in special parameters of master motor.
_dependant_motors_list = ""
_dependant_motors_list = _dependant_motors_list motor_par(master_motnum, "lb1mne")
_dependant_motors_list = _dependant_motors_list " " motor_par(master_motnum, "lb2mne")
_dependant_motors_list = _dependant_motors_list " " motor_par(master_motnum, "lfmne")
__tab3_debug ">>> tab3_config: dependant motor list: ", _dependant_motors_list
return _dependant_motors_list
}'
#%IU% (calcidx , tbl1, tbl2, front, xti, yti, z, geometry , d1, d2,d3)
#%MDESC% calcidx gives the index of the value to be calculated. Indexes are
# starting from 0 (tbl1) and go to 5 (z). The 3 leg motors and the 3 pseudo
# motors are all the time given. Depending on calcidx only 3 of them are used
# in the calculation. The geometry allows for different geometries. d1 and d2 are
# the distances between the legs. d3 is the distance between the front leg
#and the center of the rotation.
def tab3_tf(calcidx, t3_bl1, t3_bl2, t3_fro, t3_xti, t3_yti, t3_hgt, geometry, d1, d2, d3) '{
local reverse res
__tab3_debug ">>> tab3_tf: ", calcidx, t3_bl1, t3_bl2, t3_fro, t3_xti, t3_yti, t3_hgt, geometry, d1, d2, d3
if (calcidx > 2 ){
reverse = 1
}
if (geometry == 0) {
if (reverse) {
res[3] = 1000*atan( (t3_bl2 - t3_bl1) / d1 ) # xti
res[4] = 1000*atan( ( (t3_bl1 + t3_bl2)/2 - t3_fro) / d2) # yti
res[5] = (t3_bl1 + t3_bl2 + 2*t3_fro)/4 # z
} else {
res[0] = t3_hgt - d1 * tan(t3_xti/1000) / 2+d2*tan(t3_yti/1000)/2 # tbl 1
res[1] = t3_hgt + d1 * tan(t3_xti/1000) / 2+d2*tan(t3_yti/1000)/2 # tbl 2
res[2] = t3_hgt - d2 * tan(t3_yti/1000) / 2 # front
}
}
if (geometry == 1) {
if (reverse) {
res[3] = 1000*atan( (t3_bl2 - t3_bl1) / d1 ) # xti
res[4] = 1000*atan( (t3_fro - t3_bl1) / d2 ) # yti
res[5] = (t3_bl2 + t3_fro)/2 # z
} else {
res[0] = t3_hgt - d1 * tan(t3_xti/1000) / 2 - d2*tan(t3_yti/1000) / 2 # tbl 1
res[1] = t3_hgt + d1 * tan(t3_xti/1000) / 2 - d2*tan(t3_yti/1000) / 2 # tbl 2
res[2] = t3_hgt + d2 * tan(t3_yti/1000) / 2 - d1*tan(t3_xti/1000) / 2 # front
}
}
if (geometry == 2) {
if (reverse) {
res[3] = deg(atan( (t3_bl2 - t3_bl1) / d1 )) # xti
res[4] = deg(atan( (t3_bl1 - t3_fro) / d2 )) # yti
res[5] = (t3_bl1 + t3_fro)/2 # z
} else {
res[0] = t3_hgt + d2 * tan(rad(t3_yti))/2 # tbl 1
res[1] = t3_hgt + d2 * tan(rad(t3_yti))/2 + d1 * tan(rad(t3_xti)) # tbl 2
res[2] = t3_hgt - d2 * tan(rad(t3_yti))/2 # front
}
}
if (geometry == 3) {
if (reverse) {
res[3] = 1000*atan( (t3_bl2 - t3_bl1) / d1 ) # xti
res[4] = 1000*atan( ( (t3_bl1 + t3_bl2)/2 - t3_fro) / d2) # yti
res[5] = (t3_bl1 + t3_bl2)/2 # z
} else {
res[0] = t3_hgt - d1 * tan(t3_xti/1000) / 2 # tbl 1
res[1] = t3_hgt + d1 * tan(t3_xti/1000) / 2 # tbl 2
res[2] = t3_hgt - d2 * tan(t3_yti/1000) # front
}
}
if (geometry == 4) {
if (reverse) {
res[3] = 1000*atan( (t3_bl2 - t3_bl1) / d1 ) # xti
res[4] = 1000*atan( ( t3_fro - (t3_bl1 + t3_bl2)/2 ) / d2) # yti
res[5] = (t3_bl1 + t3_bl2 + 2*t3_fro)/4 # hgt
} else {
res[0] = t3_hgt - d1 * tan(t3_xti/1000) / 2 - d2 * tan(t3_yti/1000) / 2 # tbl 1
res[1] = t3_hgt + d1 * tan(t3_xti/1000) / 2 - d2 * tan(t3_yti/1000) / 2 # tbl 2
res[2] = t3_hgt + d2 * tan(t3_yti/1000) / 2 # front
}
}
if (geometry == 5) {
if (reverse) {
res[3] = 1000*atan( (t3_bl2 - t3_bl1) / d1 ) # xti
res[4] = 1000*atan( ( (t3_bl1 + t3_bl2)/2 - t3_fro) / d2) # yti
res[5] = t3_fro + ( (t3_bl1 + t3_bl2)/2 - t3_fro) * (d3/d2) #z
} else {
res[0] = t3_hgt - d1 * tan(t3_xti/1000) / 2 + (d2 - d3)*tan(t3_yti/1000) #tbl 1
res[1] = t3_hgt + d1 * tan(t3_xti/1000) / 2 + (d2 - d3)*tan(t3_yti/1000) #tbl 2
res[2] = t3_hgt - d3 * tan(t3_yti/1000) #front
}
}
if (geometry == 6) {
if (reverse) {
res[3] = deg( atan( (t3_bl2 - t3_bl1) / d1 ) ) # xti
res[4] = deg( atan( ( (t3_bl1 + t3_bl2)/2 - t3_fro) / d2) ) # yti
res[5] = (t3_bl1 + t3_bl2) / 2 # z
} else {
res[0] = t3_hgt - d1 * tan( rad(t3_xti) ) / 2 # tbl 1
res[1] = t3_hgt + d1 * tan( rad(t3_xti) ) / 2 # tbl 2
res[2] = t3_hgt - d2 * tan( rad(t3_yti) ) # front
}
}
# ID24 tripod for polychromator crystal.
if (geometry == 7) {
if (reverse) {
if(d2*d1 == 0){
print "tab3_tf--ERROR : d1 or d2 == 0"
print "---> exit"
exit
}
else{
res[3] = deg(atan((1/d1) * (t3_bl2 - t3_bl1))) # Xtilt / PSI (deg)
res[4] = deg(atan((1/d2) * (0.5 *(t3_bl1 + t3_bl2) - t3_fro))) # Ytilt / CHI (deg)
res[5] = (1/3) * (t3_bl1 + t3_bl2 + t3_fro) # Height / z (mm)
#
__tab3_debug ">>> tab3_tf: from leg1: ", t3_bl1, " leg3: ", t3_bl2, " leg2: ", t3_bl3
__tab3_debug ">>> tab3_tf: PSI: ", res[3], " CHI: ", res[4], " Z: ", res[5]
}
}
else {
res[0] = t3_hgt - 0.5 * tan(rad(t3_xti)) *d1 + (1/3) * tan(rad(t3_yti)) * d2 # tbl 1 (mm) / leg1
res[1] = t3_hgt + 0.5 * tan(rad(t3_xti)) * d1 + (1/3) * tan(rad(t3_yti)) * d2 # tbl 2 (mm) / leg3
res[2] = t3_hgt - 2/3 * tan(rad(t3_yti)) * d2 # front (mm) / leg2
#
__tab3_debug ">>> tab3_tf: from PSI: " , t3_xti , " CHI: " , t3_yti , " Z: ",t3_hgt
__tab3_debug ">>> tab3_tf: leg1: " , res[0] , " leg3: " , res[1] , " leg2: " ,res[2]
}
}
if (geometry == 8) {
if (reverse) {
local xti yti zlegs zcorr
xti = atan((1/d2) * (0.5 *(t3_bl1 + t3_bl2) - t3_fro))
yti = atan((1/d1) * (t3_bl2 - t3_bl1))
zlegs = (1/3) * (t3_bl1 + t3_bl2 + t3_fro)
if (d3 > 0) {
zcorr = d3 * (2 - cos(xti) - cos(yti))
} else {
zcorr = 0
}
res[3]= deg(xti) # xtilt (deg)
res[4]= deg(yti) # ytilt (deg)
res[5]= zlegs - zcorr # height (mm)
__tab3_debug ">>> tab3_tf: from leg1: ", t3_bl1, " leg2: ", t3_bl2, " leg3: ", t3_bl3
__tab3_debug ">>> tab3_tf: to xtilt: ", res[3], " ytilt: ", res[4], " Z: ", res[5]
}
else {
local zcorr zbase
if (d3 > 0) {
zcorr = d3 * (2 - cos(rad(t3_xti)) - cos(rad(t3_yti)))
} else {
zcorr = 0
}
zbase = t3_hgt + zcorr
res[0] = zbase - 0.5 * tan(rad(t3_yti)) * d1 + (1/3) * tan(rad(t3_xti)) * d2 # tbl 1 (mm) / leg1
res[1] = zbase + 0.5 * tan(rad(t3_yti)) * d1 + (1/3) * tan(rad(t3_xti)) * d2 # tbl 2 (mm) / leg3
res[2] = zbase - 2/3 * tan(rad(t3_xti)) * d2 # front (mm) / leg2
__tab3_debug ">>> tab3_tf: from xtilt: ", t3_xti, " ytilt: ", t3_yti, " Z: ", t3_hgt
__tab3_debug ">>> tab3_tf: to leg1: ", res[0], " leg2: ", res[1], " leg3: ", res[2]
}
}
return res[calcidx];
}'
#%UU%
#%MDESC%
# Toggles the debug mode.
if (!(whatis("__tab3_debug") & 2)) rdef __tab3_debug \'#$*\'
def tab3_debug '{
if ((whatis("__tab3_debug")>>16) <= 3) { # macro length is 3 bytes: comment
rdef __tab3_debug "eprint"
print "tab3 macro debug mode is ON"
}
else {
rdef __tab3_debug \'#\$*\'
print "tab3 macro debug mode is OFF"
}
}'
#%UU%(calcidx, t3_bl1, t3_bl2, t3_fro, t3_xti, t3_yti, t3_hgt, geometry, d1, d2, d3)
#%MDESC% Calculates [t3_bl1, t3_bl2, t3_fro] as function of [t3_xti, t3_yti, t3_hgt] if
#calcidx is <=2, and the inverse if calcidx >2
#%BR%- geometry: only geometry 7 is calculated (ID24)
#%BR%- d1 dimension: 233.83 for ID24
#%BR%- d2 dimension: 202.5 for ID24
#%BR%- d3 dimension: unused for ID24
def tab3_u(calcidx, t3_bl1, t3_bl2, t3_fro, t3_xti, t3_yti, t3_hgt, geometry, d1, d2, d3)'{
# tab3_calcu(1, x, x, x, psi, chi, z, 7, d1, d2, 0)
# tab3_calcu(4, leg1, leg3, leg2, x, x, x, 7, d1, d2, 0)
local res
if (geometry == 7) {
if (calcidx > 2 ){
res[3] = deg(atan((1/d1) * (t3_bl2 - t3_bl1))) # Xtilt / PSI (deg)
res[4] = deg(atan((1/d2) * (0.5 *(t3_bl1 + t3_bl2) - t3_fro))) # Ytilt / CHI (deg)
res[5] = (1/3) * (t3_bl1 + t3_bl2 + t3_fro) # Height / z (mm)
__tab3_debug ">>> tab3_tf: (mm) from leg1: ", t3_bl1, " leg3: ", t3_bl2, " leg2: ", t3_bl3
__tab3_debug ">>> tab3_tf: (deg) PSI: ", res[3], " CHI: ", res[4], " Z: ", res[5]
}
else {
res[0] = t3_hgt - 0.5 * tan(rad(t3_xti)) *d1 + (1/3) * tan(rad(t3_yti)) * d2 # tbl 1 (mm) / leg1
res[1] = t3_hgt + 0.5 * tan(rad(t3_xti)) * d1 + (1/3) * tan(rad(t3_yti)) * d2 # tbl 2 (mm) / leg3
res[2] = t3_hgt - 2/3 * tan(rad(t3_yti)) * d2 # front (mm) / leg2
__tab3_debug ">>> tab3_tf: (deg) from PSI: ", t3_xti, " CHI: ", t3_yti, " Z: ", t3_hgt
__tab3_debug ">>> tab3_tf: (mm) leg1: ", res[0], " leg3: ", res[1], " leg2: ", res[2]
}
}
}'
#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
#%AUTHOR% Vicente Rey. June 1995
#$Revision: 1.5 $, $Date: 2018/03/22 10:23:58 $
#%TOC%
|