diff --git a/wpilibc/src/main/native/cpp/Timer.cpp b/wpilibc/src/main/native/cpp/Timer.cpp index 1bb10efd3b..cdfa9ab278 100644 --- a/wpilibc/src/main/native/cpp/Timer.cpp +++ b/wpilibc/src/main/native/cpp/Timer.cpp @@ -17,123 +17,34 @@ namespace frc { -void Wait(double seconds) { - std::this_thread::sleep_for(std::chrono::duration(seconds)); -} +void Wait(double seconds) { frc2::Wait(units::second_t(seconds)); } -double GetTime() { - using std::chrono::duration; - using std::chrono::duration_cast; - using std::chrono::system_clock; - - return duration_cast>(system_clock::now().time_since_epoch()) - .count(); -} +double GetTime() { return frc2::GetTime().to(); } } // namespace frc using namespace frc; -// for compatibility with msvc12--see C2864 -const double Timer::kRolloverTime = (1ll << 32) / 1e6; +const double Timer::kRolloverTime = frc2::Timer::kRolloverTime.to(); Timer::Timer() { Reset(); } -Timer::Timer(const Timer& rhs) - : m_startTime(rhs.m_startTime), - m_accumulatedTime(rhs.m_accumulatedTime), - m_running(rhs.m_running) {} +double Timer::Get() const { return m_timer.Get().to(); } -Timer& Timer::operator=(const Timer& rhs) { - std::scoped_lock lock(m_mutex, rhs.m_mutex); +void Timer::Reset() { m_timer.Reset(); } - m_startTime = rhs.m_startTime; - m_accumulatedTime = rhs.m_accumulatedTime; - m_running = rhs.m_running; +void Timer::Start() { m_timer.Start(); } - return *this; -} - -Timer::Timer(Timer&& rhs) - : m_startTime(std::move(rhs.m_startTime)), - m_accumulatedTime(std::move(rhs.m_accumulatedTime)), - m_running(std::move(rhs.m_running)) {} - -Timer& Timer::operator=(Timer&& rhs) { - std::scoped_lock lock(m_mutex, rhs.m_mutex); - - m_startTime = std::move(rhs.m_startTime); - m_accumulatedTime = std::move(rhs.m_accumulatedTime); - m_running = std::move(rhs.m_running); - - return *this; -} - -double Timer::Get() const { - double result; - double currentTime = GetFPGATimestamp(); - - std::scoped_lock lock(m_mutex); - if (m_running) { - // If the current time is before the start time, then the FPGA clock rolled - // over. Compensate by adding the ~71 minutes that it takes to roll over to - // the current time. - if (currentTime < m_startTime) { - currentTime += kRolloverTime; - } - - result = (currentTime - m_startTime) + m_accumulatedTime; - } else { - result = m_accumulatedTime; - } - - return result; -} - -void Timer::Reset() { - std::scoped_lock lock(m_mutex); - m_accumulatedTime = 0; - m_startTime = GetFPGATimestamp(); -} - -void Timer::Start() { - std::scoped_lock lock(m_mutex); - if (!m_running) { - m_startTime = GetFPGATimestamp(); - m_running = true; - } -} - -void Timer::Stop() { - double temp = Get(); - - std::scoped_lock lock(m_mutex); - if (m_running) { - m_accumulatedTime = temp; - m_running = false; - } -} +void Timer::Stop() { m_timer.Stop(); } bool Timer::HasPeriodPassed(double period) { - return HasPeriodPassed(units::second_t(period)); -} - -bool Timer::HasPeriodPassed(units::second_t period) { - if (Get() > period.to()) { - std::scoped_lock lock(m_mutex); - // Advance the start time by the period. - m_startTime += period.to(); - // Don't set it to the current time... we want to avoid drift. - return true; - } - return false; + return m_timer.HasPeriodPassed(units::second_t(period)); } double Timer::GetFPGATimestamp() { - // FPGA returns the timestamp in microseconds - return RobotController::GetFPGATime() * 1.0e-6; + return frc2::Timer::GetFPGATimestamp().to(); } double Timer::GetMatchTime() { - return DriverStation::GetInstance().GetMatchTime(); + return frc2::Timer::GetMatchTime().to(); } diff --git a/wpilibc/src/main/native/cpp/frc2/Timer.cpp b/wpilibc/src/main/native/cpp/frc2/Timer.cpp new file mode 100644 index 0000000000..126cfdda67 --- /dev/null +++ b/wpilibc/src/main/native/cpp/frc2/Timer.cpp @@ -0,0 +1,137 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2008-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. */ +/*----------------------------------------------------------------------------*/ + +#include "frc2/Timer.h" + +#include +#include + +#include + +#include "frc/DriverStation.h" +#include "frc/RobotController.h" + +namespace frc2 { + +void Wait(units::second_t seconds) { + std::this_thread::sleep_for( + std::chrono::duration(seconds.to())); +} + +units::second_t GetTime() { + using std::chrono::duration; + using std::chrono::duration_cast; + using std::chrono::system_clock; + + return units::second_t( + duration_cast>(system_clock::now().time_since_epoch()) + .count()); +} + +} // namespace frc2 + +using namespace frc2; + +// for compatibility with msvc12--see C2864 +const units::second_t Timer::kRolloverTime = units::second_t((1ll << 32) / 1e6); + +Timer::Timer() { Reset(); } + +Timer::Timer(const Timer& rhs) + : m_startTime(rhs.m_startTime), + m_accumulatedTime(rhs.m_accumulatedTime), + m_running(rhs.m_running) {} + +Timer& Timer::operator=(const Timer& rhs) { + std::scoped_lock lock(m_mutex, rhs.m_mutex); + + m_startTime = rhs.m_startTime; + m_accumulatedTime = rhs.m_accumulatedTime; + m_running = rhs.m_running; + + return *this; +} + +Timer::Timer(Timer&& rhs) + : m_startTime(std::move(rhs.m_startTime)), + m_accumulatedTime(std::move(rhs.m_accumulatedTime)), + m_running(std::move(rhs.m_running)) {} + +Timer& Timer::operator=(Timer&& rhs) { + std::scoped_lock lock(m_mutex, rhs.m_mutex); + + m_startTime = std::move(rhs.m_startTime); + m_accumulatedTime = std::move(rhs.m_accumulatedTime); + m_running = std::move(rhs.m_running); + + return *this; +} + +units::second_t Timer::Get() const { + units::second_t result; + units::second_t currentTime = GetFPGATimestamp(); + + std::scoped_lock lock(m_mutex); + if (m_running) { + // If the current time is before the start time, then the FPGA clock rolled + // over. Compensate by adding the ~71 minutes that it takes to roll over to + // the current time. + if (currentTime < m_startTime) { + currentTime += kRolloverTime; + } + + result = (currentTime - m_startTime) + m_accumulatedTime; + } else { + result = m_accumulatedTime; + } + + return result; +} + +void Timer::Reset() { + std::scoped_lock lock(m_mutex); + m_accumulatedTime = 0_s; + m_startTime = GetFPGATimestamp(); +} + +void Timer::Start() { + std::scoped_lock lock(m_mutex); + if (!m_running) { + m_startTime = GetFPGATimestamp(); + m_running = true; + } +} + +void Timer::Stop() { + units::second_t temp = Get(); + + std::scoped_lock lock(m_mutex); + if (m_running) { + m_accumulatedTime = temp; + m_running = false; + } +} + +bool Timer::HasPeriodPassed(units::second_t period) { + if (Get() > period) { + std::scoped_lock lock(m_mutex); + // Advance the start time by the period. + m_startTime += period; + // Don't set it to the current time... we want to avoid drift. + return true; + } + return false; +} + +units::second_t Timer::GetFPGATimestamp() { + // FPGA returns the timestamp in microseconds + return units::second_t(frc::RobotController::GetFPGATime()) * 1.0e-6; +} + +units::second_t Timer::GetMatchTime() { + return units::second_t(frc::DriverStation::GetInstance().GetMatchTime()); +} diff --git a/wpilibc/src/main/native/include/frc/Timer.h b/wpilibc/src/main/native/include/frc/Timer.h index c293f11e29..99caa4770f 100644 --- a/wpilibc/src/main/native/include/frc/Timer.h +++ b/wpilibc/src/main/native/include/frc/Timer.h @@ -12,11 +12,10 @@ #include #include "frc/Base.h" +#include "frc2/Timer.h" namespace frc { -using TimerInterruptHandler = void (*)(void* param); - /** * Pause the task for a specified time. * @@ -57,10 +56,10 @@ class Timer { virtual ~Timer() = default; - Timer(const Timer& rhs); - Timer& operator=(const Timer& rhs); - Timer(Timer&& rhs); - Timer& operator=(Timer&& rhs); + Timer(const Timer& rhs) = default; + Timer& operator=(const Timer& rhs) = default; + Timer(Timer&& rhs) = default; + Timer& operator=(Timer&& rhs) = default; /** * Get the current time from the timer. If the clock is running it is derived @@ -104,19 +103,8 @@ class Timer { * @param period The period to check for (in seconds). * @return True if the period has passed. */ - WPI_DEPRECATED("Use unit-safe HasPeriodPassed method instead.") bool HasPeriodPassed(double period); - /** - * Check if the period specified has passed and if it has, advance the start - * time by that period. This is useful to decide if it's time to do periodic - * work without drifting later by the time it took to get around to checking. - * - * @param period The period to check for. - * @return True if the period has passed. - */ - bool HasPeriodPassed(units::second_t period); - /** * Return the FPGA system clock time in seconds. * @@ -148,10 +136,7 @@ class Timer { static const double kRolloverTime; private: - double m_startTime = 0.0; - double m_accumulatedTime = 0.0; - bool m_running = false; - mutable wpi::mutex m_mutex; + frc2::Timer m_timer; }; } // namespace frc diff --git a/wpilibc/src/main/native/include/frc2/Timer.h b/wpilibc/src/main/native/include/frc2/Timer.h new file mode 100644 index 0000000000..c1eeb16665 --- /dev/null +++ b/wpilibc/src/main/native/include/frc2/Timer.h @@ -0,0 +1,138 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2008-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. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include +#include +#include + +#include "frc/Base.h" + +namespace frc2 { + +/** + * Pause the task for a specified time. + * + * Pause the execution of the program for a specified period of time given in + * seconds. Motors will continue to run at their last assigned values, and + * sensors will continue to update. Only the task containing the wait will pause + * until the wait time is expired. + * + * @param seconds Length of time to pause, in seconds. + */ +void Wait(units::second_t seconds); + +/** + * @brief Gives real-time clock system time with nanosecond resolution + * @return The time, just in case you want the robot to start autonomous at 8pm + * on Saturday. + */ +units::second_t GetTime(); + +/** + * A wrapper for the frc::Timer class that returns unit-typed values. + */ +class Timer { + public: + /** + * Create a new timer object. + * + * Create a new timer object and reset the time to zero. The timer is + * initially not running and must be started. + */ + Timer(); + + virtual ~Timer() = default; + + Timer(const Timer& rhs); + Timer& operator=(const Timer& rhs); + Timer(Timer&& rhs); + Timer& operator=(Timer&& rhs); + + /** + * Get the current time from the timer. If the clock is running it is derived + * from the current system clock the start time stored in the timer class. If + * the clock is not running, then return the time when it was last stopped. + * + * @return Current time value for this timer in seconds + */ + units::second_t Get() const; + + /** + * Reset the timer by setting the time to 0. + * + * Make the timer startTime the current time so new requests will be relative + * to now. + */ + void Reset(); + + /** + * Start the timer running. + * + * Just set the running flag to true indicating that all time requests should + * be relative to the system clock. + */ + void Start(); + + /** + * Stop the timer. + * + * This computes the time as of now and clears the running flag, causing all + * subsequent time requests to be read from the accumulated time rather than + * looking at the system clock. + */ + void Stop(); + + /** + * Check if the period specified has passed and if it has, advance the start + * time by that period. This is useful to decide if it's time to do periodic + * work without drifting later by the time it took to get around to checking. + * + * @param period The period to check for. + * @return True if the period has passed. + */ + bool HasPeriodPassed(units::second_t period); + + /** + * Return the FPGA system clock time in seconds. + * + * Return the time from the FPGA hardware clock in seconds since the FPGA + * started. Rolls over after 71 minutes. + * + * @returns Robot running time in seconds. + */ + static units::second_t GetFPGATimestamp(); + + /** + * Return the approximate match time. + * + * The FMS does not send an official match time to the robots, but does send + * an approximate match time. The value will count down the time remaining in + * the current period (auto or teleop). + * + * Warning: This is not an official time (so it cannot be used to dispute ref + * calls or guarantee that a function will trigger before the match ends). + * + * The Practice Match function of the DS approximates the behavior seen on the + * field. + * + * @return Time remaining in current match period (auto or teleop) + */ + static units::second_t GetMatchTime(); + + // The time, in seconds, at which the 32-bit FPGA timestamp rolls over to 0 + static const units::second_t kRolloverTime; + + private: + units::second_t m_startTime = 0_s; + units::second_t m_accumulatedTime = 0_s; + bool m_running = false; + mutable wpi::mutex m_mutex; +}; + +} // namespace frc2 diff --git a/wpilibc/src/main/native/include/frc2/command/WaitCommand.h b/wpilibc/src/main/native/include/frc2/command/WaitCommand.h index f53ce541ac..15445922b1 100644 --- a/wpilibc/src/main/native/include/frc2/command/WaitCommand.h +++ b/wpilibc/src/main/native/include/frc2/command/WaitCommand.h @@ -12,7 +12,7 @@ #include "CommandBase.h" #include "CommandHelper.h" -#include "frc/Timer.h" +#include "frc2/Timer.h" namespace frc2 { /** @@ -43,7 +43,7 @@ class WaitCommand : public CommandHelper { bool RunsWhenDisabled() const override; protected: - frc::Timer m_timer; + Timer m_timer; private: units::second_t m_duration;