diff --git a/Readme.md b/Readme.md index 7c39909..71a57fe 100644 --- a/Readme.md +++ b/Readme.md @@ -184,3 +184,26 @@ cd /net/slsfs-crtl/export/sf/ioc/modules/ESB_MX/zamofing_t/R3.14.12/ export EPICS_CA_ADDR_LIST="129.129.109.255" export EPICS_CA_ADDR_LIST="129.129.126.255" caQtDm -macro 'P=SAR-ESB_MX' ESB_MX_exp + + + +PPMAC=MOTTEST-CPPM-CRM0485 +ssh root@$PPMAC sendgetsends -1 + send 1"SampleMessage\n" +&1p ->this will trigger:forward kinematic +cpx pmatch ->this will trigger:forward kinematic + + +cpx ;linear abs; X0Y0Z0B0 ->this will trigger: inverse + +cpx ;linear abs; X1.4678795645244058 Y18.549693638496166, B0.0 Z2.3 + +#7j=1.4678795645244058 +#8j=18.549693638496166 +#1j=0.0 +#2j=2.3 + +#7j=0 //cx +#8j=0 //cy +#1j=0.0 //w +#2j=2.3 //fx diff --git a/cfg/coordTrf.cfg b/cfg/coordTrf.cfg new file mode 100644 index 0000000..21cf08d --- /dev/null +++ b/cfg/coordTrf.cfg @@ -0,0 +1,47 @@ + +&1 +//#1-> 0.00001X+ 0.00001Y + A +//#2-> +1. X + .5Y + 0.01A +//#3-> + .5X +1. Y + 0.01A + +#1-> A +#2-> X +#3-> Y + +Coord[1].AltFeedRate=0 +Coord[1].Tm=1 //1ms time +Coord[1].Ta=1 +Coord[1].Td=1 +Coord[1].Ts=0 + +//Parker: Continous Force 4N -> assume 1kg load -> acceleration=a=F/m=4m/s^2 +//do not use time to accelerate but acceleration +//4m/s^2=4um/(ms)^2 Motor units=um -> JogTa= -1ms^2/4mu -2.5-> 4m/s^2 -25->0.4m/s^2 +Motor[2].JogTs=0 +Motor[2].JogTa=-2.5 +Motor[3].JogTs=0 +Motor[3].JogTa=-2.5 + + +Motor[1].MaxSpeed=360 +Motor[2].MaxSpeed=50 +Motor[3].MaxSpeed=50 + +open prog 1 + //this uses jogspeed + rapid abs + X(10000) Y(0) A(0) + X(0) Y(10000) A(0) + X(0) Y(0) A(36000) + X(0) Y(0) A(0) +close + +open prog 2 + //this uses Coord[1].Tm and limits with MaxSpeed + linear abs + X(10000) Y(0) A(0) + X(0) Y(10000) A(0) + X(0) Y(0) A(0) + X(0) Y(0) A(36000) + X(0) Y(0) A(0) +close diff --git a/cfg/mx-stage.cfg b/cfg/mx-stage.cfg index 0cbb401..dccab38 100644 --- a/cfg/mx-stage.cfg +++ b/cfg/mx-stage.cfg @@ -7,52 +7,4 @@ !torqueCtrl() !init() - - -&1 -//#1-> 0.00001X+ 0.00001Y + A -//#2-> +1. X + .5Y + 0.01A -//#3-> + .5X +1. Y + 0.01A - -#1-> A -#2-> X -#3-> Y - -Coord[1].AltFeedRate=0 -Coord[1].Tm=1 //1ms time -Coord[1].Ta=1 -Coord[1].Td=1 -Coord[1].Ts=0 - -//Parker: Continous Force 4N -> assume 1kg load -> acceleration=a=F/m=4m/s^2 -//do not use time to accelerate but acceleration -//4m/s^2=4um/(ms)^2 Motor units=um -> JogTa= -1ms^2/4mu -2.5-> 4m/s^2 -25->0.4m/s^2 -Motor[2].JogTs=0 -Motor[2].JogTa=-2.5 -Motor[3].JogTs=0 -Motor[3].JogTa=-2.5 - - -Motor[1].MaxSpeed=360 -Motor[2].MaxSpeed=50 -Motor[3].MaxSpeed=50 - -open prog 1 - //this uses jogspeed - rapid abs - X(10000) Y(0) A(0) - X(0) Y(10000) A(0) - X(0) Y(0) A(36000) - X(0) Y(0) A(0) -close - -open prog 2 - //this uses Coord[1].Tm and limits with MaxSpeed - linear abs - X(10000) Y(0) A(0) - X(0) Y(10000) A(0) - X(0) Y(0) A(0) - X(0) Y(0) A(36000) - X(0) Y(0) A(0) -close - +!coordTrf() \ No newline at end of file diff --git a/cfg/mx-stage_sim.cfg b/cfg/mx-stage_sim.cfg new file mode 100644 index 0000000..24cb47f --- /dev/null +++ b/cfg/mx-stage_sim.cfg @@ -0,0 +1,66 @@ +//simulated stage without real motors needed +$$$*** +!common() +//!common(PhaseFreq=20000,PhasePerServo=4) +//!common(PhaseFreq=20000,PhasePerServo=1) +//!common(PhaseFreq=40000) + +//Mot 1: Rotation stage LS Mecapion MDM-DC06DNC0H 32 poles = 1 rev = 16*2048=32768 phase_step +//Enc 1: Rotation stage LS Mecapion 1 rev = 1048576 enc_steps + +//Mot 2: Stage Y Parker MX80L D11 25mm one pole cycle = 13mm = 2048 phase_step +//Enc 2: Stage Y Parker MX80L D11 inc_enc 20nm one pole cycle = 13mm = 650000 enc_step (20nm/enc_step) + +//Mot 3: Stage X Parker MX80L D11 25mm one pole cycle = 13mm = 2048 phase_step +//Enc 3: Stage X Parker MX80L D11 inc_enc 20nm one pole cycle = 13mm = 650000 enc_step (20nm/enc_step) + +//Mot/Enc 4: camera base plate X +// OBSOLETE: Enc 4: Interferometer 1 + +//Mot/Enc 5: camera base plate Y +// OBSOLETE Enc 5: Interferometer 2 + +//Mot 6: Backlight 2.3A + +//Mot 7: Stada Stepper: 670mA 200 poles 1 rev = 100*2048 phase_step (2 stepper motor) +//Enc 7: Renishaw absolute BiSS + +//Mot 8: Stada Stepper: 670mA 200 poles 1 rev = 100*2048 phase_step (2 stepper motor) +//Enc 8: Renishaw absolute BiSS + +!encoder_sim(enc=1,tbl=1,mot=1) +!motor(mot=1,dirCur=0,contCur=100,peakCur=100,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True) +Motor[1].pLimits=0 +//Motor[1].pDac=PowerBrick[0].MacroOutA[0][0].a +//Motor[1].pAdc=PowerBrick[0].MacroInA[0][1].a + +!encoder_sim(enc=2,tbl=2,mot=2) +!motor(mot=2,dirCur=0,contCur=100,peakCur=1000,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True) +Motor[2].pLimits=0 + +!encoder_sim(enc=3,tbl=3,mot=3) +!motor(mot=3,dirCur=0,contCur=100,peakCur=1000,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True) +Motor[3].pLimits=0 + +!encoder_sim(enc=4,tbl=4,mot=4) +!motor(mot=4,dirCur=0,contCur=100,peakCur=1000,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True) +Motor[4].pLimits=0 + +!encoder_sim(enc=5,tbl=5,mot=5) +!motor(mot=5,dirCur=0,contCur=100,peakCur=1000,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True) +Motor[5].pLimits=0 + +!encoder_sim(enc=6,tbl=6,mot=6) +!motor(mot=6,dirCur=0,contCur=100,peakCur=1000,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True) +Motor[6].pLimits=0 + +!encoder_sim(enc=7,tbl=7,mot=7) +!motor(mot=7,dirCur=0,contCur=100,peakCur=1000,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True) +Motor[7].pLimits=0 + +!encoder_sim(enc=8,tbl=8,mot=8) +!motor(mot=8,dirCur=0,contCur=100,peakCur=1000,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True) +Motor[8].pLimits=0 + + +!coordTrf() \ No newline at end of file diff --git a/python/helicalscan.py b/python/helicalscan.py index 6c855b5..b063010 100755 --- a/python/helicalscan.py +++ b/python/helicalscan.py @@ -7,7 +7,27 @@ # *-----------------------------------------------------------------------* ''' tools to setup and execute a helical scan of a cristal -#THIS IS JUST TESTING CODE TO SOLVE FINDING THE ROTATION CENTER + +motors CX CZ RY FY + 7 8 1 2 +Mot 1: Rotation stage LS Mecapion MDM-DC06DNC0H 32 poles = 1 rev = 16*2048=32768 phase_step +Mot 2: Stage Y Parker MX80L D11 25mm one pole cycle = 13mm = 2048 phase_step +Mot 3: Stage X Parker MX80L D11 25mm one pole cycle = 13mm = 2048 phase_step +Mot/Enc 4: camera base plate X +Mot/Enc 5: camera base plate Y +Mot 6: Backlight 2.3A +Mot 7: Stada Stepper: 670mA 200 poles 1 rev = 100*2048 phase_step (2 stepper motor) +Mot 8: Stada Stepper: 670mA 200 poles 1 rev = 100*2048 phase_step (2 stepper motor) + +verbose bits: + #1 basic info + #2 plot sorting steps + 4 list program + #4 upload progress + #8 plot gather path + + + ''' import os, sys, json @@ -17,7 +37,7 @@ import matplotlib.pyplot as plt import mpl_toolkits.mplot3d as plt3d import matplotlib.animation as anim from matplotlib.widgets import Slider - +import subprocess as sprc from utilities import * d2r=2*np.pi/360 @@ -129,12 +149,12 @@ class HelicalScan: def test_coord_trf(self): self.calcParam() param = self.param - y, w, dx, dz = (4.3, .1, 0.2, 0.3) - print 'input : fy:%.3g dx:%.3g dz:%.3g w:%.3g' % (y, dx, dz, w / d2r) - (fy, w, cx, cz) = self.inv_transform(y, w, dx, dz) - print 'inv_trf: fy:%.3g cx:%.3g cz:%.3g w:%.3g' % (fy, cx, cz, w / d2r) - (y, w, dx, dz) = self.fwd_transform(fy, w, cx, cz) - print 'fwd_trf: fy:%.3g dx:%.3g dz:%.3g w:%.3g' % (y, dx, dz, w / d2r) + dx, dz, w, y, = (0.2,0.3,0.1,4.3) + print 'input : dx:%.3g dz:%.3g w:%.3g fy:%.3g' % (dx,dz,w/d2r,y) + (cx,cz,w,fy) = self.inv_transform(dx,dz,w,y) + print 'inv_trf: cx:%.3g cz:%.3g w:%.3g fy:%.3g' % (cx,cz,w/d2r,fy) + (dx, dz,w,y) = self.fwd_transform(cx,cz,w,fy) + print 'fwd_trf: dx:%.3g dz:%.3g w:%.3g fy:%.3g' % (dx,dz,w/d2r,y) # plt.ion() # fig = plt.figure() @@ -145,8 +165,7 @@ class HelicalScan: # def my_anim_func3(self,idx): # self.hCrist,pt=self.pltCrist(cx=0,ty=0,cz=0,w=10*idx*d2r,h=self.hCrist) - - def interactive_fy_cx_cz_w(self): + def interactive_cx_cz_w_fy(self): fig = plt.figure() self.manip=False#True#False self.ax=ax=plt3d.Axes3D(fig,[0.02, 0.15, 0.96, 0.83]) @@ -158,24 +177,24 @@ class HelicalScan: ctr=param[:,0:3].mean(0)[::-1] self.axSetCenter(ctr,10) - axFy = plt.axes([0.1, 0.01, 0.8, 0.02]) - axCx = plt.axes([0.1, 0.04, 0.8, 0.02]) - axCz = plt.axes([0.1, 0.07, 0.8, 0.02]) - axW = plt.axes([0.1, 0.10, 0.8, 0.02]) + axCx=plt.axes([0.1, 0.01, 0.8, 0.02]) + axCz=plt.axes([0.1, 0.04, 0.8, 0.02]) + axW =plt.axes([0.1, 0.07, 0.8, 0.02]) + axFy=plt.axes([0.1, 0.10, 0.8, 0.02]) if self.manip: lz=ax.get_xlim() lx=ax.get_ylim() ly=ax.get_zlim() else: lx = ly=lz=[-5,5] - self.sldFy = sFy = Slider(axFy, 'fy', ly[0], ly[1], valinit=(ly[0]+ly[1])/2.) - self.sldCx = sCx = Slider(axCx, 'cx', lx[0], lx[1], valinit=(lx[0]+lx[1])/2.) - self.sldCz = sCz = Slider(axCz, 'cz', lz[0], lz[1], valinit=(lz[0]+lz[1])/2.) - self.sldW =sW = Slider(axW, 'ang', -180., 180.0, valinit=0) - sFy.on_changed(self.update_fy_cx_cz_w) - sCx.on_changed(self.update_fy_cx_cz_w) - sCz.on_changed(self.update_fy_cx_cz_w) - sW.on_changed(self.update_fy_cx_cz_w) + self.sldCx=sCx=Slider(axCx, 'cx', lx[0], lx[1], valinit=(lx[0]+lx[1])/2.) + self.sldCz=sCz=Slider(axCz, 'cz', lz[0], lz[1], valinit=(lz[0]+lz[1])/2.) + self.sldW =sW =Slider(axW, 'ang', -180., 180.0, valinit=0) + self.sldFy=sFy=Slider(axFy, 'fy', ly[0], ly[1], valinit=(ly[0]+ly[1])/2.) + sCx.on_changed(self.update_cx_cz_w_fy) + sCz.on_changed(self.update_cx_cz_w_fy) + sW.on_changed(self.update_cx_cz_w_fy) + sFy.on_changed(self.update_cx_cz_w_fy) hCrist,pt=self.pltCrist() @@ -186,18 +205,19 @@ class HelicalScan: (z_i, y_i, x_i, r_i, phi_i)=param[i] p[i,0]=x_i+r_i*np.sin(phi_i) # x= x_i+r_i*cos(phi_i+w)+cx p[i,1]=y_i # y= y_i - p[i,2] =z_i+r_i*np.cos(phi_i) # z= z_i+r_i*sin(phi_i*w) + p[i,2]=z_i+r_i*np.cos(phi_i) # z= z_i+r_i*sin(phi_i*w) print p ofs=(p[1]+p[0])/2. # = center of the cristal m=Trf.trans(*ofs); self.hOrig=self.pltOrig(m) plt.show() - def update_fy_cx_cz_w(self,val): - fy = self.sldFy.val + + def update_cx_cz_w_fy(self,val): cx = self.sldCx.val cz = self.sldCz.val - w = self.sldW.val + w = self.sldW.val + fy = self.sldFy.val if self.manip: param = self.param # param[i]=(z_i, y_i, x_i, r_i,phi_i) @@ -218,7 +238,8 @@ class HelicalScan: #l.set_ydata(amp * np.sin(2 * np.pi * freq * t)) self.fig.canvas.draw_idle() - def interactive_y_dx_dz_w(self): + + def interactive_dx_dz_w_y(self): fig = plt.figure() self.ax=ax=plt3d.Axes3D(fig,[0.02, 0.15, 0.96, 0.83]) ax.set_xlabel('Z');ax.set_ylabel('X');ax.set_zlabel('Y') @@ -230,21 +251,21 @@ class HelicalScan: ctr=(0,0,0) self.axSetCenter(ctr,10) - axY = plt.axes([0.1, 0.01, 0.8, 0.02]) - axDx = plt.axes([0.1, 0.04, 0.8, 0.02]) - axDz = plt.axes([0.1, 0.07, 0.8, 0.02]) - axW = plt.axes([0.1, 0.10, 0.8, 0.02]) + axDx=plt.axes([0.1, 0.01, 0.8, 0.02]) + axDz=plt.axes([0.1, 0.04, 0.8, 0.02]) + axW =plt.axes([0.1, 0.07, 0.8, 0.02]) + axY =plt.axes([0.1, 0.10, 0.8, 0.02]) lx=[-1,1];ly=[0,1];lz=[-1,1] ly = param[:,1] - self.sldY = sY = Slider(axY, 'y', ly[0], ly[1], valinit=(ly[0]+ly[1])/2.) - self.sldDx = sDx = Slider(axDx, 'dx', lx[0], lx[1], valinit=(lx[0]+lx[1])/2.) - self.sldDz = sDz = Slider(axDz, 'dz', lz[0], lz[1], valinit=(lz[0]+lz[1])/2.) - self.sldW =sW = Slider(axW, 'ang', -180., 180.0, valinit=0) - sY.on_changed(self.update_y_dx_dz_w) - sDx.on_changed(self.update_y_dx_dz_w) - sDz.on_changed(self.update_y_dx_dz_w) - sW.on_changed(self.update_y_dx_dz_w) + self.sldDx=sDx=Slider(axDx, 'dx', lx[0], lx[1], valinit=(lx[0]+lx[1])/2.) + self.sldDz=sDz=Slider(axDz, 'dz', lz[0], lz[1], valinit=(lz[0]+lz[1])/2.) + self.sldW =sW =Slider(axW, 'ang', -180., 180.0, valinit=0) + self.sldY =sY =Slider(axY, 'y', ly[0], ly[1], valinit=(ly[0]+ly[1])/2.) + sDx.on_changed(self.update_dx_dz_w_y) + sDz.on_changed(self.update_dx_dz_w_y) + sW.on_changed(self.update_dx_dz_w_y) + sY.on_changed(self.update_dx_dz_w_y) # param[i]=(z_i, y_i, x_i, r_i,phi_i) @@ -263,21 +284,23 @@ class HelicalScan: self.hCrist=hCrist;self.fig=fig plt.show() - def update_y_dx_dz_w(self,val): - y = self.sldY.val + + def update_dx_dz_w_y(self,val): dx = self.sldDx.val dz = self.sldDz.val w = self.sldW.val + y = self.sldY.val w=w*d2r - (fy, w, cx, cz)=self.inv_transform(y,w,dx,dz) - + (cx,cz,w,fy)=self.inv_transform(dx,dz,w,y) + #print (cx,cz,w,fy) self.hCrist,pt=self.pltCrist(-fy,-cx,-cz,w,self.hCrist) self.fig.canvas.draw_idle() - def fwd_transform(self,fy,w,cx,cz): + + def fwd_transform(self,cx,cz,w,fy): #cx,cy: coarse stage - #input: fy,w,cx,cz - #output: y,w,dx,dz + #input: cx,cz,w,fy + #output: dx,dz,w,y # param[i]=(z_i, y_i, x_i, r_i,phi_i) param=self.param @@ -297,12 +320,13 @@ class HelicalScan: dx=cx-v[0] dz=cz-v[2] y=v[1] - res=(y,w,dx,dz) + res=(dx,dz,w,y) return res - def inv_transform(self,y,w,dx=0,dz=0): - #input: y,w,dx,dz - #output: y,w,cx,cz + + def inv_transform(self,dx,dz,w,y): + #input: dx,dz,w,y + #output: cx,cz,w,fy #dx,dy: deviation from cristal center line param=self.param p=np.ndarray((param.shape[0], 3)) @@ -321,7 +345,7 @@ class HelicalScan: cx=dx+v[0] cz=dz+v[2] fy=v[1] - res=(fy,w,cx,cz) + res=(cx,cz,w,fy) return res @@ -366,6 +390,7 @@ class HelicalScan: hb.set_3d_properties((o[1], o[1] + b[1])) return h + def pltCrist(self,fy=0,cx=0,cz=0,w=0,h=None): #h are the handles if h is None: @@ -414,6 +439,7 @@ class HelicalScan: #h+=(hs,hp[0]) return (h,pt) + @staticmethod def meas_rot_ctr(y,per=1): # find the amplitude bias and phase of an equidistant sampled sinus @@ -436,11 +462,252 @@ class HelicalScan: ax.set_ylim(v[0]-l2, v[0]+l2); ax.set_zlim(v[1]-l2, v[1]+l2) -def my_anim_func(idx,hs,horig): - print('anim') - a=idx*.01*2*np.pi - m=Trf.rotY(a) - hs.pltOrig(m,horig) + + def gen_coord_trf_code(self,file=None,host=None): + param=self.param + prg = [] + prg.append(''' +// Set the motors as inverse kinematic axes in CS 1 +//motors CX CZ RY FY +// 7 8 1 2 + +&1 +#7->I +#8->I +#1->I +#2->I + +open forward + define(qCX='L7', qCZ='L8', qW='L1', qFY='L2') + define(DX='C6', DZ='C8', W='C1', Y='C7') + //coord X Z B Y + define(p0_x='L10', p0_y='L11', p0_z='L12') + define(p1_x='L13', p1_y='L14', p1_z='L15') + define(f='L16') + + send 1"forward kinematic\\n"''') + for i in range(2): + #https://stackoverflow.com/questions/3471999/how-do-i-merge-two-lists-into-a-single-list + l=[j for i in zip((i,) * param.shape[1], list(param[i])) for j in i] + prg.append(" define(z_%i=%g, y_%i=%g, x_%i=%g, r_%i=%g, phi_%i=%g)"%tuple(l)) + prg.append(''' + p0_x=x_0+r_0*sin(phi_0+W) + p1_x=x_1+r_1*sin(phi_1+W) + p0_y=y_0 + p1_y=y_1 + p0_z=z_0+r_0*cos(phi_0+W) + p1_z=z_1+r_1*cos(phi_0+W) + + f=(qFY-y_0)/(y_1-y_0) + p0_x=p0_x+f*(p1_x-p0_x) + p0_y=p0_y+f*(p1_y-p0_y) + p0_z=p0_z+f*(p1_z-p0_z) + DX=qCX-p0_x + DZ=qCZ-p0_z + Y=qFY + W=qW + + D0=$000001c2; //B=$2 X=$40 Y=$80 Z=$100 hex(2+int('40',16)+int('80',16)+int('100',16)) -> 0x1c2 +close +''') + + prg.append(''' +open inverse + define(DX='C6', DZ='C8', W='C1', Y='C7') + //coord X Z B Y + //D0 is set to $000001c2 + define(qCX='L7', qCZ='L8', qW='L1', qFY='L2') + define(p0_x='L10', p0_y='L11', p0_z='L12') + define(p1_x='L13', p1_y='L14', p1_z='L15') + define(f='L16') + + send 1"inverse kinematic\\n"''') + for i in range(2): + # https://stackoverflow.com/questions/3471999/how-do-i-merge-two-lists-into-a-single-list + l = [j for i in zip((i,) * param.shape[1], list(param[i])) for j in i] + prg.append(" define(z_%i=%g, y_%i=%g, x_%i=%g, r_%i=%g, phi_%i=%g)" % tuple(l)) + prg.append(''' + p0_x=x_0+r_0*sin(phi_0+W) + p1_x=x_1+r_1*sin(phi_1+W) + p0_y=y_0 + p1_y=y_1 + p0_z=z_0+r_0*cos(phi_0+W) + p1_z=z_1+r_1*cos(phi_0+W) + + f=(qFY-y_0)/(y_1-y_0) + p0_x=p0_x+f*(p1_x-p0_x) + p0_y=p0_y+f*(p1_y-p0_y) + p0_z=p0_z+f*(p1_z-p0_z) + qCX=DX+p0_x + qCZ=DZ+p0_z + qFY=Y + qW=W + +close +''') + + if self.args.verbose & 4: + for ln in prg: + print(ln) + if file is not None: + fh = open(file, 'w') + fh.write('\n'.join(prg)) + fh.close() + if host is not None: + cmd = '/home/zamofing_t/scripts/gpasciiCommander --host ' + host + ' ' + file + print(cmd) + p = sprc.Popen(cmd, shell=True) # , stdout=sprc.PIPE, stderr=sprc.STDOUT) + # res=p.stdout.readlines(); print res + retval = p.wait() + # gather -u /var/ftp/gather/out.txt + + def gen_prog(self,prgId=2,file=None,host=None,mode=0,**kwargs): + ''' + kwargs: + acq_per : acquire period: acquire data all acq_per servo loops (default=1) + pt2pt_time : time to move from one point to the next point + ''' + prg=[] + acq_per=kwargs.get('acq_per',1) + gather={"MaxSamples":1000000, "Period":acq_per} + #Sys.ServoPeriod is dependent of !common() macro + ServoPeriod= .2 #0.2ms + #ServoPeriod = .05 + self.meta = {'timebase': ServoPeriod*gather['Period']} + #channels=["Motor[1].ActPos","Motor[2].ActPos","Motor[3].ActPos"] + channels=["Motor[7].ActPos","Motor[8].ActPos","Motor[1].ActPos","Motor[2].ActPos"] + prg.append('Gather.Enable=0') + prg.append('Gather.Items=%d'%len(channels)) + for k,v in gather.iteritems(): + prg.append('Gather.%s=%d'%(k,v)) + for i,c in enumerate(channels): + prg.append('Gather.Addr[%d]=%s.a'%(i,c)) + + + prg.append('open prog %d'%(prgId)) + # this uses Coord[1].Tm and limits with MaxSpeed + if mode==-1: #### jog a 10mm square + pos=self.points + prg.append(' linear abs') + prg.append('X(%g) Y(%g)' % tuple(pos[0, :])) + prg.append('dwell 10') + prg.append('Gather.Enable=2') + prg.append('jog2:10000') + prg.append('dwell 100') + prg.append('jog3:10000') + prg.append('dwell 100') + prg.append('jog2:-10000') + prg.append('dwell 100') + prg.append('jog3:-10000') + prg.append('dwell 100') + prg.append('Gather.Enable=0') + elif mode==0: #### linear motion + pos=self.points + prg.append(' linear abs') + prg.append('X(%g) Y(%g)' % tuple(pos[0, :])) + prg.append('dwell 10') + prg.append('Gather.Enable=2') + prg.append(' linear abs') + for idx in range(pos.shape[0]): + prg.append('X%g Y%g'%tuple(pos[idx,:])) + prg.append('dwell 100') + prg.append('Gather.Enable=0') + elif mode==1: #### pvt motion + try: + pt2pt_time=kwargs['pt2pt_time'] #how many ms to move to next point (pt2pt_time) + except KeyError: + print('missing pt2pt_time, use default=100ms') + pt2pt_time=100. + try: + cnt=kwargs['cnt'] #move path multiple times + except KeyError: + cnt=1 + + try: + pt=self.ptsCorr + except AttributeError: + pt=self.points + vel=pt[2:,:]-pt[:-2,:] + #pv is an array of posx posy velx vely + pv=np.ndarray(shape=(pt.shape[0]+2,4),dtype=pt.dtype) + pv[:]=np.NaN + #pv[ 0,(0,1)]=2*pt[0,:]-pt[1,:] + pv[ 0,(0,1)]=pt[0,:] + pv[ 1:-1,(0,1)]=pt + #pv[ -1,(0,1)]=2*pt[-1,:]-pt[-2,:] + pv[ -1,(0,1)]=pt[-1,:] + pv[(0,0,-1,-1),(2,3,2,3)]=0 + dist=pv[2:,(0,1)] - pv[:-2,(0,1)] + pv[ 1:-1,(2,3)] = 1000.*dist/(2.*pt2pt_time) + + prg.append(' linear abs') + prg.append('X%g Y%g' % tuple(pv[0, (0,1)])) + prg.append('dwell 10') + prg.append('Gather.Enable=2') + if cnt>1: + prg.append('P100=%d'%cnt) + prg.append('N100:') + prg.append(' pvt%g abs'%pt2pt_time) #100ms to next position + for idx in range(1,pv.shape[0]): + prg.append('X%g:%g Y%g:%g'%tuple(pv[idx,(0,2,1,3)])) + prg.append('X%g Y%g' % tuple(pv[-1, (0,1)])) + if cnt>1: + prg.append('dwell 10') + prg.append('P100=P100-1') + prg.append('if(P100>0)') + prg.append('{') + prg.append(' linear abs') + prg.append('X%g Y%g' % tuple(pv[0, (0,1)])) + prg.append('dwell 100') + prg.append('goto 100') + prg.append('}') + else: + prg.append('dwell 1000') + prg.append('Gather.Enable=0') + elif mode==2: #### spline motion + try: + pt2pt_time=kwargs['pt2pt_time'] #how many ms to move to next point (pt2pt_time) + except KeyError: + print('missing pt2pt_time, use default=100ms') + pt2pt_time=100. + pos=self.points + pcor=np.ndarray(pos.shape,dtype=pos.dtype);pcor[:]=np.NaN + pcor[(0,-1),:]=pos[(0,-1),:] + pcor[1:-1,:]=(-pos[0:-2,:]+8*pos[1:-1,:]-pos[2:,:])/6. + #pcor=pos + prg.append(' linear abs') + prg.append('X(%g) Y(%g)' % tuple(pcor[0, :])) + prg.append('dwell 10') + prg.append('Gather.Enable=2') + prg.append(' spline%g abs'%pt2pt_time) #100ms to next position + for idx in range(pcor.shape[0]): + prg.append('X%g Y%g'%tuple(pcor[idx,:])) + prg.append('dwell 100') + prg.append('Gather.Enable=0') + + prg.append('close') + prg.append('&1\nb%dr\n'%prgId) + if self.args.verbose & 4: + for ln in prg: + print(ln) + + if file is not None: + fh=open(file,'w') + fh.write('\n'.join(prg)) + fh.close() + if host is not None: + cmd ='gpasciiCommander --host '+host+' '+ file + print(cmd) + p = sprc.Popen(cmd, shell=True)#, stdout=sprc.PIPE, stderr=sprc.STDOUT) + #res=p.stdout.readlines(); print res + retval = p.wait() + #gather -u /var/ftp/gather/out.txt + cmd ='PBGatherPlot -m24 -v7 --host '+host + print(cmd) + p = sprc.Popen(cmd, shell=True)#, stdout=sprc.PIPE, stderr=sprc.STDOUT) + retval = p.wait() + self.prg=prg + if __name__=='__main__': from optparse import OptionParser, IndentedHelpFormatter @@ -479,11 +746,13 @@ Examples:'''+''.join(map(lambda s:cmd+s, exampleCmd))+'\n ' hs=HelicalScan(args) #hs.sequencer() + hs.args.verbose=255;hs.calcParam();hs.gen_coord_trf_code('/tmp/helicalscan.cfg','MOTTEST-CPPM-CRM0485') + #return hs.test_find_rot_ctr() hs.test_find_rot_ctr(n=5. ,per=1.,bias=2.31,ampl=4.12,phi=24.6) hs.test_coord_trf() - hs.interactive_fy_cx_cz_w() - hs.interactive_y_dx_dz_w() + hs.interactive_cx_cz_w_fy() + hs.interactive_dx_dz_w_y() #------------------ Main Code ---------------------------------- diff --git a/python/helicalscan1.svg b/python/helicalscan1.svg index d26c52f..4e4303e 100644 --- a/python/helicalscan1.svg +++ b/python/helicalscan1.svg @@ -133,15 +133,15 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="1.9573107" - inkscape:cx="306.39127" - inkscape:cy="814.96274" + inkscape:zoom="1.8926215" + inkscape:cx="369.55834" + inkscape:cy="749.80396" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" - inkscape:window-width="1920" + inkscape:window-width="1871" inkscape:window-height="1176" - inkscape:window-x="1920" + inkscape:window-x="49" inkscape:window-y="24" inkscape:window-maximized="1" inkscape:snap-bbox="false" @@ -199,8 +199,8 @@ id="path4159" inkscape:connector-curvature="0" /> yys + r="0.7958433" /> + style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.87775123;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="-5.723983" + inkscape:transform-center-y="-0.52836768" + r="1.0611243" />