Creating Tabs using GUIDE

Matlab GUIDE Tab 1

Combining GUIDE GUIs into Tabs

Last year a client asked me to add a tab to an existing GUI meant for robot control. This wouldn’t be a big deal, but the existing GUI was made using GUIDE and I didn’t want to programme the layout from scratch. Unfortunately GUIDE doesn’t support tab creation (at least as of 2015b); but I found a small hack that can help fuse two GUIs created using GUIDE as two tabs in a single window.

The idea is to export the GUIs into m-files using Export option in File menu, create tabs using uitab and replace the parent of objects from each GUI to the respective tabs. For demonstrating the trick here, I chose two samples GUIDE offers – GUI with Uicontrols & GUI with Axes & Menu.

Creating Tabs using Matlab GUIDE - UIControls

Gui 1

Creating Tabs using MATLAB GUIDE - Axes & Menu

Gui 2

Choose each one, save them (say as Gui1 & Gui2). Export each of them using File->Export, as say Gui1_export.m & Gui2_export.m.  Let’s first open Gui1_export.m. The exported file contains all the content of Gui1.m and a few more functions that define layout of the GUI. The first of these is  LayoutFcn that appears in Gui1_export.m immediately after all functions of Gui1.m. 

% --- Creates and returns a handle to the GUI figure.
function h1 = Gui1_export_LayoutFcn(policy)
% policy - create a new figure or use a singleton. 'new' or 'reuse'.
persistent hsingleton;

