www.gusucode.com > sl3ddemos工具箱matlab源码程序 > sl3ddemos/octavia_graphs.m

    function [sys, x0, str, ts, simStateCompliance] = octavia_graphs(t, ~, u, flag, ax, worldfile)
%OCTAVIA_GRAPHS S-function that displays a figure with virtual reality
%   canvas combined with three graphs.
%   This MATLAB function is designed to be used in a Simulink S-function block.
%   The S-function block inputs are displayed under the virtual canvas in
%   three graphs.
%   Block parameters define graph ranges and the associated virtual scene file.
%   It is expected that the same scene is driven by a VR Sink block
%   present in the same model.

%   Copyright 1998-2015 HUMUSOFT s.r.o. and The MathWorks, Inc.

% Store the block handle
blockHandle = gcbh;

switch flag

  % Initialization
  case 0
    [sys, x0, str, ts, simStateCompliance] = mdlInitializeSizes(ax);
    SetBlockCallbacks(blockHandle, worldfile);

  % Update
  case 2
    sys = mdlUpdate(t, u, ax, blockHandle);

  % Start
  case 'Start'
    LocalBlockStartFcn(blockHandle, worldfile)

  % Stop
  case 'Stop'
    LocalBlockStopFcn(blockHandle)

  % NameChange
  case 'NameChange'
    LocalBlockNameChangeFcn(blockHandle)

  % CopyBlock, LoadBlock
  case { 'CopyBlock', 'LoadBlock' }
    LocalBlockLoadCopyFcn(blockHandle)

  % DeleteBlock
  case 'DeleteBlock'
    LocalBlockDeleteFcn(blockHandle)

  % DeleteFigure
  case 'DeleteFigure'
    LocalFigureDeleteFcn();

  % Unused flags
  case { 3, 9 }
    sys = [];

  % Unexpected flags
  otherwise
     if ischar(flag)
       DAStudio.error('sl3d:demos:unhandledflag', flag);
     else
       DAStudio.error('sl3d:demos:unhandledflag', num2str(flag));
     end

end

% end switchyard



%=============================================================================
% mdlInitializeSizes
% Return the sizes, initial conditions, and sample times for the S-function.
%=============================================================================

function [sys, x0, str, ts, simStateCompliance] = mdlInitializeSizes(ax)

if length(ax)~=6
  DAStudio.error('sl3d:demos:axislimitsmustbedefined');
end

sizes = simsizes;
sizes.NumContStates  = 0;
sizes.NumDiscStates  = 0;
sizes.NumOutputs     = 0;
sizes.NumInputs      = 3;
sizes.DirFeedthrough = 0;
sizes.NumSampleTimes = 1;

sys = simsizes(sizes);

x0  = [];
str = [];
ts  = [-1 0];

% specify that the simState for this s-function is same as the default
simStateCompliance = 'DefaultSimState';

% end mdlInitializeSizes



%=============================================================================
% mdlUpdate
% Handle discrete state updates, sample time hits, and major time step
% requirements.
%=============================================================================

function sys = mdlUpdate(t, u, ~, block)

% always return empty, there are no states
sys = [];

% Locate the figure window associated with this block.  If it's not a valid
% handle (it may have been closed by the user), then return.
FigHandle = Get_3GFigure(block);
if ~ishandle(FigHandle)
   return;
end

% get UserData of the figure
ud = get(FigHandle, 'UserData');

if ~isnumeric(ud.G1_Line)    % HG2
  % plot the input lines
  addpoints(ud.G1_Line, t, u(1));
  addpoints(ud.G2_Line, t, u(2));
  addpoints(ud.G3_Line, t, u(3));

