another wndCenter fix; TWD calc with HDM and no VAR; COG valid check; dflt range 60°
This commit is contained in:
parent
05f8b3ec65
commit
398b8e0d02
|
@ -83,24 +83,26 @@ bool WindUtils::calcTrueWind(const double* awaVal, const double* awsVal,
|
||||||
{
|
{
|
||||||
double stw, hdt, ctw;
|
double stw, hdt, ctw;
|
||||||
double twd, tws, twa;
|
double twd, tws, twa;
|
||||||
|
double minSogVal = 0.1; // SOG below this value (m/s) is assumed to be data noise from GPS sensor
|
||||||
static const double DBL_MIN = std::numeric_limits<double>::lowest();
|
static const double DBL_MIN = std::numeric_limits<double>::lowest();
|
||||||
|
|
||||||
|
Serial.println("\ncalcTrueWind: HDT: " + String(*hdtVal) + ", HDM: " + String(*hdmVal) + ", VAR: " + String(*varVal) + ", SOG: " + String(*sogVal) + ", COG: " + String(*cogVal));
|
||||||
if (*hdtVal != DBL_MIN) {
|
if (*hdtVal != DBL_MIN) {
|
||||||
hdt = *hdtVal; // Use HDT if available
|
hdt = *hdtVal; // Use HDT if available
|
||||||
} else {
|
} else {
|
||||||
if (*hdmVal != DBL_MIN && *varVal != DBL_MIN) {
|
if (*hdmVal != DBL_MIN) {
|
||||||
hdt = *hdmVal + *varVal; // Use corrected HDM if HDT is not available
|
hdt = *hdmVal + (*varVal != DBL_MIN ? *varVal : 0.0); // Use corrected HDM if HDT is not available (or just HDM if VAR is not available)
|
||||||
hdt = to2PI(hdt);
|
hdt = to2PI(hdt);
|
||||||
} else if (*cogVal != DBL_MIN) {
|
} else if (*cogVal != DBL_MIN && *sogVal >= minSogVal) {
|
||||||
hdt = *cogVal; // Use COG as fallback if HDT and HDM are not available
|
hdt = *cogVal; // Use COG as fallback if HDT and HDM are not available, and SOG is not data noise
|
||||||
} else {
|
} else {
|
||||||
return false; // Cannot calculate without valid HDT or HDM+VAR or COG
|
return false; // Cannot calculate without valid HDT or HDM+VAR or COG
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*cogVal != DBL_MIN) {
|
if (*cogVal != DBL_MIN && *sogVal >= minSogVal ) { // if SOG is data noise, we don't trust COG
|
||||||
ctw = *cogVal; // Use COG as CTW if available
|
|
||||||
// ctw = *cogVal + ((*cogVal - hdt) / 2); // Estimate CTW from COG
|
ctw = *cogVal; // Use COG for CTW if available
|
||||||
} else {
|
} else {
|
||||||
ctw = hdt; // 2nd approximation for CTW; hdt must exist if we reach this part of the code
|
ctw = hdt; // 2nd approximation for CTW; hdt must exist if we reach this part of the code
|
||||||
}
|
}
|
||||||
|
@ -113,6 +115,7 @@ bool WindUtils::calcTrueWind(const double* awaVal, const double* awsVal,
|
||||||
// If STW and SOG are not available, we cannot calculate true wind
|
// If STW and SOG are not available, we cannot calculate true wind
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Serial.println("\ncalcTrueWind: HDT: " + String(hdt) + ", CTW: " + String(ctw) + ", STW: " + String(stw));
|
||||||
|
|
||||||
if ((*awaVal == DBL_MIN) || (*awsVal == DBL_MIN)) {
|
if ((*awaVal == DBL_MIN) || (*awsVal == DBL_MIN)) {
|
||||||
// Cannot calculate true wind without valid AWA, AWS; other checks are done earlier
|
// Cannot calculate true wind without valid AWA, AWS; other checks are done earlier
|
||||||
|
@ -140,15 +143,12 @@ void HstryBuf::fillWndBufSimData(tBoatHstryData& hstryBufs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* double genTwdSimDat()
|
/* void HstryBuf::simWndDir(double &wndDir)
|
||||||
{
|
{
|
||||||
simTwd += random(-20, 20);
|
wndDir += random(-20, 20);
|
||||||
if (simTwd < 0.0)
|
wndDir = WindUtils::to360(wndDir);
|
||||||
simTwd += 360.0;
|
|
||||||
if (simTwd >= 360.0)
|
|
||||||
simTwd -= 360.0;
|
|
||||||
|
|
||||||
int16_t z = static_cast<int16_t>(DegToRad(simTwd) * 1000.0);
|
int16_t z = static_cast<int16_t>(DegToRad(wndDir) * 1000.0);
|
||||||
pageData.boatHstry.twdHstry->add(z); // Fill the buffer with some test data
|
pageData.boatHstry.twdHstry->add(z); // Fill the buffer with some test data
|
||||||
|
|
||||||
simTws += random(-200, 150) / 10.0; // TWS value in knots
|
simTws += random(-200, 150) / 10.0; // TWS value in knots
|
||||||
|
|
|
@ -118,7 +118,7 @@ public:
|
||||||
GwConfigHandler* config = commonData->config;
|
GwConfigHandler* config = commonData->config;
|
||||||
GwLog* logger = commonData->logger;
|
GwLog* logger = commonData->logger;
|
||||||
|
|
||||||
float twsValue; // TWS value in chart area
|
// float twsValue; // TWS value in chart area
|
||||||
static String twdName, twdUnit; // TWD name and unit
|
static String twdName, twdUnit; // TWD name and unit
|
||||||
static int updFreq; // Update frequency for TWD
|
static int updFreq; // Update frequency for TWD
|
||||||
static int16_t twdLowest, twdHighest; // TWD range
|
static int16_t twdLowest, twdHighest; // TWD range
|
||||||
|
@ -161,7 +161,7 @@ public:
|
||||||
static int wndRight; // chart wind right value position
|
static int wndRight; // chart wind right value position
|
||||||
static int chrtRng; // Range of wind values from mid wind value to min/max wind value in degrees
|
static int chrtRng; // Range of wind values from mid wind value to min/max wind value in degrees
|
||||||
int diffRng; // Difference between mid and current wind value
|
int diffRng; // Difference between mid and current wind value
|
||||||
static const int dfltRng = 40; // Default range for chart
|
static const int dfltRng = 60; // Default range for chart
|
||||||
int midWndDir; // New value for wndCenter after chart start / shift
|
int midWndDir; // New value for wndCenter after chart start / shift
|
||||||
static int simTwd; // Simulation value for TWD
|
static int simTwd; // Simulation value for TWD
|
||||||
static float simTws; // Simulation value for TWS
|
static float simTws; // Simulation value for TWS
|
||||||
|
@ -189,7 +189,7 @@ public:
|
||||||
numNoData = 0;
|
numNoData = 0;
|
||||||
simTwd = pageData.boatHstry.twdHstry->getLast() / 1000.0 * radToDeg;
|
simTwd = pageData.boatHstry.twdHstry->getLast() / 1000.0 * radToDeg;
|
||||||
simTws = 0;
|
simTws = 0;
|
||||||
twsValue = 0;
|
// twsValue = 0;
|
||||||
bufStart = 0;
|
bufStart = 0;
|
||||||
oldDataIntv = 0;
|
oldDataIntv = 0;
|
||||||
numAddedBufVals, currIdx, lastIdx = 0;
|
numAddedBufVals, currIdx, lastIdx = 0;
|
||||||
|
@ -264,6 +264,7 @@ public:
|
||||||
} else if (diffRng + 10 < chrtRng) { // Reduce chart range for higher resolution if possible
|
} else if (diffRng + 10 < chrtRng) { // Reduce chart range for higher resolution if possible
|
||||||
chrtRng = max(dfltRng, int((diffRng + (diffRng >= 0 ? 9 : -1)) / 10) * 10);
|
chrtRng = max(dfltRng, int((diffRng + (diffRng >= 0 ? 9 : -1)) / 10) * 10);
|
||||||
}
|
}
|
||||||
|
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Range adjust: wndCenter: %d, diffRng: %d, chrtRng: %d", wndCenter, diffRng, chrtRng);
|
||||||
}
|
}
|
||||||
chrtScl = float(width) / float(chrtRng) / 2.0; // Chart scale: pixels per degree
|
chrtScl = float(width) / float(chrtRng) / 2.0; // Chart scale: pixels per degree
|
||||||
wndLeft = wndCenter - chrtRng;
|
wndLeft = wndCenter - chrtRng;
|
||||||
|
@ -331,8 +332,7 @@ public:
|
||||||
x = ((chrtVal - wndLeft + 360) % 360) * chrtScl;
|
x = ((chrtVal - wndLeft + 360) % 360) * chrtScl;
|
||||||
y = yOffset + cHeight - i; // Position in chart area
|
y = yOffset + cHeight - i; // Position in chart area
|
||||||
|
|
||||||
// if (i >= (numWndVals / dataIntv) - 10)
|
if (i >= (numWndVals / dataIntv) - 1) // log chart data for 1 or more lines
|
||||||
if (i >= (numWndVals / dataIntv) - 1)
|
|
||||||
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Chart: i: %d, chrtVal: %d, bufStart: %d, count: %d, linesToShow: %d", i, chrtVal, bufStart, count, (numWndVals / dataIntv));
|
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Chart: i: %d, chrtVal: %d, bufStart: %d, count: %d, linesToShow: %d", i, chrtVal, bufStart, count, (numWndVals / dataIntv));
|
||||||
|
|
||||||
if ((i == 0) || (chrtPrevVal == INT16_MIN)) {
|
if ((i == 0) || (chrtPrevVal == INT16_MIN)) {
|
||||||
|
@ -367,8 +367,11 @@ public:
|
||||||
int minWndDir = pageData.boatHstry.twdHstry->getMin(numWndVals) / 1000.0 * radToDeg;
|
int minWndDir = pageData.boatHstry.twdHstry->getMin(numWndVals) / 1000.0 * radToDeg;
|
||||||
int maxWndDir = pageData.boatHstry.twdHstry->getMax(numWndVals) / 1000.0 * radToDeg;
|
int maxWndDir = pageData.boatHstry.twdHstry->getMax(numWndVals) / 1000.0 * radToDeg;
|
||||||
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot FreeTop: Minimum: %d, Maximum: %d, OldwndCenter: %d", minWndDir, maxWndDir, wndCenter);
|
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot FreeTop: Minimum: %d, Maximum: %d, OldwndCenter: %d", minWndDir, maxWndDir, wndCenter);
|
||||||
// if ((minWndDir + 540 >= wndCenter + 540) || (maxWndDir + 540 <= wndCenter + 540)) {
|
// if (((minWndDir - wndCenter >= 0) && (minWndDir - wndCenter < 180)) || ((maxWndDir - wndCenter <= 0) && (maxWndDir - wndCenter >=180))) {
|
||||||
if (((minWndDir - wndCenter >= 0) && (minWndDir - wndCenter < 180)) || ((maxWndDir - wndCenter <= 0) && (maxWndDir - wndCenter >=180))) {
|
if ((wndRight > wndCenter && (minWndDir >= wndCenter && minWndDir <= wndRight)) ||
|
||||||
|
(wndRight <= wndCenter && (minWndDir >= wndCenter || minWndDir <= wndRight)) ||
|
||||||
|
(wndLeft < wndCenter && (maxWndDir <= wndCenter && maxWndDir >= wndLeft)) ||
|
||||||
|
(wndLeft >= wndCenter && (maxWndDir <= wndCenter || maxWndDir >= wndLeft))) {
|
||||||
// Check if all wind value are left or right of center value -> optimize chart range
|
// Check if all wind value are left or right of center value -> optimize chart range
|
||||||
midWndDir = pageData.boatHstry.twdHstry->getMid(numWndVals) / 1000.0 * radToDeg;
|
midWndDir = pageData.boatHstry.twdHstry->getMid(numWndVals) / 1000.0 * radToDeg;
|
||||||
if (midWndDir != INT16_MIN) {
|
if (midWndDir != INT16_MIN) {
|
||||||
|
@ -396,7 +399,7 @@ public:
|
||||||
int xPosTws;
|
int xPosTws;
|
||||||
static const int yPosTws = yOffset + 40;
|
static const int yPosTws = yOffset + 40;
|
||||||
|
|
||||||
twsValue = pageData.boatHstry.twsHstry->getLast() / 10.0 * 1.94384; // TWS value in knots
|
// twsValue = pageData.boatHstry.twsHstry->getLast() / 10.0 * 1.94384; // TWS value in knots
|
||||||
|
|
||||||
xPosTws = flipTws ? 20 : width - 138;
|
xPosTws = flipTws ? 20 : width - 138;
|
||||||
currentZone = (y >= yPosTws - 38) && (y <= yPosTws + 6) && (x >= xPosTws - 4) && (x <= xPosTws + 146) ? 1 : 0; // Define current zone for TWS value
|
currentZone = (y >= yPosTws - 38) && (y <= yPosTws + 6) && (x >= xPosTws - 4) && (x <= xPosTws + 146) ? 1 : 0; // Define current zone for TWS value
|
||||||
|
@ -424,12 +427,12 @@ public:
|
||||||
}
|
}
|
||||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||||
getdisplay().setCursor(xPosTws + 82, yPosTws - 14);
|
getdisplay().setCursor(xPosTws + 82, yPosTws - 14);
|
||||||
// getdisplay().print("TWS"); // Name
|
// getdisplay().print("TWS"); // Name
|
||||||
getdisplay().print(BDataName[1]); // Name
|
getdisplay().print(BDataName[1]); // Name
|
||||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||||
// getdisplay().setCursor(xPosTws + 78, yPosTws + 1);
|
// getdisplay().setCursor(xPosTws + 78, yPosTws + 1);
|
||||||
getdisplay().setCursor(xPosTws + 82, yPosTws + 1);
|
getdisplay().setCursor(xPosTws + 82, yPosTws + 1);
|
||||||
// getdisplay().printf(" kn"); // Unit
|
// getdisplay().printf(" kn"); // Unit
|
||||||
getdisplay().print(BDataUnit[1]); // Unit
|
getdisplay().print(BDataUnit[1]); // Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,7 +475,7 @@ PageDescription registerPageWindPlot(
|
||||||
createPage, // Action
|
createPage, // Action
|
||||||
0, // Number of bus values depends on selection in Web configuration
|
0, // Number of bus values depends on selection in Web configuration
|
||||||
{ "TWD", "TWS" }, // Bus values we need in the page
|
{ "TWD", "TWS" }, // Bus values we need in the page
|
||||||
// {}, // Bus values we need in the page
|
// {}, // Bus values we need in the page
|
||||||
true // Show display header on/off
|
true // Show display header on/off
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -404,7 +404,7 @@ bool addTrueWind(GwApi* api, BoatValueList* boatValues) {
|
||||||
hdtVal = hdtBVal->valid ? hdtBVal->value : DBL_MIN;
|
hdtVal = hdtBVal->valid ? hdtBVal->value : DBL_MIN;
|
||||||
hdmVal = hdmBVal->valid ? hdmBVal->value : DBL_MIN;
|
hdmVal = hdmBVal->valid ? hdmBVal->value : DBL_MIN;
|
||||||
varVal = varBVal->valid ? varBVal->value : DBL_MIN;
|
varVal = varBVal->valid ? varBVal->value : DBL_MIN;
|
||||||
api->getLogger()->logDebug(GwLog::DEBUG,"obp60task addTrueWind: AWA %.1f, AWS %.1f, COG %.1f, STW %.1f, SOG %.1f, HDT %.1f, HDM %.1f, VAR %.1f", awaBVal->value * RAD_TO_DEG, awsBVal->value * 3.6 / 1.852,
|
api->getLogger()->logDebug(GwLog::DEBUG,"obp60task addTrueWind: AWA %.1f, AWS %.1f, COG %.1f, STW %.1f, SOG %.2f, HDT %.1f, HDM %.1f, VAR %.1f", awaBVal->value * RAD_TO_DEG, awsBVal->value * 3.6 / 1.852,
|
||||||
cogBVal->value * RAD_TO_DEG, stwBVal->value * 3.6 / 1.852, sogBVal->value * 3.6 / 1.852, hdtBVal->value * RAD_TO_DEG, hdmBVal->value * RAD_TO_DEG, varBVal->value * RAD_TO_DEG);
|
cogBVal->value * RAD_TO_DEG, stwBVal->value * 3.6 / 1.852, sogBVal->value * 3.6 / 1.852, hdtBVal->value * RAD_TO_DEG, hdmBVal->value * RAD_TO_DEG, varBVal->value * RAD_TO_DEG);
|
||||||
|
|
||||||
isCalculated = WindUtils::calcTrueWind(&awaVal, &awsVal, &cogVal, &stwVal, &sogVal, &hdtVal, &hdmVal, &varVal, &twd, &tws, &twa);
|
isCalculated = WindUtils::calcTrueWind(&awaVal, &awsVal, &cogVal, &stwVal, &sogVal, &hdtVal, &hdmVal, &varVal, &twd, &tws, &twa);
|
||||||
|
@ -423,7 +423,7 @@ bool addTrueWind(GwApi* api, BoatValueList* boatValues) {
|
||||||
twaBVal->valid = true;
|
twaBVal->valid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
api->getLogger()->logDebug(GwLog::DEBUG,"obp60task addTrueWind: TWD_Valid %d, isCalculated %d, TWD %.1f, TWA %.1f, TWS %.1f", twdBVal->valid, isCalculated, twdBVal->value * RAD_TO_DEG,
|
api->getLogger()->logDebug(GwLog::DEBUG,"obp60task addTrueWind: TWD_isValid %d, isCalculated %d, TWD %.1f, TWA %.1f, TWS %.1f", twdBVal->valid, isCalculated, twdBVal->value * RAD_TO_DEG,
|
||||||
twaBVal->value * RAD_TO_DEG, twsBVal->value * 3.6 / 1.852);
|
twaBVal->value * RAD_TO_DEG, twsBVal->value * 3.6 / 1.852);
|
||||||
|
|
||||||
return isCalculated;
|
return isCalculated;
|
||||||
|
@ -463,8 +463,8 @@ void handleHstryBuf(GwApi* api, BoatValueList* boatValues, tBoatHstryData hstryB
|
||||||
GwApi::BoatValue *twsBVal = boatValues->findValueOrCreate(hstryBufList.twsHstry->getName());
|
GwApi::BoatValue *twsBVal = boatValues->findValueOrCreate(hstryBufList.twsHstry->getName());
|
||||||
GwApi::BoatValue *twaBVal = boatValues->findValueOrCreate("TWA");
|
GwApi::BoatValue *twaBVal = boatValues->findValueOrCreate("TWA");
|
||||||
|
|
||||||
api->getLogger()->logDebug(GwLog::DEBUG,"obp60task handleHstryBuf: twdBVal: %.1f, twaBVal: %.1f, twsBVal: %.1f, TWD_isValid? %d", twdBVal->value * RAD_TO_DEG,
|
api->getLogger()->logDebug(GwLog::DEBUG,"obp60task handleHstryBuf: TWD_isValid? %d, twdBVal: %.1f, twaBVal: %.1f, twsBVal: %.1f", twdBVal->valid, twdBVal->value * RAD_TO_DEG,
|
||||||
twaBVal->value * RAD_TO_DEG, twsBVal->value * 3.6 / 1.852, twdBVal->valid);
|
twaBVal->value * RAD_TO_DEG, twsBVal->value * 3.6 / 1.852);
|
||||||
calBVal = new GwApi::BoatValue("TWD"); // temporary solution for calibration of history buffer values
|
calBVal = new GwApi::BoatValue("TWD"); // temporary solution for calibration of history buffer values
|
||||||
calBVal->setFormat(twdBVal->getFormat());
|
calBVal->setFormat(twdBVal->getFormat());
|
||||||
if (twdBVal->valid) {
|
if (twdBVal->valid) {
|
||||||
|
|
Loading…
Reference in New Issue