KerMor  0.9
Model order reduction for nonlinear dynamical systems and nonlinear approximation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Model.m
Go to the documentation of this file.
1 namespace models{
2 namespace golf{
3 
4 
5 /* (Autoinserted by mtoc++)
6  * This source code has been filtered by the mtoc++ executable,
7  * which generates code that can be processed by the doxygen documentation tool.
8  *
9  * On the other hand, it can neither be interpreted by MATLAB, nor can it be compiled with a C++ compiler.
10  * Except for the comments, the function bodies of your M-file functions are untouched.
11  * Consequently, the FILTER_SOURCE_FILES doxygen switch (default in our Doxyfile.template) will produce
12  * attached source files that are highly readable by humans.
13  *
14  * Additionally, links in the doxygen generated documentation to the source code of functions and class members refer to
15  * the correct locations in the source code browser.
16  * However, the line numbers most likely do not correspond to the line numbers in the original MATLAB source files.
17  */
18 
19 class Model
20  :public models.BaseModel {
39  public:
40 
41  rad_ball = 0.021;
50  rad_hole = 0.054;
51 
52 
53  detail = 0.02;
62  vmin = 0.03;
63 
64 
66 
68 
70 
71 
72  private:
73 
74  HX_;
75 
76  HY_;
77 
78  HZ_;
79 
80 
81  private: /* ( Transient ) */
82 
83  tx_ball;
84 
85  tx_rasen;
86 
87 
88  public: /* ( Transient ) */
89 
90  Model(greenfile) {
91  if nargin < 1
92  greenfile = " bsp4 ";
93  end
94  this.tx_ball= imread(fullfile(fileparts(mfilename(" fullpath "))," tx_golfball.png "));
95 /* this.tx_ball = imread(fullfile(fileparts(mfilename('fullpath')),'tx_golfball_falschrum.png')); */
96  this.tx_rasen= imread(fullfile(fileparts(mfilename(" fullpath "))," tx_rasen.png "));
97 
98  this.T= 20;
99  this.dt= 0.04;
100 
101  this.System= models.golf.System(this);
102 
103  this.ODESolver= solvers.MLode15i;
104 
105  this.loadGreen(greenfile);
106  }
107 
108 
109  function [doublet , colvec<double>x , doublectime ] = computeTrajectory(colvec<double> mu,integer inputidx) {
110  if isa(this.ODESolver," solvers.MLWrapper ")
111  opt = this.ODESolver.odeopts;
112  opt.OutputFcn= @this.ODE_Callback;
113  this.ODESolver.odeopts= opt;
114  else
115  error(" Not working with non-MatLab solver wrappers. ");
116  end
117  [t, x, ctime] = computeTrajectory@models.BaseModel(this, mu, inputidx);
118  }
119 
120 
121  function status = ODE_Callback(double t,matrix<double> y,flag) {
122  status = 0;
123  if isempty(flag)
124  /* For cases with more than one computed state */
125  y = y(:,end);
126 
127  x = y(1:2);
128  v = y(3:4);
129 
130  /* Area check */
131  area = this.Green.area;
132  status = status || ...
133  ~(x(1)<=area(2) && x(1)>=area(1)) && (x(2)<=area(4) && x(2)>=area(3));
134 
135  /* Prüft, ob der Ball "über dem Loch schwebt" und langsam genug ist, um
136  * herein gefallen zu sein */
137  sys = this.System;
138  mu = sys.mu;
139  status = status || ...
140  ((norm(v) < sys.maxvforhole) && (norm(x-mu(5:6))<this.rad_hole));
141 
142  /* Prüft, ob der Ball noch schnell genug ist.
143  * Dabei muss beachtet werden, dass der Ball sich nicht an einem Hang
144  * befindet, er konnte dort während einer Umkehr sehr langsam werden.
145  * Dies indiziert der Gradient, der normiert auf ebener Fläche klein ist. */
146  gradient = this.gradgreen(x);
147  status = status || ...
148  ~((norm(v) > this.vmin) || (norm(gradient) > 0.040));
149  end
150  if status
151  a = 5;
152  end
153  }
154 
155 
156  function loadGreen(filename) {
157  if nargin < 2
158  filename = fullfile(fileparts(mfilename(" fullpath "))," default.mat ");
159  elseif exist(filename," file ") ~= 2
160  filename_ = fullfile(fileparts(mfilename(" fullpath ")),filename);
161  if exist(filename_," file ") == 2
162  filename = filename_;
163  else
164  filename_ = fullfile(fileparts(mfilename(" fullpath ")),[filename " .mat "]);
165  if exist(filename_," file ") == 2
166  filename = filename_;
167  else
168  error(" Invalid file name: %s ",filename);
169  end
170  end
171  end
172 
173  s = load(filename);
174  g = struct;
175  a = s.(" area ");
176  g.area= a;
177  g.hills= s.(" hills ");
178 
179  /* Set params to default parameter values */
180  h = s.(" hole ");
181  this.DefaultMu(5:6) = h(1:2);
182  p = s.(" params ");
183  this.DefaultMu(1:4) = p(:);
184  this.Green= g;
185 
186  /* Das Loch grafisch erzeugen */
187  phi = linspace(0,2*pi,50);
188  theta = linspace(0,pi,50);
189  [PHI,THETA]=meshgrid(phi,theta);
190  this.HX_= sin(THETA).*cos(PHI);
191  this.HY_= sin(THETA).*sin(PHI);
192  }
200  function z = green(colvec<double> x,matrix<double> y) {
201  hills = this.Green.hills;
202  z = 0;
203  for numhill = 1:size(hills,1)
204  rad = -log(0.05)/hills(numhill,4)^2;
205  z = z + hills(numhill,3) * exp(-((x-hills(numhill,1)).^2 +(y-hills(numhill,2)).^2)*rad);
206  end
207  }
218  function dx = gradgreen(colvec<double> x) {
219  h = sqrt(eps);
220  hlp = this.green(x(1),x(2));
221  dx = 1/h*[this.green(x(1)+h,x(2))-hlp ; this.green(x(1),x(2)+h)-hlp];
222  }
232  function map = golfcolormap() {
233  steps = 200;
234  /* Erste Farbe: Schwarz für das Loch! */
235  map([1 2 3]) = [0 0 0];
236  /* Zweite Farbe: Verlauf für das Rasengrün! */
237  map = [map; [zeros(steps+1,1) (0:1/steps:1)^t zeros(steps+1,1)] ];
238  /* Zweite Farbe: Verlauf für den Golfball!
239  *map = [map; [(0:1/steps:1)' (0:1/steps:1)' (0:1/steps:1)']]; */
240  }
241 
242 
243  function ax = initPlot(pm) {
244 
245  mu = this.System.mu;
246 
247  /* % Init hole plotting */
248  HX = mu(5) + this.rad_hole*this.HX_;
249  HY = mu(6) + this.rad_hole*this.HY_;
250  HZ = this.green(HX,HY);
251  /* Loch als horizontale Kreisfläche
252  * HZ = ones(size(HX))*hz); */
253 
254  /* % */
255  ax = pm.nextPlot(" golf "," Trace of golf ball "," [x] = m "," [y] = m ");
256  /* ,'Position',[100 100 640 480] */
257  set(gcf," Name "," Modellierung "," Renderer "," opengl ");
258 
259  /* Grünfläche zeichnen */
260  a = this.Green.area;
261  [x,y] = meshgrid(a(1):this.detail:a(2),...
262  a(3):this.detail:a(4));
263  z = this.green(x,y);
264  hGreen = surfl(ax,x,y,z);
265  colormap(this.golfcolormap);
266  hold(ax," on ");
267 
268  /* Lichteffekte */
269  set(hGreen," AmbientStrength ",.75);
270  light(" Position ",[0 0 5]," Style "," local ");
271  set(hGreen," FaceLighting "," phong "," AmbientStrength ",1)
272 
273  /* Rasentextur - Sehr langsam!
274  * hGreenTex = surfl(ax,x,y,z+0.005);
275  * set(hGreenTex,'CDATA',this.tx_rasen,'FaceColor','texturemap','FaceAlpha',.3); */
276 
277  /* Loch ins Grün einzeichnen (ein bisschen anheben, damit die grafiken sich
278  * nicht überschneiden .. */
279  hHole = surfl(ax,HX,HY,HZ+0.01);
280  /* Lochfarbe schwarz setzen */
281  set(hHole," CData ",0," FaceColor "," texturemap ");
282 
283  shading flat;
284  daspect(ax,[1 1 1]);
285  }
296  function plot(double t,matrix<double> y,pm) {
297  if nargin < 4
298  pm = PlotManager;
299  pm.LeaveOpen= true;
300  end
301 
302  ax = this.initPlot(pm);
303  withline = true;
304 
305  /* makevideo = false;
306  * video_folder = 'Video\';
307  *
308  * if makevideo
309  * set(hFigure,'DoubleBuffer','on'); % fps anpassen!
310  * mov = avifile(strcat(video_folder,'output.avi'),'compression','None','fps',round(1/t));
311  * end */
312 
313  oldgr = this.green(y(1,1),y(2,1));
314 
315  /* Ballumfang berechnen */
316  ball_circ = 2*pi*this.rad_ball;
317  /* Startoffset bestimmen */
318  oldoffset = [-this.gradgreen([y(1,1) y(2,1)]); 1];
319  oldoffset = this.rad_ball * oldoffset / norm(oldoffset);
320 
321  /* Ball am anfang einmal zeichnen */
322  [BX,BY,BZ] = sphere(50);
323  hBall = surfl(ax,this.rad_ball*BX + y(1,1)+oldoffset(1),...
324  this.rad_ball * BY + y(2,1)+oldoffset(2),...
325  this.rad_ball* BZ + oldgr +oldoffset(3));
326  /* s = size(get(hBall,'CDATA'));
327  * [xg,yg] = meshgrid(-1:2/(s(1)-1):1);
328  * col = .5*exp(-(xg.^2+yg.^2));
329  * col = min(min(get(hBall,'CDATA'))) + col*(max(max(get(hBall,'CDATA')))/max(max(col)));
330  * Textur für den Ball */
331  set(hBall," CDATA ",this.tx_ball," FaceColor "," texturemap ");
332  shading flat;
333  zoom reset;
334 
335  dt = this.dt;
336  for index = 2:size(y,2)
337 
338  /* Einmal die Höhe berechnen */
339  gr = this.green(y(1,index),y(2,index));
340 
341  /* Verschiebung bestimmen */
342  rel_move = [y(1,index)-y(1,index-1); y(2,index)-y(2,index-1); gr-oldgr];
343 
344  /* Richtung des Balles
345  * Die Rotationsschse ist senkrecht zur Bewegungsrichtung */
346  rot_axis = [-rel_move(2) rel_move(1) 0];
347 
348  if withline
349  plot3([y(1,index-1)+0.01 y(1,index)+0.01], [y(2,index-1)+0.01 y(2,index)+0.01], [oldgr+0.01 gr+0.01], " r ");
350  end
351  /* g = 9.81;
352  * gradi = grad(sol(:,index));
353  * nor = [gradi; -1];
354  * nor = nor/norm(nor);
355  * fn = nor * -g*nor(3);
356  * fb = [0; 0; -g] - fn;
357  * Gradienten
358  * plot3([sol(1,index) sol(1,index)+gradi(1)], [sol(2,index) sol(2,index)+gradi(2)], [gr gr], 'r');
359  * Normale
360  * plot3([sol(1,index) sol(1,index)+nor(1)], [sol(2,index) sol(2,index)+nor(2)], [gr gr+nor(3)], 'r');
361  * Normalenkraft
362  * plot3([sol(1,index) sol(1,index)+fn(1)], [sol(2,index) sol(2,index)+fn(2)], [gr gr+fn(3)], 'b');
363  * Hangabtriebskraft
364  * plot3([sol(1,index) sol(1,index)+fb(1)], [sol(2,index) sol(2,index)+fb(2)], [gr gr+fb(3)], 'y');
365  * Zeichnet die Drehachsen
366  * plot3([sol(1,index) rot_axis(1)+sol(1,index)],[sol(2,index) rot_axis(2)+sol(2,index)],[gr gr]+.5,'w'); */
367 
368  /* Korrekte Positionierung zum Untergrund, der Ball */
369  offset = [-this.gradgreen([y(1,index) y(2,index)]); 1];
370  offset = this.rad_ball * offset / norm(offset);
371 
372  /* Korrigierten Verschiebungsvektor bestimmen
373  * (Altes Offset weg, verschieben, neues Offset drauf */
374  absmove = rel_move-oldoffset+offset;
375 
376  /* Verschiebung der Daten vornehmen */
377  set(hBall," XData ",get(hBall," XData ")+absmove(1));
378  set(hBall," YData ",get(hBall," YData ")+absmove(2));
379  set(hBall," ZData ",get(hBall," ZData ")+absmove(3));
380 
381  /* Entspricht Drehung des Balles um Winkel alpha */
382  alpha = 360 * norm(rot_axis)/ball_circ;
383  /* Zentrum der Drehung festlegen */
384  center = [y(1,index)+offset(1) y(2,index)+offset(2) gr+offset(3)];
385 
386  /* Ball drehen! */
387  rotate(hBall,rot_axis,alpha,center);
388 
389  oldgr = gr;
390  oldoffset = offset;
391 
392  /* Beschriftung */
393  title(strcat(" Zeit: ",num2str(t(index))," s, v= ",num2str(norm((y(:,index)-y(:,index-1))*1/dt))," m/s "));
394 
395 /* if makevideo
396  * mov = addframe(mov,getframe(hFigure));
397  * % Erzeugt einzelne Dateien
398  * % print(hFigure,'-djpeg95',strcat(video_folder,'frame',num2str(v),'.jpg'));
399  * else */
400  pause(dt);
401 /* end */
402 
403  if ~ishandle(ax)
404  return;
405  end
406  end
407  hold(ax," off ");
408 /* if makevideo
409  * close(mov);
410  * end */
411  }
421  public: /* ( Static ) */ /* ( Transient ) */
422 
423  static function res = test_Golf() {
424  m = models.golf.Model(" 4_2 ");
425  [t,y] = m.simulate;
426  m = models.golf.Model(" 4_3 ");
427  [t,y] = m.simulate;
428  m = models.golf.Model(" 4_4 ");
429  [t,y] = m.simulate;
430  m = models.golf.Model(" 4_5 ");
431  [t,y] = m.simulate;
432 
433  m = models.golf.Model(" bsp1 ");
434  [t,y] = m.simulate;
435  m = models.golf.Model(" bsp2 ");
436  [t,y] = m.simulate;
437  m = models.golf.Model(" bsp3 ");
438  [t,y] = m.simulate;
439  m = models.golf.Model(" bsp4 ");
440  [t,y] = m.simulate;
441 
442  m = models.golf.Model;
443  [t,y] = m.simulate;
444  m.plot(t,y);
445  res = true;
446  }
447 
448 
449 };
450 }
451 }
452 
function loadGreen(filename)
LOADGREEN Loads a stored golf setting.
Definition: Model.m:156
BaseModel: Base class for both full and reduced models.
Definition: BaseModel.m:18
double dt
The desired time-stepsize for simulations.
Definition: BaseModel.m:291
static function res = test_Golf()
Definition: Model.m:423
models.BaseFirstOrderSystem System
The actual dynamical system used in the model.
Definition: BaseModel.m:102
function dx = gradgreen(colvec< double > x)
Gradient von g.
Definition: Model.m:218
rad_ball
Golfballradius in Meter gut: 0.015 m (42mm Durchmesser von Wikipedia)
Definition: Model.m:41
An integer value.
Model:
Definition: Model.m:19
PlotManager: Small class that allows the same plots generated by some script to be either organized a...
Definition: PlotManager.m:17
function [ double t , colvec< double > x , double ctime ] = computeTrajectory(colvec< double > mu,integer inputidx)
Definition: Model.m:109
logical LeaveOpen
Flag indicating if the plots should be left open once the PlotManager is deleted (as variable) ...
Definition: PlotManager.m:213
System:
Definition: System.m:19
System(models.BaseFullModel model)
Definition: System.m:46
solvers.BaseSolver ODESolver
The solver to use for the ODE. Must be an instance of any solvers.BaseSolver subclass.
Definition: BaseModel.m:315
mu
The current parameter for simulations, [] is none used.
double T
The final timestep up to which to simulate.
Definition: BaseModel.m:271
function status = ODE_Callback(double t,matrix< double > y, flag)
Definition: Model.m:121
Model(greenfile)
Definition: Model.m:90
colvec< double > DefaultMu
The default parameter value if none is given.
Definition: BaseModel.m:355
function map = golfcolormap()
Definition: Model.m:232
function ax = initPlot(pm)
Plotgreen: Zeichnet das Putting-Green und das zugehörige Loch.
Definition: Model.m:243
detail
Geländeauflösung.
Definition: Model.m:53
function z = green(colvec< double > x,matrix< double > y)
Green - Erzeugt eine Hügellandschaft mit gegebenen Parametern.
Definition: Model.m:200
function plot(double t,matrix< double > y, pm)
global rad_ball BX BY BZ t hFigure sol;% hBall;
Definition: Model.m:296