Blog

Lightweight Javascript library for Noise filtering using Kalman filters

(updated October 11, 2020)

Filtering noisy measurements can be an extremely difficult endeavor; take brain signals for example. While this is true, there are also many situations where the system is fairly simple and the focus lies on speed, online computation (i.e. in real time) and ease of use. Filtering distance measurements from a sonar sensor can be such a case. For these applications it is useful to have a simple, but effective, noise filtering algorithm in your toolkit. Let me introduce KalmanJS: a small library implementing the idea of Kalman filters, without any dependencies, to filter out noise in 1D systems.

I’ve used Kalman filters extensively in the past and they are a fast and easy solution for many noise filtering applications. Recently, I was in need of a small javascript library (i.e. no dependencies) that would work fast on 1D data (i.e. the dimensionality of the input data is 1). I’ve created this as part of my indoor localization project and just recently transformed the Kalman filter part into a separate library. In this blog post I quickly show how you can use the library to filter out noise. Even if you create your own implementation, it should be able to give you the gist of how everything works. In the next few days a second blog post will focus more on the how of these filters. For now, we just look at the results and some fancy figures!

Tl;dr: Why should I use Kalman filters?

  1. Low memory: the filter does not require the whole data set to function. Only a few integers.
  2. Fast (low time complexity)
  3. Easy to implement
  4. Good results (and that’s what we are here for)

Minimal working example (based on the latest browser release of KalmanJS):

<script src="kalman.min.js" type="text/javascript"></script>
<script type="text/javascript">
  var kf = new KalmanFilter();
  console.log(kf.filter(3)); // 3
  console.log(kf.filter(2)); // 2.3333333333333335
  console.log(kf.filter(1)); // 1.5000000000000002
</script>

First example: Constant data

We start with a simple exampling in the form of a constant system: our true state (e.g. distance measurements) is constant but measurements of this state are affected by high levels of noise. If you look at the graph below, would you be able to find a good estimate of the true state?

Note: Data is automatically generated, every time you refresh the page you will see a different dataset.


Figure 1: Our first data is a constant system. Unfortunately, as in real life, we only measure the noisy data. Noise is produced by adding Gaussian noise.


The data is generated by two simple map operations:

var dataConstant = Array.apply(null, {length: dataSetSize}).map(function() {
  return 4;
});
//Add noise to data
var noisyDataConstant = dataConstant.map(function(v) {
  return v + randn(0, 3);
});

randn(mean, sd) is a simple function that returns random numbers following a Gaussian distribution

So how do we filter this data? The KalmanJS library consists of a single class and each instantiation of that class represents a single system. To use the Kalman filter we apply the filter on each value of our dataset:

//Apply kalman filter
var kalmanFilter = new KalmanFilter({R: 0.01, Q: 3});

var dataConstantKalman = noisyDataConstant.map(function(v) {
  return kalmanFilter.filter(v);
});

Note that we apply the filter on each individual data point. The filter does not keep a record of all previous values; it only stores the current estimate and a measure of its certainty.

The only thing we have to worry about in our constant system is the estimate of the noise levels which are represented by R and Q.

There are more variables we can set in the filter but these are not important for our current example.

R models the process noise and describes how noisy our system internally is. Or, in other words, how much noise can we expect from the system itself? As our system is constant we can set this to a (very) low value. Q resembles the measurement noise; how much noise is caused by our measurements? As we expect that our measurements will contain most of the noise, it makes sense to set this parameter to a high number (especially in comparison to the process noise).

In real life scenario’s you usually make an estimate of R and Q based on measurements or domain knowledge. For this example we assume we know the noise levels.

Now let’s apply the Kalman filter on the data set and see how it performs:


Figure 2: Kalman filter applied on the constant data set. The true state of the system is also displayed. The Kalman filter, after some initialization, fits the data nicely.


Second example: Exponential data

Constant data is nice, but sometimes (better: often) we have a system that moves. For this second example I generated values from a simple exponential function. Depending on the noise (try reloading the page a few times) the function is only barely noticeable in the data.


Figure 3: Second example showing an exponential increasing function. Only the noisy measurements are shown.


Data is again generated using simple map operations:

var dataExponential = Array.apply(null, {length: dataSetSize}).map(function(e, i) {
  return Math.pow(1.1, i);
});

var noisyDataExponential = dataExponential.map(function(v) {
  return v + randn(0, 20);
});

Now we apply the Kalman filter the same way as in the previous example.

The Kalman filter can also incorporate movement information in its estimation steps. If you know, beforehand, that a system is non-constant you can use this to improve your results. For now, we just apply a constant filter and see how it performs.

var kalmanFilter = new KalmanFilter({R: 0.01, Q: 20});

var dataExponentialKalman = dataExponential.map(function(v) {
  return kalmanFilter.filter(v);
});

Figure 4: Result of the Kalman filter on the exponential data. Depending on the noise the results will range from “not very good” to “awful” (again, try reloading the page to see more examples). The constant filter is not able to capture the growth of the function.


Hmm, our constant Kalman filter is not really able to keep up with the exponential growth. This simple approach often works for systems that have a small growth function. The Kalman filter can easily adapt to changes if they are not to large in relation to the data points. Unfortunately, our exponential growth is to large.

Can we still rescue our exponential data?

Third example: Predicting growth

Luckily for us, the Kalman filter offers several ways to incorporate more domain knowledge. We can model how a previous state effects a new state (through the parameter A of the library) but can also incorporate motion commands. This last option is useful if you know that a function only changes given some external or internal input (e.g. a movement command to a robot).

A simple example would be a function that only grows given some external input:

//Here B is the control parameter and is multiplied by the control/action on each filter step
var kalmanFilter = new KalmanFilter({R: 0.01, Q: 20, B: 2});

//Additionally to the measurement we also give an additional control value to the filter
kalmanFilter.filter(v, 1); //Motion is applied
kalmanFilter.filter(v, 0); //Motion is not applied

How you can use these control vectors is a bit out of the scope of this post; just remember: if you have a system where there is movement caused by events there are ways to incorporate it into the filter.

For now we focus on A which is the transition variable that describes how a state transforms from a previous state to the current. In our exponential growth example we know that each new state is the result of a multiplication of the growth factor (1.1) times the previous state. We can tell this to the Kalman filter and the filter will use this additional information in the filter step:

