diff --git a/romiVendordep/src/main/java/edu/wpi/first/wpilibj/romi/OnBoardIO.java b/romiVendordep/src/main/java/edu/wpi/first/wpilibj/romi/OnBoardIO.java index 40bbead462..06591556a8 100644 --- a/romiVendordep/src/main/java/edu/wpi/first/wpilibj/romi/OnBoardIO.java +++ b/romiVendordep/src/main/java/edu/wpi/first/wpilibj/romi/OnBoardIO.java @@ -82,7 +82,7 @@ public class OnBoardIO { return m_buttonB.get(); } - double currentTime = Timer.getFPGATimestamp(); + double currentTime = Timer.getTimestamp(); if (currentTime > m_nextMessageTime) { DriverStation.reportError("Button B was not configured", true); m_nextMessageTime = currentTime + MESSAGE_INTERVAL; @@ -100,7 +100,7 @@ public class OnBoardIO { return m_buttonC.get(); } - double currentTime = Timer.getFPGATimestamp(); + double currentTime = Timer.getTimestamp(); if (currentTime > m_nextMessageTime) { DriverStation.reportError("Button C was not configured", true); m_nextMessageTime = currentTime + MESSAGE_INTERVAL; @@ -117,7 +117,7 @@ public class OnBoardIO { if (m_greenLed != null) { m_greenLed.set(value); } else { - double currentTime = Timer.getFPGATimestamp(); + double currentTime = Timer.getTimestamp(); if (currentTime > m_nextMessageTime) { DriverStation.reportError("Green LED was not configured", true); m_nextMessageTime = currentTime + MESSAGE_INTERVAL; @@ -134,7 +134,7 @@ public class OnBoardIO { if (m_redLed != null) { m_redLed.set(value); } else { - double currentTime = Timer.getFPGATimestamp(); + double currentTime = Timer.getTimestamp(); if (currentTime > m_nextMessageTime) { DriverStation.reportError("Red LED was not configured", true); m_nextMessageTime = currentTime + MESSAGE_INTERVAL; diff --git a/romiVendordep/src/main/native/cpp/romi/OnBoardIO.cpp b/romiVendordep/src/main/native/cpp/romi/OnBoardIO.cpp index bba2901f92..ce1c81bb9b 100644 --- a/romiVendordep/src/main/native/cpp/romi/OnBoardIO.cpp +++ b/romiVendordep/src/main/native/cpp/romi/OnBoardIO.cpp @@ -34,7 +34,7 @@ bool OnBoardIO::GetButtonBPressed() { return m_buttonB->Get(); } - auto currentTime = frc::Timer::GetFPGATimestamp(); + auto currentTime = frc::Timer::GetTimestamp(); if (currentTime > m_nextMessageTime) { FRC_ReportError(frc::err::Error, "{}", "Button B was not configured"); m_nextMessageTime = currentTime + kMessageInterval; @@ -47,7 +47,7 @@ bool OnBoardIO::GetButtonCPressed() { return m_buttonC->Get(); } - auto currentTime = frc::Timer::GetFPGATimestamp(); + auto currentTime = frc::Timer::GetTimestamp(); if (currentTime > m_nextMessageTime) { FRC_ReportError(frc::err::Error, "{}", "Button C was not configured"); m_nextMessageTime = currentTime + kMessageInterval; @@ -59,7 +59,7 @@ void OnBoardIO::SetGreenLed(bool value) { if (m_greenLed) { m_greenLed->Set(value); } else { - auto currentTime = frc::Timer::GetFPGATimestamp(); + auto currentTime = frc::Timer::GetTimestamp(); if (currentTime > m_nextMessageTime) { FRC_ReportError(frc::err::Error, "{}", "Green LED was not configured"); m_nextMessageTime = currentTime + kMessageInterval; @@ -71,7 +71,7 @@ void OnBoardIO::SetRedLed(bool value) { if (m_redLed) { m_redLed->Set(value); } else { - auto currentTime = frc::Timer::GetFPGATimestamp(); + auto currentTime = frc::Timer::GetTimestamp(); if (currentTime > m_nextMessageTime) { FRC_ReportError(frc::err::Error, "{}", "Red LED was not configured"); m_nextMessageTime = currentTime + kMessageInterval; diff --git a/wpilibc/src/main/native/cpp/Alert.cpp b/wpilibc/src/main/native/cpp/Alert.cpp index 2df38bcd9f..17fa52f4ea 100644 --- a/wpilibc/src/main/native/cpp/Alert.cpp +++ b/wpilibc/src/main/native/cpp/Alert.cpp @@ -149,7 +149,7 @@ void Alert::Set(bool active) { } if (active) { - m_activeStartTime = frc::RobotController::GetFPGATime(); + m_activeStartTime = frc::RobotController::GetTime(); m_activeAlerts->emplace(m_activeStartTime, m_text); } else { m_activeAlerts->erase({m_activeStartTime, m_text}); diff --git a/wpilibc/src/main/native/cpp/DriverStation.cpp b/wpilibc/src/main/native/cpp/DriverStation.cpp index 862b2464eb..6318c8899e 100644 --- a/wpilibc/src/main/native/cpp/DriverStation.cpp +++ b/wpilibc/src/main/native/cpp/DriverStation.cpp @@ -678,7 +678,7 @@ void DriverStation::StartDataLog(wpi::log::DataLog& log, bool logJoysticks) { void ReportJoystickUnpluggedErrorV(fmt::string_view format, fmt::format_args args) { auto& inst = GetInstance(); - auto currentTime = Timer::GetFPGATimestamp(); + auto currentTime = Timer::GetTimestamp(); if (currentTime > inst.nextMessageTime) { ReportErrorV(err::Error, "", 0, "", format, args); inst.nextMessageTime = currentTime + kJoystickUnpluggedMessageInterval; @@ -689,7 +689,7 @@ void ReportJoystickUnpluggedWarningV(fmt::string_view format, fmt::format_args args) { auto& inst = GetInstance(); if (DriverStation::IsFMSAttached() || !inst.silenceJoystickWarning) { - auto currentTime = Timer::GetFPGATimestamp(); + auto currentTime = Timer::GetTimestamp(); if (currentTime > inst.nextMessageTime) { ReportErrorV(warn::Warning, "", 0, "", format, args); inst.nextMessageTime = currentTime + kJoystickUnpluggedMessageInterval; diff --git a/wpilibc/src/main/native/cpp/RobotController.cpp b/wpilibc/src/main/native/cpp/RobotController.cpp index 31258f1234..72483e14df 100644 --- a/wpilibc/src/main/native/cpp/RobotController.cpp +++ b/wpilibc/src/main/native/cpp/RobotController.cpp @@ -4,6 +4,7 @@ #include "frc/RobotController.h" +#include #include #include @@ -15,6 +16,10 @@ using namespace frc; +std::function RobotController::m_timeSource = [] { + return RobotController::GetFPGATime(); +}; + int RobotController::GetFPGAVersion() { int32_t status = 0; int version = HAL_GetFPGAVersion(&status); @@ -49,6 +54,14 @@ int32_t RobotController::GetTeamNumber() { return HAL_GetTeamNumber(); } +void RobotController::SetTimeSource(std::function supplier) { + m_timeSource = supplier; +} + +uint64_t RobotController::GetTime() { + return m_timeSource(); +} + uint64_t RobotController::GetFPGATime() { int32_t status = 0; uint64_t time = HAL_GetFPGATime(&status); diff --git a/wpilibc/src/main/native/cpp/TimedRobot.cpp b/wpilibc/src/main/native/cpp/TimedRobot.cpp index 7ff22a9f34..d2c39d12c5 100644 --- a/wpilibc/src/main/native/cpp/TimedRobot.cpp +++ b/wpilibc/src/main/native/cpp/TimedRobot.cpp @@ -46,6 +46,8 @@ void TimedRobot::StartCompetition() { break; } + m_loopStartTimeUs = RobotController::GetFPGATime(); + callback.func(); // Increment the expiration time by the number of full periods it's behind @@ -97,6 +99,10 @@ TimedRobot::~TimedRobot() { } } +uint64_t TimedRobot::GetLoopStartTime() { + return m_loopStartTimeUs; +} + void TimedRobot::AddPeriodic(std::function callback, units::second_t period, units::second_t offset) { m_callbacks.emplace( diff --git a/wpilibc/src/main/native/cpp/Timer.cpp b/wpilibc/src/main/native/cpp/Timer.cpp index 02dd9bad6a..912db0a603 100644 --- a/wpilibc/src/main/native/cpp/Timer.cpp +++ b/wpilibc/src/main/native/cpp/Timer.cpp @@ -36,7 +36,7 @@ Timer::Timer() { units::second_t Timer::Get() const { if (m_running) { - return (GetFPGATimestamp() - m_startTime) + m_accumulatedTime; + return (GetTimestamp() - m_startTime) + m_accumulatedTime; } else { return m_accumulatedTime; } @@ -44,12 +44,12 @@ units::second_t Timer::Get() const { void Timer::Reset() { m_accumulatedTime = 0_s; - m_startTime = GetFPGATimestamp(); + m_startTime = GetTimestamp(); } void Timer::Start() { if (!m_running) { - m_startTime = GetFPGATimestamp(); + m_startTime = GetTimestamp(); m_running = true; } } @@ -88,6 +88,10 @@ bool Timer::IsRunning() const { return m_running; } +units::second_t Timer::GetTimestamp() { + return units::second_t{frc::RobotController::GetTime() * 1.0e-6}; +} + units::second_t Timer::GetFPGATimestamp() { // FPGA returns the timestamp in microseconds return units::second_t{frc::RobotController::GetFPGATime() * 1.0e-6}; diff --git a/wpilibc/src/main/native/include/frc/RobotController.h b/wpilibc/src/main/native/include/frc/RobotController.h index cf17466c13..272ae4a490 100644 --- a/wpilibc/src/main/native/include/frc/RobotController.h +++ b/wpilibc/src/main/native/include/frc/RobotController.h @@ -6,6 +6,7 @@ #include +#include #include #include @@ -78,6 +79,24 @@ class RobotController { */ static int32_t GetTeamNumber(); + /** + * Sets a new source to provide the clock time in microseconds. Changing this + * affects the return value of {@code GetTime}. + * + * @param supplier Function to return the time in microseconds. + */ + static void SetTimeSource(std::function supplier); + + /** + * Read the microsecond timestamp. By default, the time is based on the FPGA + * hardware clock in microseconds since the FPGA started. However, the return + * value of this method may be modified to use any time base, including + * non-monotonic and non-continuous time bases. + * + * @return The current time in microseconds. + */ + static uint64_t GetTime(); + /** * Read the microsecond-resolution timer on the FPGA. * @@ -320,6 +339,9 @@ class RobotController { * @return The status of the CAN bus */ static CANStatus GetCANStatus(); + + private: + static std::function m_timeSource; }; } // namespace frc diff --git a/wpilibc/src/main/native/include/frc/TimedRobot.h b/wpilibc/src/main/native/include/frc/TimedRobot.h index 68d5ecf14c..15afe34acb 100644 --- a/wpilibc/src/main/native/include/frc/TimedRobot.h +++ b/wpilibc/src/main/native/include/frc/TimedRobot.h @@ -56,6 +56,17 @@ class TimedRobot : public IterativeRobotBase { ~TimedRobot() override; + /** + * Return the system clock time in micrseconds for the start of the current + * periodic loop. This is in the same time base as Timer.GetFPGATimestamp(), + * but is stable through a loop. It is updated at the beginning of every + * periodic callback (including the normal periodic loop). + * + * @return Robot running time in microseconds, as of the start of the current + * periodic function. + */ + uint64_t GetLoopStartTime(); + /** * Add a callback to run at a specific period with a starting time offset. * @@ -103,6 +114,7 @@ class TimedRobot : public IterativeRobotBase { hal::Handle m_notifier; std::chrono::microseconds m_startTime; + uint64_t m_loopStartTimeUs = 0; wpi::priority_queue, std::greater> m_callbacks; diff --git a/wpilibc/src/main/native/include/frc/Timer.h b/wpilibc/src/main/native/include/frc/Timer.h index 37fe5e0c64..b3bbfd3539 100644 --- a/wpilibc/src/main/native/include/frc/Timer.h +++ b/wpilibc/src/main/native/include/frc/Timer.h @@ -118,6 +118,16 @@ class Timer { */ bool IsRunning() const; + /** + * Return the clock time in seconds. By default, the time is based on the FPGA + * hardware clock in seconds since the FPGA started. However, the return value + * of this method may be modified to use any time base, including + * non-monotonic time bases. + * + * @returns Robot running time in seconds. + */ + static units::second_t GetTimestamp(); + /** * Return the FPGA system clock time in seconds. * diff --git a/wpilibcExamples/src/main/cpp/examples/DifferentialDrivePoseEstimator/cpp/Drivetrain.cpp b/wpilibcExamples/src/main/cpp/examples/DifferentialDrivePoseEstimator/cpp/Drivetrain.cpp index 3683e9cf42..178267f1a8 100644 --- a/wpilibcExamples/src/main/cpp/examples/DifferentialDrivePoseEstimator/cpp/Drivetrain.cpp +++ b/wpilibcExamples/src/main/cpp/examples/DifferentialDrivePoseEstimator/cpp/Drivetrain.cpp @@ -106,7 +106,7 @@ void Drivetrain::UpdateOdometry() { // latency delay -- on a real robot, this must be calculated based either on // known latency or timestamps. m_poseEstimator.AddVisionMeasurement(visionMeasurement2d, - frc::Timer::GetFPGATimestamp()); + frc::Timer::GetTimestamp()); } void Drivetrain::SimulationPeriodic() { diff --git a/wpilibcExamples/src/main/cpp/examples/MecanumDrivePoseEstimator/cpp/Drivetrain.cpp b/wpilibcExamples/src/main/cpp/examples/MecanumDrivePoseEstimator/cpp/Drivetrain.cpp index 3e5326c86c..7ef5e4629a 100644 --- a/wpilibcExamples/src/main/cpp/examples/MecanumDrivePoseEstimator/cpp/Drivetrain.cpp +++ b/wpilibcExamples/src/main/cpp/examples/MecanumDrivePoseEstimator/cpp/Drivetrain.cpp @@ -67,5 +67,5 @@ void Drivetrain::UpdateOdometry() { m_poseEstimator.AddVisionMeasurement( ExampleGlobalMeasurementSensor::GetEstimatedGlobalPose( m_poseEstimator.GetEstimatedPosition()), - frc::Timer::GetFPGATimestamp() - 0.3_s); + frc::Timer::GetTimestamp() - 0.3_s); } diff --git a/wpilibcExamples/src/main/cpp/examples/SwerveDrivePoseEstimator/cpp/Drivetrain.cpp b/wpilibcExamples/src/main/cpp/examples/SwerveDrivePoseEstimator/cpp/Drivetrain.cpp index 188e944504..e834d3d271 100644 --- a/wpilibcExamples/src/main/cpp/examples/SwerveDrivePoseEstimator/cpp/Drivetrain.cpp +++ b/wpilibcExamples/src/main/cpp/examples/SwerveDrivePoseEstimator/cpp/Drivetrain.cpp @@ -41,5 +41,5 @@ void Drivetrain::UpdateOdometry() { m_poseEstimator.AddVisionMeasurement( ExampleGlobalMeasurementSensor::GetEstimatedGlobalPose( m_poseEstimator.GetEstimatedPosition()), - frc::Timer::GetFPGATimestamp() - 0.3_s); + frc::Timer::GetTimestamp() - 0.3_s); } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Alert.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Alert.java index faeda9aaf7..828a3e3a21 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Alert.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Alert.java @@ -113,7 +113,7 @@ public class Alert implements AutoCloseable { } if (active) { - m_activeStartTime = RobotController.getFPGATime(); + m_activeStartTime = RobotController.getTime(); m_activeAlerts.add(new PublishedAlert(m_activeStartTime, m_text)); } else { m_activeAlerts.remove(new PublishedAlert(m_activeStartTime, m_text)); diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DriverStation.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DriverStation.java index 1e51b5b4c9..36721e355a 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DriverStation.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DriverStation.java @@ -1328,7 +1328,7 @@ public final class DriverStation { * the DS. */ private static void reportJoystickUnpluggedError(String message) { - double currentTime = Timer.getFPGATimestamp(); + double currentTime = Timer.getTimestamp(); if (currentTime > m_nextMessageTime) { reportError(message, false); m_nextMessageTime = currentTime + JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL; @@ -1341,7 +1341,7 @@ public final class DriverStation { */ private static void reportJoystickUnpluggedWarning(String message) { if (isFMSAttached() || !m_silenceJoystickWarning) { - double currentTime = Timer.getFPGATimestamp(); + double currentTime = Timer.getTimestamp(); if (currentTime > m_nextMessageTime) { reportWarning(message, false); m_nextMessageTime = currentTime + JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL; diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/LEDPattern.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/LEDPattern.java index 5e2a65a0ea..88bb1a755b 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/LEDPattern.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/LEDPattern.java @@ -191,7 +191,7 @@ public interface LEDPattern { return (reader, writer) -> { int bufLen = reader.getLength(); - long now = WPIUtilJNI.now(); + long now = RobotController.getTime(); // index should move by (buf.length) / (period) double t = (now % (long) periodMicros) / periodMicros; @@ -242,7 +242,7 @@ public interface LEDPattern { return (reader, writer) -> { int bufLen = reader.getLength(); - long now = WPIUtilJNI.now(); + long now = RobotController.getTime(); // every step in time that's a multiple of microsPerLED will increment the offset by 1 var offset = now / microsPerLED; @@ -271,7 +271,7 @@ public interface LEDPattern { final long onTimeMicros = (long) onTime.in(Microseconds); return (reader, writer) -> { - if (WPIUtilJNI.now() % totalTimeMicros < onTimeMicros) { + if (RobotController.getTime() % totalTimeMicros < onTimeMicros) { applyTo(reader, writer); } else { kOff.applyTo(reader, writer); @@ -323,7 +323,7 @@ public interface LEDPattern { reader, (i, r, g, b) -> { // How far we are in the cycle, in the range [0, 1) - double t = (WPIUtilJNI.now() % periodMicros) / (double) periodMicros; + double t = (RobotController.getTime() % periodMicros) / (double) periodMicros; double phase = t * 2 * Math.PI; // Apply the cosine function and shift its output from [-1, 1] to [0, 1] diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotBase.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotBase.java index 4617a1ff99..eea1e2d47f 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotBase.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotBase.java @@ -118,7 +118,7 @@ public abstract class RobotBase implements AutoCloseable { @Override public double getTimestamp() { - return WPIUtilJNI.now() * 1.0e-6; + return Timer.getTimestamp(); } }); } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotController.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotController.java index 5e9d88d066..356854f356 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotController.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotController.java @@ -19,9 +19,12 @@ import edu.wpi.first.units.measure.Current; import edu.wpi.first.units.measure.Temperature; import edu.wpi.first.units.measure.Time; import edu.wpi.first.units.measure.Voltage; +import java.util.function.LongSupplier; /** Contains functions for roboRIO functionality. */ public final class RobotController { + private static LongSupplier m_timeSource = RobotController::getFPGATime; + private RobotController() { throw new UnsupportedOperationException("This is a utility class!"); } @@ -76,6 +79,38 @@ public final class RobotController { return HALUtil.getTeamNumber(); } + /** + * Sets a new source to provide the clock time in microseconds. Changing this affects the return + * value of {@code getTime} in Java. + * + * @param supplier Function to return the time in microseconds. + */ + public static void setTimeSource(LongSupplier supplier) { + m_timeSource = supplier; + } + + /** + * Read the microsecond timestamp. By default, the time is based on the FPGA hardware clock in + * microseconds since the FPGA started. However, the return value of this method may be modified + * to use any time base, including non-monotonic and non-continuous time bases. + * + * @return The current time in microseconds. + */ + public static long getTime() { + return m_timeSource.getAsLong(); + } + + /** + * Read the microsecond timestamp. By default, the time is based on the FPGA hardware clock in + * microseconds since the FPGA started. However, the return value of this method may be modified + * to use any time base, including non-monotonic and non-continuous time bases. + * + * @return The current time in a measure. + */ + public static Time getMeasureTime() { + return Microseconds.of(m_timeSource.getAsLong()); + } + /** * Read the microsecond timer from the FPGA. * diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/TimedRobot.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/TimedRobot.java index 7b59f528a6..78a8046f3d 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/TimedRobot.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/TimedRobot.java @@ -73,6 +73,7 @@ public class TimedRobot extends IterativeRobotBase { private final int m_notifier = NotifierJNI.initializeNotifier(); private long m_startTimeUs; + private long m_loopStartTimeUs; private final PriorityQueue m_callbacks = new PriorityQueue<>(); @@ -128,6 +129,8 @@ public class TimedRobot extends IterativeRobotBase { break; } + m_loopStartTimeUs = RobotController.getFPGATime(); + callback.func.run(); // Increment the expiration time by the number of full periods it's behind @@ -159,6 +162,17 @@ public class TimedRobot extends IterativeRobotBase { NotifierJNI.stopNotifier(m_notifier); } + /** + * Return the system clock time in micrseconds for the start of the current periodic loop. This is + * in the same time base as Timer.getFPGATimestamp(), but is stable through a loop. It is updated + * at the beginning of every periodic callback (including the normal periodic loop). + * + * @return Robot running time in microseconds, as of the start of the current periodic function. + */ + public long getLoopStartTime() { + return m_loopStartTimeUs; + } + /** * Add a callback to run at a specific period. * diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Timer.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Timer.java index 3e0aaf522b..fb92dc52a8 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Timer.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Timer.java @@ -11,6 +11,17 @@ package edu.wpi.first.wpilibj; * get() won't return a negative duration. */ public class Timer { + /** + * Return the clock time in seconds. By default, the time is based on the FPGA hardware clock in + * seconds since the FPGA started. However, the return value of this method may be modified to use + * any time base, including non-monotonic time bases. + * + * @return Robot running time in seconds. + */ + public static double getTimestamp() { + return RobotController.getTime() / 1000000.0; + } + /** * Return the system clock time in seconds. Return the time from the FPGA hardware clock in * seconds since the FPGA started. @@ -60,7 +71,7 @@ public class Timer { } private double getMsClock() { - return RobotController.getFPGATime() / 1000.0; + return RobotController.getTime() / 1000.0; } /** diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/smartdashboard/SendableBuilderImpl.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/smartdashboard/SendableBuilderImpl.java index 99a28624bd..09a16860e5 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/smartdashboard/SendableBuilderImpl.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/smartdashboard/SendableBuilderImpl.java @@ -43,10 +43,10 @@ import edu.wpi.first.networktables.StringSubscriber; import edu.wpi.first.networktables.StringTopic; import edu.wpi.first.networktables.Subscriber; import edu.wpi.first.networktables.Topic; -import edu.wpi.first.util.WPIUtilJNI; import edu.wpi.first.util.function.BooleanConsumer; import edu.wpi.first.util.function.FloatConsumer; import edu.wpi.first.util.function.FloatSupplier; +import edu.wpi.first.wpilibj.RobotController; import java.util.ArrayList; import java.util.List; import java.util.function.BooleanSupplier; @@ -180,7 +180,7 @@ public class SendableBuilderImpl implements NTSendableBuilder { /** Update the network table values by calling the getters for all properties. */ @Override public void update() { - long time = WPIUtilJNI.now(); + long time = RobotController.getTime(); for (Property property : m_properties) { property.update(m_controllable, time); } diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/LEDPatternTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/LEDPatternTest.java index adb96cde57..453fa5710e 100644 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/LEDPatternTest.java +++ b/wpilibj/src/test/java/edu/wpi/first/wpilibj/LEDPatternTest.java @@ -25,7 +25,6 @@ import static edu.wpi.first.wpilibj.util.Color.kYellow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; -import edu.wpi.first.util.WPIUtilJNI; import edu.wpi.first.wpilibj.util.Color; import edu.wpi.first.wpilibj.util.Color8Bit; import java.util.Map; @@ -36,6 +35,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class LEDPatternTest { + long m_mockTime; + // Applies a pattern of White, Yellow, Purple to LED triplets LEDPattern m_whiteYellowPurple = (reader, writer) -> { @@ -59,14 +60,13 @@ class LEDPatternTest { @BeforeEach void setUp() { - WPIUtilJNI.enableMockTime(); - WPIUtilJNI.setMockTime(0L); + m_mockTime = 0; + RobotController.setTimeSource(() -> m_mockTime); } @AfterEach void tearDown() { - WPIUtilJNI.setMockTime(0L); - WPIUtilJNI.disableMockTime(); + RobotController.setTimeSource(RobotController::getFPGATime); } @Test @@ -220,7 +220,7 @@ class LEDPatternTest { var scroll = base.scrollAtRelativeSpeed(Value.per(Microsecond).of(1 / 256.0)); for (int time = 0; time < 500; time++) { - WPIUtilJNI.setMockTime(time); + m_mockTime = time; scroll.applyTo(buffer); for (int led = 0; led < buffer.getLength(); led++) { @@ -254,7 +254,7 @@ class LEDPatternTest { var scroll = base.scrollAtRelativeSpeed(Value.per(Microsecond).of(-1 / 256.0)); for (int time = 0; time < 500; time++) { - WPIUtilJNI.setMockTime(time); + m_mockTime = time; scroll.applyTo(buffer); for (int led = 0; led < buffer.getLength(); led++) { @@ -290,7 +290,7 @@ class LEDPatternTest { var scroll = base.scrollAtAbsoluteSpeed(MetersPerSecond.of(16), Centimeters.of(2)); for (int time = 0; time < 500; time++) { - WPIUtilJNI.setMockTime(time * 1_250); // 1.25ms per LED + m_mockTime = time * 1_250; // 1.25ms per LED scroll.applyTo(buffer); for (int led = 0; led < buffer.getLength(); led++) { @@ -326,7 +326,7 @@ class LEDPatternTest { var scroll = base.scrollAtAbsoluteSpeed(MetersPerSecond.of(-16), Centimeters.of(2)); for (int time = 0; time < 500; time++) { - WPIUtilJNI.setMockTime(time * 1_250); // 1.25ms per LED + m_mockTime = time * 1_250; // 1.25ms per LED scroll.applyTo(buffer); for (int led = 0; led < buffer.getLength(); led++) { @@ -539,7 +539,7 @@ class LEDPatternTest { var buffer = new AddressableLEDBuffer(1); for (int t = 0; t < 8; t++) { - WPIUtilJNI.setMockTime(t * 1_000_000L); // time travel 1 second + m_mockTime = t * 1_000_000L; // time travel 1 second pattern.applyTo(buffer); Color color = buffer.getLED(0); @@ -571,7 +571,7 @@ class LEDPatternTest { var buffer = new AddressableLEDBuffer(1); for (int t = 0; t < 8; t++) { - WPIUtilJNI.setMockTime(t * 1_000_000L); // time travel 1 second + m_mockTime = t * 1_000_000L; // time travel 1 second pattern.applyTo(buffer); Color color = buffer.getLED(0); @@ -623,31 +623,31 @@ class LEDPatternTest { var buffer = new AddressableLEDBuffer(1); { - WPIUtilJNI.setMockTime(0); // start + m_mockTime = 0; // start pattern.applyTo(buffer); assertColorEquals(kWhite, buffer.getLED(0)); } { - WPIUtilJNI.setMockTime(1); // midway (down) + m_mockTime = 1; // midway (down) pattern.applyTo(buffer); assertColorEquals(midGray, buffer.getLED(0)); } { - WPIUtilJNI.setMockTime(2); // bottom + m_mockTime = 2; // bottom pattern.applyTo(buffer); assertColorEquals(kBlack, buffer.getLED(0)); } { - WPIUtilJNI.setMockTime(3); // midway (up) + m_mockTime = 3; // midway (up) pattern.applyTo(buffer); assertColorEquals(midGray, buffer.getLED(0)); } { - WPIUtilJNI.setMockTime(4); // back to start + m_mockTime = 4; // back to start pattern.applyTo(buffer); assertColorEquals(kWhite, buffer.getLED(0)); } diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/differentialdriveposeestimator/Drivetrain.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/differentialdriveposeestimator/Drivetrain.java index 40fd72700a..7df9f3b449 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/differentialdriveposeestimator/Drivetrain.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/differentialdriveposeestimator/Drivetrain.java @@ -245,7 +245,7 @@ public class Drivetrain { // Apply vision measurements. For simulation purposes only, we don't input a latency delay -- on // a real robot, this must be calculated based either on known latency or timestamps. - m_poseEstimator.addVisionMeasurement(visionMeasurement2d, Timer.getFPGATimestamp()); + m_poseEstimator.addVisionMeasurement(visionMeasurement2d, Timer.getTimestamp()); } /** This function is called periodically during simulation. */ diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/mecanumdriveposeestimator/Drivetrain.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/mecanumdriveposeestimator/Drivetrain.java index 1143278b3a..ada2b6d83e 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/mecanumdriveposeestimator/Drivetrain.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/mecanumdriveposeestimator/Drivetrain.java @@ -167,6 +167,6 @@ public class Drivetrain { m_poseEstimator.addVisionMeasurement( ExampleGlobalMeasurementSensor.getEstimatedGlobalPose( m_poseEstimator.getEstimatedPosition()), - Timer.getFPGATimestamp() - 0.3); + Timer.getTimestamp() - 0.3); } } diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/swervedriveposeestimator/Drivetrain.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/swervedriveposeestimator/Drivetrain.java index bccc93de7b..a28dfcacc2 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/swervedriveposeestimator/Drivetrain.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/swervedriveposeestimator/Drivetrain.java @@ -99,6 +99,6 @@ public class Drivetrain { m_poseEstimator.addVisionMeasurement( ExampleGlobalMeasurementSensor.getEstimatedGlobalPose( m_poseEstimator.getEstimatedPosition()), - Timer.getFPGATimestamp() - 0.3); + Timer.getTimestamp() - 0.3); } } diff --git a/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/TimerTest.java b/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/TimerTest.java index 8d0fc95ebc..8e836e8f36 100644 --- a/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/TimerTest.java +++ b/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/TimerTest.java @@ -23,11 +23,11 @@ public class TimerTest extends AbstractComsSetup { @Test public void delayTest() { // Given - long startTime = RobotController.getFPGATime(); + long startTime = RobotController.getTime(); // When Timer.delay(TIMER_RUNTIME / 1000000); - long endTime = RobotController.getFPGATime(); + long endTime = RobotController.getTime(); long difference = endTime - startTime; // Then diff --git a/wpimath/src/main/native/include/frc/estimator/PoseEstimator.h b/wpimath/src/main/native/include/frc/estimator/PoseEstimator.h index c5981e7bfb..9c3bc4d6de 100644 --- a/wpimath/src/main/native/include/frc/estimator/PoseEstimator.h +++ b/wpimath/src/main/native/include/frc/estimator/PoseEstimator.h @@ -228,8 +228,8 @@ class WPILIB_DLLEXPORT PoseEstimator { * that if you don't use your own time source by calling UpdateWithTime(), * then you must use a timestamp with an epoch since FPGA startup (i.e., * the epoch of this timestamp is the same epoch as - * frc::Timer::GetFPGATimestamp(). This means that you should use - * frc::Timer::GetFPGATimestamp() as your time source in this case. + * frc::Timer::GetTimestamp(). This means that you should use + * frc::Timer::GetTimestamp() as your time source in this case. */ void AddVisionMeasurement(const Pose2d& visionRobotPose, units::second_t timestamp) { @@ -311,8 +311,8 @@ class WPILIB_DLLEXPORT PoseEstimator { * that if you don't use your own time source by calling UpdateWithTime(), * then you must use a timestamp with an epoch since FPGA startup (i.e., * the epoch of this timestamp is the same epoch as - * frc::Timer::GetFPGATimestamp(). This means that you should use - * frc::Timer::GetFPGATimestamp() as your time source in this case. + * frc::Timer::GetTimestamp(). This means that you should use + * frc::Timer::GetTimestamp() as your time source in this case. * @param visionMeasurementStdDevs Standard deviations of the vision pose * measurement (x position in meters, y position in meters, and heading in * radians). Increase these numbers to trust the vision pose measurement