## Mike on MATLAB GraphicsGraphics & Data Visualization

Note

Mike on MATLAB Graphics has been retired and will not be updated.

# Using MATLAB Graphics from Simulink

Today we're going to take a break from the math behind parametric curves and take a look at using MATLAB Graphics from Simulink.

Combining MATLAB Graphics with Simulink is a very powerful technique for visualizing simulations, but it can be hard to figure out how to get started. Today we’re going to work through a simple example. We’ll start with double pendulum example that Guy Rouleau built as a benchmark for his blog post about SimMechanics. You can get it from the File Exchange.

We're going to modify it so that it creates a figure window which shows the pendulum animating while the simulation runs.

We'll do this in two steps. First we'll create a MATLAB class which implements all of the graphics. Next we'll use that class from Simulink. The reason for doing it in two steps is that it makes it easier to debug the graphics before we start integrating it with Simulink.

### Contents

#### Creating the parts of the visualization

If you look at the picture above, you can see that we need three parts to represent the pendulum, and two objects to represent the traces.

The traces are easy. That’s exactly what the new animatedline object is for.

trace1 = animatedline('Color', 'red');
trace2 = animatedline('Color', 'green');


The blue anchor point is also pretty easy. It’s just the punchline of a very old MATLAB graphics joke:

How do you draw a circle in MATLAB?

The answer is the rectangle command, of course! If we call the rectangle function with a Curvature property, it will round the corners off. If the value of the Curvature is [1 1], then the corners will be completely rounded off, and we'll get a circle!

circle = rectangle('Curvature',[1 1]);
r = .5;
circle.Position = [-r/2, -r/2, r, r];
circle.EdgeColor = 'none';
circle.FaceColor = 'blue';
axis equal
xlim([-2.5 2.5])


The arms are a little trickier. When they’re hanging down, we can draw them using two rectangles (one of which is really a circle), but we're going to want them to swing. The hgtransform object is the solution to that. The hgtransform object has a Matrix property which we can use to move its children around.

Here's a simple function which shows how to create an arm from an hgtransform and two rectangles.

%
% File: createArm.m
%
function p = createArm(w, r, len, col)
% Creates the geometry for one pendulum.
p = hgtransform;
l = rectangle('Parent',p);
l.Position = [-w/2, -len, w, len];
l.FaceColor = col;
l.EdgeColor = 'none';
c = rectangle('Parent',p,'Curvature',[1 1]);
c.Position = [-r/2, -(len+r/2), r, r];
c.EdgeColor = 'none';
c.FaceColor = col;
end

cla
arm = createArm(.125,r,2.5,'red');
axis equal
axis manual


Now we can change the hgtransform object's Matrix property to make the arm rotate. That's easy to do by using the makehgtform function.

arm.Matrix = makehgtform('zrotate',pi/7);


#### Creating a DoublePendulum class

If we put these parts together, we get a class which looks something like the following:

%
% File: DoublePendulum.m
%
classdef DoublePendulum < handle
% A class for implementing a MATLAB Graphics visualization of the
% Simulink model of the double pendulum which Guy Rouleau shared in
% File Exchange posting 23126.
%
properties (SetAccess=private)
Arms    = gobjects(1,2);
Traces  = gobjects(1,2);
Lengths = [2 2];
Angles  = [0 0];
BallWidth = .5;
ArmWidth = .25;
end
%
% Public methods
methods
function obj = DoublePendulum()
obj.createGeometry();
obj.updateTransforms();
end
function setAngles(obj, a1, a2)
% Call this to change the angles.
obj.Angles(1) = a1;
obj.Angles(2) = a2;
obj.updateTransforms();
end
function clearPoints(obj)
% Call this to reset the traces.
obj.Traces(1).clearpoints();
obj.Traces(2).clearpoints();
end
function r = isAlive(obj)
% Call this to check whether the figure window is still alive.
r = isvalid(obj) && ...
isvalid(obj.Arms(1)) && isvalid(obj.Arms(2)) && ...
isvalid(obj.Traces(1)) && isvalid(obj.Traces(2));
end
end
%
% Private methods
methods (Access=private)
function createArm(obj, p, len, col)
% Creates the geometry for one pendulum. This is basically a copy
% of the function we created earlier.
w = obj.ArmWidth;
l = rectangle('Parent',p);
l.Position = [-w/2, -len, w, len];
l.FaceColor = col;
l.EdgeColor = 'none';
c = rectangle('Parent',p);
r = obj.BallWidth;
c.Position = [-r/2, -(len+r/2), r, r];
c.Curvature = [1 1];
c.EdgeColor = 'none';
c.FaceColor = col;
end
% Adds the current end points of the two pendulums to the traces.
a1 = obj.Angles(1);
a2 = obj.Angles(2);
l1 = obj.Lengths(1);
l2 = obj.Lengths(2);
x1 =  l1*sin(a1);
y1 = -l1*cos(a1);
x2 = x1 + l2*sin(a1+a2);
y2 = y1 - l2*cos(a1+a2);
end
function createGeometry(obj)
% Creates all of the graphics objects for the visualization.
col1 = 'red';
col2 = 'green';
col3 = 'blue';
fig = figure;
ax = axes('Parent',fig);
% Create the traces
obj.Traces(1) = animatedline('Parent', ax, 'Color', col1);
obj.Traces(2) = animatedline('Parent', ax, 'Color', col2);
% Create the transforms
obj.Arms(1) = hgtransform('Parent', ax);
obj.Arms(2) = hgtransform('Parent', obj.Arms(1));
% Create the arms
createArm(obj, obj.Arms(1), obj.Lengths(1), col1);
createArm(obj, obj.Arms(2), obj.Lengths(2), col2);
% Create a blue circle at the origin.
c = rectangle('Parent',ax);
r = obj.BallWidth;
c.Position = [-r/2, -r/2, r, r];
c.Curvature = [1 1];
c.EdgeColor = 'none';
c.FaceColor = col3;
% Initialize the axes.
maxr = sum(obj.Lengths);
ax.DataAspectRatio = [1 1 1];
ax.XLim = [-maxr maxr];
ax.YLim = [-maxr 1];
grid(ax,'on');
ax.SortMethod = 'childorder';
end
function updateTransforms(obj)
a1 = obj.Angles(1);
a2 = obj.Angles(2);
offset = [0 -obj.Lengths(1) 0];
obj.Arms(1).Matrix = makehgtform('zrotate', a1);
obj.Arms(2).Matrix = makehgtform('translate', offset, ...
'zrotate', a2);
end
end
end


