From dab7fb940c6d26d806d2ac0593d4583acfa93945 Mon Sep 17 00:00:00 2001 From: Thierry Zamofing Date: Wed, 23 Jan 2019 12:08:47 +0000 Subject: [PATCH] major code restructure and cleanup --- python/MXTuning.py | 11 - python/PBMotionAnalyzer/PBMotionAnalyzer.py | 398 -------- .../MAError.py | 0 .../MAVelocity.py | 0 .../MAxyPlot.py | 0 .../PBMA.ico | Bin .../PBMA.png | Bin .../wxutils.py | 0 python/shapepath.py | 875 +++++++++--------- python/usr_code/Makefile | 37 +- src/triggerSync/triggerSync.layout | 6 +- src/usrServo/Makefile | 2 +- 12 files changed, 454 insertions(+), 875 deletions(-) delete mode 100755 python/PBMotionAnalyzer/PBMotionAnalyzer.py rename python/{PBMotionAnalyzer => ShapePathAnalyser}/MAError.py (100%) rename python/{PBMotionAnalyzer => ShapePathAnalyser}/MAVelocity.py (100%) rename python/{PBMotionAnalyzer => ShapePathAnalyser}/MAxyPlot.py (100%) rename python/{PBMotionAnalyzer => ShapePathAnalyser}/PBMA.ico (100%) rename python/{PBMotionAnalyzer => ShapePathAnalyser}/PBMA.png (100%) rename python/{PBMotionAnalyzer => ShapePathAnalyser}/wxutils.py (100%) diff --git a/python/MXTuning.py b/python/MXTuning.py index 5e6b458..fde1d42 100755 --- a/python/MXTuning.py +++ b/python/MXTuning.py @@ -263,17 +263,6 @@ class MXTuning(Tuning): prog+=''' iqCmd=DesPos*{V}-{y}; - if (iqCmd>maxDac) - {{ - iqCmd=maxDac; - }} - else - {{ - if (iqCmd<-maxDac) - {{ - iqCmd=-maxDac; - }} - }} //return iqCmd; pshm->P[200{motid}]=iqCmd; //lowpass of Position error return pshm->ServoCtrl(Mptr); diff --git a/python/PBMotionAnalyzer/PBMotionAnalyzer.py b/python/PBMotionAnalyzer/PBMotionAnalyzer.py deleted file mode 100755 index 95701a7..0000000 --- a/python/PBMotionAnalyzer/PBMotionAnalyzer.py +++ /dev/null @@ -1,398 +0,0 @@ -#!/usr/bin/env python -# *-----------------------------------------------------------------------* -# | | -# | Copyright (c) 2016 by Paul Scherrer Institute (http://www.psi.ch) | -# | | -# | Author Thierry Zamofing (thierry.zamofing@psi.ch) | -# *-----------------------------------------------------------------------* -from __future__ import print_function -import os,sys -import wx -import wx.py -import numpy as np -from MAxyPlot import * -from MAError import * -from MAVelocity import * -#from hdfTree import * -#from hdfGrid import * -#from hdfAttrib import * -#from hdfImage import * - -import wxutils as ut -class MADoc(): - ''' - lenRec=fh['rec'] - lenPts=fh['pts'] - pts= X,Y array - - idx 0 1 2 3 4 5 6 - OLD Motor[3].ActPos Motor[2].ActPos Motor[1].ActPos Motor[3].DesPos Motor[2].DesPos Motor[1].DesPos Gate3[1].Chan[1].UserFlag - NEW Motor[1].ActPos Motor[2].ActPos Motor[1].DesPos Motor[2].DesPos Gate3[1].Chan[1].UserFlag - NEW y.ActPos x.ActPos y.DesPos x.DesPos Gate3[1].Chan[1].UserFlag - OLD->NEW - 0->none - 1->1 - 2->0 - 3->none - 4->3 - 5->2 - -Implemented messages -0: The time slider has changed. usrData=index -1: The position slider has changed. usrData=index - ''' - - def __init__(self): - self.view=[] #list of object that have view on this document - pass - - def Update(self,skipView,msg,usrData): - for v in self.view: - if v==skipView: continue - v.OnUpdate(msg,usrData) - - -class AboutFrame(wx.Frame): - def __init__(self,parent): - wx.Frame.__init__(self,parent,-1,'About MotionAnalyzer',size=(300,330)) - imgDir=ut.Path.GetImage() - icon = wx.Icon(os.path.join(imgDir,'PBMA.ico'), wx.BITMAP_TYPE_ICO) - self.SetIcon(icon) - self.Centre() - panel=wx.Panel(self,-1) - #import pkg_resources - #v=pkg_resources.get_distribution("h5pyViewer") - v='my version info' - s='Version:'+str(v)+'\n(c) www.psi.ch\n Author: Thierry Zamofing\n thierry.zamofing@psi.ch' - - st0=wx.StaticText(panel,-1,s,(30,10)) - bmp = wx.StaticBitmap(panel,-1,wx.Bitmap(os.path.join(imgDir,'PBMA.png'), wx.BITMAP_TYPE_ANY ), (30,st0.Position[1]+st0.Size[1]+10)) - for k,v in os.environ.iteritems(): - print(k,'=',v) - -class MAMainFrame(wx.Frame): - def __init__(self, parent, title,doc): - wx.Frame.__init__(self, parent, title=title, size=wx.Size(650, 230),style = wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP) - self.doc=doc;doc.view.append(self) - imgDir=ut.Path.GetImage() - icon = wx.Icon(os.path.join(imgDir,'PBMA.ico'), wx.BITMAP_TYPE_ICO) - self.SetIcon(icon) - #wxSplt = wx.SplitterWindow(self, -1) - #wxTree = HdfTreeCtrl(wxSplt, 1, wx.DefaultPosition, (-1,-1), wx.TR_HAS_BUTTONS) - #wxTree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=1) - #wxTree.Bind(wx.EVT_TREE_ITEM_MENU, self.OnMenu, id=1) - #wx.EVT_TREE_ITEM_MENU(id, func) - #wxTxt = wx.StaticText(wxSplt, -1, '',(10,10) )#, style=wx.ALIGN_CENTRE) - - - sizer = wx.BoxSizer(wx.VERTICAL) - self.SetSizer(sizer) - wxTxt = wx.StaticText(self, wx.ID_ANY, "MyLabel", wx.DefaultPosition, wx.DefaultSize, 0 ) - - sizer.Add(wxTxt, 1, wx.LEFT | wx.TOP | wx.GROW) - - wxTimeCtrl=ut.SliderGroup(self, label='DataPoint', range=(0, 1000)) - wxTimeCtrl.SetCallback(MAMainFrame.OnSetTime, wxTimeCtrl) - sizer.Add(wxTimeCtrl.sizer, 0, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=5) #wxSplt.SplitVertically(wxTree, wxTxt) - wxPosCtrl=ut.SliderGroup(self, label='IdxInPos', range=(0, 1000)) - wxPosCtrl.SetCallback(MAMainFrame.OnSetIdxInPos, wxPosCtrl) - sizer.Add(wxPosCtrl.sizer, 0, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=5) #wxSplt.SplitVertically(wxTree, wxTxt) - wxTrigCtrl=ut.SliderGroup(self, label='IdxTrigger', range=(0, 1000)) - wxTrigCtrl.SetCallback(MAMainFrame.OnSetIdxTrigger, wxTrigCtrl) - sizer.Add(wxTrigCtrl.sizer, 0, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=5) #wxSplt.SplitVertically(wxTree, wxTxt) - #wxSplt.SetMinimumPaneSize(320) - #wxLstCtrl=HdfAttrListCtrl(wxSplt) - #wxSplt.SplitVertically(wxTree, wxLstCtrl) - self.BuildMenu() - - self.Centre() - self.wxTimeCtrl=wxTimeCtrl - self.wxPosCtrl=wxPosCtrl - self.wxTrigCtrl=wxTrigCtrl - self.wxTxt=wxTxt - #self.wxTree=wxTree - #self.display=wxTxt - - def __del__(self): - self.CloseFile() - - def OpenFile(self,fn_npz): - doc=self.doc - try: - doc.fh=fh=np.load(fn_npz) - except IOError as e: - sys.stderr.write('Unable to open File: '+fn_npz+'\n') - else: - pass - s='content of numpy file: '+fn_npz+'\n' - for k,v in fh.iteritems(): - s+=' '+k+': '+str(v.dtype)+' '+str(v.shape)+'\n' - self.wxTxt.SetLabel(s) - - rec=fh['rec'] - pts=fh['pts'] - lenRec=rec.shape[0] - lenPts=pts.shape[0] - #idxTrigger=np.hstack(([0],rec[:,4])) - #doc.idxTrigger=idxTrigger=np.where(np.diff(idxTrigger)==1)[0] - idxTrigger=rec[:,4] - doc.idxTrigger=idxTrigger=np.where(np.diff(idxTrigger)==1)[0]+1 - idxInPos=[] #first point at idx 0 - - #try:# find approximate distance of 2 points - # rng =idxTrigger[2]-idxTrigger[1] - #except IndexError: - # rng = int(lenRec / lenPts) - #idx=rng/2 - - idx=0 - for i in range(lenPts): - l=rec[idx:,(3,2)]-pts[i,:] - l2=l[:,0]**2+l[:,1]**2 - try: - ofs=l2.argmin() - except ValueError: - break#print(l2[ofs]) - idx+=ofs - idxInPos.append(idx) - #idx+=rng/2 - - doc.idxInPos=idxInPos=np.array(idxInPos) - idx=min(idxInPos.shape[0],idxTrigger.shape[0])-1 - self.SetStatusText('scaling of DesTimeBase: %f'%(float(idxInPos[idx])/idxTrigger[idx])) - #self.PlotJitter() - - self.wxTimeCtrl.slider.SetRange(0,lenRec-1) - self.wxTimeCtrl.slider.SetPageSize(idxInPos[1]-idxInPos[0]) - self.wxPosCtrl.slider.SetRange(0,lenPts-1) - self.wxPosCtrl.slider.SetPageSize(10) - self.wxTrigCtrl.slider.SetRange(0,idxTrigger.shape[0]-1) - self.wxTrigCtrl.slider.SetPageSize(10) - - def CloseFile(self): - #http://docs.wxwidgets.org/2.8/wx_windowdeletionoverview.html#windowdeletionoverview - #print 'CloseFile' - try: - self.fh.close() - del self.fh - except AttributeError as e: - pass - - def PlotJitter(self): - doc=self.doc - fh=doc.fh - idxInPos=doc.idxInPos - idxTrigger=doc.idxTrigger - #display the jitter of inPos->trigger - ts=fh['meta'].item()['timebase'] - jitter=idxTrigger[:idxInPos.shape[0]]-idxInPos - import matplotlib.pyplot as plt # used for the colormaps - plt.figure('jitter inPos -> trigger: scaling of DesTimeBase: %f'%(float(idxInPos[-1])/idxTrigger[idxInPos.shape[0]-1])) - plt.plot(jitter*ts) - plt.ylabel('jitter in ms') - plt.ylabel('point idx') - plt.show() - - def DispJitter(self,idxInPos,idxTrigger): - doc=self.doc - ts=doc.fh['meta'].item()['timebase'] - self.SetStatusText("Jitter: %.2gms scaling: %.6g"%((idxTrigger-idxInPos)*ts,float(idxInPos)/idxTrigger)) - - def OnOpen(self, event): - dlg = wx.FileDialog(self, "Choose a file", os.getcwd(), '','numpy files (*.npz;*.npy)|*.npz;*.npy|all (*.*)|*.*', wx.OPEN|wx.FD_CHANGE_DIR) - if dlg.ShowModal() == wx.ID_OK: - path = dlg.GetPath() - #mypath = os.path.basename(path) - #self.SetStatusText("You selected: %s" % mypath) - self.CloseFile() - self.OpenFile(path) - #print 'OnOpen',path - dlg.Destroy() - - def OnCloseWindow(self, event): - #print 'OnCloseWindow' - self.Destroy() - - def OnAbout(self,event): - frame=AboutFrame(self) - frame.Show() - - def BuildMenu(self): - #http://wiki.wxpython.org/AnotherTutorial#wx.MenuBar - mnBar = wx.MenuBar() - - #-------- File Menu -------- - mn = wx.Menu() - mnItem=mn.Append(wx.ID_OPEN, '&Open', 'Open a new document');self.Bind(wx.EVT_MENU, self.OnOpen, mnItem) - #mnSub = wx.Menu() - #mnItem=mnSub.Append(wx.ID_ANY, 'SubMenuEntry', 'My SubMenuEntry') - #mn.AppendMenu(wx.ID_ANY, 'SubMenu', mnSub) - mn.AppendSeparator() - mnItem=mn.Append(wx.ID_EXIT, '&Quit', 'Quit the Application');self.Bind(wx.EVT_MENU, self.OnCloseWindow, mnItem) - mnBar.Append(mn, '&File') - - self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) - - #-------- Edit Menu -------- - mn = wx.Menu() - mnItem = mn.Append(wx.ID_ANY, 'Show &XY-Path', 'Show XY-path motion path');self.Bind(wx.EVT_MENU, self.OnShowXYPath, mnItem) - mnItem = mn.Append(wx.ID_ANY, 'Show &Error', 'Show error of motion path');self.Bind(wx.EVT_MENU, self.OnShowError, mnItem) - mnItem = mn.Append(wx.ID_ANY, 'Show &Velocity', 'Show velocity of motion path');self.Bind(wx.EVT_MENU, self.OnShowVelocity, mnItem) - mnItem = mn.Append(wx.ID_ANY, '&Python Shell', 'Opens an interactive python shell"');self.Bind(wx.EVT_MENU, self.OnShell, mnItem) - - mnBar.Append(mn, '&Window') - - #-------- Help Menu -------- - mn = wx.Menu() - #mnItem=mn.Append(wx.ID_HELP,'Help','Application Help') - mnItem=mn.Append(wx.ID_ABOUT,'About','Application About');self.Bind(wx.EVT_MENU, self.OnAbout, mnItem) - mnBar.Append(mn, '&Help') - - #mn.AppendSeparator() - #mnItem = wx.MenuItem(mn, 105, '&Quit\tCtrl+Q', 'Quit the Application') - #mnItem.SetBitmap(wx.Image('stock_exit-16.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap()) - #mn.AppendItem(mnItem) - self.SetMenuBar(mnBar) - self.CreateStatusBar() - self.SetStatusText("This is the status message") - - def OnShowXYPath(self, event): - frame=MAxyPlotFrame(self,self.doc) - frame.Show(True) - - def OnShowError(self, event): - frame=MAErrorFrame(self,self.doc) - frame.Show(True) - - def OnShowVelocity(self, event): - frame=MAVelocityFrame(self,self.doc) - frame.Show(True) - - def OnShell(self, event): - frame = wx.Frame(self, -1, "wxPyShell",size=wx.Size(800, 500)) - imgDir=Path.GetImage() - icon = wx.Icon(os.path.join(imgDir,'PBMA.ico'), wx.BITMAP_TYPE_ICO) - frame.SetIcon(icon) - frame.Centre() - fh=app.GetTopWindow().fh - wnd=app.GetTopWindow() - loc={'app' :app, - 'fh' :fh, - 'pts' :fh['pts'], - 'rec' :fh['rec'] - } - introText='''Shell to the HDF5 objects -app: application object -fh: numpy file -pts: desired motion points -rec: recorded data - -#Examples: -pts -rec - -#using user defined modules -#import userSample as us;reload(us);us.test1(hid) -''' - shell=wx.py.shell.Shell(frame, introText=introText,locals=loc) - frame.Show(True) - #if loc is None, all variables are visible. the context is global - #shell.push('wnd=app.GetTopWindow()') - #for cmd in [ - # 'wnd=app.GetTopWindow();wxTree=wnd.wxTree', - # 'wxNode=wnd.wxTree.GetSelection()', - # 'print wnd.fid', - # 'lbl=wxTree.GetItemText(wxNode)', - # 'hid=wxTree.GetPyData(wxNode)']: - # shell.run(cmd, prompt=False) - - def OnUpdate(self,msg,usrData): - #this is the model-view-control update function - #print self,msg,usrData - pass - - @staticmethod - def OnSetTime(usrData, idxRec, msg): - 'called when the time slider has been changed' - #print('OnSetTime', usrData, value, msg) - view=usrData.slider.Parent - doc=view.doc - idxInPos=np.argmin(abs(doc.idxInPos-idxRec)) - view.wxPosCtrl.SetValue(idxInPos) - idxTrigger=np.argmin(abs(doc.idxTrigger-idxRec)) - view.wxTrigCtrl.SetValue(idxTrigger) - view.DispJitter(doc.idxInPos[idxInPos],doc.idxTrigger[idxTrigger]) - doc.Update(view,0,idxRec) - - @staticmethod - def OnSetIdxInPos(usrData, idxInPos, msg): - 'called when the idxInPos slider has been changed' - #print('OnSetPosIdx', usrData, value, msg) - view = usrData.slider.Parent - doc = view.doc - idxRec=doc.idxInPos[idxInPos] - view.wxTimeCtrl.SetValue(idxRec) - idxTrigger=np.argmin(abs(doc.idxTrigger-idxRec)) - view.wxTrigCtrl.SetValue(idxTrigger) - view.DispJitter(doc.idxInPos[idxInPos],doc.idxTrigger[idxTrigger]) - doc.Update(view, 0, idxRec) - - @staticmethod - def OnSetIdxTrigger(usrData, idxTrigger, msg): - 'called when the idxTrigger slider has been changed' - #print('OnSetIdxTrigger', usrData, value, msg) - view = usrData.slider.Parent - doc = view.doc - idxRec=doc.idxTrigger[idxTrigger] - view.wxTimeCtrl.SetValue(idxRec) - idxInPos=np.argmin(abs(doc.idxInPos-idxRec)) - view.wxPosCtrl.SetValue(idxInPos) - view.DispJitter(doc.idxInPos[idxInPos],doc.idxTrigger[idxTrigger]) - doc.Update(view, 0, idxRec) - - -if __name__ == '__main__': - def GetArgs(): - import sys,argparse #since python 2.7 - exampleCmd='/tmp/shapepath.npz' - parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, - description=__doc__, - epilog='Example:\n'+os.path.basename(sys.argv[0])+' '+exampleCmd+'\n ') - parser.add_argument('npzFile', nargs='?', help='the npz file with motion path data to show',default='/tmp/shapepath.npz') - - args = parser.parse_args() - return args - - - class MyApp(wx.App): - - def OnInit(self): - args=GetArgs() - doc=MADoc() - frame = MAMainFrame(None,'PBMotionAnalyzer',doc) - if args.npzFile: - frame.OpenFile(args.npzFile) - frame.Show(True) - - f1 = MAxyPlotFrame(frame, doc) - f1.Show(True) - #f2= MAErrorFrame(frame, doc) - #f2.Show(True) - #f3= MAVelocityFrame(frame, doc) - #f3.Show(True) - - self.SetTopWindow(frame) - return True - -#------------------ Main Code ---------------------------------- - #redirect stdout/stderr: - #http://www.blog.pythonlibrary.org/2009/01/01/wxpython-redirecting-stdout-stderr/ - #https://groups.google.com/forum/#!topic/wxpython-users/S9uSKIYdYoo - #https://17677433047266577941.googlegroups.com/attach/e4d343dc6a751906/REDIRECT.PY?part=2&view=1&vt=ANaJVrFeyCjCMydKnkyfFbYJM7ip07mE-ozUIBxJ5A1QuK1GhycJYJsPTxpAaNk5L2LpXvGhzRPInxDt8_WUcUyK2Ois28Dq8LNebfYoWG9Yxr-tujf5Jk4 - #http://www.wxpython.org/docs/api/wx.PyOnDemandOutputWindow-class.html - rd=not sys.stdout.isatty()#have a redirect window, if there is no console - #rd=True #force to open a redirect window - rd=False #avoid a redirect window - app = MyApp(redirect=rd) - app.MainLoop() - diff --git a/python/PBMotionAnalyzer/MAError.py b/python/ShapePathAnalyser/MAError.py similarity index 100% rename from python/PBMotionAnalyzer/MAError.py rename to python/ShapePathAnalyser/MAError.py diff --git a/python/PBMotionAnalyzer/MAVelocity.py b/python/ShapePathAnalyser/MAVelocity.py similarity index 100% rename from python/PBMotionAnalyzer/MAVelocity.py rename to python/ShapePathAnalyser/MAVelocity.py diff --git a/python/PBMotionAnalyzer/MAxyPlot.py b/python/ShapePathAnalyser/MAxyPlot.py similarity index 100% rename from python/PBMotionAnalyzer/MAxyPlot.py rename to python/ShapePathAnalyser/MAxyPlot.py diff --git a/python/PBMotionAnalyzer/PBMA.ico b/python/ShapePathAnalyser/PBMA.ico similarity index 100% rename from python/PBMotionAnalyzer/PBMA.ico rename to python/ShapePathAnalyser/PBMA.ico diff --git a/python/PBMotionAnalyzer/PBMA.png b/python/ShapePathAnalyser/PBMA.png similarity index 100% rename from python/PBMotionAnalyzer/PBMA.png rename to python/ShapePathAnalyser/PBMA.png diff --git a/python/PBMotionAnalyzer/wxutils.py b/python/ShapePathAnalyser/wxutils.py similarity index 100% rename from python/PBMotionAnalyzer/wxutils.py rename to python/ShapePathAnalyser/wxutils.py diff --git a/python/shapepath.py b/python/shapepath.py index eb84aa2..f12700c 100755 --- a/python/shapepath.py +++ b/python/shapepath.py @@ -53,7 +53,6 @@ from pbtools.misc.pp_comm import PPComm from pbtools.misc.gather import Gather from MXMotion import MotionBase - def gen_pvt(p,v, p2pt, ts): '''generates a pvt motion p: position array @@ -75,68 +74,353 @@ def gen_pvt(p,v, p2pt, ts): return pvt +class DebugPlot: + def __init__(self,spObj=None,fn=None): + if spObj is not None: + self.set_data(spObj) + elif fn is not None: + self.load_npz(fn) + else: + self.load_npz() -def debugplot_pvt(pv, meta): - # pv is an array of posx posy velx vely - #pv=pv[5:10,:] - #pv=pv[5:-4,:] - p2pt=meta['pt2pt_time'] # ms step between samples - ts=meta['timebase'] # sampling time in ms - n=int(p2pt/ts) # servo cycle between samples - k=pv.shape[0] # number of unique samples - t=np.arange(0, p2pt*k, p2pt) # time array of trajectory - ppx=gen_pvt(pv[:,0], pv[:,2], p2pt, ts) - ppy=gen_pvt(pv[:,1], pv[:,3], p2pt, ts) - tt=np.arange(0, n*(k-1))*ts # time array of trajectory + @staticmethod + def plot_gen_pvt(self,pv): + # pv is an array of posx posy velx vely + #pv=pv[5:10,:] + #pv=pv[5:-4,:] + p2pt=self.meta['pt2pt_time'] # ms step between samples + ts=self.meta['timebase'] # sampling time in ms + n=int(p2pt/ts) # servo cycle between samples + k=pv.shape[0] # number of unique samples + t=np.arange(0, p2pt*k, p2pt) # time array of trajectory + ppx=gen_pvt(pv[:,0], pv[:,2], p2pt, ts) + ppy=gen_pvt(pv[:,1], pv[:,3], p2pt, ts) + tt=np.arange(0, n*(k-1))*ts # time array of trajectory - fig=plt.figure() - ax1=fig.add_subplot(2, 1, 1) - ax2=fig.add_subplot(2, 1, 2) - #ax.xaxis.set_ticks(t) - ax1.stem(t, pv[:,0], '-r') - ax2.stem(t, pv[:,1], '-g') + fig=plt.figure() + ax1=fig.add_subplot(2, 1, 1) + ax2=fig.add_subplot(2, 1, 2) + #ax.xaxis.set_ticks(t) + ax1.stem(t, pv[:,0], '-r') + ax2.stem(t, pv[:,1], '-g') - ax1.plot(tt, ppx, '-r', label='x') - ax2.plot(tt, ppy, '-g', label='y') - #ax.legend(loc='best') + ax1.plot(tt, ppx, '-r', label='x') + ax2.plot(tt, ppy, '-g', label='y') + #ax.legend(loc='best') - ax=plt.figure().add_subplot(1, 1, 1) - ax.plot(pv[:,0], pv[:,1], '.r', label='pft') - ax.plot(ppx, ppy, '-c', label='pft') - ax.invert_xaxis() - ax.invert_yaxis() - plt.axis('equal') + ax=plt.figure().add_subplot(1, 1, 1) + ax.plot(pv[:,0], pv[:,1], '.r', label='pft') + ax.plot(ppx, ppy, '-c', label='pft') + ax.invert_xaxis() + ax.invert_yaxis() + plt.axis('equal') - ax.legend(loc='best') - plt.show(block=False) + ax.legend(loc='best') + plt.show(block=False) + + # ### frequency plots ### + # fig=plt.figure() + # ax=fig.add_subplot(1,1,1)#ax=plt.gca() + # + # #remove linear slope + # sx=ppx-(pv[-1,0]-pv[0,0])*np.arange(ppx.shape[0]) + # sy=ppy-(pv[-1,1]-pv[0,1])*np.arange(ppy.shape[0]) + # + # #normalize with l -> value of k means amplitude of k at a given frequency + # ppxf=np.fft.rfft(sx)/(2*n) + # ppyf=np.fft.rfft(sy)/(2*n) + # + # f=np.fft.rfftfreq(ppx.shape[0], d=ts*1E-3) + # f=f[1:] #remove dc value frequency + # + # mag=abs(ppxf[1:])#; mag=20*np.log10(abs(mag)) + # ax.semilogx(f,mag,'-b',label='ppx') # Bode magnitude plot + # mag=abs(ppyf[1:])#; mag=20*np.log10(abs(mag)) + # ax.semilogx(f,mag,'-g',label='ppy') # Bode magnitude plot + # #ax.yaxis.set_label_text('dB ampl') + # ax.yaxis.set_label_text('ampl') + # ax.xaxis.set_label_text('frequency [Hz]') + # plt.grid(True) + # + # ax.legend(loc='best') + # plt.show(block=False) + return (tt,ppx,ppy) + + #@staticmethod + #def onclick(event): + # print('button=%s, x=%d, y=%d, xdata=%f, ydata=%f'%( + # event.button, event.x, event.y, event.xdata, event.ydata)) + # obj=event.canvas.figure.obj + + @staticmethod + def plot_points(pts): + fig=plt.figure() + ax = fig.add_subplot(1,1,1) + ax.invert_xaxis();ax.invert_yaxis() + #hl=ax[0].plot(x, y, color=col) + hl=ax.plot(pts[:,0],pts[:,1],'r.') + hl=ax.plot(pts[:,0],pts[:,1],'y--') + #cid = fig.canvas.mpl_connect('button_press_event', self.onclick) + #fig.obj=self + plt.axis('equal') + #self.ax=ax + #self.hl=hl + + + def analyze_trigger(self): + if hasattr(self,'idxTrigger'): return + pts=self.pts # X,Y array + rec=self.rec # yA,xA,yD,xD,trig + lenRec=rec.shape[0] + lenPts=pts.shape[0] + + idxTrigger=rec[:,4] + idxTrigger=np.where(np.diff(idxTrigger)==1)[0]+1 + idxInPos=[] #first point at idx 0 + idx=0 + for i in range(lenPts): + l=rec[idx:,(3,2)]-pts[i,:] + l2=l[:,0]**2+l[:,1]**2 + try: + ofs=l2.argmin() + except ValueError: + break#print(l2[ofs]) + idx+=ofs + idxInPos.append(idx) + + idxInPos = np.array(idxInPos) + #select only triggers on a target point + i=np.abs(idxTrigger - idxInPos[1]).argmin() + j=np.abs(idxTrigger - idxInPos[-2]).argmin()+1 + self.idxTrigger=idxTrigger[i:j] + self.idxInPos=idxInPos[1:-1] + + def plot_trigger_jitter(self): + self.analyze_trigger() + ts=self.meta['timebase'] + idxTrigger=self.idxTrigger + idxInPos=self.idxInPos + jitter = idxTrigger-idxInPos + pts=self.pts # X,Y array + rec=self.rec # yA,xA,yD,xD,trig + + fig = plt.figure('trigger jitter') + ax = fig.add_subplot(1, 1, 1) + hl = [] + hl += ax.plot(jitter * ts, 'b-', label='jitter') + ax.xaxis.set_label_text('position idx') + ax.yaxis.set_label_text('jitter motion (ms)') + + + rec = self.rec # yA,xA,yD,xD,trig + ts=self.meta['timebase'] + fig = plt.figure('shot position error') + ax = fig.add_subplot(1, 1, 1) + + #errx = rec[idxTrigger, 1] - rec[idxInPos, 3] + #erry = rec[idxTrigger, 0] - rec[idxInPos, 2] + errx = rec[idxTrigger, 1] - pts[1:-1, 0] + erry = rec[idxTrigger, 0] - pts[1:-1, 1] + err = np.sqrt(errx ** 2 + erry ** 2) + + hl = [] + hl += ax.plot(errx, 'b-', label='x-error') + hl += ax.plot(erry, 'g-', label='y-error') + hl += ax.plot(err, 'r-', label='error') + ax.xaxis.set_label_text('target point index') + ax.yaxis.set_label_text('pos-error um') + legend = ax.legend(loc='best', shadow=True) + print('shot average error x %g um, y %g um, %g um' % (np.abs(errx).mean(), np.abs(erry).mean(), err.mean())) + plt.show(block=False) + + + plt.show(block=False) + + + def plot_pos_error(self): + rec = self.rec # yA,xA,yD,xD,trig + ts=self.meta['timebase'] + fig = plt.figure('position error') + ax = fig.add_subplot(1, 1, 1) + + t=np.arange(rec.shape[0],dtype=np.uint32) + errx = rec[:, 1] - rec[:, 3] + erry = rec[:, 0] - rec[:, 2] + err = np.sqrt(errx ** 2 + erry ** 2) + + hl = [] + hl += ax.plot(t, errx, 'b-', label='x-error') + hl += ax.plot(t, erry, 'g-', label='y-error') + hl += ax.plot(t, err, 'r-', label='error') + ax.xaxis.set_label_text('ms (timebase: %g ms per data point)' % ts) + ax.yaxis.set_label_text('pos-error um') + legend = ax.legend(loc='best', shadow=True) + print('motion average error x %g um, y %g um, %g um' % (np.abs(errx).mean(), np.abs(erry).mean(), err.mean())) + plt.show(block=False) + + def plot_trajectory(self): + pts = self.pts # X,Y array + rec = self.rec # yA,xA,yD,xD,trig + fig = plt.figure('trajectory') + ax = fig.add_subplot(1, 1, 1) + ax.invert_xaxis() + ax.invert_yaxis() + # hl=ax[0].plot(x, y, color=col) + hl = ax.plot(pts[:, 0], pts[:, 1], 'r.', label='points') + hl += ax.plot(pts[:, 0], pts[:, 1], 'y--', label='direct') + hl += ax.plot(rec[:, 3], rec[:, 2], 'b-', label='DesPos') # desired path + hl += ax.plot(rec[:, 1], rec[:, 0], 'g-', label='ActPos') # actual path + try: + pvt = self.pvt + except AttributeError: + pass + else: + hl = ax.plot(pvt[1], pvt[2], 'c--', label='SimPos') # simulated path + + fig2 = plt.figure('time line') + ax2 = fig2.add_subplot(1, 1, 1) + hl2 = ax2.plot(rec[:, 2], 'r-', label='desPos Mot1') + hl2 += ax2.plot(rec[:, 3], 'g-', label='desPos Mot2') + + idxTrigger = rec[:, 4] + idxTrigger = np.where(np.diff(idxTrigger) == 1)[0] + 1 + if idxTrigger.shape[0] > 0: + hl += ax.plot(rec[idxTrigger, 1], rec[idxTrigger, 0], 'xr', label='trig') # actual path + hl2 += ax2.plot(rec[:, 4], 'b-', label='trigger') + + ax.xaxis.set_label_text('x-pos um') + ax.yaxis.set_label_text('y-pos um') + ax.axis('equal') + ax.legend(loc='best') + # cid = fig.canvas.mpl_connect('button_press_event', self.onclick) + # fig.obj=self + ax2.legend(loc='best') + plt.show(block=False) + + def plot_gather(self,mode=255): + try: + meta=self.meta + pts=self.pts # X,Y array + rec = self.rec # yA,xA,yD,xD,trig + except AttributeError as e: + print('plot_gather(): '+str(e)+': no data acquired yet') + return + + if mode&1: + self.plot_trajectory() + + if mode&2: + self.plot_pos_error() + + if mode&4: + self.plot_bode(xy=(3,1),mode=31,db=True) # FX + self.plot_bode(xy=(2,0),mode=31,db=True) # FY + + if mode&8: + self.plot_trigger_jitter() + + plt.show() + + def plot_bode(self,xy=(0,1),mode=25,db=True): + '''displays a bode plot of the data + Y(s)=G(s)*X(s) + Y= output signal + X= input signal + xy are the row indexes of input and output signal + meta= meta information (dictionary) of data + + mode bits: (+mean default) + +1: display time signal + 2: display bode of X(s) signal + 4: display bode of Y(s) signal + +8: display bode of G(s) signal + +16: clip frequencies out of minFrq,maxFrq + ''' + meta=self.meta + pts=self.pts # X,Y array + rec = self.rec # yA,xA,yD,xD,trig + strMot=('FY.act','FX.act','FY.des','FX.des') + ts=meta['timebase']*1E-3 #0.2ms + num=rec.shape[0] + #rngMin=int(.01/ts);rngMax=int(num-1.001/ts) #0.01s from start 1.01 sec before end + rngMin=int(.01/ts);rngMax=rngMin+int((pts.shape[0]-2)*.01/ts) + + num=rngMax-rngMin + + minFrq=1/(num*ts)#minimal frq to show bode + maxFrq=1/(2*ts) #maximal frq to show bode + xIdx,yIdx=xy + #remove DC value + x=rec[rngMin:rngMax,xIdx]-rec[rngMin,xIdx] + y=rec[rngMin:rngMax,yIdx]-rec[rngMin,yIdx] + #make last value same as first (nice periodicity) + x=x-(x[-1]*np.arange(num)/(num-1.)) + y=y-(y[-1]*np.arange(num)/(num-1.)) + if mode&1: + t = ts*np.arange(num) + fig=plt.figure('raw {}->{}'.format(strMot[xIdx],strMot[yIdx])) + ax=fig.gca() + ax.plot(t,x,'b') + ax.plot(t,y,'g') + + fig=plt.figure('bode {}->{}'.format(strMot[xIdx],strMot[yIdx])) + ax1=fig.add_subplot(2,1,1) + ax1.grid(True) + ax1.yaxis.set_label_text('Amplitude'+ (' [dB]' if db else '')) + ax1.axvline(minFrq,c='k');ax1.axvline(maxFrq,c='k') + + ax2=fig.add_subplot(2,1,2, sharex = ax1) + ax2.grid(True) + ax2.xaxis.set_label_text('Frequency [Hz]') + ax2.yaxis.set_label_text('Phase [degree]') + + ftX=np.fft.rfft(x) + ftY=np.fft.rfft(y) + + fMax=.5/ts #fs=1/ts, fMax=1/2fs + n=ftX.shape[0] + f=np.arange(n)*fMax/(n-1) + + if mode&16: + i=int(minFrq*num*ts); j=int(maxFrq*num*ts); #print(w[i],w[j]) + f=f[i:j+1] + ftX=ftX[i:j+1] + ftY=ftY[i:j+1] + ftLst=[] + if mode&2: + ftLst.append((ftX,'b','input')) + if mode&4: + ftLst.append((ftY,'g','output')) + if mode&8: + ftLst.append((ftY/ftX,'r','out/inp')) + + for ft,c,s in ftLst: + phase=np.angle(ft) + phase=np.degrees(np.unwrap(phase)) + mag=np.abs(ft) #ftY)/np.abs(ftX) + if db: + magDb=20*np.log10(mag) #in decibel (20=10*2: factor 2 because rfft only half) + ax1.semilogx(f,magDb,c,label=s) # Bode magnitude plot + else: + ax1.semilogx(f, mag, c,label=s) # Bode magnitude plot + ax2.semilogx(f,phase,c,label=s) # Bode phase plot + ax2.set_ylim(-360,360) + ax2.legend(loc='best') + plt.show(block=False) + + def load_npz(self,fn='/tmp/shapepath.npz'): + fh=np.load(fn) + for k,v in fh.iteritems(): + setattr(self,k,v) + self.meta=self.meta.item() + + def set_data(self,spObj): + self.meta=spObj.meta + self.pts=spObj.points + self.rec=spObj.rec + try: pvt=self.pvt + except AttributeError: pass - # ### frequency plots ### - # fig=plt.figure() - # ax=fig.add_subplot(1,1,1)#ax=plt.gca() - # - # #remove linear slope - # sx=ppx-(pv[-1,0]-pv[0,0])*np.arange(ppx.shape[0]) - # sy=ppy-(pv[-1,1]-pv[0,1])*np.arange(ppy.shape[0]) - # - # #normalize with l -> value of k means amplitude of k at a given frequency - # ppxf=np.fft.rfft(sx)/(2*n) - # ppyf=np.fft.rfft(sy)/(2*n) - # - # f=np.fft.rfftfreq(ppx.shape[0], d=ts*1E-3) - # f=f[1:] #remove dc value frequency - # - # mag=abs(ppxf[1:])#; mag=20*np.log10(abs(mag)) - # ax.semilogx(f,mag,'-b',label='ppx') # Bode magnitude plot - # mag=abs(ppyf[1:])#; mag=20*np.log10(abs(mag)) - # ax.semilogx(f,mag,'-g',label='ppy') # Bode magnitude plot - # #ax.yaxis.set_label_text('dB ampl') - # ax.yaxis.set_label_text('ampl') - # ax.xaxis.set_label_text('frequency [Hz]') - # plt.grid(True) - # - # ax.legend(loc='best') - # plt.show(block=False) - return (tt,ppx,ppy) class ShapePath(MotionBase): def __init__(self,comm, gather, verbose): @@ -262,6 +546,43 @@ class ShapePath(MotionBase): self.points=pts + def sort_points(self,xy=False,grp_sz=None): + pts=self.points + verb=self.verbose + + cnt=pts.shape[0] + idx=np.ndarray(cnt,dtype=np.int32) + if grp_sz is None: + grp_cnt=int(np.sqrt(cnt)) + grp_sz=int(np.ceil(float(cnt)/grp_cnt)) + else: + grp_sz=int(grp_sz) + grp_cnt=int(np.ceil(float(cnt)/grp_sz)) + + if xy==True: + idxA=1;idxB=0 + else: + idxA=0;idxB=1 + + #sort points along idxA + pts=pts[pts[:,idxA].argsort()] + #group sorting along idxB + for i in range(grp_cnt): + a=i*grp_sz + #print a,a+grp_sz + if i%2: + idx[a:a+grp_sz]=a+pts[a:a+grp_sz,idxB].argsort()[::-1] + else: + idx[a:a+grp_sz]=a+pts[a:a+grp_sz,idxB].argsort() + #print(idx) + pts=pts[idx] + + if verb&2: + DebugPlot.plot_points(pts) + plt.show() + self.points=pts + + def opt_pts(self,fn): ''' trial to optimize path by mofing trajectory, uload real path and move the points @@ -292,6 +613,7 @@ class ShapePath(MotionBase): kwargs: acq_per : acquire period: acquire data all acq_per servo loops (default=1) ''' + if self.comm is None: return comm=self.comm gt=self.gather gt.set_phasemode(False) @@ -307,6 +629,7 @@ class ShapePath(MotionBase): self.meta = {'timebase': ServoPeriod*acq_per,'address':address} def setup_coord_trf(self): + if self.comm is None: return comm = self.comm gpascii = comm.gpascii prg = '''&1a @@ -328,58 +651,26 @@ class ShapePath(MotionBase): the type of generated program is defined by 2. runs the program on the deltatau - mode=-1 jog a 10mm square - mode=0 linear motion mode=1 pvt motion kwargs: - pt2pt_time : time to move from one point to the next point - sync_frq : synchronization mark all n points (default=10) scale : scaling velocity (default=1. value=0 would stop at the point cnt : move path multiple times (default=1) dwell : dwell time at end (default=100ms) - mode=2 spline motion mode=3 pvt motion using inverse fft velocity kwargs: same as pvt motion + numPad : number of padding points to reduce aliasing (default=16) ''' prg=['close all buffers','open prog %d'%(prgId)] comm=self.comm if comm is not None: gpascii=comm.gpascii # 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 in (1,3): #### pvt motion - pt2pt_time=kwargs.get('pt2pt_time', 100) + pt2pt_time=self.meta['pt2pt_time'] ts=self.meta['timebase'] scale=kwargs.get('scale', 1.) - self.meta['pt2pt_time']=pt2pt_time cnt=kwargs.get('cnt', 1) # move path multiple times - sync_frq=kwargs.get('sync_frq', 10) # synchronization mark all n points dwell=kwargs.get('dwell', 100) # synchronization mark all n points CoordFeedTime=1000. #Defaut deltatau value try: @@ -397,7 +688,8 @@ class ShapePath(MotionBase): dist=pv[2:,(0,1)] - pv[:-2,(0,1)] pv[ 1:-1,(2,3)] = dist/(2.*pt2pt_time)*scale #um/ms else: #mode=3: set velocity to the reconstructed inverse fourier transformation - p=pt.T.copy() #copy + numPad=kwargs.get('numPad', 16) + p=np.hstack((pt.T,pt[-1,:].repeat(numPad).reshape(2,-1))) k=p.shape[1] stp=((p[:,-1]-p[:,0])/(k-1)) #calculate steepness point to point #stp*=0 @@ -408,10 +700,14 @@ class ShapePath(MotionBase): pfd=pf*f*1j # differentiate in fourier pd=np.fft.ifft(pfd) v=pd.real.T/pt2pt_time*np.pi*2+stp/pt2pt_time - pv[ 1:-1,(2,3)] = v*scale + if numPad==0: + n=None + else: + n=-numPad + pv[ 1:-1,(2,3)] = v[:n]*scale verb=self.verbose if verb&16: - self.pvt=debugplot_pvt(pv, self.meta) + self.pvt=DebugPlot(self).plot_gen_pvt(pv) plt.show() pv[1:-1, (2, 3)]*=CoordFeedTime #scaling for Deltatau @@ -427,11 +723,7 @@ class ShapePath(MotionBase): prg.append('N100:') prg.append(' pvt%g abs'%pt2pt_time) #100ms to next position for idx in range(1,pv.shape[0]): - if sync_frq is not None and idx%sync_frq==0: - prg.append('Coord[1].Q[1]=%d'%(idx)) prg.append('X%g:%g Y%g:%g'%tuple(pv[idx,(0,2,1,3)])) - if sync_frq is not None: - prg.append('Coord[1].Q[1]=%d' % (idx)) prg.append('X%g Y%g' % tuple(pv[-1, (0,1)])) if cnt>1: prg.append('dwell 10') @@ -446,26 +738,6 @@ class ShapePath(MotionBase): else: prg.append('dwell %d'%dwell) 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) @@ -502,253 +774,6 @@ class ShapePath(MotionBase): if fnRec: np.savez_compressed(fnRec, rec=rec, pts=pts, meta=self.meta) - def sort_points(self,xy=False,grp_sz=None): - pts=self.points - verb=self.verbose - - cnt=pts.shape[0] - idx=np.ndarray(cnt,dtype=np.int32) - if grp_sz is None: - grp_cnt=int(np.sqrt(cnt)) - grp_sz=int(np.ceil(float(cnt)/grp_cnt)) - else: - grp_sz=int(grp_sz) - grp_cnt=int(np.ceil(float(cnt)/grp_sz)) - - if xy==True: - idxA=1;idxB=0 - else: - idxA=0;idxB=1 - - #sort points along idxA - pts=pts[pts[:,idxA].argsort()] - #group sorting along idxB - for i in range(grp_cnt): - a=i*grp_sz - #print a,a+grp_sz - if i%2: - idx[a:a+grp_sz]=a+pts[a:a+grp_sz,idxB].argsort()[::-1] - else: - idx[a:a+grp_sz]=a+pts[a:a+grp_sz,idxB].argsort() - #print(idx) - pts=pts[idx] - - if verb&2: - self.plot_points(pts) - plt.show() - self.points=pts - - @staticmethod - def onclick(event): - print('button=%s, x=%d, y=%d, xdata=%f, ydata=%f'%( - event.button, event.x, event.y, event.xdata, event.ydata)) - obj=event.canvas.figure.obj - - def plot_points(self,pts): - fig=plt.figure() - ax = fig.add_subplot(1,1,1) - ax.invert_xaxis();ax.invert_yaxis() - #hl=ax[0].plot(x, y, color=col) - hl=ax.plot(pts[:,0],pts[:,1],'r.') - hl=ax.plot(pts[:,0],pts[:,1],'y--') - cid = fig.canvas.mpl_connect('button_press_event', self.onclick) - fig.obj=self - plt.axis('equal') - self.ax=ax - self.hl=hl - - def plot_gather(self,mode=255): - try: - meta=self.meta - pts=self.points # X,Y array - rec = self.rec # yA,xA,yD,xD,trig - except AttributeError as e: - print('plot_gather(): '+str(e)+': no data acquired yet') - return - ts=meta['timebase'] - t=np.arange(rec.shape[0],dtype=np.uint32) - if mode&1: - fig=plt.figure('trajectory') - ax = fig.add_subplot(1,1,1) - ax.invert_xaxis();ax.invert_yaxis() - #hl=ax[0].plot(x, y, color=col) - hl=ax.plot(pts[:,0],pts[:,1],'r.',label='points') - hl+=ax.plot(pts[:,0],pts[:,1],'y--',label='direct') - hl+=ax.plot(rec[:,3],rec[:,2], 'b-',label='DesPos') # desired path - hl+=ax.plot(rec[:,1],rec[:,0],'g-',label='ActPos') # actual path - try: pvt=self.pvt - except AttributeError: pass - else: - hl=ax.plot(pvt[1], pvt[2], 'c--',label='SimPos') # simulated path - - - fig2=plt.figure('time line') - ax2=fig2.add_subplot(1, 1, 1) - hl2=ax2.plot(rec[:, 2], 'r-', label='desPos Mot1') - hl2+=ax2.plot(rec[:, 3], 'g-', label='desPos Mot2') - - idxTrigger = rec[:, 4] - idxTrigger = np.where(np.diff(idxTrigger) == 1)[0] + 1 - if idxTrigger.shape[0]>0: - hl+=ax.plot(rec[idxTrigger,1],rec[idxTrigger,0],'xr',label='trig') # actual path - hl2 += ax2.plot(rec[:, 4], 'b-',label='trigger') - - ax.xaxis.set_label_text('x-pos um') - ax.yaxis.set_label_text('y-pos um') - ax.axis('equal') - ax.legend(loc='best') - cid = fig.canvas.mpl_connect('button_press_event', self.onclick) - fig.obj=self - - ax2.legend(loc='best') - - plt.show(block=False) - - if mode&2: - fig = plt.figure('position error') - ax = fig.add_subplot(1, 1, 1) - errx=rec[:,1]-rec[:,3] - erry=rec[:,0]-rec[:,2] - err=np.sqrt(errx**2+erry**2) - - hl = [] - hl += ax.plot(t,errx,'b-',label='x-error') - hl += ax.plot(t,erry,'g-',label='y-error') - hl += ax.plot(t,err, 'r-',label='error') - ax.xaxis.set_label_text('ms (timebase: %g ms per data point)'%ts) - ax.yaxis.set_label_text('pos-error um') - legend = ax.legend(loc='upper right', shadow=True) - print('average error x %g um, y %g um, %g um'%(np.abs(errx).mean(),np.abs(erry).mean(),err.mean())) - - if mode&4: - self.bode_plot(xy=(3,1),mode=31,db=True) # FX - self.bode_plot(xy=(2,0),mode=31,db=True) # FY - - if mode&8: - lenRec = rec.shape[0] - lenPts = pts.shape[0] - # idxTrigger=np.hstack(([0],rec[:,4])) - # doc.idxTrigger=idxTrigger=np.where(np.diff(idxTrigger)==1)[0] - idxTrigger = rec[:, 4] - - idxTrigger = np.where(np.diff(idxTrigger) == 1)[0] + 1 - idxInPos = [] # first point at idx 0 - try: # find approximate distance of 2 points - rng = idxTrigger[2]-idxTrigger[1] - except IndexError: - rng = int(lenRec/lenPts) - idx = rng/2 - - for i in range(lenPts): - l=rec[idx:idx+rng,(3,2)]-pts[i,:] - l2=l[:,0]**2+l[:,1]**2 - try: - ofs=l2.argmin() - except ValueError as e: - break - idx+=ofs - idxInPos.append(idx) - idx+= rng/2 - - idxInPos = np.array(idxInPos) - num = min(idxInPos.shape[0], idxTrigger.shape[0]) - jitter=idxTrigger[:num]-idxInPos[:num] - fig = plt.figure('trigger jitter') - ax = fig.add_subplot(1, 1, 1) - hl = [] - hl += ax.plot(jitter*ts, 'b-',label='jitter') - ax.xaxis.set_label_text('position idx') - ax.yaxis.set_label_text('jitter motion (ms)') - if num>0: - print('scaling of DesTimeBase: %f'%(float(idxInPos[num-1])/idxTrigger[num-1])) - plt.show() - - def bode_plot(self,xy=(0,1),mode=25,db=True): - '''displays a bode plot of the data - Y(s)=G(s)*X(s) - Y= output signal - X= input signal - xy are the row indexes of input and output signal - meta= meta information (dictionary) of data - - mode bits: (+mean default) - +1: display time signal - 2: display bode of X(s) signal - 4: display bode of Y(s) signal - +8: display bode of G(s) signal - +16: clip frequencies out of minFrq,maxFrq - ''' - rec=self.rec - strMot=('FY.act','FX.act','FY.des','FX.des') - - ts=self.meta['timebase']*1E-3 #0.2ms - num=rec.shape[0] - #rngMin=int(.01/ts);rngMax=int(num-1.001/ts) #0.01s from start 1.01 sec before end - rngMin=int(.01/ts);rngMax=rngMin+int((self.points.shape[0]-2)*.01/ts) - - num=rngMax-rngMin - - minFrq=1/(num*ts)#minimal frq to show bode - maxFrq=1/(2*ts) #maximal frq to show bode - xIdx,yIdx=xy - #remove DC value - x=rec[rngMin:rngMax,xIdx]-rec[rngMin,xIdx] - y=rec[rngMin:rngMax,yIdx]-rec[rngMin,yIdx] - #make last value same as first (nice periodicity) - x=x-(x[-1]*np.arange(num)/(num-1.)) - y=y-(y[-1]*np.arange(num)/(num-1.)) - if mode&1: - t = ts*np.arange(num) - fig=plt.figure('raw {}->{}'.format(strMot[xIdx],strMot[yIdx])) - ax=fig.gca() - ax.plot(t,x,'b') - ax.plot(t,y,'g') - - fig=plt.figure('bode {}->{}'.format(strMot[xIdx],strMot[yIdx])) - ax1=fig.add_subplot(2,1,1) - ax1.grid(True) - ax1.yaxis.set_label_text('Amplitude'+ (' [dB]' if db else '')) - ax1.axvline(minFrq,c='k');ax1.axvline(maxFrq,c='k') - - ax2=fig.add_subplot(2,1,2, sharex = ax1) - ax2.grid(True) - ax2.xaxis.set_label_text('Frequency [Hz]') - ax2.yaxis.set_label_text('Phase [degree]') - - ftX=np.fft.rfft(x) - ftY=np.fft.rfft(y) - - fMax=.5/ts #fs=1/ts, fMax=1/2fs - n=ftX.shape[0] - f=np.arange(n)*fMax/(n-1) - - if mode&16: - i=int(minFrq*num*ts); j=int(maxFrq*num*ts); #print(w[i],w[j]) - f=f[i:j+1] - ftX=ftX[i:j+1] - ftY=ftY[i:j+1] - ftLst=[] - if mode&2: - ftLst.append((ftX,'b','input')) - if mode&4: - ftLst.append((ftY,'g','output')) - if mode&8: - ftLst.append((ftY/ftX,'r','out/inp')) - - for ft,c,s in ftLst: - phase=np.angle(ft) - phase=np.degrees(np.unwrap(phase)) - mag=np.abs(ft) #ftY)/np.abs(ftX) - if db: - magDb=20*np.log10(mag) #in decibel (20=10*2: factor 2 because rfft only half) - ax1.semilogx(f,magDb,c,label=s) # Bode magnitude plot - else: - ax1.semilogx(f, mag, c,label=s) # Bode magnitude plot - ax2.semilogx(f,phase,c,label=s) # Bode phase plot - ax2.set_ylim(-360,360) - ax2.legend() - plt.show(block=False) - if __name__=='__main__': #import logging @@ -768,6 +793,7 @@ if __name__=='__main__': def run_test(args): + dp=DebugPlot();dp.plot_gather();return #args.host=None if args.host is None: comm=gather=None @@ -791,14 +817,6 @@ if __name__=='__main__': #sp.gen_swissmx_points(width=1000,ofs=(-500,0)) #sp.gen_swissfel_points(width=1000,ofs=(-500,0)) #fn='/home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/PBMotionAnalyzer/records/mode1' - #fh=np.load(fn+'.npz') - #for k,v in fh.iteritems(): - # setattr(sp,k,v) - #sp.meta=sp.meta.item() - #sp.points=sp.pts; del sp.pts - #sp.plot_gather() - #return - fn='/tmp/shapepath' #fn='/home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/record/grid_delay_0002' # /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/record/chip000_sortedXXXX_9x9' #fn='/sf/bernina/data/p17592/res/20181203/imprints/chip000_preloc_min10um_sortedX_refs_goaround/chip000_sortedY_9x9.npz' @@ -806,37 +824,24 @@ if __name__=='__main__': #sp.setup_coord_trf() #sp.points=np.zeros((2,2)) - sp.meta={'timebase':.2} + sp.meta={'timebase':.2,'pt2pt_time':40} #sp.gather_upload(fnRec=fn+'.npz') - #sp.plot_gather() + #Tools.plot_gather(sp) #return xy=False #sp.gen_rand_points(n=14, scale=1000);sp.sort_points(xy=xy) #print(sp.points[:,0]) #sp.gen_swissmx_points(width=1000, ofs=(-500, 0)); - #sp.points=np.array([[0.,1.],[1.,0.],[0.,-1.],[-1.,0.]]) - #sp.points=np.array([[0.,1. ],[1. ,0.],[0.,-1. ],[-1. ,0.], - # [0., 1.], [1., 0.], [0., -1.], [-1., 0.], - # [0., 1.], [1., 0.], [0., -1.], [-1., 0.], - # [0., 1.], [1., 0.], [0., -1.], [-1., 0.], - # [0., 1.], [1., 0.], [0., -1.], [-1., 0.], - # ]) - # [0.,1.2],[1.2,0.],[0.,-1.2],[-1.2,0.], - # [0.,1.4],[1.4,0.],[0.,-1.4],[-1.4,0.], - # [0.,1.6],[1.6,0.],[0.,-1.6],[-1.6,0.], - # [0.,1.8],[1.8,0.],[0.,-1.8],[-1.8,0.], - # [0.,2. ],[2. ,0.],[0.,-2. ],[-2. ,0.], - # [0., 1.]]) - #sp.points*=100 #sp.gen_spiral_points(rStart=100,rInc=10,numSeg=4,numCir=60, ofs=(0, 0)) - sp.gen_spiral_points(rStart=100,rInc=20,numSeg=8,numCir=32, ofs=(0, 0)) + sp.gen_spiral_points(rStart=100,rInc=130,numSeg=4,numCir=2, ofs=(0, 0)) + #sp.gen_spiral_points(rStart=100,rInc=20,numSeg=8,numCir=32, ofs=(0, 0)) #sp.gen_closed_shifted() #sp.gen_grid_points(w=10,h=10,pitch=100,rnd=0,ofs=(0,0));sp.sort_points(False); #sp.gen_grid_points(w=1,h=10,pitch=100,rnd=0,ofs=(0,0)) - #sp.setup_motion(fnPrg=fn + '.prg', mode=1, pt2pt_time=40,scale=0) - #sp.setup_motion(fnPrg=fn + '.prg', mode=1, pt2pt_time=40,scale=1) + #sp.setup_motion(fnPrg=fn + '.prg', mode=1, scale=0) + #sp.setup_motion(fnPrg=fn + '.prg', mode=1, scale=1) #works: direct start #sp.setup_gather(acq_per=1) @@ -844,26 +849,26 @@ if __name__=='__main__': #works: simulated start and frame trigger no sync #sp.setup_gather(acq_per=1,sim=True) - #sp.setup_sync(mode=1,flag=3,pt2pt_time=40) + #sp.setup_sync(mode=1,flag=3) #works: simulated start and frame trigger with sync #sp.setup_gather(acq_per=1,sim=True) - #sp.setup_sync(mode=2,flag=3,pt2pt_time=40) + #sp.setup_sync(mode=2,flag=3) #works: simulated start real frame trigger no sync #sp.setup_gather(acq_per=1) - #sp.setup_sync(mode=1,flag=1,pt2pt_time=40) + #sp.setup_sync(mode=1,flag=1) #works: simulated start real frame trigger with sync sp.setup_gather(acq_per=1) - sp.setup_sync(mode=2,flag=1,pt2pt_time=40) + sp.setup_sync(mode=2,flag=1) sp.setup_coord_trf() # reset to shape path system - sp.setup_motion(fnPrg=fn + '.prg', mode=3, pt2pt_time=40,scale=1,dwell=10) - #sp.setup_motion(fnPrg=fn + '.prg', mode=1, pt2pt_time=40,scale=0,dwell=10) + sp.setup_motion(fnPrg=fn + '.prg', mode=3, scale=1,dwell=10) + #sp.setup_motion(fnPrg=fn + '.prg', mode=1, scale=0,dwell=10) sp.run() sp.gather_upload(fnRec=fn+'.npz') - sp.plot_gather(mode=11) + dp=DebugPlot(obj=sp);dp.plot_gather(mode=11) exit(0) # fn='/home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/data/'+time.strftime('%y-%m-%d-%H_%M_%S') @@ -896,77 +901,41 @@ if __name__=='__main__': #sp.setup_sync(mode=1) #sync with timing system (PROG) sp.setup_sync(mode=2) #sync with timing system and PLC to sync speed (PROG) sp.setup_coord_trf() # reset to shape path system - sp.setup_motion(fnPrg=fn + '.prg', mode=1, pt2pt_time=40) - #sp.gen_grid_points(w=2,h=2,pitch=50,rnd=.2);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=10,acq_per=1) - #sp.gen_swissmx_points(width=1000,ofs=(-500,0));sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40,acq_per=1) + sp.setup_motion(fnPrg=fn + '.prg', mode=1) + #sp.gen_grid_points(w=2,h=2,pitch=50,rnd=.2);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,acq_per=1) + #sp.gen_swissmx_points(width=1000,ofs=(-500,0));sp.setup_motion(fnPrg=fn+'.prg',mode=1,acq_per=1) - #sp.gen_grid_points(w=30,h=30,pitch=50,rnd=.2);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) - #sp.gen_grid_points(w=200,h=200,pitch=50,rnd=.2);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) + #sp.gen_grid_points(w=30,h=30,pitch=50,rnd=.2);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1) + #sp.gen_grid_points(w=200,h=200,pitch=50,rnd=.2);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1) - #sp.gen_grid_points(w=2,h=20,pitch=50,rnd=0);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=10,acq_per=1) - #sp.gen_rand_points(n=500, scale=1000);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=10,acq_per=1) - #sp.gen_grid_points(w=30,h=30,pitch=50,rnd=0.2);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) - #sp.gen_rand_points(n=400, scale=1000);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=10) + #sp.gen_grid_points(w=2,h=20,pitch=50,rnd=0);sp.setup_motion(fnPrg=fn+'.prg',mode=1,acq_per=1) + #sp.gen_rand_points(n=500, scale=1000);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,acq_per=1) + #sp.gen_grid_points(w=30,h=30,pitch=50,rnd=0.2);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,) + #sp.gen_rand_points(n=400, scale=1000);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1) - #sp.gen_swissmx_points(width=2000,flipx=True,flipy=True,ofs=(1014,-281));sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40,acq_per=1) - #sp.gen_grid_points(w=20,h=20,pitch=20,rnd=0,ofs=(-464,1754));sp.sort_points(True);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) - #sp.gen_grid_points(w=20,h=20,pitch=20,rnd=0,ofs=(-160,3700));sp.sort_points(False);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) - #sp.gen_grid_points(w=5,h=5,pitch=100,rnd=0,ofs=(-1590,-1070));sp.sort_points(False);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) - #sp.gen_grid_points(w=5,h=5,pitch=100,rnd=0,ofs=(-1580,-1070));sp.sort_points(False);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) - #sp.gen_grid_points(w=5,h=5,pitch=100,rnd=0,ofs=(-1580,-1060));sp.sort_points(False);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) - #sp.gen_grid_points(w=5,h=5,pitch=100,rnd=0,ofs=(-1590,-1060));sp.sort_points(False);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) + #sp.gen_swissmx_points(width=2000,flipx=True,flipy=True,ofs=(1014,-281));sp.setup_motion(fnPrg=fn+'.prg',mode=1) + #sp.gen_grid_points(w=20,h=20,pitch=20,rnd=0,ofs=(-464,1754));sp.sort_points(True);sp.setup_motion(fnPrg=fn+'.prg',mode=1) + #sp.gen_grid_points(w=20,h=20,pitch=20,rnd=0,ofs=(-160,3700));sp.sort_points(False);sp.setup_motion(fnPrg=fn+'.prg',mode=1) + #sp.gen_grid_points(w=5,h=5,pitch=100,rnd=0,ofs=(-1590,-1070));sp.sort_points(False);sp.setup_motion(fnPrg=fn+'.prg',mode=1) + #sp.gen_grid_points(w=5,h=5,pitch=100,rnd=0,ofs=(-1580,-1070));sp.sort_points(False);sp.setup_motion(fnPrg=fn+'.prg',mode=1) + #sp.gen_grid_points(w=5,h=5,pitch=100,rnd=0,ofs=(-1580,-1060));sp.sort_points(False);sp.setup_motion(fnPrg=fn+'.prg',mode=1) + #sp.gen_grid_points(w=5,h=5,pitch=100,rnd=0,ofs=(-1590,-1060));sp.sort_points(False);sp.setup_motion(fnPrg=fn+'.prg',mode=1) #>>>setup gather and sync<<< #sp.setup_gather() #sp.setup_sync() #>>>setup motion program<<< - #sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=10,acq_per=1) + #sp.setup_motion(fnPrg=fn+'.prg',mode=1) #>>>run gather and plot trajectory<<< #return sp.run() #trigger(0.5) sp.gather_upload(fnRec=fn+'.npz') - sp.plot_gather(mode=11) - - - # cfg={"points": [[100,523],[635,632],[756,213]],"sequencer":[sort_points,move_trj+')']} - #cfg={"sequencer":['gen_rand_points(n=107, scale=1000)',sort_points,move_trj+')']} - # cfg={"sequencer":['gen_grid_points(w=10,h=10,pitch=100,rnd=.2)',sort_points,move_trj+')']} - # cfg={"sequencer":['gen_grid_points(w=10,h=10,pitch=100,rnd=0.2)',sort_points,move_trj+')']} - # cfg = {"sequencer": ['gen_rand_points(n=107, scale=1000)', sort_points]} - # cfg={"sequencer":['gen_grid_points(w=20,h=20,pitch=50,rnd=.2)',sort_points,move_trj+')']} - # cfg={"sequencer":['gen_grid_points(w=20,h=20,pitch=50,rnd=.2)',sort_points,move_trj+')']} - # cfg={"sequencer":['gen_rand_points(n=400, scale=1000)',sort_points,move_trj+')']} - # cfg = {"sequencer": ['gen_grid_points(w=20,h=20,pitch=50,rnd=.2)', sort_points,move_trj+',mode=0)',]} - # cfg = {"sequencer": ['gen_grid_points(w=5,h=5,pitch=50,rnd=.2)', sort_points,move_trj+',mode=1)',]} - # cfg = {"sequencer": ['gen_grid_points(w=2,h=2,pitch=100,rnd=0)', sort_points,move_trj+',mode=0)',]} - # cfg = {"sequencer": ['gen_grid_points(w=5,h=5,pitch=100,rnd=0.2)', sort_points,move_trj+',mode=0)',]} - # cfg = {"points": [[0, 0],[100, 0],[200, 0],[300, 0],[400, 0],[400, 100],[300, 100],[200, 100],[100, 100],[0, 100],[10, 200],[100, 200],[200, 200],[300, 200],[400, 200],[410, 300],[300, 300],[200, 300],[100, 300],[0, 300],[0, 400],[100, 400],[200, 400],[300, 400],[400, 400]],"sequencer": [move_trj+',mode=0)',]} - # cfg = {"sequencer": ['gen_grid_points(w=2,h=2,pitch=10000,rnd=0)', sort_points,move_trj+',mode=-1)',]} - # cfg = {"sequencer": ['gen_grid_points(w=2,h=2,pitch=10000,rnd=0)', sort_points,move_trj+',mode=1,pt2pt_time=1000)',]} - # cfg = {"sequencer": ['gen_grid_points(w=20,h=20,pitch=50,rnd=0.2)', sort_points,move_trj+',mode=1,pt2pt_time=10,acq_per=10)',]} - # cfg = {"sequencer": ['gen_rand_points(n=400, scale=1000)', sort_points,move_trj+',mode=1,pt2pt_time=10)',]} - #cfg={"sequencer": ['gen_grid_points(w=40,h=40,pitch=100,rnd=0.4)', sort_points, - # move_trj+',mode=1,pt2pt_time=10,cnt=1)', - # ]} - - # 900npoints is a too big code block... and creates unfixable buffe locks - #cfg={"sequencer": ['gen_rand_points(n=5000, scale=100)', sort_points, - # move_trj+',mode=1,pt2pt_time=4,acq_per=10)', - # ]} - # cfg = {"sequencer": ['gen_swissfel_points(scale=300)',move_trj+',mode=1,pt2pt_time=100,acq_per=10)',]} - # cfg = {"sequencer": ['opt_pts("'+fn+'.npz")','move_trajectory(file="'+fn+'_corr.prg",mode=1,pt2pt_time=10,cnt=1)', ("'+fn+'_corr.npz")']} - # cfg = {"sequencer": ['opt_pts("'+fn+'.npz")',move_trj+',mode=1,pt2pt_time=10,cnt=1)']} - - # cfg = {"sequencer": ['gen_grid_points(w=5,h=5,pitch=100,rnd=0.4)', sort_points,move_trj+',mode=1,pt2pt_time=10,cnt=1)']} - - #cfg['sequencer'].append(gt_upld) - #cfg['sequencer'].append('plot_gather()') - + Tools.plot_gather(sp,mode=11) from optparse import OptionParser, IndentedHelpFormatter diff --git a/python/usr_code/Makefile b/python/usr_code/Makefile index f6b9a6e..24e55d4 100644 --- a/python/usr_code/Makefile +++ b/python/usr_code/Makefile @@ -20,7 +20,7 @@ #------------------------------------------------------------------------------ PPMAC=SAR-CPPM-EXPMX1 -PPMAC=MOTTEST-CPPM-CRM0573 +#PPMAC=MOTTEST-CPPM-CRM0573 #PPMAC=SAROP11-CPPM-MOT6871 PMAC_ARCH=ppc465-2 @@ -106,16 +106,35 @@ tags: find $(RTPMACINCLUDEDIR) -type f -iname "*.[chS]" | xargs ctags -a -f .tags -Debug: all +Debug: all install: all scp usralgo.ko root@$(PPMAC):/tmp scp /home/zamofing_t/Documents/prj/SwissFEL/PBTools/pbtools/usr_servo_phase/userservo_util root@$(PPMAC):/tmp - -ssh root@$(PPMAC) LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -d 9 + -ssh root@$(PPMAC) LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -d 1 + -ssh root@$(PPMAC) LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -d 2 -ssh root@$(PPMAC) rmmod usralgo -ssh root@$(PPMAC) insmod /tmp/usralgo.ko - -ssh root@$(PPMAC) LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -l 0 usr_servo_evr_tigger - -ssh root@$(PPMAC) LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -e 9 + gpasciiCommander --host $(PPMAC) -c 'Motor[1].Ctrl=Sys.ServoCtrl;Motor[2].Ctrl=Sys.ServoCtrl' + -ssh root@$(PPMAC) LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -l 1 obsvr_servo_ctrl_1 + -ssh root@$(PPMAC) LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -l 2 obsvr_servo_ctrl_2 + -ssh root@$(PPMAC) LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -e 1 + -ssh root@$(PPMAC) LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -e 2 + gpasciiCommander --host $(PPMAC) -c 'Motor[1].Ctrl=UserAlgo.ServoCtrlAddr[1];Motor[2].Ctrl=UserAlgo.ServoCtrlAddr[2]' + +#Motor[1].Ctrl +#UserAlgo.ServoCtrlAddr[1] +#Motor[1].Ctrl=Sys.PidCtrl +#Motor[1].Ctrl=UserAlgo.ServoCtrlAddr[1] +#Motor[2].Ctrl=Sys.ServoCtrl +#Motor[1].Ctrl=Sys.ServoCtrl +#>>>>>>>> DO THIS TO ACTIVATE SERVO <<<<<<<<<<< +#Motor[1].Ctrl=Sys.ServoCtrl +#Motor[2].Ctrl=Sys.ServoCtrl +#make install +#Motor[1].Ctrl=UserAlgo.ServoCtrlAddr[1] +#Motor[1].Ctrl=UserAlgo.ServoCtrlAddr[2] +#position 0.407 results in ca 0mA output #!common() @@ -130,9 +149,9 @@ install: all - #scp pp_proj.ini root@$(PPMAC):/var/ftp/usrflash/Project/Configuration/pp_proj.ini - #scp pp_proj.ini root@$(PPMAC):/tmp/pp_proj.ini - #ssh root@$(PPMAC) projpp +#scp pp_proj.ini root@$(PPMAC):/var/ftp/usrflash/Project/Configuration/pp_proj.ini +#scp pp_proj.ini root@$(PPMAC):/tmp/pp_proj.ini +#ssh root@$(PPMAC) projpp -#MotorData +#MotorData diff --git a/src/triggerSync/triggerSync.layout b/src/triggerSync/triggerSync.layout index 9eeaede..3d3f646 100644 --- a/src/triggerSync/triggerSync.layout +++ b/src/triggerSync/triggerSync.layout @@ -2,12 +2,12 @@ - + - + - + diff --git a/src/usrServo/Makefile b/src/usrServo/Makefile index 85b8a61..8a54f65 100644 --- a/src/usrServo/Makefile +++ b/src/usrServo/Makefile @@ -20,7 +20,7 @@ #------------------------------------------------------------------------------ PPMAC=SAR-CPPM-EXPMX1 -PPMAC=MOTTEST-CPPM-CRM0573 +#PPMAC=MOTTEST-CPPM-CRM0573 #PPMAC=SAROP11-CPPM-MOT6871 PMAC_ARCH=ppc465-2