signalk-polar-performance-plugin 0.0.20 → 0.0.22
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 +43 -16
package/package.json
CHANGED
package/plugin/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const halfPi = Math.PI / 2
|
|
1
2
|
var sourceAddress
|
|
2
3
|
|
|
3
4
|
module.exports = function (app) {
|
|
@@ -36,6 +37,10 @@ module.exports = function (app) {
|
|
|
36
37
|
type: 'boolean',
|
|
37
38
|
title: 'Enable calculation of Optimum Wind Angle (difference between TWA and beat/run angle (depends on beat/run angle)'
|
|
38
39
|
},
|
|
40
|
+
VMG: {
|
|
41
|
+
type: 'boolean',
|
|
42
|
+
title: 'Enable calculation of VMG, polarVMG and polar VMG ratio'
|
|
43
|
+
},
|
|
39
44
|
useSOG: {
|
|
40
45
|
type: 'boolean',
|
|
41
46
|
title: 'Use speed over ground (SOG) as boat speed.'
|
|
@@ -46,7 +51,7 @@ module.exports = function (app) {
|
|
|
46
51
|
},
|
|
47
52
|
csvTable: {
|
|
48
53
|
type: "string",
|
|
49
|
-
title: "
|
|
54
|
+
title: "Copy/paste the csv content of the polar in http://jieter.github.io/orc-data/site/ style."
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
57
|
}
|
|
@@ -83,7 +88,6 @@ module.exports = function (app) {
|
|
|
83
88
|
|
|
84
89
|
// Global variables
|
|
85
90
|
var BSP, STW, TWA, targetTWA, TWS, HDG, port // Angles in rad, speed in m/s
|
|
86
|
-
var halfPi = Math.PI / 2
|
|
87
91
|
|
|
88
92
|
// Subscribe to paths
|
|
89
93
|
let localSubscription = {
|
|
@@ -206,6 +210,11 @@ module.exports = function (app) {
|
|
|
206
210
|
if (typeof perfObj.polarSpeed != 'undefined') {
|
|
207
211
|
values.push({path: 'performance.polarSpeed', value: roundDec(perfObj.polarSpeed)})
|
|
208
212
|
values.push({path: 'performance.polarSpeedRatio', value: roundDec(perfObj.polarSpeedRatio)})
|
|
213
|
+
if (options.VMG == true) {
|
|
214
|
+
values.push({path: 'performance.velocityMadeGood', value: roundDec(perfObj.velocityMadeGood)})
|
|
215
|
+
values.push({path: 'performance.polarVelocityMadeGood', value: roundDec(perfObj.polarVelocityMadeGood)})
|
|
216
|
+
values.push({path: 'performance.polarVelocityMadeGoodRatio', value: roundDec(perfObj.polarVelocityMadeGoodRatio)})
|
|
217
|
+
}
|
|
209
218
|
}
|
|
210
219
|
if (typeof perfObj.maxSpeed != 'undefined') {
|
|
211
220
|
values.push({path: 'performance.maxSpeed', value: roundDec(perfObj.maxSpeed)})
|
|
@@ -369,11 +378,21 @@ module.exports = function (app) {
|
|
|
369
378
|
}
|
|
370
379
|
// Calculate polar performance ratio
|
|
371
380
|
if (typeof performance.polarSpeed != 'undefined') {
|
|
372
|
-
performance.polarSpeedRatio =
|
|
381
|
+
performance.polarSpeedRatio = BSP / performance.polarSpeed
|
|
382
|
+
if (options.VMG == true) {
|
|
383
|
+
performance.velocityMadeGood = Math.abs(BSP * Math.cos(TWA))
|
|
384
|
+
performance.polarVelocityMadeGood = Math.abs(performance.polarSpeed * Math.cos(TWA))
|
|
385
|
+
performance.polarVelocityMadeGoodRatio = performance.velocityMadeGood / performance.polarVelocityMadeGood
|
|
386
|
+
}
|
|
373
387
|
} else {
|
|
374
388
|
// No value would create stale values
|
|
375
389
|
performance.polarSpeed = 0
|
|
376
390
|
performance.polarSpeedRatio = 0
|
|
391
|
+
if (options.VMG == true) {
|
|
392
|
+
performance.velocityMadeGood = 0
|
|
393
|
+
performance.polarVelocityMadeGood = 0
|
|
394
|
+
performance.polarRatioVelocityMadeGood = 0
|
|
395
|
+
}
|
|
377
396
|
}
|
|
378
397
|
return performance
|
|
379
398
|
}
|
|
@@ -394,6 +413,7 @@ module.exports = function (app) {
|
|
|
394
413
|
if (row[0] == 'twa/tws') {
|
|
395
414
|
// The row with TWS columns
|
|
396
415
|
// Create empty TWS objects in polar object
|
|
416
|
+
app.debug('First row with TWS columns')
|
|
397
417
|
polar = []
|
|
398
418
|
for (let index = 1; index < row.length; index++) {
|
|
399
419
|
|
|
@@ -401,20 +421,23 @@ module.exports = function (app) {
|
|
|
401
421
|
polar.push(twsObj)
|
|
402
422
|
}
|
|
403
423
|
app.debug('polar: %s', JSON.stringify(polar))
|
|
404
|
-
} else if (row
|
|
424
|
+
} else if (row.filter(i => i === '0').length > 1) {
|
|
405
425
|
app.debug('beat and run angles are included')
|
|
406
|
-
} else if (row.includes('0')) {
|
|
407
426
|
// Beat / Run angle
|
|
408
427
|
let angle = degToRad(Number(row[0]))
|
|
409
428
|
let angleName
|
|
410
429
|
let VMGName
|
|
430
|
+
app.debug('angle < halfPi %d < %d', angle, halfPi)
|
|
411
431
|
if (angle < halfPi) {
|
|
412
432
|
angleName = 'Beat angle'
|
|
413
433
|
VMGName = 'Beat VMG'
|
|
434
|
+
app.debug('cvsToPolar: row includes Beat angle: %s', row.join(';'))
|
|
414
435
|
} else {
|
|
415
436
|
angleName = 'Run angle'
|
|
416
437
|
VMGName = 'Run VMG'
|
|
438
|
+
app.debug('cvsToPolar: row includes Run angle: %s', row.join(';'))
|
|
417
439
|
}
|
|
440
|
+
|
|
418
441
|
for (let index = 0; index < row.length-1; index++) {
|
|
419
442
|
if (row[index+1] != 0) {
|
|
420
443
|
polar[index][angleName] = angle
|
|
@@ -465,16 +488,19 @@ module.exports = function (app) {
|
|
|
465
488
|
})
|
|
466
489
|
|
|
467
490
|
// Find the beat/run angle if not set yet.
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
491
|
+
for (let index = 0; index < polar.length; index++) {
|
|
492
|
+
let tws = polar[index].tws
|
|
493
|
+
app.debug('Beat angle for TWS %s is %s', msToKts(tws).toFixed(0), polar[index]['Beat angle'])
|
|
494
|
+
// app.debug(polar[index]['Beat angle'])
|
|
495
|
+
if (typeof polar[index]['Beat angle'] == 'undefined') {
|
|
496
|
+
app.debug('Finding beat angle for TWS %s')
|
|
471
497
|
let beatVMG = 0
|
|
472
498
|
let beatElement = 0
|
|
473
499
|
let runVMG = 0
|
|
474
500
|
let runElement = 0
|
|
475
501
|
|
|
476
502
|
let twaArray = polar[index].twa
|
|
477
|
-
for (let element = 0; element < twaArray.length
|
|
503
|
+
for (let element = 0; element < twaArray.length; element++) {
|
|
478
504
|
let Obj = twaArray[element]
|
|
479
505
|
if (Obj.twa < halfPi) {
|
|
480
506
|
// Beat
|
|
@@ -488,8 +514,8 @@ module.exports = function (app) {
|
|
|
488
514
|
}
|
|
489
515
|
}
|
|
490
516
|
}
|
|
491
|
-
app.debug('beatVMG for %
|
|
492
|
-
app.debug('
|
|
517
|
+
app.debug('beatVMG for %s is %s (angle %s)', msToKts(tws).toFixed(0), msToKts(twaArray[beatElement].vmg).toFixed(2), radToDeg(twaArray[beatElement].twa).toFixed(1))
|
|
518
|
+
app.debug('runVMG for %s is %s (angle %s)', msToKts(tws).toFixed(0), msToKts(twaArray[runElement].vmg).toFixed(2), radToDeg(twaArray[runElement].twa).toFixed(1))
|
|
493
519
|
polar[index]['Beat angle'] = twaArray[beatElement].twa
|
|
494
520
|
polar[index]['Beat VMG'] = twaArray[beatElement].vmg
|
|
495
521
|
polar[index]['Run angle'] = twaArray[runElement].twa
|
|
@@ -499,18 +525,19 @@ module.exports = function (app) {
|
|
|
499
525
|
}
|
|
500
526
|
|
|
501
527
|
// And now fill in some missing ends to avoid doing expensive calculations in the main loop
|
|
502
|
-
for (let index = 0; index < polar.length
|
|
528
|
+
for (let index = 0; index < polar.length; index++) {
|
|
503
529
|
// Sorted on angle, so first is lowest
|
|
504
530
|
let tws = polar[index].tws
|
|
505
531
|
let twaArray = polar[index].twa
|
|
506
532
|
let lowTBS = twaArray[0].tbs
|
|
507
533
|
let lowTWA = twaArray[0].twa
|
|
508
534
|
|
|
509
|
-
app.debug('Padding polar for %s from 0 to first given angle (%d deg, %d kts)', msToKts(tws).toFixed(0), radToDeg(lowTWA), msToKts(lowTBS))
|
|
535
|
+
// app.debug('Padding polar for %s from 0 to first given angle (%d deg, %d kts)', msToKts(tws).toFixed(0), radToDeg(lowTWA), msToKts(lowTBS))
|
|
510
536
|
|
|
511
537
|
// Now put some extra values at the beginning
|
|
512
538
|
var topArray = []
|
|
513
539
|
for (let angle = 0; angle < lowTWA; angle = angle + degToRad(5)) {
|
|
540
|
+
app.debug('Padding for angle %d (< lowTWA)', radToDeg(angle).toFixed(1), radToDeg(lowTWA).toFixed(1))
|
|
514
541
|
let tbs = (angle / lowTWA) * Math.pow(Math.cos((-1*lowTWA + angle)*2),2) * lowTBS
|
|
515
542
|
if (tbs < 0 ) { tbs = 0 }
|
|
516
543
|
let Obj = {'twa': angle, 'tbs': tbs}
|
|
@@ -546,7 +573,7 @@ module.exports = function (app) {
|
|
|
546
573
|
function getChartData () {
|
|
547
574
|
var backgroundColor = []
|
|
548
575
|
var borderColor = []
|
|
549
|
-
for (let c = 0; c <
|
|
576
|
+
for (let c = 0; c < 20; c++) {
|
|
550
577
|
let r = 0 + (c*10)
|
|
551
578
|
let g = 130 + (c*20 % 100)
|
|
552
579
|
let b = 80 + (c*30 % 120)
|
|
@@ -565,7 +592,7 @@ module.exports = function (app) {
|
|
|
565
592
|
for (let angle = 0; angle <= 180; angle += 5) {
|
|
566
593
|
data.labels.push(angle)
|
|
567
594
|
}
|
|
568
|
-
for (let index = 0; index < polar.length
|
|
595
|
+
for (let index = 0; index < polar.length; index++) {
|
|
569
596
|
// Add x axis label TWS
|
|
570
597
|
let tws = msToKts(polar[index].tws).toFixed(0)
|
|
571
598
|
let twaArray = polar[index].twa
|
|
@@ -583,7 +610,7 @@ module.exports = function (app) {
|
|
|
583
610
|
if (twaObj.twa == polar[index]['Beat angle'] || twaObj.twa == polar[index]['Run angle']) {
|
|
584
611
|
radius = 5
|
|
585
612
|
}
|
|
586
|
-
data.datasets[index].data.push({x:
|
|
613
|
+
data.datasets[index].data.push({x: Number(radToDeg(twaObj.twa).toFixed(1)), y: Number(msToKts(twaObj.tbs).toFixed(2))})
|
|
587
614
|
data.datasets[index].pointRadius.push(radius)
|
|
588
615
|
}
|
|
589
616
|
}
|