blob: e9454d1ba247ce2a146dd0f8c03853de760de594 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#ifndef AOS_CONTROL_LOOP_CONTROL_LOOP_H_
2#define AOS_CONTROL_LOOP_CONTROL_LOOP_H_
3
Brian Silvermanb407c672014-04-09 11:58:37 -07004#include <string.h>
brians343bc112013-02-10 01:53:46 +00005
brians343bc112013-02-10 01:53:46 +00006#include "aos/common/type_traits.h"
Brian Silvermanf665d692013-02-17 22:11:39 -08007#include "aos/common/queue.h"
Brian Silverman3204dd82013-03-12 18:42:01 -07008#include "aos/common/time.h"
Brian Silverman50a9d032014-02-16 17:20:57 -08009#include "aos/common/util/log_interval.h"
brians343bc112013-02-10 01:53:46 +000010
11namespace aos {
Brian Silverman38111502014-04-10 12:36:26 -070012namespace controls {
brians343bc112013-02-10 01:53:46 +000013
14// Interface to describe runnable jobs.
15class Runnable {
16 public:
17 virtual ~Runnable() {}
18 // Runs forever.
19 virtual void Run() = 0;
20 // Does one quick piece of work and return. Does _not_ block.
21 virtual void Iterate() = 0;
22};
23
24class SerializableControlLoop : public Runnable {
25 public:
26 // Returns the size of all the data to be sent when serialized.
27 virtual size_t SeralizedSize() = 0;
28 // Serialize the current data.
29 virtual void Serialize(char *buffer) const = 0;
30 // Serialize zeroed data in case the data is out of date.
31 virtual void SerializeZeroMessage(char *buffer) const = 0;
32 // Deserialize data into the control loop.
33 virtual void Deserialize(const char *buffer) = 0;
34 // Unique identifier for the control loop.
35 // Most likely the hash of the queue group.
36 virtual uint32_t UniqueID() = 0;
37};
38
Brian Silverman3204dd82013-03-12 18:42:01 -070039// Control loops run this often, "starting" at time 0.
Brian Silverman1c3cfc02013-10-25 17:02:19 -070040constexpr time::Time kLoopFrequency = time::Time::InSeconds(0.01);
Brian Silverman3204dd82013-03-12 18:42:01 -070041
brians343bc112013-02-10 01:53:46 +000042// Provides helper methods to assist in writing control loops.
43// This template expects to be constructed with a queue group as an argument
44// that has a goal, position, status, and output queue.
45// It will then call the RunIteration method every cycle that it has enough
46// valid data for the control loop to run.
Brian Silvermand8f403a2014-12-13 19:12:04 -050047template <class T, bool fail_no_goal = true>
brians343bc112013-02-10 01:53:46 +000048class ControlLoop : public SerializableControlLoop {
49 public:
50 // Maximum age of position packets before the loop will be disabled due to
51 // invalid position data.
Austin Schuhfa033692013-02-24 01:00:55 -080052 static const int kPositionTimeoutMs = 1000;
brians343bc112013-02-10 01:53:46 +000053 // Maximum age of driver station packets before the loop will be disabled.
Austin Schuhfa033692013-02-24 01:00:55 -080054 static const int kDSPacketTimeoutMs = 500;
brians343bc112013-02-10 01:53:46 +000055
Austin Schuh3d6e3df2014-02-17 01:51:03 -080056 ControlLoop(T *control_loop)
57 : control_loop_(control_loop),
58 reset_(true),
59 has_sensor_reset_counters_(false) {}
brians343bc112013-02-10 01:53:46 +000060 // Create some convenient typedefs to reference the Goal, Position, Status,
61 // and Output structures.
62 typedef typename std::remove_reference<
63 decltype(*(static_cast<T *>(NULL)->goal.MakeMessage().get()))>::type
64 GoalType;
65 typedef typename std::remove_reference<
66 decltype(*(static_cast<T *>(NULL)->position.MakeMessage().get()))>::type
67 PositionType;
68 typedef typename std::remove_reference<
69 decltype(*(static_cast<T *>(NULL)->status.MakeMessage().get()))>::type
70 StatusType;
71 typedef typename std::remove_reference<
72 decltype(*(static_cast<T *>(NULL)->output.MakeMessage().get()))>::type
73 OutputType;
74
Brian Silvermand1e65b92014-03-08 17:07:14 -080075 // Constructs and sends a message on the output queue which sets everything to
76 // a safe state (generally motors off). For some subclasses, this will be a
77 // bit different (ie pistons).
78 // The implementation here creates a new Output message, calls Zero() on it,
79 // and then sends it.
80 virtual void ZeroOutputs();
brians343bc112013-02-10 01:53:46 +000081
Austin Schuh3d6e3df2014-02-17 01:51:03 -080082 // Returns true if the device reading the sensors reset and potentially lost
Ben Fredrickson4283bb42014-02-22 08:31:50 +000083 // track of encoder counts. Calling this read method clears the flag. After
84 // a reset, RunIteration will not be called until there is a valid position
85 // message.
Austin Schuh3d6e3df2014-02-17 01:51:03 -080086 bool reset() {
87 bool ans = reset_;
88 reset_ = false;
89 return ans;
90 }
91
brians343bc112013-02-10 01:53:46 +000092 // Sets the output to zero.
93 // Over-ride if a value of zero is not "off" for this subsystem.
94 virtual void Zero(OutputType *output) { output->Zero(); }
95
96 // Runs the loop forever.
97 virtual void Run();
98
99 // Runs one cycle of the loop.
100 virtual void Iterate();
101
102 // Returns the name of the queue group.
103 const char *name() { return control_loop_->name(); }
104
105 // Methods to serialize all the data that should be sent over the network.
106 virtual size_t SeralizedSize() { return control_loop_->goal->Size(); }
107 virtual void Serialize(char *buffer) const {
108 control_loop_->goal->Serialize(buffer);
109 }
110 virtual void SerializeZeroMessage(char *buffer) const {
111 GoalType zero_goal;
112 zero_goal.Zero();
113 zero_goal.Serialize(buffer);
114 }
115
116 virtual void Deserialize(const char *buffer) {
117 ScopedMessagePtr<GoalType> new_msg = control_loop_->goal.MakeMessage();
118 new_msg->Deserialize(buffer);
119 new_msg.Send();
120 }
121
122 virtual uint32_t UniqueID() { return control_loop_->hash(); }
123
124 protected:
125 // Runs an iteration of the control loop.
126 // goal is the last goal that was sent. It might be any number of cycles old.
127 // position is the current position, or NULL if we didn't get a position this
128 // cycle.
129 // output is the values to be sent to the motors. This is NULL if the output
130 // is going to be ignored and set to 0.
131 // status is the status of the control loop.
132 // Both output and status should be filled in by the implementation.
133 virtual void RunIteration(const GoalType *goal,
134 const PositionType *position,
135 OutputType *output,
136 StatusType *status) = 0;
137
Brian Silvermand1e65b92014-03-08 17:07:14 -0800138 T *queue_group() { return control_loop_; }
139 const T *queue_group() const { return control_loop_; }
140
brians343bc112013-02-10 01:53:46 +0000141 private:
142 // Pointer to the queue group
143 T *control_loop_;
Brian Silverman50a9d032014-02-16 17:20:57 -0800144
Austin Schuh3d6e3df2014-02-17 01:51:03 -0800145 bool reset_;
146 bool has_sensor_reset_counters_;
147 int32_t reader_pid_;
148 uint32_t cape_resets_;
149
Brian Silverman50a9d032014-02-16 17:20:57 -0800150 typedef ::aos::util::SimpleLogInterval SimpleLogInterval;
151 static constexpr ::aos::time::Time kStaleLogInterval =
152 ::aos::time::Time::InSeconds(0.1);
Brian Silverman50a9d032014-02-16 17:20:57 -0800153 SimpleLogInterval no_prior_goal_ =
154 SimpleLogInterval(kStaleLogInterval, ERROR,
155 "no prior goal");
Brian Silverman50a9d032014-02-16 17:20:57 -0800156 SimpleLogInterval no_driver_station_ =
157 SimpleLogInterval(kStaleLogInterval, ERROR,
158 "no driver station packet");
159 SimpleLogInterval driver_station_old_ =
160 SimpleLogInterval(kStaleLogInterval, ERROR,
161 "driver station packet is too old");
Brian Silverman4910efb2014-02-17 11:10:10 -0800162 SimpleLogInterval no_sensor_generation_ =
163 SimpleLogInterval(kStaleLogInterval, ERROR,
164 "no sensor_generation message");
Brian Silverman2704ecf2014-04-09 20:24:03 -0700165 SimpleLogInterval motors_off_log_ =
166 SimpleLogInterval(kStaleLogInterval, WARNING, "motors disabled");
brians343bc112013-02-10 01:53:46 +0000167};
168
Brian Silverman38111502014-04-10 12:36:26 -0700169} // namespace controls
brians343bc112013-02-10 01:53:46 +0000170} // namespace aos
171
Briana6553ed2014-04-02 21:26:46 -0700172#include "aos/common/controls/control_loop-tmpl.h" // IWYU pragma: export
brians343bc112013-02-10 01:53:46 +0000173
174#endif