else                         % HG1
  % store data points to UserData
  if isempty(ud.XData)
    x_data  = [t t];
    y1_data = [u(1) u(1)];
    y2_data = [u(2) u(2)];
    y3_data = [u(3) u(3)];
  else
    x_data  = [ud.XData(end) t];
    y1_data = [ud.Y1Data(end) u(1)];
    y2_data = [ud.Y2Data(end) u(2)];
    y3_data = [ud.Y3Data(end) u(3)];
  end

  % plot the input lines
  set(ud.G1_Line, ...
      'Xdata', x_data, ...
      'Ydata', y1_data);

  set(ud.G2_Line, ...
     'Xdata', x_data, ...
     'Ydata', y2_data);

  set(ud.G3_Line, ...
     'Xdata', x_data, ...
     'Ydata', y3_data);

  % update the stored data points
  ud.XData(end+1)  = t;
  ud.Y1Data(end+1) = u(1);
  ud.Y2Data(end+1) = u(2);
  ud.Y3Data(end+1) = u(3);
  set(FigHandle, 'UserData', ud);

  % flush event queue
  drawnow;

end

% end mdlUpdate



%=============================================================================
% LocalBlockStartFcn
% Function that is called when the simulation starts.
% Initialize the figure.
%=============================================================================

function LocalBlockStartFcn(block, worldfile)

% get the figure associated with this block, create a figure if it doesn't
% exist
FigHandle = Get_3GFigure(block);
if ~ishandle(FigHandle)
  FigHandle = Create_3GFigure(block, worldfile);
end

% get UserData of the figure
ud = get(FigHandle, 'UserData');

% erase previously drawn lines (if any)
if ~isnumeric(ud.G1_Line)     % HG2
  clearpoints(ud.G1_Line);
  clearpoints(ud.G2_Line);
  clearpoints(ud.G3_Line);
else                          % HG1
  % allow to erase previously drawn lines (if any)
  set(ud.G1_Line, 'Erasemode', 'normal');
  set(ud.G2_Line, 'Erasemode', 'normal');
  set(ud.G3_Line, 'Erasemode', 'normal');

  % clear lines
  set(ud.G1_Line, 'XData', [], 'YData', []);
  set(ud.G2_Line, 'XData', [], 'YData', []);
  set(ud.G3_Line, 'XData', [], 'YData', []);

  % start at [0,0]; line will be appended in each simulation step
  set(ud.G1_Line, 'XData', 0, 'YData', 0, 'Erasemode', 'none');
  set(ud.G2_Line, 'XData', 0, 'YData', 0, 'Erasemode', 'none');
  set(ud.G3_Line, 'XData', 0, 'YData', 0, 'Erasemode', 'none');

  % erase data points stored in UserData
  ud.XData  = [];
  ud.Y1Data = [];
  ud.Y2Data = [];
  ud.Y3Data = [];
end

% set the graph ranges
set(ud.G1_Axes, 'YLim', evalin('base', get_param(block, 'y1range')));
set(ud.G2_Axes, 'YLim', evalin('base', get_param(block, 'y2range')));
set(ud.G3_Axes, 'YLim', evalin('base', get_param(block, 'y3range')));

set(FigHandle, 'UserData', ud);

% end LocalBlockStartFcn



%=============================================================================
% LocalBlockStopFcn
% At the end of the simulation, set the graph's data to contain
% the complete set of points that were acquired during the simulation.
% Recall that during the simulation, the lines are only small segments from
% the last time step to the current one.
%=============================================================================

function LocalBlockStopFcn(block)

FigHandle = Get_3GFigure(block);
if ishandle(FigHandle)

  % Get UserData of the figure.
  ud = get(FigHandle, 'UserData');

  % necessary for HG1 only
  if isnumeric(ud.G1_Line)
    set(ud.G1_Line, ...
        'Xdata', ud.XData, ...
        'Ydata', ud.Y1Data);

    set(ud.G2_Line, ...
        'Xdata', ud.XData, ...
        'Ydata', ud.Y2Data);

    set(ud.G3_Line, ...
        'Xdata', ud.XData, ...
        'Ydata', ud.Y3Data);
  end
end

% end LocalBlockStopFcn



%=============================================================================
% LocalBlockNameChangeFcn
% Function that handles name changes of the block.
%=============================================================================

function LocalBlockNameChangeFcn(block)

% get the figure associated with this block, if it's valid, change
% the name of the figure
FigHandle = Get_3GFigure(block);
if ishandle(FigHandle)
  set(FigHandle, 'Name', BlockFigureTitle(block));
end

% end LocalBlockNameChangeFcn