var kalmanFilter = new KalmanFilter({R: 0.01, Q: 20, A: 1.1});

var dataExponentialKalman = dataExponential.map(function(v) {
  return kalmanFilter.filter(v);
});

This adjustment results in a far better fit. Using our prior estimate of the growth we are able to nicely fit the data and filter out a large portion of the noise:


Figure 5: Result of the new Kalman filter (with growth model) on the exponential data. The filter performs far better than the previous filter which did not have any model for the growth of the data.


Interactive example

Want to experiment with the variables and various settings yourself? @benwinding made a nice interactive demo of the Kalman JS library. In the demo you can see how the settings interact and how this effects the filtered output.

Wrapping up

By now you should have a rough idea of how you can apply Kalman filters to filter out noise. If you want to see the internal workings of the filter I used in this post you can check out the GitHub repository. For everyone who has 1D data and is in need of a low complexity implementation, I suggest that you give these type of filters a try. They are fast and easy to use.

Higher dimensional data? Rest assured, there are also multi-dimensional implementations available on the web!

Any questions or comments? Please see the comments section below.

KalmanJS in other languages

Kalman filters can be useful in a broad range of projects. Regularly I get questions whether KalmanJS is available in other languages than Javascript. Several contributers have made implementations of my library in other languages, including Python, Java and Objective-C. These versions are stored in the contrib folder on GitHub.

Disclaimer: These implementations are often untested and are only placed in the contrib folder for convenience in the hope that they can be useful for other projects.

W. Bulten, A. C. V. Rossum and W. F. G. Haselager, “Human SLAM, Indoor Localisation of Devices and Users,” 2016 IEEE First International Conference on Internet-of-Things Design and Implementation (IoTDI), Berlin, 2016, pp. 211-222. doi: 10.1109/IoTDI.2015.19 Online publication

Comments (108)

M Mihai Miculescu

Great article! Thanks!
However, I cannot read it on Chrome / Desktop. I get this:
"This webpage is not available
ERR_SSL_VERSION_OR_CIPHER_MISMATCH
A secure connection cannot be established because this site uses an unsupported protocol."

I can read it on Firefox/Desktop
and on my Android smartphone, using ... Chrome ... :)

W Wouter Bulten

Thanks! I will definitely look in to the ssl error. Are you using Windows on your Desktop by any chance?

M Mihai Miculescu

Yes

W Wouter Bulten

The type of SSL certificate that I use is unfortunately not supported on Windows XP using Chrome and IE but Firefox, as you said, works fine.

M Mihai Miculescu

I plan to use the filter for a Grove - 3-Axis Digital Accelerometer(±1.5g), connected via i2c to an Edison SoC. The sensor measures the 3 components of the acceleration vector a, namely ax, ay and az respectively.
My question is: use 3 instances of your 1d filter, one for each axis, or look elsewhere for a multidimensional implementation?
After all, the 3 components of the acceleration vector as measured by the sensor describe the one and same phenomenon ...

W Wouter Bulten

It depends on your application. For example: I've used this type of filter and a 3-axis accelerometer to count steps. I first compute the norm of the x,y,z values and then apply the filter on this new value. This is more efficient than running the filter 3 times.

See https://github.com/wouterbu... for an example.

You can also use a 3D version but these are computationally more expensive, harder to implement and give only benefit if you actually require them for your application.

Let me know if you need any more help :)

M Mihai Miculescu

It is to be mounted on a car model. Another application would be on a drone, for flight data recording. Something like a " black box" for analyzing the vehicle behavior during operation in both cases. Further development would be for providing data, alongside a digital compass and a gps, for remote controlling the vehicles

W Wouter Bulten

So you just want to record the x,y,z values?

If you need filtered individual values, I think you can use both methods. It is probably fine to just perform the filter 3 times, the complexity is low so it shouldn't have that much impact. Just make sure that you use a separate filter for each channel.

You can also use a multidimensional filter if you suspect that noise in one axis has an effect on the noise of another level (which is probably the case). I'm, however, not sure whether the improvement in accuracy (if any) is worth the extra work.

M Mihai Miculescu

Thanks!

K Kyungho Lee

I appreciate for your wonderful, detailed explanation on how to create a simplified Kalman filter. By the way, I was also impressed by the quality of the plots in the article. Which library do you use for generating these plots by any chance? :) Happy new year!

W Wouter Bulten

