2013-12-15 18:30:16 -05:00
|
|
|
/*----------------------------------------------------------------------------*/
|
2017-08-23 22:06:13 -07:00
|
|
|
/* Copyright (c) 2008-2017 FIRST. All Rights Reserved. */
|
2013-12-15 18:30:16 -05:00
|
|
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
2016-01-02 03:02:34 -08:00
|
|
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
|
|
|
/* the project. */
|
2013-12-15 18:30:16 -05:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#include "Timer.h"
|
|
|
|
|
|
2016-05-26 20:19:23 -07:00
|
|
|
#include <chrono>
|
|
|
|
|
#include <thread>
|
2016-09-25 16:50:13 -07:00
|
|
|
|
2017-08-27 00:11:52 -07:00
|
|
|
#include <HAL/HAL.h>
|
|
|
|
|
|
2016-10-25 19:01:18 -07:00
|
|
|
#include "DriverStation.h"
|
2013-12-15 18:30:16 -05:00
|
|
|
#include "Utility.h"
|
2014-08-04 15:25:41 -04:00
|
|
|
|
2016-11-01 22:33:12 -07:00
|
|
|
namespace frc {
|
|
|
|
|
|
2013-12-15 18:30:16 -05:00
|
|
|
/**
|
|
|
|
|
* Pause the task for a specified time.
|
2014-08-04 15:25:41 -04:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* Pause the execution of the program for a specified period of time given in
|
2016-05-20 17:30:37 -07:00
|
|
|
* seconds. Motors will continue to run at their last assigned values, and
|
2017-11-16 00:33:51 -08:00
|
|
|
* sensors will continue to update. Only the task containing the wait will pause
|
|
|
|
|
* until the wait time is expired.
|
2014-08-04 15:25:41 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @param seconds Length of time to pause, in seconds.
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void Wait(double seconds) {
|
2016-05-26 20:19:23 -07:00
|
|
|
std::this_thread::sleep_for(std::chrono::duration<double>(seconds));
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2014-12-29 14:09:37 -05:00
|
|
|
/**
|
2013-12-15 18:30:16 -05:00
|
|
|
* Return the FPGA system clock time in seconds.
|
2017-11-16 00:33:51 -08:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* This is deprecated and just forwards to Timer::GetFPGATimestamp().
|
2017-11-16 00:33:51 -08:00
|
|
|
*
|
2014-12-29 14:09:37 -05:00
|
|
|
* @return Robot running time in seconds.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
double GetClock() { return Timer::GetFPGATimestamp(); }
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
2017-11-16 00:33:51 -08:00
|
|
|
* @brief Gives real-time clock system time with nanosecond resolution
|
2015-06-25 15:07:55 -04:00
|
|
|
* @return The time, just in case you want the robot to start autonomous at 8pm
|
2016-05-20 17:30:37 -07:00
|
|
|
* on Saturday.
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
double GetTime() {
|
2017-08-07 17:36:34 -07:00
|
|
|
using std::chrono::duration;
|
|
|
|
|
using std::chrono::duration_cast;
|
|
|
|
|
using std::chrono::system_clock;
|
|
|
|
|
|
2016-05-26 20:19:23 -07:00
|
|
|
return duration_cast<duration<double>>(system_clock::now().time_since_epoch())
|
|
|
|
|
.count();
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2016-11-01 22:33:12 -07:00
|
|
|
} // namespace frc
|
|
|
|
|
|
|
|
|
|
using namespace frc;
|
|
|
|
|
|
2016-05-20 17:30:37 -07:00
|
|
|
// for compatibility with msvc12--see C2864
|
2015-04-26 19:19:57 -04:00
|
|
|
const double Timer::kRolloverTime = (1ll << 32) / 1e6;
|
2013-12-15 18:30:16 -05:00
|
|
|
/**
|
|
|
|
|
* Create a new timer object.
|
2014-08-04 15:25:41 -04:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* Create a new timer object and reset the time to zero. The timer is initially
|
2017-11-16 00:33:51 -08:00
|
|
|
* not running and must be started.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2017-11-16 00:33:51 -08:00
|
|
|
Timer::Timer() { Reset(); }
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
2015-06-25 15:07:55 -04:00
|
|
|
* Get the current time from the timer. If the clock is running it is derived
|
2016-05-20 17:30:37 -07:00
|
|
|
* 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.
|
2014-08-04 15:25:41 -04:00
|
|
|
*
|
2014-12-29 14:09:37 -05:00
|
|
|
* @return Current time value for this timer in seconds
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
double Timer::Get() const {
|
|
|
|
|
double result;
|
|
|
|
|
double currentTime = GetFPGATimestamp();
|
|
|
|
|
|
2017-11-22 17:10:21 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_mutex);
|
2015-06-25 15:07:55 -04:00
|
|
|
if (m_running) {
|
2017-11-16 00:33:51 -08:00
|
|
|
// 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.
|
2015-06-25 15:07:55 -04:00
|
|
|
if (currentTime < m_startTime) {
|
|
|
|
|
currentTime += kRolloverTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = (currentTime - m_startTime) + m_accumulatedTime;
|
|
|
|
|
} else {
|
|
|
|
|
result = m_accumulatedTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reset the timer by setting the time to 0.
|
2014-08-04 15:25:41 -04:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* Make the timer startTime the current time so new requests will be relative to
|
2016-05-20 17:30:37 -07:00
|
|
|
* now.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void Timer::Reset() {
|
2017-11-22 17:10:21 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_mutex);
|
2015-06-25 15:07:55 -04:00
|
|
|
m_accumulatedTime = 0;
|
|
|
|
|
m_startTime = GetFPGATimestamp();
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Start the timer running.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* Just set the running flag to true indicating that all time requests should be
|
|
|
|
|
* relative to the system clock.
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void Timer::Start() {
|
2017-11-22 17:10:21 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_mutex);
|
2015-06-25 15:07:55 -04:00
|
|
|
if (!m_running) {
|
|
|
|
|
m_startTime = GetFPGATimestamp();
|
|
|
|
|
m_running = true;
|
|
|
|
|
}
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Stop the timer.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* 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.
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void Timer::Stop() {
|
|
|
|
|
double temp = Get();
|
|
|
|
|
|
2017-11-22 17:10:21 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_mutex);
|
2015-06-25 15:07:55 -04:00
|
|
|
if (m_running) {
|
|
|
|
|
m_accumulatedTime = temp;
|
|
|
|
|
m_running = false;
|
|
|
|
|
}
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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 (in seconds).
|
2017-11-16 00:33:51 -08:00
|
|
|
* @return True if the period has passed.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
bool Timer::HasPeriodPassed(double period) {
|
|
|
|
|
if (Get() > period) {
|
2017-11-22 17:10:21 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_mutex);
|
2015-06-25 15:07:55 -04:00
|
|
|
// 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;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2014-12-29 14:09:37 -05:00
|
|
|
/**
|
2013-12-15 18:30:16 -05:00
|
|
|
* Return the FPGA system clock time in seconds.
|
2014-08-04 15:25:41 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* Return the time from the FPGA hardware clock in seconds since the FPGA
|
2016-05-20 17:30:37 -07:00
|
|
|
* started. Rolls over after 71 minutes.
|
|
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @returns Robot running time in seconds.
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
double Timer::GetFPGATimestamp() {
|
|
|
|
|
// FPGA returns the timestamp in microseconds
|
|
|
|
|
// Call the helper GetFPGATime() in Utility.cpp
|
|
|
|
|
return GetFPGATime() * 1.0e-6;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
2016-10-25 19:01:18 -07:00
|
|
|
|
|
|
|
|
/**
|
2017-11-23 00:19:05 -08:00
|
|
|
* Return the approximate match time.
|
2017-11-16 00:33:51 -08:00
|
|
|
*
|
2017-11-23 00:19:05 -08:00
|
|
|
* 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).
|
2016-10-25 19:01:18 -07:00
|
|
|
*
|
2017-11-23 00:19:05 -08:00
|
|
|
* 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 behaviour seen on the
|
|
|
|
|
* field.
|
|
|
|
|
*
|
|
|
|
|
* @return Time remaining in current match period (auto or teleop)
|
2016-10-25 19:01:18 -07:00
|
|
|
*/
|
|
|
|
|
double Timer::GetMatchTime() {
|
|
|
|
|
return DriverStation::GetInstance().GetMatchTime();
|
|
|
|
|
}
|