mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-23 01:21:42 +00:00
Add ability to end startCompetition() main loop (#2032)
This is useful for both cleanly exiting from simulation and for unit testing at a framework level. This change required removing move constructor/assignment from IterativeRobot.
This commit is contained in:
@@ -394,6 +394,11 @@ class DriverStation : public ErrorBase {
|
||||
*/
|
||||
void InTest(bool entering) { m_userInTest = entering; }
|
||||
|
||||
/**
|
||||
* Forces WaitForData() to return immediately.
|
||||
*/
|
||||
void WakeupWaitForData();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Copy data from the DS task for the user.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2008-2018 FIRST. All Rights Reserved. */
|
||||
/* 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. */
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "frc/IterativeRobotBase.h"
|
||||
|
||||
namespace frc {
|
||||
@@ -28,9 +30,6 @@ class IterativeRobot : public IterativeRobotBase {
|
||||
IterativeRobot();
|
||||
virtual ~IterativeRobot() = default;
|
||||
|
||||
IterativeRobot(IterativeRobot&&) = default;
|
||||
IterativeRobot& operator=(IterativeRobot&&) = default;
|
||||
|
||||
/**
|
||||
* Provide an alternate "main loop" via StartCompetition().
|
||||
*
|
||||
@@ -38,6 +37,14 @@ class IterativeRobot : public IterativeRobotBase {
|
||||
* with the DS packets.
|
||||
*/
|
||||
void StartCompetition() override;
|
||||
|
||||
/**
|
||||
* Ends the main loop in StartCompetition().
|
||||
*/
|
||||
void EndCompetition() override;
|
||||
|
||||
private:
|
||||
std::atomic<bool> m_exit{false};
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
|
||||
@@ -7,9 +7,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include <hal/Main.h>
|
||||
#include <wpi/condition_variable.h>
|
||||
#include <wpi/mutex.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
#include "frc/Base.h"
|
||||
@@ -23,9 +26,13 @@ int RunHALInitialization();
|
||||
namespace impl {
|
||||
|
||||
template <class Robot>
|
||||
void RunRobot() {
|
||||
static Robot robot;
|
||||
robot.StartCompetition();
|
||||
void RunRobot(wpi::mutex& m, Robot** robot) {
|
||||
static Robot theRobot;
|
||||
{
|
||||
std::scoped_lock lock{m};
|
||||
*robot = &theRobot;
|
||||
}
|
||||
theRobot.StartCompetition();
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
@@ -36,20 +43,50 @@ int StartRobot() {
|
||||
if (halInit != 0) {
|
||||
return halInit;
|
||||
}
|
||||
|
||||
static wpi::mutex m;
|
||||
static wpi::condition_variable cv;
|
||||
static Robot* robot = nullptr;
|
||||
static bool exited = false;
|
||||
|
||||
if (HAL_HasMain()) {
|
||||
std::thread([] {
|
||||
std::thread thr([] {
|
||||
try {
|
||||
impl::RunRobot<Robot>();
|
||||
impl::RunRobot<Robot>(m, &robot);
|
||||
} catch (...) {
|
||||
HAL_ExitMain();
|
||||
{
|
||||
std::scoped_lock lock{m};
|
||||
robot = nullptr;
|
||||
exited = true;
|
||||
}
|
||||
cv.notify_all();
|
||||
throw;
|
||||
}
|
||||
|
||||
HAL_ExitMain();
|
||||
})
|
||||
.detach();
|
||||
{
|
||||
std::scoped_lock lock{m};
|
||||
robot = nullptr;
|
||||
exited = true;
|
||||
}
|
||||
cv.notify_all();
|
||||
});
|
||||
|
||||
HAL_RunMain();
|
||||
|
||||
// signal loop to exit
|
||||
if (robot) robot->EndCompetition();
|
||||
|
||||
// prefer to join, but detach to exit if it doesn't exit in a timely manner
|
||||
using namespace std::chrono_literals;
|
||||
std::unique_lock lock{m};
|
||||
if (cv.wait_for(lock, 1s, [] { return exited; }))
|
||||
thr.join();
|
||||
else
|
||||
thr.detach();
|
||||
} else {
|
||||
impl::RunRobot<Robot>();
|
||||
impl::RunRobot<Robot>(m, &robot);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -127,6 +164,8 @@ class RobotBase {
|
||||
|
||||
virtual void StartCompetition() = 0;
|
||||
|
||||
virtual void EndCompetition() = 0;
|
||||
|
||||
static constexpr bool IsReal() {
|
||||
#ifdef __FRC_ROBORIO__
|
||||
return true;
|
||||
|
||||
@@ -34,6 +34,11 @@ class TimedRobot : public IterativeRobotBase, public ErrorBase {
|
||||
*/
|
||||
void StartCompetition() override;
|
||||
|
||||
/**
|
||||
* Ends the main loop in StartCompetition().
|
||||
*/
|
||||
void EndCompetition() override;
|
||||
|
||||
/**
|
||||
* Get the time period between calls to Periodic() functions.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user