function [sys,x0,str,ts] = metronomeAnimation(t,x,u,flag,runpause) %metronomeAnimation S-function for making pendulum animation. % % See also: PENDDEMO. % Copyright 1990-2002 The MathWorks, Inc. % $Revision: 1.21 $ % Plots every major integration step, but has no states of its own switch flag, %%%%%%%%%%%%%%%%%% % Initialization % %%%%%%%%%%%%%%%%%% case 0, [sys,x0,str,ts]=mdlInitializeSizes; %%%%%%%%%% % Update % %%%%%%%%%% case 2, sys=mdlUpdate(t,x,u,runpause); %%%%%%%%%%%%%%%% % Unused flags % %%%%%%%%%%%%%%%% case { 1, 3, 4, 9 }, sys = []; %%%%%%%%%%%%%%% % DeleteBlock % %%%%%%%%%%%%%%% case 'DeleteBlock', LocalDeleteBlock %%%%%%%%%%%%%%% % DeleteFigure % %%%%%%%%%%%%%%% case 'DeleteFigure', LocalDeleteFigure %%%%%%%%%% % Slider % %%%%%%%%%% case 'Slider', LocalSlider %%%%%%%%% % Close % %%%%%%%%% case 'Close', LocalClose %%%%%%%%%%%% % Playback % %%%%%%%%%%%% case 'Playback', LocalPlayback %%%%%%%%%%%%%%%%%%%% % Unexpected flags % %%%%%%%%%%%%%%%%%%%% otherwise error(['Unhandled flag = ',num2str(flag)]); end % end metronomeAnimation % %============================================================================= % mdlInitializeSizes % Return the sizes, initial conditions, and sample times for the S-function. %============================================================================= % function [sys,x0,str,ts]=mdlInitializeSizes % % call simsizes for a sizes structure, fill it in and convert it to a % sizes array. % sizes = simsizes; sizes.NumContStates = 0; sizes.NumDiscStates = 0; sizes.NumOutputs = 0; sizes.NumInputs = 2; sizes.DirFeedthrough = 1; sizes.NumSampleTimes = 1; sys = simsizes(sizes); % % initialize the initial conditions % x0 = []; % % str is always an empty matrix % str = []; % % initialize the array of sample times, for the pendulum demo, % the animation is updated every 0.1 seconds % ts = [0.1 0]; % % create the figure, if necessary % LocalPendInit; % end mdlInitializeSizes % %============================================================================= % mdlUpdate % Update the pendulum animation. %============================================================================= % function sys=mdlUpdate(t,x,u,runpause) fig = get_param(gcbh,'UserData'); if ishandle(fig), if strcmp(get(fig,'Visible'),'on'), ud = get(fig,'UserData'); LocalPendSets(t,ud,u,runpause); end end; sys = []; % end mdlUpdate % %============================================================================= % LocalDeleteBlock % The animation block is being deleted, delete the associated figure. %============================================================================= % function LocalDeleteBlock fig = get_param(gcbh,'UserData'); if ishandle(fig), delete(fig); set_param(gcbh,'UserData',-1) end % end LocalDeleteBlock % %============================================================================= % LocalDeleteFigure % The animation figure is being deleted, set the S-function UserData to -1. %============================================================================= % function LocalDeleteFigure ud = get(gcbf,'UserData'); set_param(ud.Block,'UserData',-1); % end LocalDeleteFigure % %============================================================================= % LocalSlider % The callback function for the animation window slider uicontrol. Change % the reference block's value. %============================================================================= % function LocalSlider ud = get(gcbf,'UserData'); % end LocalSlider % %============================================================================= % LocalClose % The callback function for the animation window close button. Delete % the animation figure window. %============================================================================= % function LocalClose delete(gcbf) % end LocalClose % %============================================================================= % LocalPlayback % The callback function for the animation window playback button. Playback % the animation. %============================================================================= % function LocalPlayback % % first find the animation data in the base workspace, issue an error % if the information isn't there % t = evalin('base','t','[]'); y = evalin('base','y','[]'); if isempty(t) | isempty(y), errordlg(... ['You must first run the simulation before '... 'playing back the animation.'],... 'Animation Playback Error'); end % % playback the animation, note that the playback is wrapped in a try-catch % because is it is possible for the figure and it's children to be deleted % during the drawnow in LocalPendSets % try ud = get(gcbf,'UserData'); for i=1:length(t), LocalPendSets(t(i),ud,y(i,:)); end end % end LocalPlayback % %============================================================================= % LocalPendSets % Local function to set the position of the graphics objects in the % inverted pendulum animation window. %============================================================================= % function LocalPendSets(time,ud,u,runpause) u = u([1 2]); XDelta = 2; PDelta = 0.2; XPendTop = u(1) + 10*sin(u(2)); YPendTop = 10*cos(u(2)); PDcosT = PDelta*cos(u(2)); PDsinT = -PDelta*sin(u(2)); set(ud.Cart,... 'XData',ones(2,1)*[u(1)-XDelta u(1)+XDelta]); set(ud.Pend,... 'XData',[XPendTop-PDcosT XPendTop+PDcosT; u(1)-PDcosT u(1)+PDcosT], ... 'YData',[YPendTop-PDsinT YPendTop+PDsinT; -PDsinT PDsinT]); set(ud.TimeField,... 'String',num2str(time)); % set(ud.RefMark,... % 'XData',u(1)+[-XDelta 0 XDelta]); % Force plot to be drawn if runpause pause(.10) drawnow end % end LocalPendSets % %============================================================================= % LocalPendInit % Local function to initialize the pendulum animation. If the animation % window already exists, it is brought to the front. Otherwise, a new % figure window is created. %============================================================================= % function LocalPendInit % % The name of the reference is derived from the name of the % subsystem block that owns the pendulum animation S-function block. % This subsystem is the current system and is assumed to be the same % layer at which the reference block resides. % sys = get_param(gcs,'Parent'); TimeClock = 0; RefSignal = 0; XCart = 0; Theta = 0; XDelta = 2; PDelta = 0.2; XPendTop = XCart + 10*sin(Theta); % Will be zero YPendTop = 10*cos(Theta); % Will be 10 PDcosT = PDelta*cos(Theta); % Will be 0.2 PDsinT = -PDelta*sin(Theta); % Will be zero % % The animation figure handle is stored in the pendulum block's UserData. % If it exists, initialize the reference mark, time, cart, and pendulum % positions/strings/etc. % Fig = get_param(gcbh,'UserData'); if ishandle(Fig), FigUD = get(Fig,'UserData'); % set(FigUD.RefMark,... % 'XData',RefSignal+[-XDelta 0 XDelta]); set(FigUD.TimeField,... 'String',num2str(TimeClock)); set(FigUD.Cart,... 'XData',ones(2,1)*[XCart-XDelta XCart+XDelta]); set(FigUD.Pend,... 'XData',[XPendTop-PDcosT XPendTop+PDcosT; XCart-PDcosT XCart+PDcosT],... 'YData',[YPendTop-PDsinT YPendTop+PDsinT; -PDsinT PDsinT]); % % bring it to the front % figure(Fig); return end % % the animation figure doesn't exist, create a new one and store its % handle in the animation block's UserData % FigureName = 'Metronome Visualization'; Fig = figure(... 'Units', 'pixel',... 'Position', [100 100 500 300],... 'Name', FigureName,... 'NumberTitle', 'off',... 'IntegerHandle', 'off',... 'HandleVisibility','callback',... 'Resize', 'off',... 'DeleteFcn', 'metronomeAnimation([],[],[],''DeleteFigure'')',... 'CloseRequestFcn', 'metronomeAnimation([],[],[],''Close'');'); AxesH = axes(... 'Parent', Fig,... 'Units', 'pixel',... 'Position',[50 50 400 200],... 'CLim', [1 64], ... 'Xlim', [-12 12],... 'Ylim', [-2 10],... 'Visible', 'off'); Cart = surface(... 'Parent', AxesH,... 'XData', ones(2,1)*[XCart-XDelta XCart+XDelta],... 'YData', [0 0; -2 -2],... 'ZData', zeros(2),... 'CData', ones(2),... 'EraseMode','xor'); Pend = surface(... 'Parent', AxesH,... 'XData', [XPendTop-PDcosT XPendTop+PDcosT; XCart-PDcosT XCart+PDcosT],... 'YData', [YPendTop-PDsinT YPendTop+PDsinT; -PDsinT PDsinT],... 'ZData', zeros(2),... 'CData', 11*ones(2),... 'EraseMode','xor'); % RefMark = patch(... % 'Parent', AxesH,... % 'XData', RefSignal+[-XDelta 0 XDelta],... % 'YData', [-2 0 -2],... % 'CData', 22); uicontrol(... 'Parent', Fig,... 'Style', 'text',... 'Units', 'pixel',... 'Position',[0 0 500 50]); uicontrol(... 'Parent', Fig,... 'Style', 'text',... 'Units', 'pixel',... 'Position', [150 0 100 25], ... 'HorizontalAlignment','right',... 'String', 'Time: '); TimeField = uicontrol(... 'Parent', Fig,... 'Style', 'text',... 'Units', 'pixel', ... 'Position', [250 0 100 25],... 'HorizontalAlignment','left',... 'String', num2str(TimeClock)); % SlideControl = uicontrol(... % 'Parent', Fig,... % 'Style', 'slider',... % 'Units', 'pixel', ... % 'Position', [100 25 300 22],... % 'Min', -9,... % 'Max', 9,... % 'Value', RefSignal,... % 'Callback', 'metronomeAnimation([],[],[],''Slider'');'); uicontrol(... 'Parent', Fig,... 'Style', 'pushbutton',... 'Position',[415 15 70 20],... 'String', 'Close', ... 'Callback','metronomeAnimation([],[],[],''Close'');'); % uicontrol(... % 'Parent', Fig,... % 'Style', 'pushbutton',... % 'Position',[15 15 70 20],... % 'String', 'Playback', ... % 'Callback','metronomeAnimation([],[],[],''Playback'');',... % 'Interruptible','off',... % 'BusyAction','cancel'); % set(RefMark,'EraseMode','xor'); % % all the HG objects are created, store them into the Figure's UserData % FigUD.Cart = Cart; FigUD.Pend = Pend; FigUD.TimeField = TimeField; % FigUD.SlideControl = SlideControl; % FigUD.RefMark = RefMark; FigUD.Block = get_param(gcbh,'Handle'); set(Fig,'UserData',FigUD); drawnow % % store the figure handle in the animation block's UserData % set_param(gcbh,'UserData',Fig); % end LocalPendInit