node-pid-controller
Advanced tools
Comparing version 0.1.2 to 1.0.0
118
lib/index.js
@@ -0,75 +1,79 @@ | ||
"use strict"; | ||
/** | ||
* PID Controller. | ||
*/ | ||
var Controller = function(k_p, k_i, k_d, dt) { | ||
var i_max; | ||
if (typeof k_p === 'object') { | ||
var options = k_p; | ||
k_p = options.k_p; | ||
k_i = options.k_i; | ||
k_d = options.k_d; | ||
dt = options.dt; | ||
i_max = options.i_max; | ||
} | ||
class Controller { | ||
constructor(k_p, k_i, k_d, dt) { | ||
let i_max; | ||
if (typeof k_p === 'object') { | ||
let options = k_p; | ||
k_p = options.k_p; | ||
k_i = options.k_i; | ||
k_d = options.k_d; | ||
dt = options.dt; | ||
i_max = options.i_max; | ||
} | ||
// PID constants | ||
this.k_p = (typeof k_p === 'number') ? k_p : 1; | ||
this.k_i = k_i || 0; | ||
this.k_d = k_d || 0; | ||
// PID constants | ||
this.k_p = (typeof k_p === 'number') ? k_p : 1; | ||
this.k_i = k_i || 0; | ||
this.k_d = k_d || 0; | ||
// Interval of time between two updates | ||
// If not set, it will be automatically calculated | ||
this.dt = dt || 0; | ||
// Interval of time between two updates | ||
// If not set, it will be automatically calculated | ||
this.dt = dt || 0; | ||
// Maximum absolute value of sumError | ||
this.i_max = i_max || 0; | ||
// Maximum absolute value of sumError | ||
this.i_max = i_max || 0; | ||
this.sumError = 0; | ||
this.lastError = 0; | ||
this.lastTime = 0; | ||
this.sumError = 0; | ||
this.lastError = 0; | ||
this.lastTime = 0; | ||
this.target = 0; // default value, can be modified with .setTarget | ||
}; | ||
this.target = 0; // default value, can be modified with .setTarget | ||
} | ||
Controller.prototype.setTarget = function(target) { | ||
this.target = target; | ||
}; | ||
setTarget(target) { | ||
this.target = target; | ||
} | ||
Controller.prototype.update = function(currentValue) { | ||
this.currentValue = currentValue; | ||
update(currentValue) { | ||
this.currentValue = currentValue; | ||
// Calculate dt | ||
var dt = this.dt; | ||
if (!dt) { | ||
var currentTime = Date.now(); | ||
if (this.lastTime === 0) { // First time update() is called | ||
dt = 0; | ||
} else { | ||
dt = (currentTime - this.lastTime) / 1000; // in seconds | ||
// Calculate dt | ||
let dt = this.dt; | ||
if (!dt) { | ||
let currentTime = Date.now(); | ||
if (this.lastTime === 0) { // First time update() is called | ||
dt = 0; | ||
} else { | ||
dt = (currentTime - this.lastTime) / 1000; // in seconds | ||
} | ||
this.lastTime = currentTime; | ||
} | ||
this.lastTime = currentTime; | ||
} | ||
if (typeof dt !== 'number' || dt === 0) { | ||
dt = 1; | ||
} | ||
if (typeof dt !== 'number' || dt === 0) { | ||
dt = 1; | ||
} | ||
var error = (this.target - this.currentValue); | ||
this.sumError = this.sumError + error*dt; | ||
if (this.i_max > 0 && Math.abs(this.sumError) > this.i_max) { | ||
var sumSign = (this.sumError > 0) ? 1 : -1; | ||
this.sumError = sumSign * this.i_max; | ||
} | ||
let error = (this.target - this.currentValue); | ||
this.sumError = this.sumError + error*dt; | ||
if (this.i_max > 0 && Math.abs(this.sumError) > this.i_max) { | ||
let sumSign = (this.sumError > 0) ? 1 : -1; | ||
this.sumError = sumSign * this.i_max; | ||
} | ||
var dError = (error - this.lastError)/dt; | ||
this.lastError = error; | ||
let dError = (error - this.lastError)/dt; | ||
this.lastError = error; | ||
return (this.k_p*error) + (this.k_i * this.sumError) + (this.k_d * dError); | ||
}; | ||
return (this.k_p*error) + (this.k_i * this.sumError) + (this.k_d * dError); | ||
} | ||
Controller.prototype.reset = function() { | ||
this.sumError = 0; | ||
this.lastError = 0; | ||
this.lastTime = 0; | ||
}; | ||
reset() { | ||
this.sumError = 0; | ||
this.lastError = 0; | ||
this.lastTime = 0; | ||
} | ||
} | ||
module.exports = Controller; |
{ | ||
"name": "node-pid-controller", | ||
"version": "0.1.2", | ||
"version": "1.0.0", | ||
"description": "Node.js PID controller", | ||
@@ -15,3 +15,3 @@ "keywords": [ | ||
"engines": { | ||
"node": ">= v0.8.0" | ||
"node": ">= v4.0.0" | ||
}, | ||
@@ -18,0 +18,0 @@ "dependencies": {}, |
@@ -22,5 +22,5 @@ # node-pid-controller | ||
```js | ||
var Controller = require('node-pid-controller'); | ||
let Controller = require('node-pid-controller'); | ||
var ctr = new Controller({ | ||
let ctr = new Controller({ | ||
k_p: 0.25, | ||
@@ -35,3 +35,3 @@ k_i: 0.01, | ||
```js | ||
var ctr = new Controller(0.25, 0.01, 0.01, 1); // k_p, k_i, k_d, dt | ||
let ctr = new Controller(0.25, 0.01, 0.01, 1); // k_p, k_i, k_d, dt | ||
``` | ||
@@ -48,3 +48,3 @@ | ||
```js | ||
var correction = ctr.update(110); // 110km/h is the current speed | ||
let correction = ctr.update(110); // 110km/h is the current speed | ||
``` | ||
@@ -57,8 +57,8 @@ | ||
```js | ||
var goalReached = false | ||
let goalReached = false | ||
while (!goalReached) { | ||
var output = measureFromSomeSensor(); | ||
var input = ctr.update(output); | ||
let output = measureFromSomeSensor(); | ||
let input = ctr.update(output); | ||
applyInputToActuator(input); | ||
goalReached = (input === 0) ? true : false; // in the case of continuous control, you let this variable 'false' | ||
goalReached = (input === 0) ? true : false; // in the case of continuous control, you let this letiable 'false' | ||
} | ||
@@ -65,0 +65,0 @@ ``` |
@@ -0,1 +1,3 @@ | ||
"use strict"; | ||
/** | ||
@@ -5,3 +7,3 @@ * Module dependencies. | ||
var Controller = require('../') | ||
let Controller = require('../') | ||
, should = require('should') | ||
@@ -14,5 +16,5 @@ , assert = require('assert') | ||
*/ | ||
describe('pid-controller', function(){ | ||
describe('pid-controller', () => { | ||
var options = { | ||
let options = { | ||
k_p: 0.5, | ||
@@ -25,5 +27,5 @@ k_i: 0.1, | ||
// Create the controller | ||
var ctr = new Controller(options.k_p, options.k_i, options.k_d, options.dt); | ||
let ctr = new Controller(options.k_p, options.k_i, options.k_d, options.dt); | ||
it('should have set the coefficient', function() { | ||
it('should have set the coefficient', () => { | ||
ctr.k_p.should.equal(options.k_p); | ||
@@ -35,4 +37,4 @@ ctr.k_i.should.equal(options.k_i); | ||
it('should have set the coefficient from an options object', function(){ | ||
var ctr = new Controller(options); | ||
it('should have set the coefficient from an options object', () => { | ||
let ctr = new Controller(options); | ||
@@ -45,4 +47,4 @@ ctr.k_p.should.equal(options.k_p); | ||
it('should set the target', function(){ | ||
var v = 120; // 120km/h | ||
it('should set the target', () => { | ||
let v = 120; // 120km/h | ||
ctr.setTarget(v); | ||
@@ -52,9 +54,9 @@ ctr.target.should.equal(v); | ||
it('should return the correction', function(){ | ||
var vt = 110; // current speed | ||
var correction = ctr.update(vt); | ||
it('should return the correction', () => { | ||
let vt = 110; // current speed | ||
let correction = ctr.update(vt); | ||
correction.should.equal(8); | ||
}); | ||
it('should reset the controller', function(){ | ||
it('should reset the controller', () => { | ||
ctr.reset(); | ||
@@ -66,5 +68,5 @@ ctr.sumError.should.equal(0); | ||
it('should return the correction for the given update interval', function(){ | ||
it('should return the correction for the given update interval', () => { | ||
ctr.dt = 2; // 2 seconds between updates | ||
var correction = ctr.update(115); | ||
let correction = ctr.update(115); | ||
correction.should.equal(4); | ||
@@ -74,7 +76,7 @@ ctr.dt = options.dt; // Reset dt | ||
it('should return the correction with sumError <= i_max', function() { | ||
var ctr = new Controller(options); | ||
it('should return the correction with sumError <= i_max', () => { | ||
let ctr = new Controller(options); | ||
ctr.i_max = 5; // sumError will be 10 | ||
ctr.setTarget(120); | ||
var correction = ctr.update(110); | ||
let correction = ctr.update(110); | ||
correction.should.equal(7.5); | ||
@@ -84,6 +86,6 @@ ctr.sumError.should.be.belowOrEqual(ctr.i_max); | ||
it('should return a null correction', function(){ | ||
var ctr = new Controller(0, 0, 0); | ||
it('should return a null correction', () => { | ||
let ctr = new Controller(0, 0, 0); | ||
ctr.setTarget(120); | ||
var correction = ctr.update(110); | ||
let correction = ctr.update(110); | ||
correction.should.equal(0); | ||
@@ -90,0 +92,0 @@ }); |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
6661
135
0