Thanks! Happy new year to you too :) I use ChartJS (http://www.chartjs.org/) for the charts on this page. Really nice library and easy to use (though, the chart options are limited).

K Kyungho Lee

Thank you for your reply. I will try using it!

S Scott Mahr

Hi, I am working on a simple system that I measure in two ways. It is a system where I am trying to measure the vertical position of an object. I have a barometric altimeter (measures height, with noise and drift) and an accelerometer(measures acceleration with noise). I would like to combine these measurements into a best guess of the vertical position. I think I need a 3d system right? Where I have position, velocity and acceleration as my three parameters? Any ideas for other JS libraries that could help me with this?

Thanks,

Scott

W Wouter Bulten

Hi Scott!

Did you already take a look at my other article about Kalman filters? (See https://wouterbulten.nl/blo... ) There I explain more of the background of the technique.

Regarding your specific question: In what way do you want to use the accelerometer for measuring? To predict movement and to account for that in your estimation?

Whether you need a 3D system depends on your output. It is totally possible to use 1D Kalman filters on your individual channels. If you only want to estimate height, another option is to first combine all your sensors and put a filter on the position estimate.

For example: In another project I've used an accelerometer as an input for a pedometer (to count steps). There I use the 3 axes of the sensor but apply the filter on the norm of the acceleration vector, and not on the individual values.

S Scott Mahr

Hi Wouter, thanks for the quick reply. I just read your other article. I think I have a pretty good handle on what Kalman filters do, I just don't know exactly how best to set mine up. My current thinking is to have the three parameters be acceleration, velocity and position. Based on the current state, I can put in a model for what the next likely state of those parameters would be. I am using the magnitude of the accelerometer, assuming my object is moving in only one direction. My impression is that the kalman filter can have inputs measuring two of these parameters (position and acceleration), and take into account measurement and system uncertainty to give the most likely true position. I basically want to fuse together acceleration and height measurements to get a better idea of what the system is doing. Is this is reasonable approach?

Thanks,

Scott

W Wouter Bulten

Hi Scott,

From what I understand from your description you have three scalar values:

- Acceleration measured by the accelerometer
- Velocity measured by ??
- Position (or height) measured by the altimeter

Your goal is to estimate what the individual true value of these parameters are given the noisy sensor measurements. Am I correct? Or are you interested in a single 'position' value?

For the individual parameters you could use a 1D Kalman filter to smooth the output of the sensors. You will need a separate filter for each sensor. That would be a very easy and computational fast approach.

If you are more interested in a single position value then you can also fuse all the sensors and use the combined information in the update step of the filter. See also the example on Wikipedia: https://en.wikipedia.org/wi...

Maybe it is also good to take in to account that the values are probably correlated. E.g. a weather balloon's acceleration and position are both influenced by wind.

In general: Start by defining your state. What do you want to estimate? i.e. what is your x? Start from there and then go forward: how is x updated? etc. (see my other post for the definition of the transition model)

Small note about the lib: The library in this post only works for 1D systems, that's why its so lightweight. If you go for a multidimensional approach you should look for another library or implement the formula's yourself. The latter is probably the most efficient option (in terms of computation) but will require some more effort.

S Sander Ploegsma

Hi Wouter,

Nice article! I am trying to find the right mathematical approach to 'predict' the amount of connections for a web service in order to find out how to scale it accordingly. I am thinking that something like a Kalman Filter could help me smoothen out stuff like a server becoming unhealthy and getting replaced, temporarily dropping its connections and therefore 'polluting' the data.

What I do not really understand is how to set a correct value for Q. Let's say I have 1000 connections which drop to near-zero for a brief moment and then come back up to 1000, would that mean that I'd set Q to 1000?

W Wouter Bulten

Hi Sander, thanks!

Cool application. Would definitely like to hear what your outcomes are!

Regarding Q: R models the process noise and Q the measurement noise. The value of these constants depends on your system and the way you measure. I assume that most of your noise will be in the system. A drop in the amount of available connections will always be caused by a server being unhealthy (the process). And not by a fault in measuring (the measurement), right? If so Q can be set to a very low value as you will assume that your measurements are correct.

A Arman Assylkhan

Hi, Wouter!
First of all my gratitude for your article!
I am working on a project for ibeacons detection and distance estimation with Node-RED (node js based) language. I can detect beacons and read their data (RSSI particularly).
I wanted to apply Kalman filtering for the noise cancelation but a bit stuck here.
Was wondering if you could clarify some points:
Do we need to feed the RSSI data to the Kalman filter as an array or we can just keep updating the values one-by-one?
If you have used Node-RED, is it even possible to use Kalman filter in node-red?
I've tried to use kalman-filter node designed for Node-RED from here https://github.com/syuhei17... but it didn't work for me
Was wondering if you could clarify for me these points.

W Wouter Bulten

Hi! Thanks :)

The answers to your questions:

1. One-by-one is fine! It is one of the benefits of the Kalman filter.
2. I looked at your source code and it seems fine. What seems to be the problem? Make sure to pass numbers though!

Succes!

M Mika Andrianarijaona

Thank you for sharing this. I will give a try to the JS module.

M mark

Sorry am not an expert programmer but how can I apply the filter to given RSSI from an ibeacon. i.e. RSSI as only input to the filter. I would like to find the estimated distance the beacon is away. Thank you.

W Wouter Bulten

Hi Mark! The filter is a 1D filter so only has a single input. Just pass your measured RSSI to the filter and you will get a filtered return value :)

M mark

Does it mean all I do it is this
e.g RSSI for ibeacon is -72 then I will get back another RSSI?

import KalmanFilter from 'kalmanjs';

const kf = new KalmanFilter();
kf.filter(-72);

I see the JS requires alot of parameters
constructor({R = 1, Q = 1, A = 1, B = 0, C = 1} = {})

Sorry to trouble you.

W Wouter Bulten

Yes! That's all there is to it :)

One disclaimer:

The parameters are used to model the system, and to get good results these must be set to sensible values. For RSSI you can start with assuming that the system is constant and look at example 1 of this article. (If you're not afraid of some math look at: https://wouterbulten.nl/blo... )

A good starting point could be something like this:

var kalmanFilter = new KalmanFilter({R: 0.01, Q: 3});

This assumes a constant model with low process noise (R) and high measurement noise (Q). Q models the noise from the measurements which is often high with RSSI. To further tune it to your situation measure the variance of the RSSI signal over time and set Q to that.

M mark

Thank you for the help. This is what I should be doing correct and try out different R and Q values?
var kf = new KalmanFilter({R: 0.01, Q: 3});
var result = kf.filter(rssivalue);

W Wouter Bulten

Yes! Let me know how it works :)

S Sagar Sen

Thanks Wouter for the very intuitive tutorial. I am using it to filter my strain gauge data. However, I have a DC offset that changes over time. The red signal in the figure represents the original signal and the blue one is the filtered signal. You can see a overall downward trend that I want to also filter. Any thoughts?
Should this be a 2D Kalman filter?https://uploads.disquscdn.c...

W Wouter Bulten

Hi Sagar,

Your input data is still 1D right?

Did you read my other article that goes deeper in to the math behind kalman filters? https://wouterbulten.nl/blo... In the 1D variant there are two parts of the transition model: the current state is based on the previous state (given some transformation matrix A) and a control. With simple static systems, such as used in the first examples of this article, the latter is zero and A is an identity matrix (i.e. previous state = current state + noise). In your example it seems that the transformation matrix A is not a identity matrix but should represent the downward trend. See the "Predicting growth" example where A represents a growth.

A nice toy example is that of a flying drone: Given no motor actions the drone will drop out of the sky. In that case A should be some negative transformation, transforming the previous state (e.g. 100 meters above ground) to a lower current state (e.g. 90 meters).

A Anton Prabhakar

Hi Wouter,

I'm very new to this Beacon technology, and im also trying to estimate the distance between a beacon and mobile phone using the RSSI value received. Between i came to know that filters are to be used to smoothen the received rssi value, here your library comes into handy. But i have some doubts like

var kalmanFilter = new KalmanFilter({R: 0.01, Q: 3});

I can understand the process noise(R) and measurement noise(Q), but why are you fixing the Q value to 3. Is it you trying to say that the measured raw rssi value would be plus or minus 3 of the original value ?

Looking forward to your reply

W Wouter Bulten

Hi Anton!

You are going in the right direction, filtering is really useful when working with RSSI values.