%=============================================================================
% LocalBlockLoadCopyFcn
% This is the block LoadFcn and CopyFcn. Initialize the block's
% UserData such that a figure is not associated with the block.
%=============================================================================

function LocalBlockLoadCopyFcn(block)

Set_3GFigure(block, -1);

% end LocalBlockLoadCopyFcn



%=============================================================================
% LocalBlockDeleteFcn
% This is the block DeleteFcn. Delete the block's figure window,
% if present, upon deletion of the block.
%=============================================================================

function LocalBlockDeleteFcn(block)

% Get the figure handle associated with the block, if it exists, delete
% the figure.
FigHandle = Get_3GFigure(block);
if ishandle(FigHandle)
  delete(FigHandle);
  Set_3GFigure(block, -1);
end

% end LocalBlockDeleteFcn



%=============================================================================
% LocalFigureDeleteFcn
% This is the figure DeleteFcn. The figure window is
% being deleted, update the block UserData to reflect the change.
%=============================================================================

function LocalFigureDeleteFcn()

% Get the block associated with this figure and set its figure to -1
ud = get(gcbf, 'UserData');
if ~isempty(ud)
  Set_3GFigure(ud.Block, -1);
end

% end LocalFigureDeleteFcn



%=============================================================================
% Get_3GFigure
% Retrieves the figure window associated with this S-function block
% from the block's parent subsystem's UserData.
%=============================================================================

function FigHandle = Get_3GFigure(block)

if strcmp(get_param(block, 'BlockType'), 'S-Function')
  block = get_param(block, 'Parent');
end

FigHandle = get_param(block, 'UserData');
if isempty(FigHandle)
  FigHandle = -1;
end

% end Get_3GFigure



%=============================================================================
% Set_3GFigure
% Stores the figure window associated with this S-function block
% in the block's parent subsystem's UserData.
%=============================================================================

function Set_3GFigure(block, FigHandle)

if strcmp(get_param(bdroot, 'BlockDiagramType'), 'model')
  if strcmp(get_param(block, 'BlockType'), 'S-Function')
    block = get_param(block, 'Parent');
  end

  set_param(block, 'UserData', FigHandle);
end

% end Set_3GFigure



%=============================================================================
% Create_3GFigure
% Creates the figure window associated with this S-function block.
%=============================================================================

function FigHandle = Create_3GFigure(block, worldfile)

% the figure doesn't exist, create one
FigHandle = figure('Units',          'pixels', ...
                   'Position',       [100 100 800 600], ...
                   'Color',          [0.314 0.314 0.314], ...
                   'Name',           BlockFigureTitle(block), ...
                   'Tag',            'octavia_graphs_fig', ...
                   'NumberTitle',    'off', ...
                   'IntegerHandle',  'off', ...
                   'Toolbar',        'none', ...
                   'DeleteFcn',      'octavia_graphs([], [], [], ''DeleteFigure'', [], [])');

% store the block handle in the figure UserData
ud.Block = block;

% the x-axis (time) range corresponds to the model Stop time
stoptime = str2double(get_param(bdroot, 'StopTime'));

% create the first graph in the figure
ud.G1_Axes = axes('Position', [0.05 0.1 0.28 0.25], ...
                  'XGrid',    'on', ...
                  'YGrid',    'on', ...
                  'Color',    'k', ...
                  'XColor',   'w', ...
                  'YColor',   'w', ...
                  'XLim',     [0 stoptime]);
set(ud.G1_Axes, 'Title', title('Speed [m/s]', 'Color', 'w'));
ud.XData = [];
ud.Y1Data = [];

% create the second graph in the figure
ud.G2_Axes = axes('Position', [0.37 0.1 0.28 0.25], ...
                  'XGrid',    'on', ...
                  'YGrid',    'on', ...
                  'Color',    'k', ...
                  'XColor',   'w', ...
                  'YColor',   'w', ...
                  'XLim',     [0 stoptime]);
set(ud.G2_Axes, 'Title', title('Longitudal acceleration [m/s^2]', 'Color', 'w'));
ud.XData = [];
ud.Y2Data = [];

