blob: bb76ffa66467e9b6c0d6b34467ae266cf1f2f54e [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
4#include <cstring>
5
6#include "aos/aos_core.h"
7#include "aos/common/control_loop/Timing.h"
brians343bc112013-02-10 01:53:46 +00008#include "aos/common/type_traits.h"
Brian Silvermanf665d692013-02-17 22:11:39 -08009#include "aos/common/queue.h"
Brian Silverman3204dd82013-03-12 18:42:01 -070010#include "aos/common/time.h"
brians343bc112013-02-10 01:53:46 +000011
12namespace aos {
13namespace control_loops {
14
15// Interface to describe runnable jobs.
16class Runnable {
17 public:
18 virtual ~Runnable() {}
19 // Runs forever.
20 virtual void Run() = 0;
21 // Does one quick piece of work and return. Does _not_ block.
22 virtual void Iterate() = 0;
23};
24
25class SerializableControlLoop : public Runnable {
26 public:
27 // Returns the size of all the data to be sent when serialized.
28 virtual size_t SeralizedSize() = 0;
29 // Serialize the current data.
30 virtual void Serialize(char *buffer) const = 0;
31 // Serialize zeroed data in case the data is out of date.
32 virtual void SerializeZeroMessage(char *buffer) const = 0;
33 // Deserialize data into the control loop.
34 virtual void Deserialize(const char *buffer) = 0;
35 // Unique identifier for the control loop.
36 // Most likely the hash of the queue group.
37 virtual uint32_t UniqueID() = 0;
38};
39
Brian Silverman3204dd82013-03-12 18:42:01 -070040// Control loops run this often, "starting" at time 0.
41const time::Time kLoopFrequency = time::Time::InSeconds(0.01);
42
brians343bc112013-02-10 01:53:46 +000043// Provides helper methods to assist in writing control loops.
44// This template expects to be constructed with a queue group as an argument
45// that has a goal, position, status, and output queue.
46// It will then call the RunIteration method every cycle that it has enough
47// valid data for the control loop to run.
48// If has_position is false, the control loop will always use NULL as the
49// position and not check the queue. This is used for "loops" that control
50// motors open loop.
51template <class T, bool has_position = true>
52class ControlLoop : public SerializableControlLoop {
53 public:
54 // Maximum age of position packets before the loop will be disabled due to
55 // invalid position data.
Austin Schuhfa033692013-02-24 01:00:55 -080056 static const int kPositionTimeoutMs = 1000;
brians343bc112013-02-10 01:53:46 +000057 // Maximum age of driver station packets before the loop will be disabled.
Austin Schuhfa033692013-02-24 01:00:55 -080058 static const int kDSPacketTimeoutMs = 500;
brians343bc112013-02-10 01:53:46 +000059
60 ControlLoop(T *control_loop) : control_loop_(control_loop) {}
61
62 // Create some convenient typedefs to reference the Goal, Position, Status,
63 // and Output structures.
64 typedef typename std::remove_reference<
65 decltype(*(static_cast<T *>(NULL)->goal.MakeMessage().get()))>::type
66 GoalType;
67 typedef typename std::remove_reference<
68 decltype(*(static_cast<T *>(NULL)->position.MakeMessage().get()))>::type
69 PositionType;
70 typedef typename std::remove_reference<
71 decltype(*(static_cast<T *>(NULL)->status.MakeMessage().get()))>::type
72 StatusType;
73 typedef typename std::remove_reference<
74 decltype(*(static_cast<T *>(NULL)->output.MakeMessage().get()))>::type
75 OutputType;
76
77 // Constructs and sends a message on the output queue which will stop all the
78 // motors. Calls Zero to clear all the state.
79 void ZeroOutputs();
80
81 // Sets the output to zero.
82 // Over-ride if a value of zero is not "off" for this subsystem.
83 virtual void Zero(OutputType *output) { output->Zero(); }
84
85 // Runs the loop forever.
86 virtual void Run();
87
88 // Runs one cycle of the loop.
89 virtual void Iterate();
90
91 // Returns the name of the queue group.
92 const char *name() { return control_loop_->name(); }
93
94 // Methods to serialize all the data that should be sent over the network.
95 virtual size_t SeralizedSize() { return control_loop_->goal->Size(); }
96 virtual void Serialize(char *buffer) const {
97 control_loop_->goal->Serialize(buffer);
98 }
99 virtual void SerializeZeroMessage(char *buffer) const {
100 GoalType zero_goal;
101 zero_goal.Zero();
102 zero_goal.Serialize(buffer);
103 }
104
105 virtual void Deserialize(const char *buffer) {
106 ScopedMessagePtr<GoalType> new_msg = control_loop_->goal.MakeMessage();
107 new_msg->Deserialize(buffer);
108 new_msg.Send();
109 }
110
111 virtual uint32_t UniqueID() { return control_loop_->hash(); }
112
113 protected:
114 // Runs an iteration of the control loop.
115 // goal is the last goal that was sent. It might be any number of cycles old.
116 // position is the current position, or NULL if we didn't get a position this
117 // cycle.
118 // output is the values to be sent to the motors. This is NULL if the output
119 // is going to be ignored and set to 0.
120 // status is the status of the control loop.
121 // Both output and status should be filled in by the implementation.
122 virtual void RunIteration(const GoalType *goal,
123 const PositionType *position,
124 OutputType *output,
125 StatusType *status) = 0;
126
127 private:
128 // Pointer to the queue group
129 T *control_loop_;
130};
131
132} // namespace control_loops
133} // namespace aos
134
135#include "aos/common/control_loop/ControlLoop-tmpl.h" // IWYU pragma: export
136
137#endif