I wrote a paper on this topic that could be of interest to you. See http://ieeexplore.ieee.org/... In this paper I use both Kalman Filters and SLAM to locate beacons.

To come back to your question: Fixing Q is purely convenience. Normally you do not know the true noise level in your data (as it is noise) and that's why you try to estimate it as good as possible. In my experiments I measured the noise and used that as a value for Q. If, by any means, you have more information about changes in the noise level you can of course integrate that in your system. For example, if you know that entering a specific room increases the noise level you can increase Q and by that tell the system to trust the raw RSSI value less.

A Anton Prabhakar

Thanks for your quick reply. And I also want to know that whether the noise in rssi value differ from beacon to beacon ?

W Wouter Bulten

Definitely! Though, in my experience, the environment has often a larger effect on the noise than the individual Bluetooth radio's. (Assuming equal devices in terms of hardware and such)

A A. Gisept

Why R for Process noise and Q for Measurement noise while in every resource on Kalma Filters I find it is "Measurement Noise(R) and Process Noise(Q)"?

W Wouter Bulten

I use the definitions from the great "Probabilistic Robotics" book by Thrun et al. See:

S. Thrun, W. Burgard, and D. Fox, Probabilistic robotics. the MIT Press, 2005.

T Tarik

Hello

My gratitude for the good work. I am trying to use the module in node.js environment and have two questions:
1. i am getting "not defined" error for the randn function. what am i missing?
2. what do you mean by dataset? a set of measured rssi values i guess. in my module i am measuring rssi and pushing the values to an array of say 100 elements. how do i kalman-filter those data?

Thanks in advance

W Wouter Bulten

Hi Tarik,

1. As stated in the article "randn(mean, sd) is a simple function that returns random numbers following a Gaussian distribution". This is not part of the default JS environment. You can replace it with a normal uniform random function if it is just for testing.
2. You can just filter the values when they come in. The filter does not need the previous values. So just call the filter() function for any value that comes in.
3. You don't need the length of the dataset. The dataSetSize variable in these examples are just used to generate some example data.

T tarik

Thank you. as far as my program goes, i input the algorithm with the whole array of measured rssi values, and it returned a new filtered array, which is achieved by the .map functionality.
By the way do you have any method or advice as to how to establish the R and Q values in the real environment, which will be a car service in my case. In the blog you mention somewhere that you measured the noise but don't explain how.
are we supposed to find the correct value by trial and error or what?

Thanks again

W Wouter Bulten

Copying from an answer I gave some time a go:

"Fixing Q is purely convenience. Normally you do not know the true noise level in your data (as it is noise) and that's why you try to estimate it as good as possible. In my experiments I measured the noise and used that as a value for Q. If, by any means, you have more information about changes in the noise level you can of course integrate that in your system. For example, if you know that entering a specific room increases the noise level you can increase Q and by that tell the system to trust the raw RSSI value less."

So, yes, in my experiments I recorded RSSI over time and calculated the noise level from that (i.e. the standard deviation of a signal that should be constant).

T tarik

Your last sentence is critical, mentioning standard deviation. So is Q std-dev. of the measured signals in a noisy environment? So i measure rsssi say 1.000 times and calculate the std-dev as 3, and that means the Q is 3?
Sorry but i am trying to get a concrete definition of Q...

W Wouter Bulten

Technically Q is a covariance matrix. More details can also be found here: http://ieeexplore.ieee.org/...

But, yes, sampling the RSSI within your environment and setting Q to the variance of that would be a sensible approach.

T tarik

Two more and probably the last questions:
1. i have a set of rssi values and i get a new set by kalman-filtering. now do i calculate the arithmetic average to get a single value out of them or what?
2. if i have a data set of really inconsistent measurements, does applying a sort of data smoothing method before applying kalman distorts the functionality of kalman?

Thanks and my best regards

W Wouter Bulten

Hi Tarik,

1. The idea of the filter is that you process the values one by one as they come in (which will always result in a single number). So normally you would do this filtering in an online setting and then just take the last filtered value. If you want an example, I implemented this in a indoor localization algorithm/app. The part about applying the filter can be found here: https://github.com/wouterbu...

2. The kalman filter is meant to smooth your data. So yes, using another smoothing step would probably not help much.

T tarik

just to make sure: can we say that kalman filter is used for measuring the distance of static object. but when we try to locate a moving object, another version of kalman, which is usually referred to as extended or non linear kalman filter should be used.

W Wouter Bulten

Hi Tarik, did you by any change were able to read my paper? As that addresses locating objects during movement.

This library is for a 1D kalman filter. It works best for static objects, but I also used it for moving objects. If your sample rate is large enough you can make the assumption that the device is static within a small time frame, because the noise caused by the measurements is usually larger than the difference caused by the movement (assuming the object is moving slowly, e.g. walking speed).

For location, however, you cannot use a 1D filter alone as distance is at least 2D (x,y) and sometimes 3D (x,y,z) and this implementation of the Kalman filter would not be able to represent that. So to come back to your question: you can use this Kalman filter in the process of locating a moving object but for the actual localization itself you will need something else. An extended kalman filter can be used for this, but it depends a bit on your application.

T tarik

yes i have read, but maybe couldnt understand very well. thank you again for your time to answer me :)

W Wouter Bulten

No problem! Good luck with your project :) Let me know if you have any additional questions.

