Számítógépes modellezés Házi Feladat Szabó Bálint JKA5SE 2009. január 25.
1. Feladat definiálása A feladat során egy mér rszer kiegészítéseként egy méréskiértékel és jegyz könyvkészít algoritmust kell készíteni. Mérés során rugóer tárolós fékmunkahengerek karakterisztikáit kell méréssel meghatározni. Ezek a fékmunkahengerek két kamrából állnak: üzemi és rögzít fék kamrából. A munkahenger karakterisztikái az alábbiak szerint néz ki: A nyomórúd löketének függvényében kell felvenni a nyomórúd által szolgáltatott er t. Az üzemi fékkamránál ez különböz nyomások mellett kell elvégezni, rögzít fék kamra esetében ez csak egy görbét jelent: 1. ábra: Rugóer tárolós fékmunkahengerek karakterisztikája
A mérés a következ képpen zajlott le. Az üzemi kamránál minden egyes löketpozíciónál rögzítettük az er t különböz nyomások mellett. Azaz minden egyes löketnél a következ függvényeket kapjuk: 12 10 Er [kn] Mért nyomás [bar] Löket [mm] Beállított nyomás [bar] 8 6 4 2 0-2 0 10 20 30 40 50 60 70 Id [s] 2. ábra: Mérés során egy adott löketnél felvett adatok Ezeket az adatsorokat egy MAT fájlban rögzítjük külön-külön, vagyis minden egyes löketet külön adatfájl tartalmaz. A rögzít fék kamra mérése manuális, így itt egy Excel tábla tartalmazza a lök rúd által biztosított er t a löket függvényében. A feladat során tehát egy olyan programot kell készíteni, amely az el re megadott MAT illetve Excel tábla adatait feldolgozza, elkészíti a karakterisztikát, és ebb l jegyz könyvet generál PDF formátumban. A feladat megoldásához még szükséges tudni a fájlok felépítését. A MAT fájl egy darab struktúra nev változót tartalmaz, amelynek neve az adott fájlnévvel megegyezik. A változó felépítése a következ :
Fájlnév.X.Data Fájlnév.Y(1,1).Data Fájlnév.Y(1,2).Data Fájlnév.Y(1,3).Data Fájlnév.Y(1,4).Data Az id értékeket tartalmazza [s] Er szenzor jeleit tartalmazza [N] Mért nyomásértékek [bar] Mért löketértékek [mm] El írt nyomásérték [bar] Ebb l a fájlból annyi van, ahány különböz löketnél megvizsgáltuk a munkahengert. Egy adatsor több különböz nyomásérték melletti mérést tartalmaz. A mérés során a löket közel állandó (persze a rszer rugalmassága miatt ez is változik kis mértékben) de a nyomások és a er jel lépcs zetesen változik (2.ábra). A rögzít fék adatsora egy Excel fájl tartalmazza. Az adatokat a Munka1 nev munkafüzet tartalmazza. Az els oszlop a löket a második pedig az er ket tartalmazza. 2. Feladat megoldása A készített program 6 fájlból áll: Testreport_v3.m Ez a f modulja az algoritmusnak, ezt kell futtatni Testreport_v3.fig A Matlab GUI fájlja reportmaker.m Ez a program végzi el a mérési adatok kiértékelését sorting_order_asc.m Az adatsorok sorrbe állításához kell repgen3.rpt Ez a fájl definiálja a jegyz könyv formátumát param.mat A paraméterértékeket tartalmazza a GUI-hoz
3. ábra: A program kezel felülete Az Actuator data részben kell megadni a fékmunkahenger azonosító adatait, amelyek majd a jegyz könyvben is szerepelnek. A Testing data részben néhány méréssel kapcsolatos adatot kell megadni illetve a feldolgozáshoz szükséges adatokat, mint például a fájl neve, a fájlok (vagyis a löketek) száma, illetve elérési útja. A What to create részben kell megadni, hogy a pdf formátumú jegyz könyv mellett milyen fájlokat hozzon még létre a program. A Create Report nyomógomb hatására a szoftver kiértékeli a mérési adatokat, és elkészíti a kért fájlokat. A Quit nyomógomb hatására a program bezárja az ablakot és elmenti a megadott paramétereket, hogy legközelebbi futtatáskor már ugyanezeket a paramétereket kínálja fel. 3. Az algoritmus m ködése 3.1 A f modul (Testreport_v3.m) A párbeszédablak megnyitásakor a következ parancsokat hajtja végre:
if exist('param.mat') == 2; load('param.mat'); else load('param0.mat'); handles.param = param; guidata(hobject,handles); A program legels futtatásakor az eredetileg definiált param0.mat fájlt tölti be, de ha már létezik a param.mat fájl, akkor ezt tölti be. Az ablak bezárásakor a következ kódot futtatja a program: param{1} = get(handles.ac_type,'string'); param{2} = get(handles.drw_nr,'string'); param{3} = get(handles.smp_nr,'string'); param{4} = get(handles.knorr_id,'string'); param{5} = get(handles.tester_name,'string '); param{6} = get(handles.testdate,'string'); param{7} = get(handles.filepath,'string'); param{8} = get(handles.filename,'string'); param{9} = get(handles.parkfile,'string'); param{10} = get(handles.numfiles,'string'); save('param.mat', 'param'); Vagyis a felhasználó által megadott paramétereket menti el a param.mat fájlba, amit következ futtatáskor tölt be. A Create Report nyomógomb lenyomásakor pedig a következ kódsorozat fut le: Az els sorok változókba töltik be a kért információkat: fn = get(handles.filename, 'string'); pn = get(handles.filepath, 'string'); nov = str2double(get(handles.numfiles, 'string')); pf = get(handles.parkfile, 'string'); dat_actype = get(handles.ac_type, 'string'); dat_drwnum = get(handles.drw_nr, 'string'); dat_sample = get(handles.smp_nr, 'string'); dat_knorrid = get(handles.knorr_id, 'string'); dat_tester = get(handles.tester_name, 'string'); dat_date = get(handles.testdate, 'string'); Ezután a kód futtatja a kiértékel algoritmust az üzemi fék adataira: [cylinderchar] = reportmaker(fn, pn, nov); np = length(cylinderchar{3,1});
A rögzít fék adatainak beolvasásához egy Excelfájlból kell adatokat inmportálni: parkdata = importdata([pn pf]); park_pos = parkdata.munka1(:,1); park_force = parkdata.munka1(:,2); cylinderchar{3,2} = parkdata.munka1; Majd a kapott adatok alapján elkészíti a karakterisztika diagramját: h = figure(1); hold on; for i = 1 : np; vec = cylinderchar{2,i}; plot(vec(:,1), vec(:,2)); t1 = find(abs(vec(:,1) - 30) < 1); t2 = vec(t1,2) + 250; text(30, t2, [num2str(cylinderchar{3,1}(i)) 'bar'], 'FontSize', 11); clear vec; plot(park_pos, park_force, '--'); grid on; xlabel('stroke [mm]', 'FontSize', 12); ylabel('force [N]', 'FontSize', 12); print(h,'-djpeg',which('char.jpg')); Végül elkészíti a jegyz könyvet, valamint a kért fájlokat: if exist([pn 'reports\']) ~= 7; mkdir(pn, 'reports\'); if (get(handles.c_jpg,'value') == get(handles.c_jpg,'max')); copyfile(which('char.jpg'),[pn 'reports\actuator_' dat_sample '_fig.jpg']); if (get(handles.c_mat,'value') == get(handles.c_mat,'max')); savename = [pn 'reports\actuator_' dat_sample '.mat']; save(savename, 'cylinderchar'); if (get(handles.c_xls,'value') == get(handles.c_xls,'max')); xlsname = [pn 'reports\actuator_' dat_sample '.xls']; for i = 1 : np; sheetname = ['pressure = ' num2str(cylinderchar{3,1}(i)) ' bar']; xlsdata{1,1} = 'Measured pressure:'; xlsdata{1,2} = cylinderchar{1,i}; xlsdata{1,3} = '[bar]'; xlsdata{3,1} = 'Position'; xlsdata{4,1} = '[mm]'; xlsdata{3,2} = 'Output force'; xlsdata{4,2} = '[N]'; for j = 1:nov; xlsdata{j+5,1} = cylinderchar{2,i}(j,1); xlsdata{j+5,2} = cylinderchar{2,i}(j,2); xlswrite(xlsname, xlsdata, sheetname); clear xlsdata;
xlspark{1,1} = 'Position [mm]'; xlspark{1,2} = 'Force [N]'; for j = 1:length(park_pos); xlspark{j+2,1} = park_pos(j,1); xlspark{j+2,2} = park_force(j,1); xlswrite(xlsname, xlspark, 'Parking Chamber'); table_1 = {'Actuator size: ' dat_actype; 'Drawing number: ' dat_drwnum; 'Knorr ID Number:' dat_knorrid; 'Sample number:' dat_sample}; table_2 = {'Measured by: ' dat_tester; 'Testing date: ' dat_date}; assignin('base','table_1', table_1); assignin('base','table_2', table_2); copyfile(which('haldex_logo.jpg'), [pn 'reports\haldex_logo.jpg']); report('repgen3.rpt',['-o' pn 'reports\actuator_' dat_sample '_v.pdf']); delete([pn 'reports\haldex_logo.jpg']); 3.2 Kiértékel algoritmus (reportmaker.m) A függvény a beolvasott adatfájl (struktúra típusú) neve, elérési útja és a fájlok száma ismeretében ad egy struktúra típusú változót eredményül, amely a feldolgozott adatokat tartalmazza: function [data_out] = reportmaker(filenamestring, pathstring, filenumber); A függvény els részében egy ciklus fut, amelynek ismétlési száma megegyezik a fájlok számával. Ezen belül a következ feladatokat végzi el: namindex = 1; for i = 1 : filenumber; is_err = 1; while is_err ~= 0; if (namindex < 10); filnam = [filenamestring '0' int2str(namindex) '.mat']; else filnam = [filenamestring int2str(namindex) '.mat']; filnamtot = [pathstring filnam]; if exist(filnamtot) == 0; is_err = 1; else is_err = 0; namindex = namindex + 1; assignin('base','filnamtot',filnamtot); evalin('base','load(filnamtot)'); varname = filnam(1:(length(filnam)-4));
res = evalin('base', varname); time = res.x.data; force = res.y(1,1).data; pres_is = res.y(1,2).data; position = res.y(1,3).data; pres_must = res.y(1,4).data; n = length(time); A fenti részben beolvassa az i-edik fájlt, és az egyes adatsorokat (id, er, mért és kért nyomás) külön-külön változókba menti el. Minden fájl több mérési pontot tartalmaz. Egy fájl azonos löket mellett több nyomásérték melletti mérési munkapontot tartalmaz. A következ részben egy újabb ciklus kezd dik a f cikluson belül, amelyben megkeressük az egyes nyomásértékekhez tartozó mérési adatsorok kezdetét és végét. Mivel az er mérés csak a nyomás stabilizálódását követ en kezd dött el, ezért az er mérés alapján történik a az egyes adatsorok kezdetének és végének azonosítása: k = 1; l = 1; for j = 2 : n; if (force(j) >= 0) & (force(j-1) < 0); start(k) = j; pres0(k) = pres_must(j+5); k = k + 1; if (force(j) < 0) & (force(j-1) >= 0); stop(l) = j; l = l + 1; ns = length(start); Az el z ekben az egyes munkapontokhoz tartozó adatsorokat gy jtöttük össze, ezt követ en pedig ezek átlagát számítjuk ki. Így ezután már minden egyes löketnél és nyomásértéknél relkezésünkre áll egy átlagos nyomás és er érték. err = 0; ns2 = ns; for j = 1 : ns; if j < ns; if pres0(j) < pres0(j+1); index = j - err; result.force(index,i) = mean(force(start(j):stop(j))); result.pres(index,i) = mean(pres_is(start(j):stop(j)));
pres(index) = pres0(j); else err = err + 1; ns2 = ns2-1; else index = j - err; result.force(index,i) = mean(force(start(j):stop(j))); result.pres(index,i) = mean(pres_is(start(j):stop(j))); pres(index) = pres0(j); result.pos(i) = mean(position(1:stop(ns))); clear res time force pres_is position pres_must start stop pres0; Ezt követ en löket szerint növekv sorrbe rezzük majd a kimen adatokat egy új változóba mentjük el: indvec = sorting_order_asc(result.pos); for i = 1 : ns2; val_p = 0; for j = 1 : filenumber; ind = indvec(j); vec_fp(j,2) = result.force(i,ind); vec_fp(j,1) = result.pos(ind); val_p = val_p + result.pres(i,ind); cylinderchar{2,i} = vec_fp; cylinderchar{1,i} = val_p / filenumber; clear vec_fp; cylinderchar{3,1} = pres; clear result; data_out = cylinderchar; 3.3 A változók sorba rezése (sorting_order_asc.m) function [index_order] = sorting_order_asc(input_vec); len = length(input_vec); output_vec = input_vec; ordvec = 1:len;
for i = 1 : len; [minval, minplace] = min(output_vec(i:len)); t1(1) = minval; t2(1) = ordvec(minplace+i-1); if minplace > 1; for j = (i+1) : (minplace + i - 1); t1(j) = output_vec(j-1); t2(j) = ordvec(j-1); output_vec((i+1):length(t1)) = t1((i+1):length(t1)); ordvec((i+1):length(t2)) = t2((i+1):length(t2)); output_vec(i) = t1(1); ordvec(i) = t2(1); clear t1 t2; index_order = ordvec;