Comparing version 1.0.0-beta to 1.1.0
@@ -1,10 +0,24 @@ | ||
"use strict"; | ||
'use strict'; | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
function _classCallCheck(instance, Constructor) { | ||
if (!(instance instanceof Constructor)) { | ||
throw new TypeError("Cannot call a class as a function"); | ||
} | ||
} | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
function _defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _createClass(Constructor, protoProps, staticProps) { | ||
if (protoProps) _defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) _defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
} | ||
@@ -17,9 +31,9 @@ /** | ||
* @version Version: 1.0.0-beta | ||
* @copyright Copyright 2015 Wouter Bulten | ||
* @license GNU LESSER GENERAL PUBLIC LICENSE v3 | ||
* @copyright Copyright 2015-2018 Wouter Bulten | ||
* @license MIT License | ||
* @preserve | ||
*/ | ||
var KalmanFilter = (function () { | ||
var KalmanFilter = | ||
/*#__PURE__*/ | ||
function () { | ||
/** | ||
@@ -34,20 +48,19 @@ * Create 1-dimensional kalman filter | ||
*/ | ||
function KalmanFilter() { | ||
var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, | ||
_ref$R = _ref.R, | ||
R = _ref$R === void 0 ? 1 : _ref$R, | ||
_ref$Q = _ref.Q, | ||
Q = _ref$Q === void 0 ? 1 : _ref$Q, | ||
_ref$A = _ref.A, | ||
A = _ref$A === void 0 ? 1 : _ref$A, | ||
_ref$B = _ref.B, | ||
B = _ref$B === void 0 ? 0 : _ref$B, | ||
_ref$C = _ref.C, | ||
C = _ref$C === void 0 ? 1 : _ref$C; | ||
var _ref$R = _ref.R; | ||
var R = _ref$R === undefined ? 1 : _ref$R; | ||
var _ref$Q = _ref.Q; | ||
var Q = _ref$Q === undefined ? 1 : _ref$Q; | ||
var _ref$A = _ref.A; | ||
var A = _ref$A === undefined ? 1 : _ref$A; | ||
var _ref$B = _ref.B; | ||
var B = _ref$B === undefined ? 0 : _ref$B; | ||
var _ref$C = _ref.C; | ||
var C = _ref$C === undefined ? 1 : _ref$C; | ||
_classCallCheck(this, KalmanFilter); | ||
this.R = R; // noise power desirable | ||
this.Q = Q; // noise power estimated | ||
@@ -61,3 +74,2 @@ | ||
} | ||
/** | ||
@@ -70,6 +82,7 @@ * Filter a new value | ||
_createClass(KalmanFilter, [{ | ||
key: "filter", | ||
value: function filter(z) { | ||
var u = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1]; | ||
var u = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; | ||
@@ -80,11 +93,8 @@ if (isNaN(this.x)) { | ||
} else { | ||
// Compute prediction | ||
var predX = this.A * this.x + this.B * u; | ||
var predCov = this.A * this.cov * this.A + this.R; | ||
var predX = this.predict(u); | ||
var predCov = this.uncertainty(); // Kalman gain | ||
// Kalman gain | ||
var K = predCov * this.C * (1 / (this.C * predCov * this.C + this.Q)); | ||
var K = predCov * this.C * (1 / (this.C * predCov * this.C + this.Q)); // Correction | ||
// Correction | ||
this.x = predX + K * (z - this.C * predX); | ||
@@ -96,4 +106,25 @@ this.cov = predCov - K * this.C * predCov; | ||
} | ||
/** | ||
* Predict next value | ||
* @param {Number} [u] Control | ||
* @return {Number} | ||
*/ | ||
}, { | ||
key: "predict", | ||
value: function predict() { | ||
var u = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; | ||
return this.A * this.x + this.B * u; | ||
} | ||
/** | ||
* Return uncertainty of filter | ||
* @return {Number} | ||
*/ | ||
}, { | ||
key: "uncertainty", | ||
value: function uncertainty() { | ||
return this.A * this.cov * this.A + this.R; | ||
} | ||
/** | ||
* Return the last filtered measurement | ||
@@ -108,3 +139,2 @@ * @return {Number} | ||
} | ||
/** | ||
@@ -120,3 +150,2 @@ * Set measurement noise Q | ||
} | ||
/** | ||
@@ -135,5 +164,5 @@ * Set the process noise R | ||
return KalmanFilter; | ||
})(); | ||
}(); | ||
exports.default = KalmanFilter; | ||
//# sourceMappingURL=kalman.js.map | ||
module.exports = KalmanFilter; | ||
//# sourceMappingURL=kalman.js.map |
{ | ||
"name": "kalmanjs", | ||
"version": "1.0.0-beta", | ||
"version": "1.1.0", | ||
"private": false, | ||
"devDependencies": { | ||
"babel-cli": "^6.2.0", | ||
"babel-preset-es2015": "^6.1.18", | ||
"eslint": "^1.10.3", | ||
"eslint-config-airbnb": "^1.0.2", | ||
"uglify-js": "^2.6.1" | ||
"@babel/cli": "^7.2.3", | ||
"@babel/core": "^7.2.2", | ||
"@babel/preset-env": "^7.2.3", | ||
"rollup": "^1.1.0", | ||
"rollup-plugin-babel": "^4.3.1", | ||
"rollup-plugin-node-resolve": "^4.0.0", | ||
"uglify-js": "^3.4.9" | ||
}, | ||
@@ -23,5 +25,6 @@ "repository": { | ||
"scripts": { | ||
"compile": "babel --source-maps -d lib/ src/", | ||
"minify": "uglifyjs lib/kalman.js --compress --preamble '//kalmanjs, LGPL-3.0, https://github.com/wouterbulten/kalmanjs' --source-map lib/kalman.min.js.map --in-source-map lib/kalman.js.map --mangle -o lib/kalman.min.js", | ||
"prepublish": "npm run compile && npm run minify" | ||
"compile": "npx babel src --source-maps --out-dir lib", | ||
"minify": "npx uglifyjs dist/kalman.js --beautify \"beautify=false, preamble='/*kalmanjs, Wouter Bulten, MIT, https://github.com/wouterbulten/kalmanjs */'\" --compress --source-map \"content='dist/kalman.js.map'\" --mangle -o dist/kalman.min.js", | ||
"build": "npx rollup -c", | ||
"prepublishOnly": "npm run build" | ||
}, | ||
@@ -36,3 +39,3 @@ "keywords": [ | ||
"author": "Wouter Bulten (https://wouterbulten.nl)", | ||
"license": "LGPL-3.0" | ||
"license": "MIT" | ||
} |
113
README.md
@@ -7,2 +7,13 @@ # KalmanJS | ||
## Background | ||
I wrote two blog posts on explaining Kalman filters in general and applying them on noisy data in particular: | ||
* [KalmanJS, Lightweight Javascript Library for Noise filtering](https://www.wouterbulten.nl/blog/tech/lightweight-javascript-library-for-noise-filtering/) | ||
* [Kalman filters explained: Removing noise from RSSI signals](https://www.wouterbulten.nl/blog/tech/kalman-filters-explained-removing-noise-from-rssi-signals/) | ||
## Questions? | ||
Please see the blog post ([KalmanJS, Lightweight Javascript Library for Noise filtering](https://wouterbulten.nl/blog/tech/lightweight-javascript-library-for-noise-filtering/)) for more information about using this library. Any questions can be posted there as comments. | ||
## Installation | ||
@@ -12,2 +23,24 @@ | ||
### In the browser | ||
Include the `kalman.js` or `kalman.min.js` from the `dist` folder on your webpage, the filter can then be used directly. | ||
```html | ||
<script src="kalman.min.js" type="text/javascript"></script> | ||
<script type="text/javascript"> | ||
var kf = new KalmanFilter(); | ||
console.log(kf.filter(3)); | ||
console.log(kf.filter(2)); | ||
console.log(kf.filter(1)); | ||
</script> | ||
``` | ||
Should output (with default settings): | ||
``` | ||
3 | ||
2.3333333333333335 | ||
1.5000000000000002 | ||
``` | ||
### Node (es6) | ||
@@ -20,5 +53,15 @@ `npm install kalmanjs` | ||
const kf = new KalmanFilter(); | ||
kf.filter(2); | ||
console.log(kf.filter(3)); | ||
console.log(kf.filter(2)); | ||
console.log(kf.filter(1)); | ||
``` | ||
Should output (with default settings): | ||
``` | ||
3 | ||
2.3333333333333335 | ||
1.5000000000000002 | ||
``` | ||
### Node (es5) | ||
@@ -28,9 +71,19 @@ `npm install kalmanjs` | ||
```javascript | ||
var KalmanFilter = require('kalmanjs').default; | ||
var KalmanFilter = require('kalmanjs'); | ||
var kf = new KalmanFilter(); | ||
kf.filter(2); | ||
console.log(kf.filter(3)); | ||
console.log(kf.filter(2)); | ||
console.log(kf.filter(1)); | ||
``` | ||
Should output (with default settings): | ||
``` | ||
3 | ||
2.3333333333333335 | ||
1.5000000000000002 | ||
``` | ||
## Applying the filter on a dataset | ||
@@ -64,22 +117,48 @@ | ||
## Background | ||
## Reference | ||
* [KalmanJS, Lightweight Javascript Library for Noise filtering](https://wouterbulten.nl/blog/tech/lightweight-javascript-library-for-noise-filtering/) | ||
* [Kalman filters explained: Removing noise from RSSI signals](https://wouterbulten.nl/blog/tech/kalman-filters-explained-removing-noise-from-rssi-signals/) | ||
This project was part of my research on indoor localization. Please see my [paper](http://ieeexplore.ieee.org/document/7471364) or this [presentation](https://www.wouterbulten.nl/blog/tech/iotdi-ic2e-conference-presentation-human-slam/) for more information. You can use the following reference if you want to cite my paper: | ||
> 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 [URL](http://ieeexplore.ieee.org/document/7471364) | ||
Or, if you prefer in BibTeX format: | ||
```tex | ||
@INPROCEEDINGS{7471364, | ||
author={W. Bulten and A. C. V. Rossum and W. F. G. Haselager}, | ||
booktitle={2016 IEEE First International Conference on Internet-of-Things Design and Implementation (IoTDI)}, | ||
title={Human SLAM, Indoor Localisation of Devices and Users}, | ||
year={2016}, | ||
pages={211-222}, | ||
keywords={RSSI;data privacy;indoor environment;ubiquitous computing;FastSLAM;RSSI update;SLAC algorithm;device RSSI;device indoor localisation;device location;device position;environment noise;human SLAM;nontrivial environment;received signal strength indicator;simultaneous localisation and configuration;smart space;user indoor localisation;user motion data;user privacy;Estimation;Performance evaluation;Privacy;Simultaneous localization and mapping;Privacy;Simultaneous localization and mapping;Smart Homes;Ubiquitous computing;Wireless sensor networks}, | ||
doi={10.1109/IoTDI.2015.19}, | ||
month={April},} | ||
``` | ||
## 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 and sometimes another library is available. I would encourage searching for it if you require another implementation. For convenience, this repository contains a *contrib* folder with user-submitted implementations in other languages. | ||
## Copyright | ||
Copyright (C) 2015 Wouter Bulten | ||
MIT License | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU Lesser General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
Copyright (c) 2018 Wouter Bulten | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
You should have received a copy of the GNU Lesser General Public License | ||
along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Copyleft License
License(Experimental) Copyleft license information was found.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
Non-permissive License
License(Experimental) A license not known to be considered permissive was found.
Found 1 instance in 1 package
0
100
138
0
160
16247
7
5