If you would like to have even more information: My master thesis can be read online ( http://theses.ubn.ru.nl/han... ) and contains a lot of background information on indoor localization. It also explains some of the subjects in more depth than the paper (as the paper is a summary).

T Tarik

and one more question. would datasetsize be the length of the array of measured rssi values for my case?

P PRATIK NAIK

how can i use this filter for GPS in android for getting precious location?

W Wouter Bulten

Hi Pratik, in what format is your data? Are they just floats? If so, please look here https://github.com/wouterbu... for an implementation in Java you could use in Android.

R Ramdhani Izmar

Sir.. i'm very interest about your method to filter noise and get Smooth RSSI value.. by the way, i have same problem... how to include my RSSI value to your kalman filter method. for example i have RSSI value : -76dbm, -75dbm, -75dbm. how to input the value to kalman filter on kalman flter variable ?

W Wouter Bulten

Hi! You can call the filter() function for every RSSI value you measure. The output is the current estimate of the signal strength at that point in time.

A Akın Evren Özsu

but, doesnt it have to be filter in array? it is filtering according to what?

W Wouter Bulten

The filter is an online filter and filters one value at a time. The current state is stored inside the class so you can just pass your values one-by-one.

M Matt Gregg

Would this work with a sinusoidal wave?

W Wouter Bulten

Yes you could. However, if you know that the data follows a certain function its best to incorporate it into the movement model. Take a look at https://github.com/wouterbu... you could change that implementation to follow your wave. Let me know if you got it working, could be a nice extension :)

W Wern_Ancheta

thank you for this! Is it possible to use it to predict bus arrival times using GPS data?

W Wouter Bulten

For GPS data: yes. You could use this to filter longitude/latitude to get a smooth signal. Location is 2D (or 3D) though, so a 2D filter could even be better as you can take uncertainty of both inputs in to account. If you want a simple approach you can just use two 1D filters.

How you go from GPS to prediction of arrival time.. that's more an application question.

A Anandaram Katragadda

Hi Wouter

We are looking to implement the kalmankfilter in embedded system, Doyou have C code for the kalman filter

Regards
Anand

W Wouter Bulten

Hi! Currently there is only a Java and python implementation available in the contrib folder. See https://github.com/wouterbu...

However, there are other (possibly also C) implementations available online. You could also try to implement a C version yourself based on one of the implementations in the repo.

A Anandaram Katragadda

https://uploads.disquscdn.c... https://uploads.disquscdn.c... https://uploads.disquscdn.c... Hi Wouter

Noted. Quick query we tried to run the kalman filter and weighted avaerage on a moving BT beacon RSSI values to identify the distance from a Fixed BT transmitter , when we run with the Parameters R=0.01, Q= 3 , R=0.01, Q=20 , B=2 , R=0.01, Q=20, A=1.1, I see curves very strange in the motion of the last 2, can you help us where we are doing wrong.

W Wouter Bulten

Hi,

Did you try out the examples of the article or is there a underlying reasoning for your values of A and B? Namely, B models motion and A models transitions from t-1 to t. If the values that you set for A and B do not match the system you are modelling the values will be extremely off (which can be seen in your examples).

For example: lets say you model the position of a drone. Given no motion a drone will slowly fall to the ground. So your A should be negative. However, if you set A to a positive value then the model will never be able to correctly capture the real events (as the motion model does not match).

A Anandaram Katragadda

Hi wouter, Thanks for your response, we had actually used your constants to check and see the results. We yhoutho you had also modelled the object moving and given values to A and B. What you recommend values( A, B) for a person carrying a BT Rx, moving towards a BT tx ?

W Wouter Bulten

If your movement model is unknown I would disregard A and B, and see if increasing R and Q gives you enough to overcome the invalid motion model. If you take enough measurements the model will eventually show the correct values. The Kalman filter is then primarily used to smooth the values.

If you know that someone is getting closer to a beacon you can try to use negative values for A (depending on whether you are measuring meters or RSSI).

Did you also read my article on RSSI filtering? https://www.wouterbulten.nl...

A Anandaram Katragadda

Thanks for the info. wouter. will check

J Javier Melendez

Hey Wouter!
Great work, all your papers are clear and easy to understand even for beginners.
I read this about 9 months ago, and tried to implement it in an indoor position system.
However the team decided that a particle filter was the way to go. Nowadays, our beacons still transmit noisy RSSI values that the particle filter can't compensate.
Do you recommend to pass the data through the KF before putting the RSSI values into the Particle Filter?.
Also, what model do you recommend for RSSI value reading, is predicting growth the way to go?
Thanks for sharing!!!

W Wouter Bulten

Hi Javier,

Thanks! That's exactly what I did for my Human SLAM project. First filter the values using a KF and then combine it in a particle filter (also based on other sensory input). You can read more about it here http://ieeexplore.ieee.org/... or https://www.wouterbulten.nl... or see the slides of my presentation on it here: https://www.wouterbulten.nl...

J Javier Melendez

I'm so glad to hear that!
I see that if you use a pure constant, the filter loses responsiveness thus the localization algorithm wouldn't be so precise. In your experience do you recommend one specific model for the RSSI noisy signals?

W Wouter Bulten

You are correct. I use a constant as I have a high update frequency and found that a constant noise filtering worked fine. The filtered signal is then used as an input for a particle filter that can deal with any remaining noise.

In my experiments I used: R: 0.008 and Q: 4

A Andi Eppler

Hey Wouter!

First of all, thank you for your work! Your filter is understandable, smart and with your examples it is easy to use.
I am using your kalman filter also for RSSI data but from bluetooth beacons. I am calculating the distance for a real time application. I use the Java-Version of your filter for an Android application.

https://uploads.disquscdn.c...

My problem is: There seems to be a sort of "delay". The peaks of the kalman curve seems to be late. I thought I would fix this problem by using input information for the motion. But with my input information, the curve is still delayed and the results are not better with the input.
I collected the data by walking up and down towards the beacon. So I estimate a sinus course.

Do you have any suggestions for me to get rid of the delay?

W Wouter Bulten

Hi Andi,

Thanks for your post! The delay is somewhat expected: the Kalman filter (without movement model) thinks that the signal should be a constant number with added noise. The more measurements you do the better the filter will be able to estimate this number. If you are walking towards the beacon, at first the filter thinks the increase in signal is noise (as it assumes it to be static). After a while, as more measurements will show that the static number has changed, the filter catches up. This delay you are seeing is the result of that, but at the same time this delay also means that noise gets filtered out.

If you want to lower the delay there are a few things you can do:

1) Add a motion model. You already tried this but I'm not sure the implementation is correct. I just saw that the Java version on github is missing the input to the motion model. The Javascript version has a second parameter (u) where you can enter the motion. See https://github.com/wouterbu... If you have time you could look at the JS version and update the Java class. A pull request would be greatly appreciated!

2) Lower the noise parameters. If you assume the noise is lower the filter will react faster to changes. Downside: there will be more noise in the data.

A Andi Eppler

Thank you for your response, Wouter! :)
I just used the kalman filter for a short period of time. Therefore I haven't seen any time-depending improvements yet.

1) I've just updated the Java class for my needs by expanding the constructor KalmanFilter(double R, double Q) to KalmanFilter(double R, double Q, double A, double B , double C).
Also, I've changed the method filter(double measurement) to filter(double measurement, double u) and removed the term on https://github.com/wouterbu... .

