blob: 27c96e7345abb25d3b73fc9334bcdacd884c77e5 [file] [log] [blame]
#ifndef FRC971_WPILIB_LOOP_OUTPUT_HANDLER_H_
#define FRC971_WPILIB_LOOP_OUTPUT_HANDLER_H_
#include <atomic>
#include <chrono>
#include "aos/scoped/scoped_fd.h"
#include "aos/time/time.h"
#include "aos/util/log_interval.h"
namespace frc971 {
namespace wpilib {
// Handles sending the output from a single control loop to the hardware.
//
// This class implements stopping motors when no new values are received for too
// long efficiently.
//
// The intended use is to have a subclass for each loop which implements the
// pure virtual methods and is then run in a separate thread. The operator()
// loops writing values until Quit() is called.
class LoopOutputHandler {
public:
LoopOutputHandler(
::std::chrono::nanoseconds timeout = ::std::chrono::milliseconds(100));
void Quit() { run_ = false; }
void operator()();
protected:
// Read a message from the appropriate queue.
// This must block.
virtual void Read() = 0;
// Send the output from the appropriate queue to the hardware.
// Read() will always be called at least once before per invocation of this.
virtual void Write() = 0;
// Stop all outputs. This will be called in a separate thread (if at all).
// The subclass implementation should handle any appropriate logging.
// This will be called exactly once if Read() blocks for too long and once
// after Quit is called.
virtual void Stop() = 0;
private:
// The thread that actually contains a timerfd to implement timeouts. The
// idea is to have a timerfd that is repeatedly set to the timeout expiration
// in the future so it will never actually expire unless it is not reset for
// too long.
//
// This class nicely encapsulates the raw fd and manipulating it. Its
// operator() loops until Quit() is called, calling Stop() on its associated
// LoopOutputHandler whenever the timerfd expires.
class Watchdog {
public:
Watchdog(LoopOutputHandler *handler, ::std::chrono::nanoseconds timeout);
void operator()();
void Reset();
void Quit() { run_ = false; }
private:
LoopOutputHandler *const handler_;
const ::std::chrono::nanoseconds timeout_;
::aos::ScopedFD timerfd_;
::std::atomic<bool> run_{true};
};
Watchdog watchdog_;
::std::atomic<bool> run_{true};
::aos::util::SimpleLogInterval no_joystick_state_ =
::aos::util::SimpleLogInterval(::std::chrono::milliseconds(500), INFO,
"no joystick state -> not outputting");
::aos::util::SimpleLogInterval fake_joystick_state_ =
::aos::util::SimpleLogInterval(::std::chrono::milliseconds(500), DEBUG,
"fake joystick state -> not outputting");
};
} // namespace wpilib
} // namespace frc971
#endif // FRC971_WPILIB_LOOP_OUTPUT_HANDLER_H_