Here, you will find handles of objects being created starting with h1 = figure(… , h2 = axes(…, h3  etc. h1 will be handle to the figure window and is parent for rest of the objects (you can notice that ‘Parent’ field for each subsequent object handle is set to h1). After defining h1 we create tabs using uitabgroup and uitab as follows.

%%% %%% %%% %%% %%% %%% TAB CREATION %%% %%% %%% %%% %%% %%%
ht = uitabgroup('parent',h1,'Position',[0 0 1 .95]);
h1tab = uitab(ht,'title','GUI 1');
h2tab = uitab(ht,'title','GUI 2');

For the object handles h2, h3, h4 etc whose definitions follow, we will replace h1 with h1tab as parent. E.g.

h2 = uicontrol(...
'Parent',h1tab,...

(You may do find and replace, but be careful and don’t replace h1 with h1tab in hsingleton = h1 statement)

Running the Gui1_export.m at this point shows two tabs with titles GUI 1 & GUI 2, with GUI 1 selected as the default tab. Selecting GUI2 will show an empty figure as GUI2 objects have not been added yet. Now, go to LayoutFcn of Gui2_export.m and replace parents of object handles h2, h3, etc. with h2tab. Copy the text from “appdata = [ ];” immediately preceeding definition of h2 in LayoutFcn to Gui2_export.m until the end of function except for hsingleton = h1; line.

Combining GUIDE GUIs into Tabs

Open Gui1_export.m and right after definitions of Gui1 objects and before hsingleton definition, load Gui2_export.mat* and paste the text copied from Gui2_export.m as shown below.

* mat files are generated during export, but in this particular example it isn’t generated and hence this  can be skipped.

How to Fuse GUIDE GUIs into tabs

Now run the file Gui1_export.m and the GUI figure with two tabs shows up. I had to edit the positions of objects on GUI 2 tab. Many variable names used by handles of Gui1 will be overwritten by Gui2 and will hence be lost, but this never created me any problems. Note that all callbacks of Gui2 objects are configured to refer Gui2_export.m and hence this file will be required for functioning of callbacks of Gui2 objects.

Matlab GUIDE Tab 2

I attached the scripts and mat files that run fine in R2012b (in later versions they might produce warnings and might produce errors in earlier versions). Gui1_export.m Gui2_export.m Gui1_export.mat

VariablePulseWidth s-function

How to write s-functions in Matlab

Matlab s-functions seem scarier than they really are. Understanding how Simulink works and what goes behind the scenes when you simulate helps learning s-functions. In this blog I’ll show you how to write a simple s-function to generate variable width pulse train (variable width PWM or variable duty-cycle pulse generator). One often requires that pulse width (or duty cycle) of a pulse generator be variable via a signal rather than specified as a constant in block parameters. s-function demos has an example to the same effect, but I have simplified it quite a bit to avoid confusion to beginners from unnecessary methods and stuff (like Dwork).

Start with a new model file with pulse generator block, a level-2 s-function block and a repeating sequence block. We shall use the repeating sequence to generate a triangular wave and feed it to the s-function block which will change pulse width of the pulse generator block according to the instantaneous value of the triangular wave.

An s-function block has two block parameters – the name of the s-function and the parameters you want to pass into the s-function. You can right away name your s-function and click ‘edit’ and Matlab will create a new file (if a file with that name doesn’t exist ). Alternatively, you can open a blank new m-file and use it to define the s-function. Define the primary function with no outputs, but with one input, say ‘block’. Inside there you just need to call setup(block), which is going to be another function we need to define in the same file.

function variablePulseWidth(block)
% Variable Pulse Width s-Function
% Use this block to vary pulse width (duty-cycle) of a pulse generator
% Connect the input port to the signal which dictates the duty cycle as a
% percentage. Range of values the signal can take would be 0 to 100 (both
% end points excluded).
% (c) Planck Technical,2013
setup(block)

Writing the s-function begins with defining the setup method. Setup initialises the s-function block by setting some basic attributes like number of input & output ports, their types and sizes, number of parameters the s-function should accept from the block-parameters window, sample time of the block, etc. Here, you will also need to declare other callback methods that you will be using to design the functioning of the block. Predominantly many of these methods have only one input argument, which, we will call ‘block’ (- its a special datatype of class Simulink.MSFcnRunTimeBlock).

function setup(block)
% Register number of ports
block.NumInputPorts = 1;
block.NumOutputPorts = 0;

We do not need any output ports for this s-function as the output will be from the pulse generator and we will only be using this s-function to change the pulse width setting of the generator block. Next, properties of each of these input and output ports have to be specified.

% Specify inport properties
block.InputPort(1).Dimensions = 1;
block.InputPort(1).DatatypeID = 0; % double
block.InputPort(1).Complexity = 'Real';
block.InputPort(1).DirectFeedthrough = false;
%
% No output port, So no properties to set here

With a little foresight, its recommended that we use s-function dialog box parameters to specify name of the pulse generator block whose pulse width has to be varied. This is handy if there are multiple pulse blocks and each of them needs to be controlled, may be with different signal.

% We'll use Pulse Generator block name as input to s-function
block.NumDialogPrms = 1;

Specify the sample time of the block as a vector of two values [sampling period, offset]. Here, the sample time is set to be inherited.

% Register sample time to inherited
block.SampleTimes = [-1 0];

After initialising the block using above lines of code, Simulink likes to get on with the business of computing the block outputs. However, before that there could be additional things a user might be interested in doing before computing the outputs. Things like some initialisation tasks or computations associated with this (or other) block(s). For such things, Simulink provides methods like Start and InitializeConditions. There might also be some tasks which are to be carried out only at major time steps, or at termination of simulation which can be addressed using one or more of methods listed here. Of all these methods, only two – ‘Outputs’ and ‘Terminate’ are required to be declared while the rest are optional. In our example, there isn’t really a need for these, so the code below only shows the two necessary methods.

% Register all methods to be used in this file
block.RegBlockMethod('Outputs', @outputs); % Required
block.RegBlockMethod('Terminate', @terminate); % Required

During Simulation, ‘Outputs’ method is called at each time step (major and minor). ‘Start’ & ‘InitializeConditions’ are called at the beginning of the simulation. ’Terminate’ is called only after simulation (or its termination) or when an s-function block is deleted. Declaring all methods to be used in the file marks end of the ‘setup’ method. All these registered methods now need to be defined.

Our plan is to utilise ‘Outputs’ method, which is executed at every time step, to change the pulse width parameter of the Pulse block.

function outputs(block)
pulseBlock = block.DialogPrm(1).Data;
pulseBlockPath = [get_param(block.BlockHandle,'parent'),'/',pulseBlock];
set_param(pulseBlockPath,'PulseWidth',num2str((block.InputPort(1).data)));

The first line fetches the dialog parameter from the block parameters dialog box, where user mentions of the name of the Pulse block. E.g. if user mentions ‘Pulse Generator 1′  in the dialog box, the same string is fetched into the variable ‘pulseBlock’. If user declares two parameters in the setup method, the dialog box can input two input arguments and the second one can be accessed as block.DialogPrm(2).Data. The second line makes the full path to the pulse block, which is used in third line to set ‘PulseWidth’ parameter of this block. Data coming into the input port of the s-function is accessed as block.InputPort(1).data. If there are two input ports declared in setup method, the data into second port can be accessed as block.InputPort(2).Data. Whenever block parameters are being set, they need to be written as strings. Hence, numeric data in the input port of s-function is converted to string using num2str.

We will not use terminate method, it may be safely left blank.

function terminate(block)

Save the m-file with a filename exactly matching the function name used at the very top. You are now good to start using the variablePulseWidth s-function.

Variable Pulse Width Pulse Generator with s-function

Variable Pulse Width Pulse Generator with s-function

Its possible that you get an error complaining that PulseWidth must be a number between 0 and 100. That happens at the beginning of simulation when the s-function block is executed before the block feeding1 its input, i.e. the Repeating Sequence source block. If Simulink executes s-function before its feeding block in, there will be no data present at its input port, i.e., block.InputPort(1).data is zero. However, zero is invalid entry for pulse width. This issue can be addressed by changing the block execution order of these two blocks. Right-click a block to choose  ”Properties” and enter a number (integers starting with zero) in ‘Priority’ field. Entering a greater integer for s-function compared to that of its feeding block lowers the priority of the s-function block and updating the figure (CTRL+D) will  show you new block execution order (if you have it enabled from Display Tab > Blocks > Block Execution Order).

The initial value chosen for pulse width can be either specified manually in the block parameters window of Pulse Generator block. Or, it can be done via s-function’s optional method Start or InitializeConditions. E.g. I can include one of these methods in the file (after registering it in setup method as block.RegBlockMethod(‘InitializeConditions’, @initConditions) ). The function name you choose can be anything- it doesn’t have to match the method name.

function initConditions(block)
pulseBlock = block.DialogPrm(1).Data;
pulseBlockPath = [get_param(block.BlockHandle,'parent'),'/',pulseBlock];
set_param(pulseBlockPath,'PulseWidth','50');

The above function would ensure the first pulse will be of 50% duty cycle. Instead of hard coding it inside the function, this can be made a user specifiable parameter in the s-function dialog box. Then, your s-function will have 2 parameters and you will specify them separated by commas in the parameters box as ‘Pulse Generator 1′,50. Note that the name of block must be in single quotes as its a string. The parameter 50 can be specified as a number or as a string ’50′, but must be used accordingly in the InitializeConditions function.

The built-in s-function templates make writing s-functions a bit easier. Matlab provides two templates – a basic one (msfcntmpl_basic.m) and a full template (msfcntmpl.m). The former lists 7 most used (of the 25 available) callback methods, while the latter lists almost all. To open these templates, click on the link in documentation or use these links

>> edit([matlabroot,'/toolbox/simulink/blocks/msfuntmpl_basic.m'])
>> edit([matlabroot,'/toolbox/simulink/blocks/msfuntmpl.m'])

In a followup post someday, I’ll try and highlight more advanced uses of s-functions, using these other optional methods that I skipped here. How have your experiences been with s-functions? Do you like to see a specific use of s-functions in a followup blog post here? Share your thoughts and comments.

EDIT: Model file attached as requested by a commenter: varpulsewidthexample   All the code is in the post, just use it in a file named varpulsewidexample.mdl

 

Simulating Dynamic Systems with Matlab (Solving ODEs)

I prefer Simulink to Matlab for simulations as doing it with former is much more cleaner and scalable. However some of my trainees prefer Matlab for their own reasons. I wanted to create a how-to post demonstrating this simple procedure.

Simulate the following MIMO system governed by the differential equations

dynamic system simulation using matlab

for u1(t) = 0.1sin(t) and u2(t) = 5 (a constant), with initial conditions y1(0) = 1.5 and y2(0) = -0.5 in time range [0,50s]. Given a0=a1=a2 = 1.

I’m unable to put nice latex here, so I’ll define some text notation. A’ in equation above will be written as Adot. A” will be Adotdot. Start with choosing  state variables. Obviously, you’ll need at least 3 states, say x1, x2 & x3. Say, x1 = y1, x2 = y1dot & x3 = y2. I hence have

x1dot = x2
x2dot = -a1 x2 - a0(x1+x3) + u1(t)
x3dot =  -a2(x3-x1) + u2(t)
y1 = x1
y2 = x3

This is now of the form Xdot = F(X,u(t)) & Y = H(X)

I need to formulate this state equation to be able to write a function to compute F. Create a function file samplesys.m with the following content.

function dx = samplesys(t,x,k)
dx = zeros(3,1);
dx(1) = x(2);
dx(2) = -k(2)*x(2) - k(1)*(x(1)+x(3)) + 0.1*sin(t);
dx(3) = -k(3)*(x(3)-x(1)) + 5;

The system has 3 parameters a0-a1 which I’m passing into the function as a vector k which will have [a0, a1, a2]. Second line with zeros function preallocates memory to make a 3×1 vector for output dx. With n-states this will be an nx1 vector. Once this function is created you can use available ode solvers like ode45 to simulate the system in the following fashion.

>> timeSpan = [0,50]; % Solve from t=0 to t=50
>> IC = [1.5;0;-0.5]; % initial conditions. Note that ic of y1dot (i.e. x2) is not specified, and hence assumed zero.
>> [tsim,y] = ode45(@(t,y,k) samplesys(t,y,[1,1,1]),timeSpan,IC);

That should yield you simulation time ‘tsim’ and output ‘y’ in workspace which can be plotted using plot function. tsim is a column vector with each value specifying simulation time at that time step and y is a matrix with each row giving you states at corresponding time step. Each column of y corresponds to a state chosen.

ode45 uses default max step-size of tspan/50 and rel-tol of 1e-3. If the graph produced is coarse it can be refined with a refine factor (say 20, here) or by lowering max step. These options can be specified using odeset function as
opts = odeset('MaxStep',0.1,'Refine',20);
[tsim,y] = ode45(@(t,y,k) samplesys(t,y,[1,1,1]),timeSpan,IC,opts);

odeset options can optionally be specified at the end of the solver function. Plotting columns 1 & 3 of y w.r.t tsim gives the plots shown. For verification that I coded the function right, I made a simulink model of the same system with same simulation settings and plotted the results against those from Matlab. Unsurprisingly, they overlap.

Simulation result & comparison with output of Simulink model

Simulation result & comparison with output of Simulink model

Here I chose to evaluate the inputs u1 & u2 right inside the function. However, they can be inputs to the function too. Function definition in such a case would look like function dx = samplesys(t,x,u1,u2,k). u1 & u2 in such a case must be structures or matrices with time and signal information. Time info is essential as you will have to evaluate u1 & u2 values at the particular instant ‘t’ using interpolation.

ode45 solver has been available in Matlab as a function, but the functions for other solvers like ode15s, ode23, etc haven’t been readily available until recently (R2012b ?). If your version doesn’t have the other solvers try finding them for download on Mathworks support site.

Share your thoughts and tips on using ode functions for our readers.

Getting Started with GUIs using GUIDE

Guide is a simple tool in Matlab to swiftly create custom GUIs. Its a GUI to create a GUI, but needs some coding to get it working. In today’s blog I’ll show how to make some simple GUIs with Guide. Once you get the gist of the technique you will be playing around with GUIs in no time.

Type guide at the Matlab prompt and choose blank template at the query. The interface you see should like the one below.

Matlab GUIDE

The panel on the left shows you all the various kinds of objects you can create in a Matlab GUI viz., pushbuttons, togglebuttons, radiobuttons, edit fields, text strings, checkboxes, axes, dropdown/popup menu, listboxes, tables, sliderbars, and a panel to create groups of these objects. To keep it simple, I’ll demonstrate building a GUI for a basic task like multiplying two numbers, say speed and time to yield distance.

Guide Example

Creating the interface should be just drag-and-drop task. To edit the strings on the objects, double-click on them to open up property-inspector. Change the value of field called “string” from the default one to the one you want.

GUIDE Inspector

So I ‘ve 3 edit-fields, 3 static-texts, and a pushbutton as shown below. As user enters numbers in speed and time edit fields and pushes the pushbutton, the distance value is calculated and displayed. These are the objects, their tags and values in my GUI:

Object

Tag

Value/string

Text string for SPEED

text1

Speed

Text string for TIME

text2

Time

Text string for DISTANCE

text3

Distance

Edit field for SPEED

edit1

0

Edit field for TIME

edit2

0

Edit field for DISTANCE

edit3

0

Pushbutton

pushbutton1

Calculate

Now save the gui with a valid name and run it. You would be seeing the interface with the objects you put. Also notice that Matlab creates two files with the filename you used – a .fig file and an .m file. You may try using the GUI but it doesn’t yet work. That’s because although the objects exist they haven’t been programmed to communicate with each other, which will be the next task.

To understand how GUIs work in Matlab one must understand two things. First, graphics in Matlab are managed by means of what are called handles. Every window/interface that Matlab creates gets a handle. E.g. your main Matlab window has the handle 0 (numeric zero). Handles (as of 2013a) can be positive integers or fractions (it can be controlled if an object should get an integer handle). Think of handles as addresses for graphical objects. Second, GUI objects are associated with event functions which are automatically invoked when an event occurs. E.g. clicking on a pushbutton, changing value in a text field, toggling a toggle button, switching a radio button, etc are all events that trigger execution of a designated function called “callback function”. It’s the callback functions that pour life into a GUI. When you create an object in your GUI using Guide, Matlab automatically creates a placeholder template in the m-file for callback linked to the object. The name of the callback function will bear the tag of the object. E.g. for an object with tag “pushbutton1″ you will see a function with definition function pushbutton1_Callback(hobject,eventdata,handles) .

This function is automatically invoked when pushbutton1 of the GUI is clicked on. Hence, whatever action the function is coded to carry out will be performed. During the callback hobject will have handle to the object whose callback is being executed, which is a very handy thing to have. eventdata is blank and left unused often, and handles is a structure containing handles of all the objects placed in the GUI. E.g. handles.pushbutton1 will have handle to the object with tag pushbutton1.

In our example, we need only one action: to calculate the product of the numbers and display inside the edit field corresponding to ‘Distance’, when user clicks on the “Calculate” pushbutton. We will hence define only the pushbutton’s callback function. In the m-file, scroll down to locate pushbutton1_Callback and place the following code.

function pushbutton1_Callback(hObject, eventdata, handles)
speed_string = get(handles.edit1,'value');
time_string = get(handles.edit2,'value');
speed_val = str2double(speed_str);
time_val = str2double(time_str);
distance_val = speed_val * time_val;
distance_string = num2str(distance_val);
set(handles.edit3,distance_string);

get function fetches value of a particular property of the object specified by the field. Its syntax is get(handle,’property_name’). In the above code, we are fetching the strings in the two edit fields, converting them to numbers and multiplying them. Conversion to numbers can be done by str2double or str2num. Then we use put function to write a value to the specified property with the following syntax - put(handle,’property_name’,'value’). Note that value is in quotes only if the property takes a string rather than a number as is the case with text edit fields, static texts, pushbuttons, etc. In case of radiobuttons and checkboxes value is either 0 or 1 denoting whether or not the button is OFF or ON.

As the callback finishes execution, the GUI has new string in the distance field. Note that we didn’t bother about callback functions for edit fields which are invoked when user changes value in the field. For a novice, it would be a good exercise to enhance the above GUI to update the distance field as soon as user changes value in speed or time field. Such a design obviates “Calculate” pushbutton.

You might also see a lot of other placeholders functions created in the m file like createfunctions, etc which are automatically created by GUI. If you don’t intend to use them, you can get rid of them by deleting their references in property inspector, but deleting them from m-file directly is a bad idea. This is one of the drawbacks of Guide – it messes up m-file quite a bit. Guide is good in cases where you anticipate your GUI to continuously evolve in design and is has moderate complexity. Guide is a nice, expedites GUI design & layout, but is still a clumsy tool. GUIs created by it tend to be slightly slower in response compared to those created manually. I’d prefer to use Guide to quickly show my client the concept but would avoid it in cases of very complex GUIs with a lot of objects or where the specs/requirements aren’t changing. Creating GUIs without Guide involves creating the figure, objects, etc manually using functions like uicontrol. Planning a GUI layout with manual design could be time-consuming, needs some patience and practice and is worth only if the GUI is too complex for Guide to handle.

I would be happy to answer your questions on Guide/GUIs. How do you design your GUIs? Share your experiences, tips for our readers. Leave a question/comment below.

Writing Efficient Matlab Code by Vectorization

Let me start with an example – sum up all numbers in a 10000×10000 matrix (of the default type double), which would involve 100M floating point additions. Look at the two implementations below:

% Code A:
x = randn(1e4);
s=0;
tic
for i=1:1e4
for j=1:1e4
s=s+x(i,j)*x(i,j);
end
end
toc

Avg Time Taken* : 2.2s

% Code B:
s=0; tic, s = sum(x(:)); toc

Avg Time Taken* : 0.06s

* on a 2.5Ghz Intel Core-I5 with R2011a running on OS 10.8

It can be seen that Code-A takes whopping 36 times longer than Code-B to do the same task. The reason B is faster is because it does a vectorised addition in contrast to a repetitive addition by loops of A.

Vectorization is akin to batch processing – its lot faster to execute a task on bunch of numbers than executing the same task individually on the same bunch of numbers. This is not really any magic, but an exploitation of processor architecture with some smart coding. Think of it like time taken for you to fetch groceries all in one go versus the time taken if you had to visit the store once for every item on your wife’s list.

Another example – Get averages of every two successive numbers in an array. i.e. if x = [0,1,2,3,4,5] create a y which is [0.5,1.5,2.5,3.5,4.5]. It might be tempting to put a loop for the purpose, but it can be done much more elegantly using indexing as follows.

y = (x(1:end-1)+x(2:end))/2;

Another example: evaluating a function in 2 independent variables over a given 2D space. Let the function be the Sinc function given as f(x,y) = { sin((x^2+y^2)^0.5) } / ((x^2+y^2)^0.5) in the space [-2pi, 2pi].

[x,y] = meshgrid(-2*pi:0.1:2*pi,-2*pi:0.1:2*pi);
z = sin(sqrt(x.^2+y.^2)) ./ (sqrt(x.^2+y.^2))

In real world problems, vectorization makes day and night difference. It could be so pronounced for a computationally intensive task that one might have to wait for days in contrast to waiting a few minutes with vectorization exploited. Vectorising has no syntaxes per se, its just an art of utilising some cool features, operators and builtin functions. E.g  . (the dot) operator for element-wise operations, functions like repmat, reshape. It’s a skill that you nurture with some practice.

Loops are inherently inefficient in Matlab, but they have come a long way in the last 8 years or so, thanks to JIT compiler (see the 4th comment in the article here). Loops however cannot be ditched altogether. There would be situations where using a loop becomes inevitable to realise some logic (e.g. in cases where current computation depends on previous computation). Its would be a good habit for budding Matlab programmers to think on lines of vectorization and resort to loops only as last option. Vectorization has a downside too. It’s demanding on memory and if computations  push the machine to limits with “out of memory” errors you might want to have a relook at vectorization strategy. You might have to reduce the amount of vectorization in favour of loops (with better memory management) to strike a good balance between speed of execution and memory demand.

I would love to see your comments. Share your experiences with vectorization.