2) I have lowered the noise parameters, simulated a longer period of measurements and it seems that the delay is getting smaller.

But my current kalman filter does still not satisfy my needs. At the moment, I have nearly no idea how to change the values and it's more trial and error than logical thinking. I think, with more knowledge about the kalman filter, I will find a satisfying solution. :)
At the moment I use following values:
R: 0.008, Q: 2, A: 1, B: 1, C: 1 and u: 0.2

W Wouter Bulten

If you have something stable, a pull request on Github would be very helpful to other people using the Java version :)

Regarding your values:

- The value for R seems fine. Most noise comes from the environment and not from the process.
- For Q, I would measure your RSSI values and compute the variance, then use that value for Q. You want Q to reflect the noise of your environment.
- A seems fine to. With A=1, you assume that without movement the signal should be the same.
- B and u completely depend on how you model motion. RSSI is not linear so this can be tricky within the 1D kalman filter. What you could do here is model distance to the device (using Log-distance path loss model) instead of RSSI directly. In that way you can more easily use B and u. For example, if you know the user moved 1 m, you can set u to 1 (given that B is 1).

Due take in to account that the Kalman filtert could be to simple for your needs. It is a very good lightweight filter but don't expect magic ;) Some form of delay for example is exactly how the filter should behave. I have used this filter in a project where I wanted to locate Bluetooth beacons inside a room. I used the Kalman filter to remove the largest noise from the RSSI signals but then used those values in a particle filter for further processing.

Let me know if you have any specific questions and I'll see if I can help you out!

J jaggedsoft

This is amazing. Nice work!

W Wouter Bulten

Thanks :)

A andresmafra

While tracking GPS lat and lng, this can be used to estimate the compass direction?

W Wouter Bulten

The Kalman filter can be used to de-noise a signal. So, possibly, yes :) You would still need to do the calculation of the direction yourself and then use the filter to remove noise.

S s0b31t

Hi Wouter

Thanks for your great work! We use the filter in an Android application, walk up and down toward a wifi beacon, or stay static. We do try several parameter combinations, however can't get a satisfied result so far. We follow each of your comments in this post and another one https://www.wouterbulten.nl... to avoid missing anything important, could you take a look at our samples? That would be much appreciated.

https://uploads.disquscdn.c... https://uploads.disquscdn.c... https://uploads.disquscdn.c... https://uploads.disquscdn.c... https://uploads.disquscdn.c...
https://uploads.disquscdn.c... https://uploads.disquscdn.c... https://uploads.disquscdn.c... https://uploads.disquscdn.c...
https://uploads.disquscdn.c...
https://uploads.disquscdn.c...

You can see in these samples, when setting Q to 0.1 and u with 0 gets the best fit, but i don't think it's proper result, we calculate the wifi RSSI variance when static and get 11(with some distance away, and gets smaller when closer). And when use motion model, the filtered result gets more ridiculous when stay static. We do try filter with RSSI to meters and transfer back to RSSI, the results are even worse, which not included here.

W Wouter Bulten

Hi!

Nice graphs! Based on your input, I think you have a wrong assumption in the motion model. The parameters u and B controls the update of the system on each step. If you set u and B both to 1 this results in an increase of the predicted value of B*u=1. You can also see this in your last graph; the filter signal goes up even though the original signal is fairly constant. If you take 50 samples per second this means that the expected value goes up with 50 every second. In other words:

u: Only set this value to 1 if the user is moving, set it to zero when you know the user is static.
B: Make this a good approximation of the distance decrease/increase in each step.

If you want to use a motion model you need to determine an expected update for each step. This can be done using the Log-Distance pathloss model (see https://www.wouterbulten.nl.... As you can see in the formula, the expected RSSI update is not linear but depends on the distance to the device. However, this 1D kalman filter only works with linear functions. You could approximate the distance model but it will be very inaccurate.

You could try two things:

1) Filter the estimated distance (in meters) instead of RSSI. Now you can incorporate a basic linear motion model. For example by assuming that the user moves 50cm closer each step (B=0.5, u=1).

2) Disable the motion model and let the filter work everything out itself (u=0, B=0). This is what I usually do as there is so much noise in the signal that a simple motion model is just not powerful enough.

In my indoor localisation project I used approach 2) and used a SLAM approach for modelling motion and location (https://www.wouterbulten.nl....

T ToastyInk

Thanks for sharing this library it's been very useful so far although I do have a question ...

I'm using multilateration to calculate the location of an aircraft using the time difference of arrival (TDOA) technique but there is some variation in the calculated positions (which I'm treating as noise) as well as the timesteps between them. The multilateration process produces a lat,lon pair and an HDOP estimate for each aircraft position but these positions are not calculated on a regular basis but can be any interval apart, anything from less than one second to 5 seconds is not unusual.

I''m trying to produce a smoothed flight path based on these lat, lon pairs and it works rather well but the problem is that the Kalman filtered positions consistently lag behind the actual aircraft position acquired by observation.

I'm treating each coordinate (lat and lon) as independant of one another (possibly not a valid assumption) with the following parameters:

R: 0.01
Q: 3
A: 1
B: 0
C: 1
u: 0

I get the best results (athough the filtered position lags behind) using the values above. I've played around with changing the value of B (0.05) and u (1) but I simply get a wierd offset applied to the filtered position.

Is there anything that you would recommend to reduce the apparent lag ? I've tweaked most of the values and have found that a value of R<1 introduces the delay whilst values > 1 there's almost no delay but the result is a lot noisier whilst increasing the value of Q helps smoothness but also adds to the delay.

Would it be worth moving to a 2D version of the filter or is my assumption that it's two 1D problems valid ?

W Wouter Bulten

Hi! Could you apply the filter to the TDOA data? That seems to make more sense in your case. You filtered the noisy measurement and then determine the latitude and longitude based on the filter values.

K karthikeyan

Hi Wouter,

Thanks for you fantastic work!. I'm working on the estimating the distance between a mobile phone and a beacon. I 've an android application which will listen to the incoming RSSI
values from the beacon. We take tests with mobile phone held in hand and moving towards and away from the beacon. Below is a sample plot which shows when a user is moving towards
the beacon from 2 meters. I used the python implementation from your library with the following values:
R: 0.008, Q: 2, A: 1, B: 0, C: 1 and u: 1

I need more understanding about the following parameters

