signalk-polar-performance-plugin 0.0.21 → 0.0.23

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/plugin/index.js +65 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signalk-polar-performance-plugin",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "description": "A plugin that calculates performance information based on a (CSV) polar diagram.",
5
5
  "main": "plugin/index.js",
6
6
  "scripts": {
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'
@@ -37,6 +38,10 @@ module.exports = function (app) {
37
38
  type: 'boolean',
38
39
  title: 'Enable calculation of Optimum Wind Angle (difference between TWA and beat/run angle (depends on beat/run angle)'
39
40
  },
41
+ VMG: {
42
+ type: 'boolean',
43
+ title: 'Enable calculation of VMG, polarVMG and polar VMG ratio'
44
+ },
40
45
  useSOG: {
41
46
  type: 'boolean',
42
47
  title: 'Use speed over ground (SOG) as boat speed.'
@@ -45,9 +50,24 @@ module.exports = function (app) {
45
50
  type: 'boolean',
46
51
  title: 'Enable writing of maximum speed angle and boat speed for a given TWS'
47
52
  },
53
+ dampingTWA: {
54
+ type: 'number',
55
+ title: 'True Wind Angle damping factor (0 = no damping, 1 = full damping)',
56
+ default: 0
57
+ },
58
+ dampingTWS: {
59
+ type: 'number',
60
+ title: 'True Wind Speed damping factor (0 = no damping, 1 = full damping)',
61
+ default: 0
62
+ },
63
+ dampingBSP: {
64
+ type: 'number',
65
+ title: 'Boat speed damping factor (0 = no damping, 1 = full damping)',
66
+ default: 0
67
+ },
48
68
  csvTable: {
49
69
  type: "string",
50
- title: "Enter csv with polar in http://jieter.github.io/orc-data/site/ style."
70
+ title: "Copy/paste the csv content of the polar in http://jieter.github.io/orc-data/site/ style."
51
71
  }
52
72
  }
53
73
  }
