blob: 972d7ef70f0f34be0ed964eee64ea46bfee1f272 [file] [log] [blame]
Brian Silvermand8f403a2014-12-13 19:12:04 -05001#ifndef FRC971_WPILIB_LOOP_OUTPUT_HANDLER_H_
2#define FRC971_WPILIB_LOOP_OUTPUT_HANDLER_H_
3
Brian Silverman425492b2015-12-30 15:23:55 -08004#include <atomic>
5
Brian Silvermand8f403a2014-12-13 19:12:04 -05006#include "aos/common/scoped_fd.h"
7#include "aos/common/time.h"
8#include "aos/common/util/log_interval.h"
9
Brian Silvermand8f403a2014-12-13 19:12:04 -050010namespace frc971 {
11namespace wpilib {
12
13// Handles sending the output from a single control loop to the hardware.
14//
15// This class implements stopping motors when no new values are received for too
16// long efficiently.
17//
18// The intended use is to have a subclass for each loop which implements the
19// pure virtual methods and is then run in a separate thread. The operator()
20// loops writing values until Quit() is called.
21class LoopOutputHandler {
22 public:
Austin Schuhbb227f82015-09-06 15:27:52 -070023 LoopOutputHandler(
24 const ::aos::time::Time &timeout = ::aos::time::Time::InSeconds(0.10));
Brian Silvermand8f403a2014-12-13 19:12:04 -050025
26 void Quit() { run_ = false; }
27
28 void operator()();
29
30 protected:
31 // Read a message from the appropriate queue.
32 // This must block.
33 virtual void Read() = 0;
34
35 // Send the output from the appropriate queue to the hardware.
36 // Read() will always be called at least once before per invocation of this.
37 virtual void Write() = 0;
38
39 // Stop all outputs. This will be called in a separate thread (if at all).
40 // The subclass implementation should handle any appropriate logging.
41 // This will be called exactly once if Read() blocks for too long and once
42 // after Quit is called.
43 virtual void Stop() = 0;
44
45 private:
46 // The thread that actually contains a timerfd to implement timeouts. The
47 // idea is to have a timerfd that is repeatedly set to the timeout expiration
48 // in the future so it will never actually expire unless it is not reset for
49 // too long.
50 //
51 // This class nicely encapsulates the raw fd and manipulating it. Its
52 // operator() loops until Quit() is called, calling Stop() on its associated
53 // LoopOutputHandler whenever the timerfd expires.
54 class Watchdog {
55 public:
Austin Schuhbb227f82015-09-06 15:27:52 -070056 Watchdog(LoopOutputHandler *handler, const ::aos::time::Time &timeout);
Brian Silvermand8f403a2014-12-13 19:12:04 -050057
58 void operator()();
59
60 void Reset();
61
62 void Quit() { run_ = false; }
63
64 private:
65 LoopOutputHandler *const handler_;
66
Austin Schuhbb227f82015-09-06 15:27:52 -070067 const ::aos::time::Time timeout_;
68
Brian Silvermand8f403a2014-12-13 19:12:04 -050069 ::aos::ScopedFD timerfd_;
70
71 ::std::atomic<bool> run_{true};
72 };
73
Brian Silvermand8f403a2014-12-13 19:12:04 -050074 Watchdog watchdog_;
75
76 ::std::atomic<bool> run_{true};
77
Brian Silverman699f0cb2015-02-05 19:45:01 -050078 ::aos::util::SimpleLogInterval no_joystick_state_ =
Brian Silvermand8f403a2014-12-13 19:12:04 -050079 ::aos::util::SimpleLogInterval(::aos::time::Time::InSeconds(0.5), INFO,
Brian Silverman699f0cb2015-02-05 19:45:01 -050080 "no joystick state -> not outputting");
81 ::aos::util::SimpleLogInterval fake_joystick_state_ =
Brian Silvermand8f403a2014-12-13 19:12:04 -050082 ::aos::util::SimpleLogInterval(::aos::time::Time::InSeconds(0.5), DEBUG,
Brian Silverman699f0cb2015-02-05 19:45:01 -050083 "fake joystick state -> not outputting");
Brian Silvermand8f403a2014-12-13 19:12:04 -050084};
85
86} // namespace wpilib
87} // namespace frc971
88
89#endif // FRC971_WPILIB_LOOP_OUTPUT_HANDLER_H_