% create the third graph in the figure
ud.G3_Axes = axes('Position', [0.69 0.1 0.28 0.25], ...
                  'XGrid',    'on', ...
                  'YGrid',    'on', ...
                  'Color',    'k', ...
                  'XColor',   'w', ...
                  'YColor',   'w', ...
                  'XLim',     [0 stoptime]);
set(ud.G3_Axes, 'Title', title('Lateral acceleration [m/s^2]', 'Color', 'w'));
ud.XData = [];
ud.Y3Data = [];

% draw the lines
try
  % try HG2 first
  ud.G1_Line = animatedline('Parent', ud.G1_Axes, ...
                            'Color', 'y', ...
                            'MaximumNumPoints', 5000);
  ud.G2_Line = animatedline('Parent', ud.G2_Axes, ...
                            'Color', 'y', ...
                            'MaximumNumPoints', 5000);
  ud.G3_Line = animatedline('Parent', ud.G3_Axes, ...
                            'Color', 'y', ...
                            'MaximumNumPoints', 5000);
catch
  % fallback to HG1 if not available
  ud.G1_Line = line(0, 0, 'Parent', ud.G1_Axes, 'EraseMode', 'None', 'Color', 'y', 'LineStyle', '-');
  ud.G2_Line = line(0, 0, 'Parent', ud.G2_Axes, 'EraseMode', 'None', 'Color', 'y', 'LineStyle', '-');
  ud.G3_Line = line(0, 0, 'Parent', ud.G3_Axes, 'EraseMode', 'None', 'Color', 'y', 'LineStyle', '-');
end

% open vrworld if not open already
mfilepath = fullfile(fileparts(get_param(bdroot(block), 'Filename')), worldfile);
if (exist(mfilepath, 'file') == 2)
  vr_world = vrworld(mfilepath);
else
  vr_world = vrworld(worldfile);
end
if ~isopen(vr_world)
  open(vr_world);
end
ud.vr_world = vr_world;

% create two canvases in the figure
vr.canvas(vr_world, 'Parent', FigHandle, ...
          'Units', 'normalized', ...
          'Position', [0.03 0.45 0.45 0.53]);
c2 = vr.canvas(vr_world, 'Parent', FigHandle, ...
               'Units', 'normalized', ...
               'Position', [0.52 0.45 0.45 0.53]);
set(c2, 'Viewpoint', 'View_Driver_Car1');

% Associate the figure with the block, and set the figure's UserData.
Set_3GFigure(block, FigHandle);
set(FigHandle, 'UserData', ud, 'HandleVisibility', 'callback');

% end Create_3GFigure



%=============================================================================
% BlockFigureTitle
% String for figure window title
%=============================================================================

function title = BlockFigureTitle(block)
  iotype = get_param(block, 'iotype');
  if strcmp(iotype, 'viewer')
    title = viewertitle(block, false);
  else
    title = get_param(block, 'Name');
  end

% end BlockFigureTitle



%=============================================================================
% SetBlockCallbacks
% This sets the callbacks of the block if it is not a reference.
%=============================================================================

function SetBlockCallbacks(block, worldfile)

% the actual source of the block is the parent subsystem
parent = get_param(block, 'Parent');

% set the callbacks for the block so that it has the proper functionality
callbacks = {
'CopyFcn',       'octavia_graphs([], [], [], ''CopyBlock'', [], [])'; ...
'DeleteFcn',     'octavia_graphs([], [], [], ''DeleteBlock'', [], [])'; ...
'LoadFcn',       'octavia_graphs([], [], [], ''LoadBlock'', [], [])'; ...
'StartFcn',      sprintf('octavia_graphs([], [], [], ''Start'', [], ''%s'')', worldfile); ...
'StopFcn'        'octavia_graphs([], [], [], ''Stop'', [], [])'; ...
'NameChangeFcn', 'octavia_graphs([], [], [], ''NameChange'', [], [])'; ...
};

for i=1:length(callbacks)
  if ~strcmp(get_param(parent, callbacks{i,1}), callbacks{i,2})
    set_param(parent, callbacks{i,:})
  end
end

% end SetBlockCallbacks