@@ -137,20 +157,21 @@ module.exports = function (app) {
137
157
  deltas.forEach(delta => {
138
158
  // app.debug('handleData: %s', JSON.stringify(delta))
139
159
  if (delta.path == 'navigation.speedThroughWater') {
140
- STW = delta.value
160
+ STW = applyDamping (delta.value, 'BSP', options.dampingBSP || 0, 3)
141
161
  BSP = STW
142
162
  // app.debug('speedThroughWater (STW): %d', STW)
143
163
  } else if (delta.path == 'navigation.speedOverGround') {
144
- SOG = delta.value
164
+ SOG = applyDamping (delta.value, 'BSP', options.dampingBSP || 0, 3)
145
165
  BSP = SOG
146
166
  // app.debug('speedThroughWater (STW): %d', STW)
147
167
  } else if (delta.path == 'navigation.headingTrue') {
148
168
  HDG = delta.value
149
169
  // app.debug('heading (HDG): %d', HDG)
150
170
  } else if (delta.path == 'environment.wind.speedTrue') {
151
- TWS = delta.value
152
- // app.debug('environment.wind.speedTrue (TWS): %d', TWS)
153
- app.debug('TWS: %d TWA: %d BSP: %d', msToKts(TWS), radToDeg(TWA)*port, msToKts(BSP))
171
+ // applyDamping (Xn, unit, a, n)
172
+ TWS = applyDamping (delta.value, 'TWS', options.dampingTWS || 0, 3)
173
+ // app.debug('environment.wind.speedTrue (TWS): %d applyDamping: %d', delta.value, TWS)
174
+ // app.debug('TWS: %d TWA: %d BSP: %d', msToKts(TWS), radToDeg(TWA)*port, msToKts(BSP))
154
175
  sendUpdates(getPerformanceData(TWS, TWA, BSP))
155
176
  } else if (delta.path == 'environment.wind.angleTrueWater') {
156
177
  if (delta.value < 0) {
@@ -158,7 +179,8 @@ module.exports = function (app) {
158
179
  } else {
159
180
  port = 1
160
181
  }
161
- TWA = Math.abs(delta.value)
182
+ TWA = Math.abs(applyDamping (delta.value, 'TWA', options.dampingTWA || 0, 1))
183
+ // app.debug('environment.wind.angleTrueWater (TWA): %s applyDamping: %s', radToDeg(delta.value).toFixed(0), radToDeg(TWA).toFixed(0))
162
184
  }
163
185
  })
164
186
  }
@@ -206,6 +228,13 @@ module.exports = function (app) {
206
228
  if (typeof perfObj.polarSpeed != 'undefined') {
207
229
  values.push({path: 'performance.polarSpeed', value: roundDec(perfObj.polarSpeed)})
208
230
  values.push({path: 'performance.polarSpeedRatio', value: roundDec(perfObj.polarSpeedRatio)})
231
+ if (typeof perfObj.velocityMadeGood != 'undefined') {
232
+ values.push({path: 'performance.velocityMadeGood', value: roundDec(perfObj.velocityMadeGood)})
233
+ values.push({path: 'performance.polarVelocityMadeGood', value: roundDec(perfObj.polarVelocityMadeGood)})
234
+ metas.push({path: 'performance.polarVelocityMadeGood', value: {"units": "m/s"}})
235
+ values.push({path: 'performance.polarVelocityMadeGoodRatio', value: roundDec(perfObj.polarVelocityMadeGoodRatio)})
236
+ metas.push({path: 'performance.polarVelocityMadeGoodRatio', value: {"units": "ratio"}})
237
+ }
209
238
  }
210
239
  if (typeof perfObj.maxSpeed != 'undefined') {
211
240
  values.push({path: 'performance.maxSpeed', value: roundDec(perfObj.maxSpeed)})
@@ -369,11 +398,21 @@ module.exports = function (app) {
369
398
  }
370
399
  // Calculate polar performance ratio
371
400
  if (typeof performance.polarSpeed != 'undefined') {
372
- performance.polarSpeedRatio = (1 / performance.polarSpeed) * BSP
401
+ performance.polarSpeedRatio = BSP / performance.polarSpeed
402
+ if (options.VMG == true) {
403
+ performance.velocityMadeGood = Math.abs(BSP * Math.cos(TWA))
404
+ performance.polarVelocityMadeGood = Math.abs(performance.polarSpeed * Math.cos(TWA))
405
+ performance.polarVelocityMadeGoodRatio = performance.velocityMadeGood / performance.polarVelocityMadeGood
406
+ }
373
407
  } else {
374
408
  // No value would create stale values
375
409
  performance.polarSpeed = 0
376
410
  performance.polarSpeedRatio = 0
411
+ if (options.VMG == true) {
412
+ performance.velocityMadeGood = 0
413
+ performance.polarVelocityMadeGood = 0
414
+ performance.polarRatioVelocityMadeGood = 0
415
+ }
377
416
  }
378
417
  return performance
379
418
  }
@@ -597,6 +636,23 @@ module.exports = function (app) {
597
636
  }
598
637
  return data
599
638
  }
639
+
640
+ function applyDamping (Xn, unit, a, n) {
641
+ if (typeof damping[unit] == 'undefined') {
642
+ // Doesn't exist yet, make array for unit
643
+ damping[unit] = {Yn: []}
644
+ }
645
+ // Yn = a * Yn-1 + (1-a) * Xn
646
+ let Yn = a * (damping[unit]['Yn'][n-1] || Xn) + (1-a) * Xn
647
+ // Add Yn to begin of Yn array
648
+ damping[unit]['Yn'].push(Yn)
649
+ // Remove last value from Yn array if needed
650
+ if (damping[unit]['Yn'].length > n+1) {
651
+ damping[unit]['Yn'].shift()
652
+ }
653
+ // app.debug('Unit: %s array: %s', unit, damping[unit]['Yn'].join(','))
654
+ return Yn
655
+ }
600
656
  }
601
657
 
602
658
  plugin.stop = function () {
@@ -636,3 +692,4 @@ function roundDec (value) {
636
692
  value = Number(value.toFixed(3))
637
693
  return value
638
694
  }
695
+