full openloop bode plot
This commit is contained in:
@@ -16,14 +16,14 @@ other available tuning progs on the powerbrick are:
|
|||||||
currentautotunecalc
|
currentautotunecalc
|
||||||
currentstep
|
currentstep
|
||||||
filtercalculation
|
filtercalculation
|
||||||
openloopchirp
|
openloopchirp +
|
||||||
openloopsine
|
openloopsine +
|
||||||
openlooptestmove
|
openlooptestmove
|
||||||
othertrajectory
|
othertrajectory
|
||||||
parabolicmove
|
parabolicmove
|
||||||
randommove
|
randommove
|
||||||
sinesweep
|
sinesweep +
|
||||||
sinusoidal
|
sinusoidal +
|
||||||
stepmove
|
stepmove
|
||||||
user_gantry_crosscoupled.h
|
user_gantry_crosscoupled.h
|
||||||
usertrajectory
|
usertrajectory
|
||||||
@@ -45,6 +45,7 @@ import matplotlib as mpl
|
|||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import subprocess as sprc
|
import subprocess as sprc
|
||||||
import telnetlib
|
import telnetlib
|
||||||
|
from scipy.signal.waveforms import chirp
|
||||||
from utilities import *
|
from utilities import *
|
||||||
|
|
||||||
class PBTuning:
|
class PBTuning:
|
||||||
@@ -181,33 +182,56 @@ class PBTuning:
|
|||||||
meta['file']=file
|
meta['file']=file
|
||||||
else:
|
else:
|
||||||
mode=1
|
mode=1
|
||||||
|
#Sys.ServoPeriod=0.2ms = 5kHz -> therefore factor 2000 for the time second->servoCnt
|
||||||
|
#don't know why the frequency must be scaled...
|
||||||
if openloop:
|
if openloop:
|
||||||
data=self.do_command('openloopchirp',motor,amp,minFrq,maxFrq,tSec*1000,mode,0)
|
data=self.do_command('openloopchirp',motor,amp,minFrq/2.,maxFrq/2.,tSec*2000,mode,0)
|
||||||
else:
|
else:
|
||||||
#sinesweep, chirpmove?
|
data=self.do_command('sinesweep', motor, amp, minFrq/2., maxFrq/2., tSec*2000, mode, 0)
|
||||||
data=self.do_command('sinesweep', motor, amp, minFrq, maxFrq, tSec*1000, mode, 0)
|
|
||||||
data = data[:, (1, 2)]
|
data = data[:, (1, 2)]
|
||||||
|
|
||||||
meta={'motor':motor,'date':time.asctime(),'minFrq':minFrq,'maxFrq':maxFrq,'tSec':tSec,'amp':amp}
|
meta={'motor':motor,'date':time.asctime(),'minFrq':minFrq,'maxFrq':maxFrq,'tSec':tSec,'amp':amp}
|
||||||
np.savez_compressed(file, data=data, meta=meta)
|
np.savez_compressed(file, data=data, meta=meta)
|
||||||
meta['file'] = file
|
meta['file'] = file
|
||||||
self.bode_chirp_plot(data, meta)
|
self.bode_chirp_plot(data, meta,openloop)
|
||||||
|
|
||||||
def bode_chirp_plot(self, data, meta):
|
def bode_chirp_plot(self, data, meta,openloop):
|
||||||
tSec=meta['tSec']
|
tSec=meta['tSec']
|
||||||
minFrq=meta['minFrq']
|
minFrq=meta['minFrq']
|
||||||
maxFrq=meta['maxFrq']
|
maxFrq=meta['maxFrq']
|
||||||
|
|
||||||
|
#n=25000
|
||||||
|
#t=np.linspace(0, tSec, 2*n+1, endpoint=True)
|
||||||
|
#c=chirp(t, f0=minFrq, f1=maxFrq, t1=tSec, phi=-90, method='logarithmic')
|
||||||
|
|
||||||
|
#plt.figure()
|
||||||
|
#plt.clf()
|
||||||
|
#plt.subplot(2, 1, 1)
|
||||||
|
#plt.plot(t, c)
|
||||||
|
#tstr="Logarithmic Chirp, f(0)=%g, f(%g)=%g"%(minFrq, tSec, maxFrq)
|
||||||
|
#plt.title(tstr)
|
||||||
|
|
||||||
|
#plt.subplot(2, 1, 2)
|
||||||
|
#plt.plot(t, minFrq*(maxFrq/minFrq)**(t/tSec), 'r')
|
||||||
|
## yscale('log')
|
||||||
|
#plt.grid(True)
|
||||||
|
#plt.ylabel('Frequency (Hz)')
|
||||||
|
#plt.xlabel('time (sec)')
|
||||||
|
|
||||||
|
if openloop:
|
||||||
n=1000
|
n=1000
|
||||||
d=np.concatenate((np.ones(n-1)*data[0, 1],data[:, 1]))
|
d=np.concatenate((np.ones(n-1)*data[0, 1],data[:, 1]))
|
||||||
d=np.convolve(d,np.ones(n),'valid')/n
|
d=np.convolve(d,np.ones(n),'valid')/n
|
||||||
data[:, 1]-=d
|
data[:, 1]-=d
|
||||||
|
# 5..150 Hz
|
||||||
#5..150 Hz
|
# 15 sec
|
||||||
#15 sec
|
c = data[:, 0]
|
||||||
|
o = data[:, 1]
|
||||||
|
o -= o[0]
|
||||||
|
else:
|
||||||
|
data=data-data[0,:]
|
||||||
c = data[:,0]
|
c = data[:,0]
|
||||||
o=data[:,1]
|
o=data[:,1]
|
||||||
o-=o[0]
|
|
||||||
t = np.linspace(0, tSec, data.shape[0], endpoint=True)
|
t = np.linspace(0, tSec, data.shape[0], endpoint=True)
|
||||||
n=data.shape[0]/2
|
n=data.shape[0]/2
|
||||||
fig=plt.figure()
|
fig=plt.figure()
|
||||||
@@ -222,30 +246,34 @@ class PBTuning:
|
|||||||
#ts=t1/(2*n)#samplingperiode =t[1]-t[0]
|
#ts=t1/(2*n)#samplingperiode =t[1]-t[0]
|
||||||
#w_k=2*pi*k/T
|
#w_k=2*pi*k/T
|
||||||
#w=2*np.pi*np.arange(n+1)/t1*(2*n)
|
#w=2*np.pi*np.arange(n+1)/t1*(2*n)
|
||||||
i=int(minFrq*tSec); j=int(maxFrq*tSec); #print(w[i],w[j])
|
f=np.arange(n+1)/tSec #Hz
|
||||||
w=np.arange(n+1)/tSec #Hz
|
|
||||||
w=w[i:j+1]
|
|
||||||
#w*=2.*np.pi #rad/sec
|
#w*=2.*np.pi #rad/sec
|
||||||
fig=plt.figure()
|
fig=plt.figure()
|
||||||
fig.canvas.set_window_title(os.path.basename(meta['file']+' bode'))
|
fig.canvas.set_window_title(os.path.basename(meta['file']+' bode'))
|
||||||
ftX=np.fft.rfft(c)
|
ftX=np.fft.rfft(c)
|
||||||
ftY=np.fft.rfft(o)
|
ftY=np.fft.rfft(o)
|
||||||
|
|
||||||
|
i=int(minFrq*tSec); j=int(maxFrq*tSec); #print(w[i],w[j])
|
||||||
|
f=f[i:j+1]
|
||||||
|
ftX=ftX[i:j+1]
|
||||||
|
ftY=ftY[i:j+1]
|
||||||
|
|
||||||
ft=ftY/ftX
|
ft=ftY/ftX
|
||||||
phase=np.angle(ft)
|
phase=np.angle(ft)
|
||||||
phase=np.degrees(np.unwrap(phase[i:j+1]))
|
phase=np.degrees(np.unwrap(phase))
|
||||||
|
|
||||||
#magDb=10*np.log10(np.abs(ft)) #in decibel
|
#magDb=10*np.log10(np.abs(ft)) #in decibel
|
||||||
mag=np.abs(ftY)/np.abs(ftX)
|
mag=np.abs(ftY)/np.abs(ftX)
|
||||||
magDb=20*np.log10(mag[i:j+1]) #in decibel (20=10*2: factor 2 because rfft only half)
|
magDb=20*np.log10(mag) #in decibel (20=10*2: factor 2 because rfft only half)
|
||||||
#magDb=np.abs(ftY)/np.abs(ftX)
|
#magDb=np.abs(ftY)/np.abs(ftX)
|
||||||
ax=plt.subplot(2,1,1)
|
ax=plt.subplot(2,1,1)
|
||||||
ax.semilogx(w,magDb,'b') # Bode magnitude plot
|
ax.semilogx(f,magDb,'b') # Bode magnitude plot
|
||||||
#ax.plot(w,magDb) # Bode magnitude plot
|
#ax.plot(w,magDb) # Bode magnitude plot
|
||||||
ax.axvline(minFrq,c='k');ax.axvline(maxFrq,c='k')
|
ax.axvline(minFrq,c='k');ax.axvline(maxFrq,c='k')
|
||||||
ax.grid(True)
|
ax.grid(True)
|
||||||
ax=plt.subplot(2,1,2)
|
ax=plt.subplot(2,1,2)
|
||||||
|
|
||||||
ax.semilogx(w,phase,'b') # Bode phase plot
|
ax.semilogx(f,phase,'b') # Bode phase plot
|
||||||
ax.yaxis.set_label_text('Amplitude [dB]')
|
ax.yaxis.set_label_text('Amplitude [dB]')
|
||||||
|
|
||||||
#ax.set_ylim(phase[i],phase[j])
|
#ax.set_ylim(phase[i],phase[j])
|
||||||
@@ -258,6 +286,64 @@ class PBTuning:
|
|||||||
#meta={'motor':motor,'date':time.asctime()}
|
#meta={'motor':motor,'date':time.asctime()}
|
||||||
#np.savez_compressed(file, bode=bode, meta=meta)
|
#np.savez_compressed(file, bode=bode, meta=meta)
|
||||||
|
|
||||||
|
def bode_full_plot(self, mot,base):
|
||||||
|
fn='sine_ol_mot%d_ext.npz'%mot
|
||||||
|
file=os.path.join(base,fn)
|
||||||
|
f=np.load(file)
|
||||||
|
bode=f['bode']
|
||||||
|
meta=f['meta'].item()
|
||||||
|
frq=bode[:,0]
|
||||||
|
mag=bode[:,1]
|
||||||
|
phase=bode[:,2]
|
||||||
|
|
||||||
|
for fn in ('chirp_ol_mot%d_exta.npz','chirp_ol_mot%d_extb.npz','chirp_ol_mot%d_extc.npz'):
|
||||||
|
fn=fn%mot
|
||||||
|
file=os.path.join(base,fn)
|
||||||
|
f=np.load(file)
|
||||||
|
data=f['data']
|
||||||
|
meta=f['meta'].item()
|
||||||
|
tSec=meta['tSec']
|
||||||
|
minFrq=meta['minFrq']
|
||||||
|
maxFrq=meta['maxFrq']
|
||||||
|
amp=meta['amp']
|
||||||
|
n=1000
|
||||||
|
d=np.concatenate((np.ones(n-1)*data[0, 1],data[:, 1]))
|
||||||
|
d=np.convolve(d,np.ones(n),'valid')/n
|
||||||
|
data[:, 1]-=d
|
||||||
|
# 5..150 Hz
|
||||||
|
# 15 sec
|
||||||
|
c = data[:, 0]
|
||||||
|
o = data[:, 1]
|
||||||
|
o -= o[0]
|
||||||
|
n=data.shape[0]/2
|
||||||
|
ftX=np.fft.rfft(c)
|
||||||
|
ftY=np.fft.rfft(o)
|
||||||
|
i=int(minFrq*tSec); j=int(maxFrq*tSec); #print(w[i],w[j])
|
||||||
|
f=np.arange(n+1)/tSec #Hz
|
||||||
|
f=f[i:j+1]
|
||||||
|
ftX=ftX[i:j+1]
|
||||||
|
ftY=ftY[i:j+1]
|
||||||
|
|
||||||
|
ft=ftY/ftX
|
||||||
|
frq=np.concatenate((frq,f))
|
||||||
|
phase=np.concatenate((phase,np.angle(ft)))
|
||||||
|
#if amp==50:amp*=np.sqrt(2)
|
||||||
|
mag=np.concatenate((mag,(np.abs(ftY)/np.abs(ftX))))
|
||||||
|
|
||||||
|
db_mag=20*np.log10(mag)
|
||||||
|
phase=np.degrees(np.unwrap(phase))# numpy.unwrap(p, discont=3.141592653589793, axis=-1)
|
||||||
|
fig = plt.figure()
|
||||||
|
fig.canvas.set_window_title('full bode of motor %d'%mot)
|
||||||
|
ax = fig.add_subplot(2, 1, 1)
|
||||||
|
ax.semilogx(frq, db_mag,'-') # Bode magnitude plot
|
||||||
|
ax.xaxis.set_label_text('dB Mag.')
|
||||||
|
plt.grid(True)
|
||||||
|
#ax.loglog(frqLst, bode[:,0],'.-') # Bode magnitude plot
|
||||||
|
ax = fig.add_subplot(2, 1, 2)
|
||||||
|
ax.semilogx(frq, phase,'-') # Bode phase plot
|
||||||
|
ax.xaxis.set_label_text('phase')
|
||||||
|
ax.set_ylim(-360,0)
|
||||||
|
plt.grid(True)
|
||||||
|
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__=='__main__':
|
||||||
@@ -286,10 +372,44 @@ Examples:'''+''.join(map(lambda s:cmd+s, exampleCmd))+'\n '
|
|||||||
|
|
||||||
#plt.ion()
|
#plt.ion()
|
||||||
tune=PBTuning(args)
|
tune=PBTuning(args)
|
||||||
|
#data=self.do_command('openloopsine',motor,amp,frq,rep,0)
|
||||||
|
# #data=self.do_command('openloopchirp',motor,amp,minFrq,maxFrq,tSec*1000,mode,0)
|
||||||
|
|
||||||
|
#THIS IS A TEST TO DO 5 Hz during 10 seconds
|
||||||
|
#frq=5
|
||||||
|
#frq2=frq*1.1
|
||||||
|
#ts=10 #seconds
|
||||||
|
|
||||||
|
#5 kHz Servo
|
||||||
|
#ds=tune.do_command('openloopsine', 2, 20, frq, frq*ts, 0)
|
||||||
|
#dc=tune.do_command('openloopchirp', 2, 20, frq/2., frq2/2., ts*2000, 1, 0) #THIS IS NOT 10 Seconds!!!
|
||||||
|
|
||||||
|
#dc=tune.do_command('openloopchirp', 2, 10, 5, 6, 10*1000, 1, 0) #THIS IS NOT 10 Seconds!!!
|
||||||
|
#ds=ds-ds[0,:]
|
||||||
|
#dc=dc-dc[0,:]
|
||||||
|
#plt.figure()
|
||||||
|
#plt.plot(ds[:,0],'b')
|
||||||
|
#plt.plot(ds[:,1],'g')
|
||||||
|
#plt.figure()
|
||||||
|
#plt.plot(dc[:,0],'b')
|
||||||
|
#plt.plot(dc[:,1],'g')
|
||||||
|
#plt.show()
|
||||||
|
#return
|
||||||
base='/home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/PBTuning/'
|
base='/home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/PBTuning/'
|
||||||
|
#file=os.path.join(base, 'sine_ol_mot_tst.npz')
|
||||||
|
#tune.bode_sine(openloop=True,file=file,motor=2, minFrq=20,maxFrq=200,numFrq=30)
|
||||||
|
#file=os.path.join(base, 'chirp_ol_mot_tst.npz')
|
||||||
|
#tune.bode_chirp(openloop=True, file=file, motor=2, minFrq=20,maxFrq=200,tSec=30.)
|
||||||
|
#plt.show()
|
||||||
|
#return
|
||||||
|
|
||||||
if args.plot:
|
if args.plot:
|
||||||
#display bode plots
|
#display bode plots
|
||||||
|
if args.plot[0]=='ext':
|
||||||
|
tune.bode_full_plot(mot=1,base=base)
|
||||||
|
tune.bode_full_plot(mot=2,base=base)
|
||||||
|
plt.show()
|
||||||
|
return
|
||||||
for fn in args.plot:
|
for fn in args.plot:
|
||||||
if os.path.basename(fn).startswith('sine_ol_mot'):
|
if os.path.basename(fn).startswith('sine_ol_mot'):
|
||||||
tune.bode_sine(openloop=True,file=fn)
|
tune.bode_sine(openloop=True,file=fn)
|
||||||
@@ -312,7 +432,11 @@ Examples:'''+''.join(map(lambda s:cmd+s, exampleCmd))+'\n '
|
|||||||
tune.bode_sine(openloop=True,file=file,motor=mot)
|
tune.bode_sine(openloop=True,file=file,motor=mot)
|
||||||
elif mode==2:
|
elif mode==2:
|
||||||
file=os.path.join(base,'chirp_ol_mot%d_%s.npz'%(mot,tag))
|
file=os.path.join(base,'chirp_ol_mot%d_%s.npz'%(mot,tag))
|
||||||
tune.bode_chirp(openloop=True,file=file,motor=mot,maxFrq=500)
|
#def bode_chirp(self,openloop=True,motor=1,minFrq=10,maxFrq=150,tSec=30.,amp=10,mode=1,file='/tmp/gather.npz'):
|
||||||
|
#tune.bode_chirp(openloop=True,file=file,motor=mot, minFrq=10, maxFrq=300, tSec=30)
|
||||||
|
tune.bode_chirp(openloop=True,file=file[:-4]+'a.npz',motor=mot, minFrq=10, maxFrq=300, tSec=30)
|
||||||
|
tune.bode_chirp(openloop=True,file=file[:-4]+'b.npz',motor=mot,amp=50,minFrq=100,maxFrq=500, tSec=30)
|
||||||
|
tune.bode_chirp(openloop=True,file=file[:-4]+'c.npz',motor=mot,amp=50,minFrq=300,maxFrq=1500,tSec=10)
|
||||||
elif mode==3:
|
elif mode==3:
|
||||||
ol=True
|
ol=True
|
||||||
file=os.path.join(base,'sine_cl_mot%d_%s.npz'%(mot,tag))
|
file=os.path.join(base,'sine_cl_mot%d_%s.npz'%(mot,tag))
|
||||||
@@ -321,10 +445,19 @@ Examples:'''+''.join(map(lambda s:cmd+s, exampleCmd))+'\n '
|
|||||||
file=os.path.join(base,'chirp_cl_mot%d_%s.npz'%(mot,tag))
|
file=os.path.join(base,'chirp_cl_mot%d_%s.npz'%(mot,tag))
|
||||||
tune.bode_chirp(openloop=False,file=file,motor=mot)
|
tune.bode_chirp(openloop=False,file=file,motor=mot)
|
||||||
#tune.do_command('stepmove',1,100,500,0,0)
|
#tune.do_command('stepmove',1,100,500,0,0)
|
||||||
|
|
||||||
|
|
||||||
plt.show()
|
plt.show()
|
||||||
#------------------ Main Code ----------------------------------
|
#------------------ Main Code ----------------------------------
|
||||||
#ssh_test()
|
#ssh_test()
|
||||||
ret=parse_args()
|
ret=parse_args()
|
||||||
exit(ret)
|
exit(ret)
|
||||||
|
|
||||||
|
#enable plc1
|
||||||
|
#./PBTuning.py --host SAR-CPPM-EXPMX1 --mode 1 --mot 1 --tag ext
|
||||||
|
#enable plc1
|
||||||
|
#./PBTuning.py --host SAR-CPPM-EXPMX1 --mode 2 --mot 1 --tag ext
|
||||||
|
#enable plc1
|
||||||
|
#./PBTuning.py --host SAR-CPPM-EXPMX1 --mode 1 --mot 2 --tag ext
|
||||||
|
#enable plc1
|
||||||
|
#./PBTuning.py --host SAR-CPPM-EXPMX1 --mode 2 --mot 2 --tag ext
|
||||||
|
#enable plc1
|
||||||
|
#./PBTuning.py --host SAR-CPPM-EXPMX1 --plot ext
|
||||||
|
|||||||
Reference in New Issue
Block a user