Q - For Q you have mentioned in one of your comments to use variance. What if I used STD instead as I think variance will have high values in my case where STD is 13.
My STD will chnage in each position, does that mean I shall change Q as well

A - Quoting from one of your comments "A seems fine to. With A=1, you assume that without movement." Since I'm in motion towards and away from the beacon,
what shall be the best input for A?

B and u - Again from your comments "B and u completely depend on how you model motion. RSSI is not linear so this can be tricky within the 1D kalman filter. What you could do here is
model distance to the device (using Log-distance path loss model) instead of RSSI directly. In that way you can more easily use B and u. For example, if you know the user moved 1 m,
you can set u to 1 (given that B is 1)."
So u mean that instead of using the rssi values directly to the filter() method, what I should do is use the rssi in the log-normal distance formula
i.e Math.pow(10d, ((double) txPower - rssi) / (10 * 2)) and use this in the filter() method every time to see better results ?.

From various comments and discussion from this blog I understood that even for moving object you are considering the static model of kalman filtering why do you do that? Since it won't be linear
curve when in motion can alternative like extended kalman filter can be used, as the intution behind it is for polynomial curves correct me if I'm wrong?

Thanks,

K Karthikeyan Deenadayalan

Could not upload the plot in the previous comment https://uploads.disquscdn.c...

K Karthikeyan Deenadayalan

If I have to add few changes to the existing python code to change it into extended Kalman filter what changes do I need to do.

W Wouter Bulten

You will probably need a bit more than 'a few' changes. I would suggest to look for an existing implementation if you need something quick. Something like https://github.com/rlabbe/K...

W Wouter Bulten

Hi, thank you for the compliments. To address your points:

1. Yes, use the standard deviation. That's also how I determined the initial values in my experiment.
2. If you know that the user moves, and know the direction, you should encode that in the model. That will probably improve your results. In practice it is however difficult to accurately model the movement of a user (if they can move freely).
3. Given point 2. If you have motion information, the best way to integrate this in to the filter is to model distance instead of RSSI. Otherwise you will have to use a non linear mapping (as you also mentioned in your comment) to map the movement to the RSSI-space.
4. I assumed a static system for three reasons: First, by taking multiple measurements within a small time frame, the filter was able to keep up with changes due to movement (to some extent). Second, it is very hard to get good motion estimates that fit with in the (simple) kalman filter model). And last, the rssi estimates were passed to a particle filter for further processing (see the FastSLAM post). In the particle filter I integrated motion information (from an accelerometer) and data from multiple becaons to estimate the position of user.

