diff --git a/gui/include/gui/ocpn_frame.h b/gui/include/gui/ocpn_frame.h index 94623671c7..8187e83081 100644 --- a/gui/include/gui/ocpn_frame.h +++ b/gui/include/gui/ocpn_frame.h @@ -346,7 +346,7 @@ class MyFrame : public wxFrame { void SendFixToPlugins(); void ProcessAnchorWatch(); void ProcessLogAndBells(); - + void CalculateCOGAverage(); void CheckToolbarPosition(); void ODoSetSize(void); diff --git a/gui/src/ocpn_frame.cpp b/gui/src/ocpn_frame.cpp index b7d4f70ad5..0e282b0377 100644 --- a/gui/src/ocpn_frame.cpp +++ b/gui/src/ocpn_frame.cpp @@ -5142,10 +5142,44 @@ void MyFrame::HandleGPSWatchdogMsg(std::shared_ptr msg) { } } +void MyFrame::CalculateCOGAverage() { + // Maintain average COG for Course Up Mode + if (!std::isnan(gCog)) { + if (g_COGAvgSec > 0) { + // Make a hole + for (int i = g_COGAvgSec - 1; i > 0; i--) COGTable[i] = COGTable[i - 1]; + COGTable[0] = gCog; + + double sum = 0., count = 0; + for (int i = 0; i < g_COGAvgSec; i++) { + double adder = COGTable[i]; + if (std::isnan(adder)) continue; + + if (fabs(adder - g_COGAvg) > 180.) { + if ((adder - g_COGAvg) > 0.) + adder -= 360.; + else + adder += 360.; + } + + sum += adder; + count++; + } + sum /= count; + + if (sum < 0.) + sum += 360.; + else if (sum >= 360.) + sum -= 360.; + + g_COGAvg = sum; + } else + g_COGAvg = gCog; + } +} + void MyFrame::HandleBasicNavMsg(std::shared_ptr msg) { m_fixtime = msg->time; - bool b_Pos_retrigger = false; - bool b_Hdt_retrigger = false; double hdt_data_interval = 0; double fix_time_interval = 0; @@ -5166,45 +5200,37 @@ void MyFrame::HandleBasicNavMsg(std::shared_ptr msg) { DistanceBearingMercator(gLat, gLon, gLat_gt, gLon_gt, &brg, &dist); double implied_sog = dist / (fix_time_interval / 3600); - // printf("-------------- SOG: %g %g %g\n", fix_time_interval, gSog, - // implied_sog); - if (dist < .001) { - return; // probably a duplicate message, ignore it - } - - // shuffle history data - gLat_gt_m2 = gLat_gt_m1; - gLon_gt_m2 = gLon_gt_m1; - gLat_gt_m1 = gLat_gt; - gLon_gt_m1 = gLon_gt; - gCog_gt_m1 = gCog_gt; - - gLat_gt = gLat; - gLon_gt = gLon; - gCog_gt = gCog; - gSog_gt = gSog; - fix_time_gt = fix_time_gt_now; - - if (std::isnan(gCog_gt_m1)) return; // Startup - - if ((fabs(gSog - implied_sog) / gSog) > 0.5) { - // Probably a synthetic data stream, with multiple position sources. - // Do not try to interpolate position at 10 Hz. - gSog_gt = 0; - cog_rate_gt = 0; - // printf("---Skip SOG\n"); - return; + if (dist > .001) { // Avoid duplicate position report + // shuffle history data + gLat_gt_m2 = gLat_gt_m1; + gLon_gt_m2 = gLon_gt_m1; + gLat_gt_m1 = gLat_gt; + gLon_gt_m1 = gLon_gt; + gCog_gt_m1 = gCog_gt; + + gLat_gt = gLat; + gLon_gt = gLon; + gCog_gt = gCog; + gSog_gt = gSog; + fix_time_gt = fix_time_gt_now; + + if (std::isnan(gCog_gt_m1)) return; // Startup + + if ((fabs(gSog - implied_sog) / gSog) > 0.5) { + // Probably a synthetic data stream, with multiple position sources. + // Do not try to interpolate position at 10 Hz. + gSog_gt = 0; + cog_rate_gt = 0; + } else { + // Calculate an estimated Rate-of-turn + double diff = gCog_gt - gCog_gt_m1; + double tentative_cog_rate_gt = diff / (fix_time_gt - fix_time_gt_last); + tentative_cog_rate_gt *= 1e9; // degrees / sec + // Sanity check, and resolve the "phase" problem at +/- North + if (fabs(tentative_cog_rate_gt - cog_rate_gt) < 180.) + cog_rate_gt = tentative_cog_rate_gt; + } } - - // Calculate an estimated Rate-of-turn - double diff = gCog_gt - gCog_gt_m1; - double tentative_cog_rate_gt = diff / (fix_time_gt - fix_time_gt_last); - tentative_cog_rate_gt *= 1e9; // degrees / sec - // Sanity check, and resolve the "phase" problem at +/- North - if (fabs(tentative_cog_rate_gt - cog_rate_gt) < 180.) - cog_rate_gt = tentative_cog_rate_gt; - - b_Pos_retrigger = true; } else if ((msg->vflag & HDT_UPDATE) == HDT_UPDATE) { if (!std::isnan(gHdt)) { // Prepare to estimate the gHdt from prior ground truth measurements @@ -5227,52 +5253,15 @@ void MyFrame::HandleBasicNavMsg(std::shared_ptr msg) { // Sanity check, and resolve the "phase" problem at +/- North if (fabs(tentative_hdt_rate_gt - hdt_rate_gt) < 180.) hdt_rate_gt = tentative_hdt_rate_gt; - b_Hdt_retrigger = true; } } } if (std::isnan(gHdt)) gHdt_gt = NAN; // Handle loss of signal - // Maintain average COG for Course Up Mode - if (!std::isnan(gCog)) { - if (g_COGAvgSec > 0) { - // Make a hole - for (int i = g_COGAvgSec - 1; i > 0; i--) COGTable[i] = COGTable[i - 1]; - COGTable[0] = gCog; - - double sum = 0., count = 0; - for (int i = 0; i < g_COGAvgSec; i++) { - double adder = COGTable[i]; - if (std::isnan(adder)) continue; - - if (fabs(adder - g_COGAvg) > 180.) { - if ((adder - g_COGAvg) > 0.) - adder -= 360.; - else - adder += 360.; - } - - sum += adder; - count++; - } - sum /= count; - - if (sum < 0.) - sum += 360.; - else if (sum >= 360.) - sum -= 360.; - - g_COGAvg = sum; - } else - g_COGAvg = gCog; - } - + // Some housekeeping + CalculateCOGAverage(); FilterCogSog(); - // If gSog is greater than some threshold, we determine that we are - // "cruising" - if (gSog > 3.0) g_bCruising = true; - // Maintain the GPS position validity flag // Determined by source validity of RMC, GGA, GLL (N0183) // or PGNs 129029, 129025 (N2K) @@ -5288,99 +5277,6 @@ void MyFrame::HandleBasicNavMsg(std::shared_ptr msg) { bVelocityValid = true; UpdateStatusBar(); - -#if 0 -#ifdef ocpnUPDATE_SYSTEM_TIME - - // Use the fix time to update the local system clock, only once per - // session - if (!m_bTimeIsSet) { - if (!s_bSetSystemTime) { - m_bTimeIsSet = true; - return; - } - wxDateTime Fix_Time(wxDateTime::Now()); - - if (6 == sfixtime.Len() || - 6 == sfixtime.find('.')) { // perfectly recognised format? - wxString a; - long b; - a = sfixtime.Mid(0, 2); - if (a.ToLong(&b)) Fix_Time.SetHour((wxDateTime::wxDateTime_t)b); - a = sfixtime.Mid(2, 2); - if (a.ToLong(&b)) Fix_Time.SetMinute((wxDateTime::wxDateTime_t)b); - a = sfixtime.Mid(4, 2); - if (a.ToLong(&b)) Fix_Time.SetSecond((wxDateTime::wxDateTime_t)b); - } else - return; // not a good sfixtime format - - time_t TimeOff = Fix_Time.GetTicks() - wxDateTime::Now().GetTicks(); - - if (g_bHasHwClock) { // if a realtime hardwareclock isavailable we only - // check for time and a max of 2 hours of to prevent - // bogus info from some gps devices - if ((abs(TimeOff) > 20) && (abs(TimeOff) < 7200)) { - wxString msg; - msg.Printf(_T("Setting system time, delta t is %d seconds"), TimeOff); - wxLogMessage(msg); -#ifdef __WXMSW__ - // Fix up the fix_time to convert to GMT - Fix_Time = Fix_Time.ToGMT(); - - // Code snippet following borrowed from wxDateCtrl, MSW - const wxDateTime::Tm tm(Fix_Time.GetTm()); - SYSTEMTIME stm; - stm.wYear = (WXWORD)tm.year; - stm.wMonth = (WXWORD)(tm.mon - wxDateTime::Jan + 1); - stm.wDay = tm.mday; - stm.wDayOfWeek = 0; - stm.wHour = Fix_Time.GetHour(); - stm.wMinute = tm.min; - stm.wSecond = tm.sec; - stm.wMilliseconds = 0; - - ::SetSystemTime(&stm); // in GMT -#else - // This contortion sets the system date/time on POSIX host - // Requires the following line in /etc/sudoers - // "nav ALL=NOPASSWD:/bin/date *" (where nav is your username) - // or "%sudo ALL=NOPASSWD:/bin/date *" - wxString CommandStr("sudo /bin/date +%T --utc --set=\""); - CommandStr.Append(Fix_Time.Format("%T")); - CommandStr.Append("\""); - msg.Printf(_T("Linux command is:")); - msg += CommandStr; - wxLogMessage(msg); - wxExecute(CommandStr, wxEXEC_ASYNC); -#endif //__WXMSW__ - } - m_bTimeIsSet = true; - } else { // no hw-clock set both date and time - if (gRmcDate.Len() == 6) { -#if !defined(__WXMSW__) // not for windows - wxString a; - long b; - Fix_Time.SetMonth((wxDateTime::Month)2); - a = gRmcDate.Mid(0, 2); - if (a.ToLong(&b)) Fix_Time.SetDay(b); - a = gRmcDate.Mid(2, 2); - if (a.ToLong(&b)) Fix_Time.SetMonth((wxDateTime::Month)(b - 1)); - a = gRmcDate.Mid(4, 2); - if (a.ToLong(&b)) - Fix_Time.SetYear(b + 2000); // TODO fix this before the year 2100 - wxString msg; - wxString CommandStr("sudo /bin/date --utc --set=\""); - CommandStr.Append(Fix_Time.Format("%D %T\"")); - msg.Printf(_T("Set Date/Time, Linux command is: %s"), CommandStr); - wxLogMessage(msg); - wxExecute(CommandStr, wxEXEC_ASYNC); -#endif // !__WXMSW__ - m_bTimeIsSet = true; - } - } - } -#endif // ocpnUPDATE_SYSTEM_TIME -#endif } void MyFrame::UpdateStatusBar() { @@ -5877,6 +5773,10 @@ void MyFrame::OnFrameTimer1(wxTimerEvent &event) { return; } + // If gSog is greater than some threshold, + // we determine that we are"cruising" + if (gSog > 3.0) g_bCruising = true; + // Update the Toolbar Status windows and lower status bar // just after start of ticks. diff --git a/model/src/comm_decoder.cpp b/model/src/comm_decoder.cpp index d117830e25..262fe0a8bb 100644 --- a/model/src/comm_decoder.cpp +++ b/model/src/comm_decoder.cpp @@ -188,6 +188,22 @@ bool CommDecoder::DecodeVTG(std::string s, NavData& temp_data) { temp_data.gCog = m_NMEA0183.Vtg.TrackDegreesTrue; } + // If COG-T is not available but COG-M is, then + // create COG-T from COG-M and gVar + if (!std::isnan(m_NMEA0183.Vtg.SpeedKnots) && + !std::isnan(m_NMEA0183.Vtg.TrackDegreesMagnetic)) { + // establish gVar, if not already set + if (std::isnan(gVar) && (g_UserVar != 0.0)) gVar = g_UserVar; + + double cogt = m_NMEA0183.Vtg.TrackDegreesMagnetic + gVar; + if (!std::isnan(cogt)) { + if (cogt < 0) + cogt += 360.0; + else if (cogt >= 360) + cogt -= 360.0; + temp_data.gCog = cogt; + } + } return true; }