signalk-polar-performance-plugin 0.0.22 → 0.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/plugin/index.js +56 -9
package/package.json
CHANGED
package/plugin/index.js
CHANGED
|
@@ -5,6 +5,7 @@ module.exports = function (app) {
|
|
|
5
5
|
var plugin = {}
|
|
6
6
|
var unsubscribes = []
|
|
7
7
|
var timers = []
|
|
8
|
+
var damping = {}
|
|
8
9
|
|
|
9
10
|
plugin.id = 'signalk-polar-performance-plugin'
|
|
10
11
|
plugin.name = 'Polar performance plugin'
|
|
@@ -49,6 +50,22 @@ module.exports = function (app) {
|
|
|
49
50
|
type: 'boolean',
|
|
50
51
|
title: 'Enable writing of maximum speed angle and boat speed for a given TWS'
|
|
51
52
|
},
|
|
53
|
+
dampingTWA: {
|
|
54
|
+
type: 'number',
|
|
55
|
+
description: 'If data appears erratic or too sensitive, damping may be applied to amke information appear more stable. With damping set to 0, the data is presented in raw form wih no damping applied.',
|
|
56
|
+
title: 'True Wind Angle damping seconds',
|
|
57
|
+
default: 1
|
|
58
|
+
},
|
|
59
|
+
dampingTWS: {
|
|
60
|
+
type: 'number',
|
|
61
|
+
title: 'True Wind Speed damping seconds',
|
|
62
|
+
default: 1
|
|
63
|
+
},
|
|
64
|
+
dampingBSP: {
|
|
65
|
+
type: 'number',
|
|
66
|
+
title: 'Boat speed damping damping',
|
|
67
|
+
default: 1
|
|
68
|
+
},
|
|
52
69
|
csvTable: {
|
|
53
70
|
type: "string",
|
|
54
71
|
title: "Copy/paste the csv content of the polar in http://jieter.github.io/orc-data/site/ style."
|
|
@@ -141,20 +158,21 @@ module.exports = function (app) {
|
|
|
141
158
|
deltas.forEach(delta => {
|
|
142
159
|
// app.debug('handleData: %s', JSON.stringify(delta))
|
|
143
160
|
if (delta.path == 'navigation.speedThroughWater') {
|
|
144
|
-
STW = delta.value
|
|
161
|
+
STW = applyDamping (delta.value, 'BSP', options.dampingBSP || 0)
|
|
145
162
|
BSP = STW
|
|
146
163
|
// app.debug('speedThroughWater (STW): %d', STW)
|
|
147
164
|
} else if (delta.path == 'navigation.speedOverGround') {
|
|
148
|
-
SOG = delta.value
|
|
165
|
+
SOG = applyDamping (delta.value, 'BSP', options.dampingBSP || 0)
|
|
149
166
|
BSP = SOG
|
|
150
167
|
// app.debug('speedThroughWater (STW): %d', STW)
|
|
151
168
|
} else if (delta.path == 'navigation.headingTrue') {
|
|
152
169
|
HDG = delta.value
|
|
153
170
|
// app.debug('heading (HDG): %d', HDG)
|
|
154
171
|
} else if (delta.path == 'environment.wind.speedTrue') {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
app.debug('TWS: %d
|
|
172
|
+
// applyDamping (Xn, unit, a, n)
|
|
173
|
+
TWS = applyDamping (delta.value, 'TWS', options.dampingTWS || 0)
|
|
174
|
+
// app.debug('environment.wind.speedTrue (TWS): %d applyDamping: %d', delta.value, TWS)
|
|
175
|
+
// app.debug('TWS: %d TWA: %d BSP: %d', msToKts(TWS), radToDeg(TWA)*port, msToKts(BSP))
|
|
158
176
|
sendUpdates(getPerformanceData(TWS, TWA, BSP))
|
|
159
177
|
} else if (delta.path == 'environment.wind.angleTrueWater') {
|
|
160
178
|
if (delta.value < 0) {
|
|
@@ -162,7 +180,8 @@ module.exports = function (app) {
|
|
|
162
180
|
} else {
|
|
163
181
|
port = 1
|
|
164
182
|
}
|
|
165
|
-
TWA = Math.abs(delta.value)
|
|
183
|
+
TWA = Math.abs(applyDamping (delta.value, 'TWA', options.dampingTWA || 0))
|
|
184
|
+
app.debug('environment.wind.angleTrueWater (TWA): %s applyDamping: %s', radToDeg(delta.value).toFixed(0), radToDeg(TWA).toFixed(0))
|
|
166
185
|
}
|
|
167
186
|
})
|
|
168
187
|
}
|
|
@@ -210,10 +229,12 @@ module.exports = function (app) {
|
|
|
210
229
|
if (typeof perfObj.polarSpeed != 'undefined') {
|
|
211
230
|
values.push({path: 'performance.polarSpeed', value: roundDec(perfObj.polarSpeed)})
|
|
212
231
|
values.push({path: 'performance.polarSpeedRatio', value: roundDec(perfObj.polarSpeedRatio)})
|
|
213
|
-
if (
|
|
232
|
+
if (typeof perfObj.velocityMadeGood != 'undefined') {
|
|
214
233
|
values.push({path: 'performance.velocityMadeGood', value: roundDec(perfObj.velocityMadeGood)})
|
|
215
234
|
values.push({path: 'performance.polarVelocityMadeGood', value: roundDec(perfObj.polarVelocityMadeGood)})
|
|
235
|
+
metas.push({path: 'performance.polarVelocityMadeGood', value: {"units": "m/s"}})
|
|
216
236
|
values.push({path: 'performance.polarVelocityMadeGoodRatio', value: roundDec(perfObj.polarVelocityMadeGoodRatio)})
|
|
237
|
+
metas.push({path: 'performance.polarVelocityMadeGoodRatio', value: {"units": "ratio"}})
|
|
217
238
|
}
|
|
218
239
|
}
|
|
219
240
|
if (typeof perfObj.maxSpeed != 'undefined') {
|
|
@@ -616,6 +637,27 @@ module.exports = function (app) {
|
|
|
616
637
|
}
|
|
617
638
|
return data
|
|
618
639
|
}
|
|
640
|
+
|
|
641
|
+
function applyDamping (Xn, unit, RC) {
|
|
642
|
+
if (RC == 0) {
|
|
643
|
+
return Xn
|
|
644
|
+
} else {
|
|
645
|
+
if (typeof damping[unit] == 'undefined') {
|
|
646
|
+
// Doesn't exist yet, make obj for unit
|
|
647
|
+
damping[unit] = {Yn: Xn, dt: Date.now()}
|
|
648
|
+
}
|
|
649
|
+
// Calculate a
|
|
650
|
+
let dt = (Date.now() - damping[unit].dt)/1000
|
|
651
|
+
damping[unit].dt = Date.now()
|
|
652
|
+
let a = dt / (RC + dt)
|
|
653
|
+
// Yn = (1-a) * Yn-1 + a * Xn
|
|
654
|
+
let Yn = (1-a) * (damping[unit].Yn || Xn) + a * Xn
|
|
655
|
+
// Remember Yn
|
|
656
|
+
damping[unit].Yn = Yn
|
|
657
|
+
// app.debug('Unit: %s dt: %d a: %d obj: %s', unit, dt, a, JSON.stringify(damping[unit]))
|
|
658
|
+
return Yn
|
|
659
|
+
}
|
|
660
|
+
}
|
|
619
661
|
}
|
|
620
662
|
|
|
621
663
|
plugin.stop = function () {
|
|
@@ -652,6 +694,11 @@ function msToKts(ms) {
|
|
|
652
694
|
}
|
|
653
695
|
|
|
654
696
|
function roundDec (value) {
|
|
655
|
-
value
|
|
656
|
-
|
|
697
|
+
if (typeof value == 'undefined') {
|
|
698
|
+
return undefined
|
|
699
|
+
} else {
|
|
700
|
+
value = Number(value.toFixed(3))
|
|
701
|
+
return value
|
|
702
|
+
}
|
|
657
703
|
}
|
|
704
|
+
|