mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
Pneumatics still have CAN modules. The refactored code is now eight plugins for sensors and actuators. There is some code reuse that should be refactored out, but that level of abstraction will wait until we figure out how these plugins are integrating with gazebo proper. Change-Id: I357e695ef05af6dda83a39ba60380686bd57d11a Closes: artf2610, artf2623
205 lines
5.1 KiB
C++
205 lines
5.1 KiB
C++
/*----------------------------------------------------------------------------*/
|
|
/* Copyright (c) FIRST 2008. 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 $(WIND_BASE)/WPILib. */
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
#include "Timer.h"
|
|
|
|
#include <time.h>
|
|
|
|
#include "HAL/cpp/Synchronized.hpp"
|
|
#include "Utility.h"
|
|
|
|
/**
|
|
* 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(double seconds)
|
|
{
|
|
if (seconds < 0.0) return;
|
|
|
|
double start = wpilib::internal::simTime;
|
|
|
|
while ((wpilib::internal::simTime - start) < seconds) {
|
|
takeMultiWait(wpilib::internal::time_wait, 0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Return the FPGA system clock time in seconds.
|
|
* This is deprecated and just forwards to Timer::GetFPGATimestamp().
|
|
* @returns Robot running time in seconds.
|
|
*/
|
|
double GetClock()
|
|
{
|
|
return Timer::GetFPGATimestamp();
|
|
}
|
|
|
|
/**
|
|
* @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 (except in simulation).
|
|
*/
|
|
double GetTime()
|
|
{
|
|
return Timer::GetFPGATimestamp(); // The epoch starts when Gazebo starts
|
|
}
|
|
|
|
/**
|
|
* 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::Timer()
|
|
: m_startTime (0.0)
|
|
, m_accumulatedTime (0.0)
|
|
, m_running (false)
|
|
, m_semaphore (0)
|
|
{
|
|
//Creates a semaphore to control access to critical regions.
|
|
//Initially 'open'
|
|
m_semaphore = initializeMutexNormal();
|
|
Reset();
|
|
}
|
|
|
|
Timer::~Timer()
|
|
{
|
|
deleteMutex(m_semaphore);
|
|
}
|
|
|
|
/**
|
|
* 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 unsigned Current time value for this timer in seconds
|
|
*/
|
|
double Timer::Get()
|
|
{
|
|
double result;
|
|
double currentTime = GetFPGATimestamp();
|
|
|
|
Synchronized sync(m_semaphore);
|
|
if(m_running)
|
|
{
|
|
// This math won't work if the timer rolled over (71 minutes after boot).
|
|
// TODO: Check for it and compensate.
|
|
result = (currentTime - m_startTime) + m_accumulatedTime;
|
|
}
|
|
else
|
|
{
|
|
result = m_accumulatedTime;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* 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 Timer::Reset()
|
|
{
|
|
Synchronized sync(m_semaphore);
|
|
m_accumulatedTime = 0;
|
|
m_startTime = GetFPGATimestamp();
|
|
}
|
|
|
|
/**
|
|
* Start the timer running.
|
|
* Just set the running flag to true indicating that all time requests should be
|
|
* relative to the system clock.
|
|
*/
|
|
void Timer::Start()
|
|
{
|
|
Synchronized sync(m_semaphore);
|
|
if (!m_running)
|
|
{
|
|
m_startTime = GetFPGATimestamp();
|
|
m_running = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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 Timer::Stop()
|
|
{
|
|
double temp = Get();
|
|
|
|
Synchronized sync(m_semaphore);
|
|
if (m_running)
|
|
{
|
|
m_accumulatedTime = temp;
|
|
m_running = false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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).
|
|
* @return If the period has passed.
|
|
*/
|
|
bool Timer::HasPeriodPassed(double period)
|
|
{
|
|
if (Get() > period)
|
|
{
|
|
Synchronized sync(m_semaphore);
|
|
// Advance the start time by the period.
|
|
// Don't set it to the current time... we want to avoid drift.
|
|
m_startTime += period;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
double Timer::GetFPGATimestamp()
|
|
{
|
|
// FPGA returns the timestamp in microseconds
|
|
// Call the helper GetFPGATime() in Utility.cpp
|
|
return wpilib::internal::simTime;
|
|
}
|
|
|
|
// Internal function that reads the PPC timestamp counter.
|
|
extern "C"
|
|
{
|
|
uint32_t niTimestamp32(void);
|
|
uint64_t niTimestamp64(void);
|
|
}
|
|
|
|
// Internal stuff
|
|
#include "simulation/SimFloatInput.h"
|
|
#include "simulation/MainNode.h"
|
|
namespace wpilib { namespace internal {
|
|
double simTime = 0;
|
|
MULTIWAIT_ID time_wait = initializeMultiWait();
|
|
|
|
void time_callback(const msgs::ConstFloat64Ptr &msg) {
|
|
simTime = msg->data();
|
|
giveMultiWait(time_wait);
|
|
}
|
|
|
|
transport::SubscriberPtr time_pub = MainNode::Subscribe("~/time", &time_callback);
|
|
}}
|