usr_servo code generation

This commit is contained in:
2018-11-02 16:56:25 +01:00
parent 8807ccbd85
commit d7e0cf7764
12 changed files with 863 additions and 67 deletions

View File

@@ -15,6 +15,8 @@ Modes:
4 plot the full bode recording
5 plot the full bode recording with an approximation model
6 plot all raw acquired data files
7 custom chirp test
8 generate observer code (after files generated with matlab)
-> check https://github.com/klauer/ppmac for fast data gathering server which supports
phase gathering -> not yet compiling: /home/zamofing_t/Documents/prj/SwissFEL/PowerBrickInspector/ppmac/fast_gather
@@ -201,6 +203,90 @@ class MXTuning(Tuning):
ax.semilogx(f, phase,'-k',lw=1) # Bode phase plot
# tp print see also: print(np.poly1d([1,2,3], variable='s')), print(np.poly1d([1,2,3], r=True, variable='s'))
def usr_servo_gen_code(self,fn='/tmp/ssc1.mat'):
import scipy.io,re
#the file ssc[1|2].mat has been generated with matlab:
#[mot1, mot2]=identifyFxFyStage();
#[pb]=simFxFyStage(mot1);
#[ssc]=StateSpaceControlDesign(mot1);
mat=scipy.io.loadmat(fn)
motid=int(re.search('(\d)\.mat',fn).group(1))
A=mat['Aoz']
B=mat['Boz']
C=mat['Coz']
D=mat['Doz']
V=mat['V']
u=('DesPos','IqMeas','IqVolts','ActPos')
y=('obsvOut',)
progSample='''double usr_servo_ctrl_{motid}(MotorData *Mptr)
{{
pshm->P[2000]=pshm->P[2000]*.9999+abs(Mptr->PosError)*0.0001; //lowpass of Position error
return pshm->ServoCtrl(Mptr);
}}'''.format(motid=motid)
prog='''double obsvr_servo_ctrl_{motid}(MotorData *Mptr)
{{
//x[n+1]=A*x[n]+B*u
//y=C*x[n]+D*x[n]
//u=[{u}].T
double x[{A.shape[0]}]; //new state
static double _x[{A.shape[0]}]={{0,0,0,0}}; //old state
//double {u}; // input values
double {y},iqCmd; // output values
double maxDac=Mptr->MaxDac;
'''.format(motid=motid,A=A,xInit=','.join('0'*A.shape[0]),u=', '.join(u),y=', '.join(y))
s=' //input values\n'
for i in range(len(u)):
s+=' double {u}=Mptr->{u};\n'.format(u=u[i])
prog+=s+'''\n
if (Mptr->ClosedLoop)
{
return iqCmd;
}
else
{
Mptr->Servo.Integrator=0.0;
return 0.0;
}
'''
s=' //x[n+1]=A*x[n]+B*u;\n'
for i in range(A.shape[0]):
s+=' x[%d]='%i
for j in range(A.shape[1]):
s+='%+28.22g*_x[%d]'%(A[i,j],j)
for j in range(B.shape[0]):
s+='%+28.22g*%s'%(B[i,j],u[j])
s+=';\n'
prog+=s+'\n'
s=' //y=C*x[n]+D*x[n];\n'
for i in range(C.shape[0]):
s+=' %s='%y[i]
for j in range(C.shape[1]):
s+='%+28.22g*_x[%d]'%(C[i,j],j)
s+=';\n'
prog+=s+'\n'
prog+=''' iqCmd=DesPos*{V}-{y};
if (iqCmd>maxDac)
{{
iqCmd=maxDac;
}}
else
{{
if (iqCmd<-maxDac)
{{
iqCmd=-maxDac;
}}
}}
return iqCmd;
}}'''.format(V=V[0,0],y=y[0])
hdr='''double obsvr_servo_ctrl_{motid}(MotorData *Mptr);
EXPORT_SYMBOL(obsvr_servo_ctrl_{motid});'''.format(motid=motid)
return (hdr,prog)
def bode(mdl):
w,mag,phase = signal.bode(mdl,1000)
@@ -250,6 +336,7 @@ Examples:'''+''.join(map(lambda s:cmd+s, exampleCmd))+'\n '
#plt.ion()
args.host='MOTTEST-CPPM-CRM0573'
args.host=None
if args.host is None:
comm=gt=None
else:
@@ -342,10 +429,42 @@ Examples:'''+''.join(map(lambda s:cmd+s, exampleCmd))+'\n '
tune.custom_chirp(motor=1,minFrq=100,maxFrq=3000,amp=10,tSec=5,mode=0,file='/tmp/cst_chirp0.npz')
#tune.custom_chirp(motor=2,minFrq=1,maxFrq=1000,tSec=5,mode=1,file='/tmp/cst_chirp1.npz')
#tune.custom_chirp(motor=1,minFrq=1,maxFrq=3000,tSec=5,mode=2,file='/tmp/cst_chirp2.npz')
elif mode==8: #generater code
#before this can be done, the observer controller has to be designed with matlab:
#s.a.ESB_MX/matlab/Readme.md
#clear;
#clear global;
#close all;
#[mot1,mot2]=identifyFxFyStage();
#[pb]=simFxFyStage(mot1);
#[ssc]=StateSpaceControlDesign(mot1);
#[pb]=simFxFyStage(mot2);
#[ssc]=StateSpaceControlDesign(mot2);
#after this go to: python/usr_code and call make to build the controller
#to activate the controller checkout: PBTools/pbtools/usr_servo_phase
base=os.path.dirname(__file__)
(hdr1,prog1)=tune.usr_servo_gen_code('/tmp/ssc1.mat')
(hdr2,prog2)=tune.usr_servo_gen_code('/tmp/ssc2.mat')
fn_ct=os.path.join(base,'usr_code/usrcode_template.c')
fn_ht=os.path.join(base,'usr_code/usrcode_template.h')
fnc=os.path.join(base,'usr_code/usrcode.c')
fnh=os.path.join(base,'usr_code/usrcode.h')
s=open(fn_ht).read()
s=s.replace('<usr_header>',hdr1+'\n\n'+hdr2)
fh=open(fnh,'w')
fh.write(s)
fh.close()
print(fnh+' generated.')
s=open(fn_ct).read()
s=s.replace('<usr_code>',prog1+'\n\n'+prog2)
fh=open(fnc,'w')
fh.write(s)
fh.close()
print(fnc+' generated.')
print('now compile it looking at PBTools/pbtools/usr_servo_phase/usrServoSample')
plt.show()
#------------------ Main Code ----------------------------------
#ssh_test()
#ssh_test()'/tmp/usrcode.c'
ret=parse_args()
exit(ret)