<body>
<div class="title">Lesson 11: Simulation with TOSSIM</div>
-<div class="subtitle">Last Modified: 18 May 2006</div>
+<div class="subtitle">Last Modified: 20 April 2007</div>
<p>This lesson introduces the TOSSIM simulator. You will become
familiar with how to compile TOSSIM and use some of its
<li>Inject packets.</li>
</ul>
</p>
-
-
+
+ <p><b>Note:</b> This tutorial is for TOSSIM in TinyOS 2.0.1. If
+ you are using TinyOS 2.0.0, it has a slightly different
+ A HREF="lesson11-200.html">tutorial.</A> The principal difference
+ between the two is how you specify noise in RF simulation.
+ </p>
<h1>Introduction</h1>
TOSSIM simulates entire TinyOS applications. It works by
</pre>
-
<p>Currently, the only platform TOSSIM supports is the
micaz. You should see output similar to this:</p>
<pre>
not properly compile on the first try. <A HREF="#appendix">Appendix A</A>
addresses some of the common causes and gives possible solutions.</p>
- <A name="#compiling"></A>
+
+ <A name="#compiling"></A>
<p>Compiling TOSSIM has five basic steps. Let's go through
<pre>
>>> m = t.getNode(32);
>>> m.bootAtTime(45654);
->>> t.runNextEVent()
+>>> t.runNextEvent()
1
</pre>
+ <p><b>Segmentation faults:</b>If trying to do this causes TOSSIM
+ to throw a segmentation violation (segfault), then chances are
+ you are using a version of gcc that does not work well with the
+ dynamic linking that TOSSIM is doing. In particular, it has been
+ verified to work properly with 4.0.2 and 3.6, but some people
+ have encountered problems with gcc 4.1.1.</p>
+
<p>Instead of using raw simulation ticks, you can also use the
call <code>ticksPerSecond()</code>. However, you want to be careful
to add some random bits into this number: having every node
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__',
'__swig_getmethods__', '__swig_setmethods__', '__weakref__', 'addChannel',
'currentNode', 'getNode', 'init', 'mac', 'newPacket', 'radio', 'removeChannel',
-'runNextEvent', 'setCurrentNode', 'setTime', 'this', 'thisown', 'time', 'timeStr']
+'runNextEvent', 'setCurrentNode', 'setTime', 'this', 'thisown', 'ticksPerSecond', 'time', 'timeStr']
</pre>
<p>The most common utility functions are:</p>
<li><b><code>gain(src, dest)</code></b>: Return the gain value of the
link from <i>src</i> to <i>dest</i>.</li>
- <li><b><code>remove(src, dest)</code></b>: Remove the link from
- <i>src</i> to <i>dest</i>.</li>
+ <li><b><code>threshold()</code></b>: Return the CCA threshold.</li>
+ <li><b><code>setThreshold(val)</code></b>: Set the CCA threshold value in
+ dBm. The default is -72dbM.</li>
+
+ </ul>
- <li><b><code>setNoise(node, mean, variance)</code></b>: Set the noise
- floor at <i>node</i> to be a gaussian distribution with
- <i>mean</i> and <i>variance</i>.</li>
+ <p>The default values for TOSSIM's radio model are based on the CC2420 radio,
+ used in the micaZ, telos family, and imote2. It uses an SNR curve derived
+ from experimental data collected using two micaZ nodes, RF shielding, and
+ a variable attenuator.</p>
+
+ <p>In addition to the radio propagation above, TOSSIM
+ also simulates the RF noise and interference a node hears, both from other
+ nodes as well as outside sources. It uses the Closest Pattern Matching (CPM)
+ algorithm. CPM takes a noise trace as input and generates a statistical model
+ from it. This model can capture bursts of interference and other correlated
+ phenomena, such that it greatly improves the quality of the RF simulation.
+ It is not perfect (there are several things it does not handle, such as
+ correlated interference at nodes that are close to one another), but
+ it is much better than traditional, independent packet loss models. For
+ more details, please refer to the paper "Improving Wireless Simulation through
+ Noise Modeling," by Lee et al.</p>
+
- <li><b><code>sensitivity()</code></b>: Return the receive sensitivity of
- the nodes.</li>
+ <p>To configure CPM, you need to feed it a noise trace. You accomplish this
+ by calling <tt>addNoiseTraceReading</tt> on a Mote object. Once you
+ have fed the entire noise trace, you must call <tt>createNoiseModel</tt>
+ on the node. The directory <tt>tos/lib/tossim/noise</tt> contains
+ sample noise traces, which are a series of noise readings, one per line.
+ For example, these are the first 10 lines of meyer-heavy.txt,
+ which is a noise trace taken from Meyer Library at Stanford University:</p>
- <li><b><code>setSensitivity(val)</code></b>: Set the receive sensitivity
- of nodes to be <i>val</i>. The sensitivity is how much
- stronger a signal must be for it to be received
- uncorrupted. E.g., a sensitivity of 3.0 (the default value)
- means that a packet must be 3dBm greater than the sum of
- noise and concurrent transmissions for it to be received
- uncorrupted.</li>
+ <pre>
+-39
+-98
+-98
+-98
+-99
+-98
+-94
+-98
+-98
+-98
+</pre>
- <li><b><code>threshold()</code></b>: Return the CCA threshold.</li>
+ <p>As you can see, the hardware noise floor is around -98 dBm,
+ but there are spikes of interference around -86dBm and -87dBm.</p>
- <li><b><code>setThreshold(val)</code></b>: Set the CCA threshold value in
- dBm.The default is -95.</li>
-
- </ul>
+ <p>This piece of code will give a node a noise model from a noise trace
+ file. It works for nodes 0-7: you can change the range appropriately:</p>
+
+ <pre>
+noise = open("meyer-heavy.txt", "r")
+lines = noise.readlines()
+for line in lines:
+ str = line.strip()
+ if (str != ""):
+ val = int(str)
+ for i in range(0, 7):
+ t.getNode(i).addNoiseTraceReading(val)
- <p>The Radio object only deals with physical layer
+for i in range(0, 7):
+ t.getNode(i).createNoiseModel()</pre>
+
+
+ <p>CPM can use a good deal of RAM: using the entire meyer-heavy
+ trace as input has a cost of approximately 10MB per node. You
+ can reduce this overhead by using a shorter trace; this will of
+ course reduce simulation fidelity. <u>The trace
+ must be at least 100 entries long, or CPM will not work as it does
+ not have enough data to generate a statistical model.</u> </p>
+
+ <p>You can also use
+ <p>The Radio object only deals with physical layer
propagation. The MAC object deals with the data link layer,
packet lengths, and radio bandwidth. The default TOSSIM MAC
object is for a CSMA protocol. You get a reference to the MAC
t.addChannel("RadioCountToLedsC", sys.stdout)
t.addChannel("Boot", sys.stdout)
+noise = open("meyer-heavy.txt", "r")
+lines = noise.readlines()
+for line in lines:
+ str = line.strip()
+ if (str != ""):
+ val = int(str)
+ for i in range(1, 4):
+ t.getNode(i).addNoiseTraceReading(val)
+
+for i in range(1, 4):
+ print "Creating noise model for ",i;
+ t.getNode(i).createNoiseModel()
+
t.getNode(1).bootAtTime(100001);
t.getNode(2).bootAtTime(800008);
t.getNode(3).bootAtTime(1800009);
-r.setNoise(1, -100.0, 5.0)
-r.setNoise(2, -100.0, 5.0)
-r.setNoise(3, -100.0, 5.0)
-
for i in range(0, 100):
t.runNextEvent()
</pre>
DEBUG (1): Received packet of length 2.
</pre>
- <p>If you set the noise to be 30 plus or minus 5 dBm instead
- of 80 plus or minus 5 dBm, then nodes will never transmit, as
- the default CCA threshold is -95 dBm. You'll see something
- like this:</p>
+ <p>If you set node's clear channel assessment to be at -110dBm,
+ then nodes will never transmit, as noise and interference never
+ drop this low. You'll see something like this:</p>
<pre>
1 2 -54.0
2 1 -55.0
file format is
<pre>
-noise n avg std
gain src dest g
</pre>
- where each statement is on a separate line. The <i>noise</i>
- statement defines the noise observed at node <i>n</i> with
- an average of <i>avg</i> and a standard deviation of
- <i>std</i>. The <i>gain</i> statement defines a propagation
+ where each statement is on a separate line.
+ The <i>gain</i> statement defines a propagation
gain <i>g</i> when <i>src</i> transmits to <i>dest</i>. This
is a snippet of python code that will parse this file
format:
<pre>
-f = open("mirage-1.txt", "r")
+f = open("15-15-tight-mica2-grid.txt", "r")
lines = f.readlines()
for line in lines:
if (len(s) > 0):
if (s[0] == "gain"):
r.add(int(s[1]), int(s[2]), float(s[3]))
- elif (s[0] == "noise"):
- r.setNoise(int(s[1]), float(s[2]), float(s[3]))
</pre></p>
<p>TOSSIM has a tool for the second option of generating a
<p>The format of a configuration file is beyond the scope of
this document: the tool has its own <A
- HREF="usc-topologies.html">documentation</A>. TOSSIM has two sample configuration
+ HREF="usc-topologies.html">documentation</A>. TOSSIM has a few sample configuration
files generated from the tool in
- <code>tos/lib/tossim/topologies</code>. The first is <code><A
- HREF="">grid.txt</A></code>, which is a 10x10 grid of nodes
- spaced roughly 40 feet apart. Each node is placed randomly
- within a 40'x40' "cell." The cells follow a strict grid. The
- second file is <code><A HREF="">scatter.txt</A></code>, which is
- 100 nodes scattered randomly (with a uniform distribution)
- over a 360'x360' area. Note that the tool uses random numbers,
+ <code>tos/lib/tossim/topologies</code>.
+ Note that the tool uses random numbers,
these configuration files can generate multiple different
network topologies. Network topology files generated from the
- tool follow the same format as <code>mirage-1.txt</code>.</p>
+ tool follow the same format as <code>15-15-tight-mica2-grid.txt</code>.
+ If you have topologies measured from real networks, we would love
+ to include them in the TOSSIM distribution.</p>
<h1>Variables</h1>
variables properly. You do this by instantiating a Python
object that parses the XML file to extract all of the relevant
information. You have to import the Python support package for
- TOSSIM to do this:</p>
+ TOSSIM to do this. First, set your PYTHONPATH environment variable
+ to point to <tt>tinyos-2.x/support/sdk/python</tt>. This tells
+ Python where to find the TOSSIM packages. Then, in an interpreter
+ type this:</p>
<pre>
from tinyos.tossim.TossimApp import *
if (len(s) > 0):
if (s[0] == "gain"):
r.add(int(s[1]), int(s[2]), float(s[3]))
- elif (s[0] == "noise"):
- r.setNoise(int(s[1]), float(s[2]), float(s[3]))
+
+noise = open("meyer-heavy.txt", "r")
+lines = noise.readlines()
+for line in lines:
+ str = line.strip()
+ if (str != ""):
+ val = int(str)
+ for i in range(0, 4):
+ t.getNode(i).addNoiseTraceReading(val)
for i in range (0, 4):
- m = t.getNode(i)
- m.bootAtTime(randint(1000, 2000) * 1000000)
+ t.getNode(i).createNoiseModel()
+ t.getNode(i).bootAtTime(i * 2351217 + 23542399)
m = t.getNode(0)
v = m.getVariable("RadioCountToLedsC.counter")
+
+
while (v.getData() < 10):
t.runNextEvent()
+print "Counter variable at node 0 reached 10."
</pre>
<p>The TOSSIM <A
if (len(s) > 0):
if (s[0] == "gain"):
r.add(int(s[1]), int(s[2]), float(s[3]))
- elif (s[0] == "noise"):
- r.setNoise(int(s[1]), float(s[2]), float(s[3]))
+
+noise = open("meyer-heavy.txt", "r")
+lines = noise.readlines()
+for line in lines:
+ str = line.strip()
+ if (str != ""):
+ val = int(str)
+ for i in range(0, 4):
+ t.getNode(i).addNoiseTraceReading(val)
+
+for i in range (0, 4):
+ t.getNode(i).createNoiseModel()
for i in range(0, 60):
t.runNextEvent();
pkt.setType(msg.get_amType())
pkt.setDestination(0)
-print "Delivering " + msg.__str__() + " to 0 at " + str(t.time() + 3);
+print "Delivering " + str(msg) + " to 0 at " + str(t.time() + 3);
pkt.deliver(0, t.time() + 3)
want to deliver a packet through C++, you can do so.</p>
<p>Usually, the C++ and Python versions of a program look pretty
- similar. For example:</p>
+ similar. For example (note that this program will use a lot of RAM
+ and take a long time to start due to its noise models):</p>
<table WIDTH=800>
<PRE>
import TOSSIM
import sys
+import random
from RadioCountMsg import *
for i in range(0, 999):
m = t.getNode(i);
m.bootAtTime(5000003 * i + 1);
- r.setNoise(i, -99.0, 3.0);
+
for j in range (0, 2):
if (j != i):
r.add(i, j, -50.0);
-
-
+ # Create random noise stream
+ for j in range (0, 500):
+ m.addNoiseTraceReading(int(random.random() * 20) - 70);
+ m.createNoiseModel()
for i in range(0, 1000000):
t.runNextEvent();
<TD VALIGN=TOP>
<PRE>
#include <tossim.h>
-
+#include <stdlib.h>
int main() {
for (int i = 0; i < 999; i++) {
Mote* m = t->getNode(i);
m->bootAtTime(5000003 * i + 1);
- r->setNoise(i, -99.0, 3);
for (int j = 0; j < 2; j++) {
if (i != j) {
r->add(i, j, -50.0);
}
}
+ for (int j = 0; j < 500; j++) {
+ m->addNoiseTraceReading((char)(drand48() * 20) - 70);
+ }
+ m->createNoiseModel();
}
+
for (int i = 0; i < 1000000; i++) {
t->runNextEvent();
}
<i>slow</i>:</p>
<pre>
-(gdb) watch UscGainInterferenceModelC$receiving[23]
-Hardware watchpoint 2: UscGainInterferenceModelC$receiving[23]
+(gdb) watch CpmModelC$receiving[23]
+Hardware watchpoint 2: CpmModelC$receiving[23]
</pre>
<p>This variable happens to be an internal variable in the
<li>You have Python support installed, but it turns out to
be incompatible with TOSSIM.</li>
-
+
+ <li>You have a variant of gcc/g++ installed that
+ expects slightly different compilation options than the
+ normal installation.</li>
</ol>
<p>We'll visit each in turn.</p>
<p><b>Symptom:</b> You've verified that you have the
needed Python files and libraries, but compilation is
still saying that it can't link to them ("undefined
- reference") or can't find them.</p>
+ reference") or can't find them ("cannot find -lpython2.4").</p>
<p><b>Solution:</b> Change the sim.extra file to point to
- the correct directories.</p>
+ the correct directories using -L and -I flags.</p>
<h2>You have Python support installed, but it turns out to
be incompatible with TOSSIM.</h2>
<tt>tos/lib/tossim</tt>, or install a different version of
Python.</p>
- <p>Hopefully, these solutions worked and you can get back
+ <h2>You have a variant of gcc/g++ installed that
+ expects slightly different compilation options than the
+ normal installation.</h2>
+
+ <p><b>Symptom:</b> g++ complains that it cannot find
+ main() when you are compiling the shared library
+ ("undefined reference to `_WinMain@16'").</p>
+
+ <p><b>Solution:</b> There are two possible solutions.
+ The first is to include a dummy main(), as described
+ in this <A HREF="http://mail.millennium.berkeley.edu/pipermail/tinyos-help/2006-December/021719.html">tinyos-help posting.</A> The
+ second is to add the -shared option, as described in
+ this <A HREF="http://curl.haxx.se/mail/archive-2003-01/0056.html">web page</A>.
+
+ <p>Hopefully, these solutions worked and you can get back
to <A HREF="#compiling">compiling</A>, If not, then you
should email tinyos-help.</p>
</center>