FAQ: Using Matlab with TinyOS

Last updated 28 April 2005

This FAQ answers many common questions about using TinyOS through Matlab. To find more general info about this topic, see the Tutorial

Table of Contents

What is Matlab, where do I get it, how do I install it, etc?

Matlab is one name that refers to many things (like Java).  It is a programming language as well as an interpreter as well as a set of libraries.  The language is vector-based, making it very easy to write mathematical or data-manipulating applications quickly and easily.  There are also "toolboxes" for things like visualizing data, designing digital filters, machine learning, statistical analysis, etc.  However, it is an interpreted language, making it slower than a language like C or Java.  It is also a scripting language, and large applications may be better written in an object-oriented language. Being an interpreted scripting language, however, is also part of what makes Matlab an appealing way to interact with a sensor network: the user can interact with the network by calling commands on the Matlab command line. In contrast, once a java application is started in can only be controlled through a GUI.

Matlab is commercial software that can be bought from www.mathworks.com.  However, students can obtain fully functional versions that have one restriction:  matrices cannot be larger than 100 X 100.

What are the Matlab commands, syntax, programming model, environment, etc?

This answer is meant to demonstrate the key concepts in Matlab so that you know what to look for in the help files.  It is not intended to be a substitute for the help files.   The Matlab help documents are extremely useful, as is this Matlab primer.

Part I: A few examples

create a variable

a=3

You should see it show up in your workspace window.  It is a 1*1 matrix and if you click on it it should have the value 3 in the first element of the matrix.

Create an array

b=[1 2 3]

create an array using a series

b=1:2:5

Multiply

c=a*b

Create a matrix

d=[1 2 3;4 5 6;7 8 9]

index the matrix

d(2,1)

Notice that the first element is indexed by '1'and not '0'.  Index a whole column or row using the colon operator

d(:,1)

d(1,:)

index using logical indices

d(logical([1 1 0]),1)

d(1,([0 1 1]))

Notice that logical([1 1 0]) = [1 2], so d(logical([1 1 0]),1) really indexes the 1st column of the 1st and 2nd row.  index a matrix using array indices

d(3)

d(4)

index using the 'end' operator

d(1,end)

d(end,1)

index using array indices and the end operator

d(end)

index using a function, and logical array indices

d(logical(mod(d,2)==0))

make an assignment using the colon operator

d(1,:) = [11 22 33]

make an assignment to a column using the ' operator (transpose operator)

d(:,1) = [11 44 77]'

use a compare operator

d>10

make an assignment using a compare operator as logical indices

d(logical(d>5))=10

matrix multiply

a*d

c*d

d*c

a*c*d

d*d

multiply element-by-element (use the .* operator)

d.*d

delete an element

b(2)=[]

delete a row

d(:,2)=[]

Create a string

a='hey'

index the string

a(2)

create a string array

a(2,:)='you'

index the string array

a(2,1)

As you can see, strings are really just matrices. This can be a problem because matrices must be rectangular whereas strings are frequently different different size.  For example, the following won't work because the resulting matrix would not be rectangular:

a(3,:)='get me a drink'

Instead, we can use cell arrays.  Cell arrays are identical to arrays except that they use curly brackets.  Also, each element can be of any size and different elements can be of different data types:

a{1}='hey'

a{2}='you'

a{3}='get me a drink'

a{1,4}=d

Index a cell array

a{2,1}

plot your data on the y axis

data=[1 2 3 7 8 9]

plot(data)

now, put your data on the x axis, with the array 1 2 3 4 5 6 on the y axis

plot(data,1:length(data))

The most important thing you need to learn is how to use Matlab help.   It is extremely valuable.  The windows based help index has a searchable and indexable interface.  The command-prompt help is also useful, e.g.

help plot

A script in matlab is any file with a .m file extension.  It is similar to a shell script in that all Matlab commands in the script are run when you run the script.  You can run a script by typing its name in the Matlab shell whenever the file is in the Matlab path.

A function in matlab is any file with a .m file extension where the first non-commented line is of the form:

function [result1, result2...] = functionName(param1, param2,...)

The file name must be functionName.m and be in the Matlab path.  params1, param2,etc are parameters of the funciton and result1, result2, etc are the return values.  (Yes, matlab functions can have more than one return value.)  You can call the function above with:

[a b] = functionName(c, d)

The difference between a script and a function is that a function has it's own workspace whereas a script uses the workspace of it's calling function (perhaps the command line).

Note that all function parameters and return values are passed by value (except for java objects, which are passed by reference).

Matlab has global variables: any two functions that have a variable defined as global share that variable.  I.e., if your main workspace has a variable declared global and you want to effect it in a function, declare it global in the function also and you have, in a sense, imported it to your local workspace.

Global variables are not the only way to have a variable persist between function calls.  A matlab object is basically a directory that ends with a "@" symbol.  Matlab objects are not a very nice abstraction. See the help files for more info. If you want to use matlab objects with a java-like syntax, use the "genericClass" package (found on the internet)

How do I set up my Matlab environment to use with TinyOS?

Step 1:  call "defineTOSEnvironment.m"

This matlab script, found in tinyos-1.x/tools/matlab, sets up your matlab path, initializes the Matlab comm stack, etc. This must be called each time you start a new Matlab session if you want to use TinyOS. It is often convenient to call this from your startup.m script, which is called by matlab everytime you start a new matlab session (see help files). Usually, this file can be found in ~/matlab in Unix or /MATLABPATH/toolbox/work on windows.

Step 2:  Compile the TinyOS Matlab tools (written in Java)

The net.tinyos.matlab.MatlabControl class is needed to call matlab commands from Java, and is required to use TinyOS with Matlab.  To compile this, type make matlab in the tinyos-1.x/tools/java/net/tinyos/matlab directory. You must have the .jar file C:\MATLAB\java\jar\jmi.jar in your CLASSPATH environment variable.

Step 3:  Add the TinyOS Java tool chain to your Matlab classpath

You need to tell Matlab where your TinyOS Java tools are located.  In Matlab 7 or greater, you can simply add a command like the following to the defineTOSenvironment.m file

javaclasspath('/path/to/tinyos-1.x/tools/java');

If you are running Matlab 6.5 or earlier, you must edit Matlab's classpath.txt file and restart matlab. Open Matlab and type the following command:

edit classpath.txt

The Matlab editor will open with the classath.txt file.  You need to add the directory of both your TinyOS Java tools and of your comm.jar file.  The resulting file should look something like this:

classpath.txt
    ## FILE: classpath.txt
    ##
    ## Entries:
    ## o path_to_jarfile
    ## o [alpha,glnx86,sol2,unix,win32,mac]=path_to_jarfile
    ## o $matlabroot/path_to_jarfile
    ## o $jre_home/path_to_jarfile
    ##
    .
    c:\tinyos\cygwin\opt\tinyos-1.x\tools\java\
    c:\tinyos\jdk1.4.1_02\j2sdk1.4.1_02\jre\lib\ext\comm.jar
    $jre_home/lib/rt.jar
    $jre_home/lib/i18n.jar
    $jre_home/lib/swingall.jar
    $matlabroot/java/patch
    $matlabroot/java/jar/util.jar
    ...
      

where the bold lines are the ones you just added.  

How do I use the TinyOS Java tool chain from within a Matlab session?

It is often easier to use an existing Java tool with TinyOS than to rewrite it in Matlab. For example, one would like to use tools for Deluge, trickle, etc to inject packets reliably. As an example, we could start the Java Oscilloscope tool directly from Matlab instead of using the matlab version that we examined in the tutorial:

net.tinyos.oscope.oscilloscope.main({'125'})

This starts the oscilloscope application, and you should see the java gui open and connect to your serial forwarder.

The following table provides an overview of the Matlab syntax for using Java.  It is essentially the same as Java syntax except that there is no "new" operator and functions with no arguments do not terminate with empty parenthesis  "( )".  Type these commands into your Matlab command window to see what they do.

Overview of Matlab syntax for using Java objects

Instantiate an Object

f = java.awt.Frame
f = java.awt.Frame("My Frame")

Call a function

f.show
f.resize(500,500)
f.hide

Call a static function

java.awt.Frame.getFrames

Access public member variable

f.WIDTH

Introsection: class name

classname = class(f)

Introspection: methods

methods java.awt.Frame
methods java.awt.Frame -full
methodsview java.awt.Frame

Introspection: variables

fields(f)

Import

import java.awt.*