J jordi mesa
The first thing to congratulate you on your incredible work ... I have a question I want to implement your kalmanjs filter to filter the latitude and longitude that my GPS receives so that it does not give me wrong data. But I can't implement it ... I have to save an array first with GPS readings or the filter function is already doing it ... I'm doing this ... but I'm sure it's wrong. var kf_lat = new KalmanFilter ({R: 0.01, Q: 3}); var kf_lng = new KalmanFilter ({R: 0.01, Q: 3}); lat_kf = kf_lat.filter (Location.lat); lng_kf = kf_lng.filter (Location.lng); The Values returned to me is as if they were not filtered because it continues to move incorrectly, it does not stabilize the longitude and latitude when stopped.
W Wouter Bulten
Hi Jordi, You don't have to save an array first. You can pass the raw values to the filter as they come in. The filter will update it's state internally. So for each measurement you will call filter(). So something like this: ```js f= new KalmanFilter ({R: 0.01, Q: 3}); # measure something value = f.filter(measurement); # measure new value value = f.filter(measurement); #etc. ```` If the value should be static but the filtered value is still jumping around, it could be that there is a lot of noise in the measurements. You could try changing the parameters of the filter (e.g. make Q larger). Have you already done some calculations of the standard deviation of your measurements over time? Good luck! Wouter
A Anil
Hello Wouter, Thank you very much for your great work. Have gone through many article on Kalman filter, but your blogs very easy to understand and get start with. I am trying to port your kalman filter code to my BLE based distance measurement using RSSI. I am new js scripts, but it looks like kalman.js is straight forward to port. Later I wish to port slacjs code for step detection using accelerometer, distance estimation using kalman filter and localisation using particle js, 1. But not sure where to start with, please give me pointers to start with this code. 2. Also related to kalman filter parameters B and u, please clarify how can I use, suppose if I know person moving 50cm, you mentioned in one of the comments use B=0.5 and u=1, please let know the relation between B and u and how do I vary based on the movement. 3. Also if user moving away, do I need to use negative values for B and u ? Thanks -Anil
W Wouter Bulten
Hi Anil, Thank you for your interest! There are quite some examples on my blog and the Github repo on how to use the Kalman.js library. I would suggest to start there. Feel free to add a comment here if you have any specific questions regarding the examples. You can see B and u as the step size and number of steps. Imagine a person that has a average step size of 1m (this is B). If somebody sets a step (u=1) you expect that that person is 1m further away. If you know somebody did two steps (between the measurements), you can set u to 2 for example. If someone didn't move between measurements, you set it to 0. If you know the effect is the reverse, you can use a negative u. B does not change, because your estimate of someones step size is constant (unless their legs grew in the meantime ;) ). Note that in my experiments I did not model movement using the Kalman filter but did this in a later stage (i.e. u=0). I took enough RSSI measurements every second that the Kalman filter was able to smooth the data and keep up with movement to a fair extent.
A Anil
Hello Wouter, Thank you very much on your quick response. One clarification, related to direction, if another person approaching the receiver then u is positive and if person moving away from the receiver then u is negative ?
W Wouter Bulten
It depends on how you model the system. But yes, if you think that the predicted value is lower because someone is moving away, you can use a negative u. You can think of modelling a helicopter's height above the ground. If the helicopter is climbing, u is positive. If it's descending, u is negative.
A ahmed
Hey Wouter! thank you for your work. I am using your kalman filter for RSSI data from bluetooth beacons for estimating the distance between a mobile phone and a beacon. 1- For example, I've collecting 5 values rssi from the beacon in the same position[-41,-42,-49,-52,-37], and I used the python implementation from your library on the previous values , the result of filter is [-41,-41.5, -44.3, -46.7,-43.9 ] which value among the 5 result values I use to calculate the ditance? Can I use the means? 2- Can i also use the kalman filter with rssi data from wifi? Thank you in advance.
W Wouter Bulten
Hi Ahmed, Are these measurements from the same beacon but at different time points? The idea is that you pass every value you receive to the filter as they come in, and then use the output as the current best estimate. The filter already does the "averaging" for you. The output of the filter is the best estimate of the real value at that point in time. Of course, at the start you will need to feed multiple values to get a better estimate (as they system does not have any history and the first measurement can be an outlier). And yes, you can use the filter for any data that you need to smooth. Regards, Wouter
A ahmed
Thank you very much on your quick response. Yes the measurements from the same beacon. My goal is to convert the rssi value to a distance (m) ,as I explained previously I collected 5 rssi values in the same position from the same beacon and I applied the filter to it. - input to filter=[-41,-42,-49,-52,-37] from the same beacon and position . - output=[-41,-41.5, -44.3, -46.7,-43.9 ] the formula used for the rssi to distance conversion: distance=10^(( C0 - Rssi )/(10*N)) N , C0 :two constant. My problem is: which value among the 5 values results of filter I use to calculate the distance? Can I use the means of (-41,-41.5, -44.3, -46.7,-43.9)? In reality I have collected for each position 100 values from each beacon and to better explain my problem I have done an example of 5 values. Thank you very much.
W Wouter Bulten
Hi Ahmed, What you are trying to do is exactly what I was also doing in my [HumanSLAM](https://www.wouterbulten.nl/posts/human-slam-indoor-localization-using-particle-filters/) project. I assume you want to have a continuous estimate of the distance, right? The idea is that you create a KalmanFilter per device, and pass the values to the filter when they come in. At the point that you need the estimate you take the latest value. In your case, the last value is the filter's best estimate of the RSSI value (based on the parameters you have set). Regards, Wouter
L Lahiru
Great article! Thanks! I got a lot of things from your article. I have a small question. Can i implemet tis 2D or 3D type data ex [2, 3] or [2, 3, 3] Thank you very much.
W Wouter Bulten
Hi Lahiru, Thanks! This library is only applicable to 1D streams of data. E.g. a list of RSSI noise measurements. If you need to filter 2D data (e.g. a position) you could look at the Extended Kalman Filter. Regarding your other question on Github, I'm not sure what is going wrong for you. If you supply a value to filter() you should get the filtered output back. Note that the first value you supply is not filtered as the filter has no evidence to adjust the measurement.
L Lahiru
Hi Wouter Bulten, Thanks for your kindly reply. I will try with Extended Kalman Filter when I input data into kalmanjs it not changing var KalmanFilter = require('kalmanjs'); var kalmanFilter = new KalmanFilter({R: 0.01, Q: 3}); var incoming_data = getting_input_from_sensor console.log("Input", incoming_data); console.log("Filter", kf.filter(incoming_data)); input 34.3 Filter 34.3 input 35.3 Filter 35.3 input 34.8 Filter 34.8 input 37.5 Filter 37.5 input 31.3 Filter 31.3 These outputs are the same Waths wrong I did
W Wouter Bulten
Hi, Note that you need to reuse the filter object. So e.g.: ```js var KalmanFilter = require(‘kalmanjs’); var kf = new KalmanFilter({R: 0.01, Q: 3}); var incoming_data = getting_input_from_sensor console.log(“Input”, incoming_data); console.log(“Filter”, kf.filter(incoming_data)); # Reuse 'kf' here var incoming_data = getting_input_from_sensor console.log(“Input”, incoming_data); console.log(“Filter”, kf.filter(incoming_data)); # etc.. var incoming_data = getting_input_from_sensor console.log(“Input”, incoming_data); console.log(“Filter”, kf.filter(incoming_data)); ```
L Lahiru
Hi, Thanks for your kindly reply. ops, Incoming data are infinite, Is there an easy way to do that??
W Wouter Bulten
You can pass new data to the filter as long as you want. I usually created one dedicated filter per device. Good luck with your project!
Z Zakir
Dear Wouter Bulten, First thing first, I read your article and I found it interesting. can you help me to share me the noisy data and how you apply on it to get filtered data. I am little bit mis track. Thanks and regards.
W Wouter Bulten
Thanks! There is a nice demo that was made by @benwinding that shows how to use and plot the data: https://benwinding.github.io/kalmanjs-examples/examples/demo1.html Hope that helps! Source is here: https://github.com/benwinding/kalmanjs-examples
J joey
Dear Wouter Bulten, Your article is really interesting to me as I am doing a similar task. i am currently doing a task in which I need to remove the noise from RSSI by using a filter like Kalman in Arduino. For the transmitter and receiver, we are using the LoRA module. I am able to transmit and receive the RSSI. Now if on the receiver side I need to implement the Kalman filter, what changes do I need to do in my code? Do I only need to edit the receiver side code and create a Kalman function in it, which will be called every time it receives the RSSI value? which library I need to use. Which theoretical formula/steps of the Kalman filter we are using: which steps i need to do, do i just have to do this: 1. while true do 2. obtain noisy U1 3. goto Kalman, obtain filtered U1 4. end while 5. function KALMAN(U) or do i also have to update Kalman gain, update estimate, update error estimate and then at last return U hat. also, which filters are one of the best for removing noise from RSSI?
W Wouter Bulten
Hi, in principle you only have to call the filter() function (at least for the JS version of the library). Make sure to keep the same object and not create a new one on every incoming measurement. If you re-create it, all the history will be lost. Good luck!
G GeorgeHu
Hello Wouter, Thank you very much for the blog post that is easy to understand the basic usage of KalmanFilter. Now in practise I still need some guidance on applying the filter. We have a uwb indoor location system in use and the position data in (x,y) is not so precise in some situation, i.e affected by NLOS, and also we have jitter in the data. What we plan to do is to add an IMU device and trying to merge data from IMU to improve the situation, So basically we have uwb data (x,y) and IMU data, is it feasibile to apply Kalman filter for this case? And I have read the code of "3-axis accelerometer" example and not sure if I can follow that method. Thanks!
W Wouter Bulten
Yes, you can use a Kalman Filter for such a use case. You have to decide whether you: - (simply) want to use 1D filters for each input (so filer xy and IMU separately). - combine the measurements in one filter, for that you will need a (kalman) filter that takes more than one input. I did a project many years ago on indoor localization. The code is online in case you would like to explore: https://github.com/wouterbulten/slacjs

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