Notice the createGeometry method which creates each of the parts we talked about earlier. It creates two traces (one red and one green), followed by two arms (again, one red and one green), and then adds a blue circle at the origin.

Also notice the setAngles method. That adds a new angle to each of the traces, and calls makehgtform to rotate each of the two arms.

Now we can create an instance of this class at the MATLAB command line, and use the setAngles method to make it move.

cla
h = DoublePendulum();
for a=pi/5:.1:2*pi/5
h.setAngles(a,-a/2);
end


Once we have it working, we're ready to move on to the next step.

The final step is to connect it to Simulink. There are a couple of different ways to do this. We’re going to do it with an S-function. We drag a Level-2 MATLAB S-Function block out of the library, connect it to the same signal as the scope labeled "Angle Position", and set its S-function to the following:

%
% File: doublePendulumSFunction.m
%
function doublePendulumSFunction(block)
% Level-2 MATLAB file S-function for visualizing a double pendulum.
setup(block)
end
%
% Called when the block is added to a model.
function setup(block)
%
% 1 input port, no output ports
block.NumInputPorts  = 1;
block.NumOutputPorts = 0;
%
% Setup functional port properties
block.SetPreCompInpPortInfoToDynamic;
%
% The input is a vector of 2 angles
block.InputPort(1).Dimensions = 2;
%
% Register block methods
block.RegBlockMethod('Start',   @Start);
block.RegBlockMethod('Outputs', @Output);
%
% To work in external mode
block.SetSimViewingDevice(true);
end
%
% Called when the simulation starts.
function Start(block)
%
% Check to see if we already have an instance of DoublePendulum
ud = get_param(block.BlockHandle,'UserData');
if isempty(ud)
vis = [];
else
vis = ud.vis;
end
%
% If not, create one
if isempty(vis) || ~isa(vis,'DoublePendulum') || ~vis.isAlive
vis = DoublePendulum();
else
vis.clearPoints();
end
ud.vis = vis;
%
% Save it in UserData
set_param(block.BlockHandle,'UserData',ud);
end
%
% Called when the simulation time changes.
function Output(block)
if block.IsMajorTimeStep
% Every time step, call setAngles
ud = get_param(block.BlockHandle,'UserData');
vis = ud.vis;
if isempty(vis) || ~isa(vis,'DoublePendulum') || ~vis.isAlive
return;
end
vis.setAngles(block.InputPort(1).Data(1), ...
block.InputPort(1).Data(2));
end
end


There are three pieces to this S-Function.

1. The setup function gets called when the block gets loaded. This tells Simulink how to connect the block up to the rest of the model, and it registers the two functions which do the real work.
2. The function Start gets called when the simulation starts. All it does is create an instance of the DoublePendulum class we defined above, and saves it away in the block's UserData.
3. The function Output gets called whenever the simulation updates the block's inputs. All we need to do here is call the setAngles method on our DoublePendulum class. It will do all the work of updating our visualization.

#### Results

And that's it! Just press the Run button, and away we go with our pendulum swinging around wildly.

Have you got Simulink models which could benefit from custom MATLAB graphics like this?

Published with MATLAB® R2014b