Conversion of function parameters and return values are taken care of automatically.  Essentially, all primitive types, including strings and arrays, are automatically converted and are passed by value.  Java objects are left as Java objects and are passed by reference.  Using Java from Matlab is completely supported by Mathworks and is well documented in the the "Matlab/Java interface" section of the Matlab help files. 

While the syntax above allows one to manipulate Java objects from Matlab, they do not allow matlab functions to be called from Java. To do that, you must use the net.tinyos.matlab.MatlabControl.java class. See the MatlabControl webpage for more details.
Where should I keep my Matlab files?

The Matlab directory structure was meant to mirror that of the tinyos-1.x directory.  Each of the directories is meant to serve the following purposes:

Making Java classes Matlab Friendly

Using Java classes from Matlab reveals two common bugs that should be fixed before using your Java classes from Matlab.  While both of these bugs are really due to slopy programming, they never cause errors in the default Java environment (i.e. starting a java app from the command line) so you will find them in a lot of Java classes, including those in the TinyOS Java toolset.

A. Command Line Arguments

Let's say that you're using a shell and you want SerialForwarder to connect to COM2 instead of COM1 and you want oscilloscope to listen for Group ID 122 instead of 125.  From your shell, you would pass command line arguments as follows:

java net/tinyos/sf/SerialForward -comm COM2
java net/tinyos/oscope/oscilliscope
122

If you want to do the same thing from the Matlab command prompt, you would use the following syntax

net.tinyos.sf.SerialForward.main({'-port','COM2'})
net.tinyos.oscope.oscilloscope.main({'122'})

This is because the command line arguments from your shell are automatically packaged up into string arrays and passed to the static main function of your class.  In Matlab you need to pass string arrays directly.  In Matlab syntax,  '...' is a string and {'...', '...', ..., '...'} is an array of strings.

Now, what if we don't want to pass any command line arguments?  We should send a null array, which in matlab would be '{ }'.  Let's try it:

net.tinyos.sf.SerialForward.main({})

We get a null pointer exception!  This is because the main function in SerialForwarder uses the string before checking if it is null.  Since sending no command-line arguments from the shell doesn't result in a null string being passed, this normally doesn't cause an error.  However, this should be fixed if this class were to be used from Matlab.

B. Virtual Machines

If you had used the shell commands above, notice that you would have called the "java" command twice.  This means that you have started two JVMs (Java Virtual Machines), one that is running SerialForwarder and one that is running Oscilloscope.

In Matlab, on the other hand, you instantiated both objects within the same JVM.  Furthermore, Matlab itself is also running in this same JVM.  This is only important for the java.lang.System class, which directly refers to the JVM you are running in;  java.lang.System.exit() will kill your JVM, and therefore both classes and your Matlab session!  You will see this if you close the oscilloscope window, because this causes oscilloscope to call System.exit().  If this class were to be used from Matlab, it should be changed to first close the socket, then deregister itself from everything and release all resources (i.e. dispose the window).  The java garbage collector would then take care of the rest. System.exit( ) should never be called.

How about debugging?

Debugging Matlab is extremely simple:

  1. open the function you want to debug in your Matlab editor
  2. click to the left of the line to set a breakpoint
  3. use the commands from the Matlab editor to control flow of execution

Since Matlab is an interpreted language, debugging when execution is stopped is simple.  See the Matlab help files for more information on the matlab debugger.

Debugging Java objects in Matlab is easy in some sense since you can instantiate arbitrary objects and call arbitrary functions.  However, it is in some sense difficult because the Matlab debugger does not step into Java objects. You can, however, start your Java object using a Java debugger which is written in Java from Matlab, allowing you to debug your Java object by using Matlab as a Java interpreter.

How can I make it run faster?

There are a couple of reasons why your app might be running slowly.  Here are a few tips to make it run faster:

1.  Vectorize your code.  See the mathworks help and documentation in both the help files and online.  Vectorizing your code (using matrix or array commands instead of for loops) is at least 15 times faster than for loops.

2.  In general, use matlab commands whenever possible instead of your own code, especially when you are about to introduce a for loop.

3.  Minimize screen printing and graphing. 

4.  Use the profile command to find out which of your functions are taking all the time.  Read about it in the help files.  It tells you which functions are taking what percentage of CPU time and gives you plots, etc. allowing you to streamline your code.

----------------
Kamin Whitehouse