Blog

Simple WSN Simulation with Matplotlib Animations

My internship and thesis revolves around WSNs: Wireless Sensor Networks. To get some more insights in the workings of these networks and I built a small simulator in Python. The full source can be found on the SLACTest1 repository on GitHub.

The setup of the simulation is simple: a fixed world (without obstructions) contains a set of nodes. A subset of these nodes are fixed (i.e. Access Points or AP’s) and the rest is moving (e.g. users, usually one). All nodes are randomly places within the boundaries of the world, all moving nodes are initialised with a random movement (speed and direction).

An example simulation consisting of 100 static access points and one moving node. The blue line is the movement trace of the user. The left figure represents the simulated world. The right is the predicted movement trace of the user based on signal strengths measurements (using PCA); this I will address in a seperate post.

For brevity I won’t show the full source code here (see the repo) but only the relevant parts. The movement of the users is a simple bounce or pinball effect:

def move(self):
	xn = max(min(self.x + math.cos(self.r) * self.s, self.maxX), 0)
	yn = max(min(self.y + math.sin(self.r) * self.s, self.maxY), 0)

	if xn == 0 or xn == self.maxX:
		self.r = math.pi - self.r
	elif yn == 0 or yn == self.maxY:
		self.r = 2 * math.pi - self.r

	self.moveToPosition(xn, yn)

Running the simulation only requires setting up a specific controller with the appropriate nodes:

# Create a new world
world = env.World(xMax, yMax)
# Instantiate nodes with a random position
nodes = [wsn.FixedAP(maxX = world.getMaxX(), maxY = world.getMaxY()) for x in range(0, fixedNodes)]
user = wsn.MovingAP(maxX = world.getMaxX(), maxY = world.getMaxY())
nodes.append(user)

# Create a network controller, containing the world and nodes
controller = NetworkController(world, nodes, False)
# Initialize the world, gives nodes initial speed and direction
controller.initialize()

# Simulate movement in the network
for i in range(0, steps):

	# Update the total network
	controller.iterate()

Creating a moving figure

The most difficult part of the whole simulator is not simulating movement or the world state, its the visualization. Matplotlib has support for animations2 but the documentation is not as extensive as for the other types of plots. The most basic example uses a update function to plot every frame (through FuncAnimation). For the WSN simulation I opted for the subclassing method:

class PlaybackAnimation(animation.TimedAnimation):
    '''
    Animator object
    '''
    def __init__(self, <plot data>):

    	# Setup a figure object
        fig, (combAx, predAx) = plt.subplots(1, 2, squeeze=True, figsize=(24,10)  )

       	# Setup your plots here as you would normally do
       	# self.plt = ...

        animation.TimedAnimation.__init__(self, fig, interval=100, blit=True)

    def show(self):
        self.plt.show()

    def _draw_frame(self, iteration):

        # Update the data of your plots
        # You can retrieve the data with:
        #	yourplt.get_data()
        # and set the data with:
        #	yourplt.set_data(x, y)

        # This step is important as it tells the animation which plots have been updated
        # Set _drawn_artists to a list of all the plot objects that have changed.
        self._drawn_artists = [ plots ]

    def _init_draw(self):
    	# Init all plots by setting there data to zero, e.g.:
        # self.plt.set_data([], [])

    def new_frame_seq(self):
        # here you return an enumerate object describing the length of the animation
        # e.g.:
        # return iter(range(len(self.data) - 2))

Read the comments in the above snippet for some guidelines during the implementation of your animator. The animation can then be showed using the show() function or it can be saved to a file (make sure that you have a version of ffmpeg installed):

anim = PlayBackAnimation(data)
anim.save("simulation.mp4", writer="ffmpeg")

Closing remarks

Creating this simulation showed me one thing: sometimes it takes you more work to show what you have done (i.e. showing the simulation) than doing the actual work self (the world model). In Python, creating the world and simulating the nodes is trivial and very easy. Unfortunately, the animation capabilities of Matplotlib are a bit more difficult and underdocumented. If your focus is primarily animating than you’re better off with something like Matlab.

Footnotes

  1. The repo contains the full SLAC project in which I combine Gaussian Processes with localization.

  2. Matplotlib animation API

Comments (6)

M Mohammad Fazlul Hasan Shariff

Hi Wouter!
Great work on the SLACTest project. I am also working on something similar and I was wondering if there is a way I can modify your original project to run it on a terminal in Ubuntu? I mean, I don't exactly need an animation like how you have created (awesome work on that by the way!) but where exactly can I make some modifications so that I can "simulate" some "messages" being passed through the nodes and it would show the same on the terminal? (for example: "node1: message passed to neighbours 2,3,4","node2: message passed to neighbours 1,3,4"... and so on). Thanks in advance for your help and great article! :)

W Wouter Bulten

Hi! Thanks :)

If you want to use my code you can just remove the animator object. The NetworkController has an 'iterate' method that runs a single iteration of the simulation. So, in your program you can just call this method and disregard the network animator.

M Mohammad Fazlul Hasan Shariff

Thank you for your response. Is it also possible that I can use the project (with the above descriptions taken into consideration) to run it in a single, complete python script? I wish to not have any dependencies like calling other scripts etc... Thanks for the help :)
(Please excuse me for my silly questions, the reason is that I am trying to run lightweight neural networks on the similar project and it would help greatly if everything is in a single script)

W Wouter Bulten

Of course, you can just download the code from GitHub. However, importing local modules should not be an issue performance-wise. As far as I know, there is no need to concatenate all files. You can check https://github.com/wouterbu... for an example of how everything ties together. Good luck!

Just out of curiosity: how are you combining deep learning (?) with WSN?

M Mohammad Fazlul Hasan Shariff

I am planning on using a dataset from an Intel Berkely Lab experiment (http://db.csail.mit.edu/lab... into the project. Firstly, I want to simulate that the attributes "temperature", "humidity" etc. are being passed from one node to its neighbours.
The real reason why I would use deep learning here is that I plan on doing anomaly/error detection. Some data shows 122.323 deg. C which is obviously not a normal room temperature and I need to be able to detect this using LNNs :)

W Wouter Bulten

Cool, well good luck with your project! If you need some simple noise filtering, there is also a blog post on Kalman filtering on the website. Could be of use to you!

Adding new comments is no longer possible. If you have a question or remark, please reach out via the contact page.

Copyright © 2026 Wouter Bulten

I may not have gone where I intended to go, but I think I have ended up where I needed to be.

— Douglas Adams, The Long Dark Tea-Time of the Soul

Colophon & disclaimer