diff --git a/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp b/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp index 73d4c1537a..90dc54b77a 100644 --- a/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp +++ b/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp @@ -27,8 +27,8 @@ IterativeRobotBase::IterativeRobotBase(double period) : IterativeRobotBase(units::second_t(period)) {} IterativeRobotBase::IterativeRobotBase(units::second_t period) - : m_period(period.to()), - m_watchdog(period.to(), [this] { PrintLoopOverrunMessage(); }) {} + : m_period(period), + m_watchdog(period, [this] { PrintLoopOverrunMessage(); }) {} void IterativeRobotBase::RobotInit() { wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n"; @@ -174,7 +174,8 @@ void IterativeRobotBase::PrintLoopOverrunMessage() { wpi::SmallString<128> str; wpi::raw_svector_ostream buf(str); - buf << "Loop time of " << wpi::format("%.6f", m_period) << "s overrun\n"; + buf << "Loop time of " << wpi::format("%.6f", m_period.to()) + << "s overrun\n"; DriverStation::ReportWarning(str); } diff --git a/wpilibc/src/main/native/cpp/TimedRobot.cpp b/wpilibc/src/main/native/cpp/TimedRobot.cpp index 9d0459c221..ffff2ddcb8 100644 --- a/wpilibc/src/main/native/cpp/TimedRobot.cpp +++ b/wpilibc/src/main/native/cpp/TimedRobot.cpp @@ -25,7 +25,7 @@ void TimedRobot::StartCompetition() { // Tell the DS that the robot is ready to be enabled HAL_ObserveUserProgramStarting(); - m_expirationTime = Timer::GetFPGATimestamp() + m_period; + m_expirationTime = units::second_t{Timer::GetFPGATimestamp()} + m_period; UpdateAlarm(); // Loop forever, calling the appropriate mode-dependent function diff --git a/wpilibc/src/main/native/cpp/Watchdog.cpp b/wpilibc/src/main/native/cpp/Watchdog.cpp index 49f4bd5f34..e5be4fae76 100644 --- a/wpilibc/src/main/native/cpp/Watchdog.cpp +++ b/wpilibc/src/main/native/cpp/Watchdog.cpp @@ -54,7 +54,7 @@ void Watchdog::Thread::Main() { if (!watchdog->m_suppressTimeoutMessage) { wpi::outs() << "Watchdog not fed within " << wpi::format("%.6f", - watchdog->m_timeout.count() / 1.0e6) + watchdog->m_timeout.count() / 1.0e9) << "s\n"; } } @@ -78,9 +78,10 @@ void Watchdog::Thread::Main() { } Watchdog::Watchdog(double timeout, std::function callback) - : m_timeout(static_cast(timeout * 1.0e6)), - m_callback(callback), - m_owner(&GetThreadOwner()) {} + : Watchdog(units::second_t{timeout}, callback) {} + +Watchdog::Watchdog(units::second_t timeout, std::function callback) + : m_timeout(timeout), m_callback(callback), m_owner(&GetThreadOwner()) {} Watchdog::~Watchdog() { Disable(); } @@ -89,6 +90,13 @@ double Watchdog::GetTime() const { } void Watchdog::SetTimeout(double timeout) { + SetTimeout(units::second_t{timeout}); +} + +void Watchdog::SetTimeout(units::second_t timeout) { + using std::chrono::duration_cast; + using std::chrono::microseconds; + m_startTime = hal::fpga_clock::now(); m_epochs.clear(); @@ -96,11 +104,11 @@ void Watchdog::SetTimeout(double timeout) { auto thr = m_owner->GetThread(); if (!thr) return; - m_timeout = std::chrono::microseconds(static_cast(timeout * 1.0e6)); + m_timeout = timeout; m_isExpired = false; thr->m_watchdogs.remove(this); - m_expirationTime = m_startTime + m_timeout; + m_expirationTime = m_startTime + duration_cast(m_timeout); thr->m_watchdogs.emplace(this); thr->m_cond.notify_all(); } @@ -109,7 +117,7 @@ double Watchdog::GetTimeout() const { // Locks mutex auto thr = m_owner->GetThread(); - return m_timeout.count() / 1.0e6; + return m_timeout.count() / 1.0e9; } bool Watchdog::IsExpired() const { @@ -140,6 +148,9 @@ void Watchdog::PrintEpochs() { void Watchdog::Reset() { Enable(); } void Watchdog::Enable() { + using std::chrono::duration_cast; + using std::chrono::microseconds; + m_startTime = hal::fpga_clock::now(); m_epochs.clear(); @@ -150,7 +161,7 @@ void Watchdog::Enable() { m_isExpired = false; thr->m_watchdogs.remove(this); - m_expirationTime = m_startTime + m_timeout; + m_expirationTime = m_startTime + duration_cast(m_timeout); thr->m_watchdogs.emplace(this); thr->m_cond.notify_all(); } diff --git a/wpilibc/src/main/native/include/frc/IterativeRobotBase.h b/wpilibc/src/main/native/include/frc/IterativeRobotBase.h index 6011f48deb..b78765a198 100644 --- a/wpilibc/src/main/native/include/frc/IterativeRobotBase.h +++ b/wpilibc/src/main/native/include/frc/IterativeRobotBase.h @@ -161,7 +161,7 @@ class IterativeRobotBase : public RobotBase { void LoopFunc(); - double m_period; + units::second_t m_period; private: enum class Mode { kNone, kDisabled, kAutonomous, kTeleop, kTest }; diff --git a/wpilibc/src/main/native/include/frc/TimedRobot.h b/wpilibc/src/main/native/include/frc/TimedRobot.h index fcc498e0c5..1c8ff801a7 100644 --- a/wpilibc/src/main/native/include/frc/TimedRobot.h +++ b/wpilibc/src/main/native/include/frc/TimedRobot.h @@ -63,7 +63,7 @@ class TimedRobot : public IterativeRobotBase, public ErrorBase { hal::Handle m_notifier; // The absolute expiration time - double m_expirationTime = 0; + units::second_t m_expirationTime{0}; /** * Update the HAL alarm time. diff --git a/wpilibc/src/main/native/include/frc/Watchdog.h b/wpilibc/src/main/native/include/frc/Watchdog.h index e15da1fe42..b36cf23456 100644 --- a/wpilibc/src/main/native/include/frc/Watchdog.h +++ b/wpilibc/src/main/native/include/frc/Watchdog.h @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018 FIRST. All Rights Reserved. */ +/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -12,9 +12,11 @@ #include #include +#include #include #include #include +#include namespace frc { @@ -36,10 +38,25 @@ class Watchdog { * resolution. * @param callback This function is called when the timeout expires. */ + WPI_DEPRECATED("Use unit-safe version instead") Watchdog(double timeout, std::function callback); + /** + * Watchdog constructor. + * + * @param timeout The watchdog's timeout in seconds with microsecond + * resolution. + * @param callback This function is called when the timeout expires. + */ + Watchdog(units::second_t timeout, std::function callback); + template + WPI_DEPRECATED("Use unit-safe version instead") Watchdog(double timeout, Callable&& f, Arg&& arg, Args&&... args) + : Watchdog(units::second_t{timeout}, arg, args...) {} + + template + Watchdog(units::second_t timeout, Callable&& f, Arg&& arg, Args&&... args) : Watchdog(timeout, std::bind(std::forward(f), std::forward(arg), std::forward(args)...)) {} @@ -60,8 +77,17 @@ class Watchdog { * @param timeout The watchdog's timeout in seconds with microsecond * resolution. */ + WPI_DEPRECATED("Use unit-safe version instead") void SetTimeout(double timeout); + /** + * Sets the watchdog's timeout. + * + * @param timeout The watchdog's timeout in seconds with microsecond + * resolution. + */ + void SetTimeout(units::second_t timeout); + /** * Returns the watchdog's timeout in seconds. */ @@ -119,13 +145,13 @@ class Watchdog { static constexpr std::chrono::milliseconds kMinPrintPeriod{1000}; hal::fpga_clock::time_point m_startTime; - std::chrono::microseconds m_timeout; + std::chrono::nanoseconds m_timeout; hal::fpga_clock::time_point m_expirationTime; std::function m_callback; hal::fpga_clock::time_point m_lastTimeoutPrintTime = hal::fpga_clock::epoch(); hal::fpga_clock::time_point m_lastEpochsPrintTime = hal::fpga_clock::epoch(); - wpi::StringMap m_epochs; + wpi::StringMap m_epochs; bool m_isExpired = false; bool m_suppressTimeoutMessage = false; diff --git a/wpilibc/src/test/native/cpp/WatchdogTest.cpp b/wpilibc/src/test/native/cpp/WatchdogTest.cpp index f4921546c3..10ff99691a 100644 --- a/wpilibc/src/test/native/cpp/WatchdogTest.cpp +++ b/wpilibc/src/test/native/cpp/WatchdogTest.cpp @@ -24,7 +24,7 @@ TEST(WatchdogTest, EnableDisable) { #endif uint32_t watchdogCounter = 0; - Watchdog watchdog(0.4, [&] { watchdogCounter++; }); + Watchdog watchdog(0.4_s, [&] { watchdogCounter++; }); wpi::outs() << "Run 1\n"; watchdog.Enable(); @@ -59,7 +59,7 @@ TEST(WatchdogTest, Reset) { #endif uint32_t watchdogCounter = 0; - Watchdog watchdog(0.4, [&] { watchdogCounter++; }); + Watchdog watchdog(0.4_s, [&] { watchdogCounter++; }); watchdog.Enable(); std::this_thread::sleep_for(std::chrono::milliseconds(200)); @@ -77,11 +77,11 @@ TEST(WatchdogTest, SetTimeout) { #endif uint32_t watchdogCounter = 0; - Watchdog watchdog(1.0, [&] { watchdogCounter++; }); + Watchdog watchdog(1.0_s, [&] { watchdogCounter++; }); watchdog.Enable(); std::this_thread::sleep_for(std::chrono::milliseconds(200)); - watchdog.SetTimeout(0.2); + watchdog.SetTimeout(0.2_s); EXPECT_EQ(0.2, watchdog.GetTimeout()); EXPECT_EQ(0u, watchdogCounter) << "Watchdog triggered early"; @@ -98,7 +98,7 @@ TEST(WatchdogTest, DISABLED_IsExpired) { #else TEST(WatchdogTest, IsExpired) { #endif - Watchdog watchdog(0.2, [] {}); + Watchdog watchdog(0.2_s, [] {}); EXPECT_FALSE(watchdog.IsExpired()); watchdog.Enable(); @@ -120,7 +120,7 @@ TEST(WatchdogTest, Epochs) { #endif uint32_t watchdogCounter = 0; - Watchdog watchdog(0.4, [&] { watchdogCounter++; }); + Watchdog watchdog(0.4_s, [&] { watchdogCounter++; }); wpi::outs() << "Run 1\n"; watchdog.Enable(); @@ -153,8 +153,8 @@ TEST(WatchdogTest, MultiWatchdog) { uint32_t watchdogCounter1 = 0; uint32_t watchdogCounter2 = 0; - Watchdog watchdog1(0.2, [&] { watchdogCounter1++; }); - Watchdog watchdog2(0.6, [&] { watchdogCounter2++; }); + Watchdog watchdog1(0.2_s, [&] { watchdogCounter1++; }); + Watchdog watchdog2(0.6_s, [&] { watchdogCounter2++; }); watchdog2.Enable(); std::this_thread::sleep_for(std::chrono::milliseconds(200));