blob: b69cf01e8a955d82b3c392a5ee78573f4985b54e [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"
8#include "aos/common/messages/RobotState.q.h"
9#include "aos/common/type_traits.h"
10
11namespace aos {
12namespace control_loops {
13
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
39// Provides helper methods to assist in writing control loops.
40// This template expects to be constructed with a queue group as an argument
41// that has a goal, position, status, and output queue.
42// It will then call the RunIteration method every cycle that it has enough
43// valid data for the control loop to run.
44// If has_position is false, the control loop will always use NULL as the
45// position and not check the queue. This is used for "loops" that control
46// motors open loop.
47template <class T, bool has_position = true>
48class ControlLoop : public SerializableControlLoop {
49 public:
50 // Maximum age of position packets before the loop will be disabled due to
51 // invalid position data.
52 static const int kPositionTimeoutMs = 100;
53 // Maximum age of driver station packets before the loop will be disabled.
54 static const int kDSPacketTimeoutMs = 100;
55
56 ControlLoop(T *control_loop) : control_loop_(control_loop) {}
57
58 // Create some convenient typedefs to reference the Goal, Position, Status,
59 // and Output structures.
60 typedef typename std::remove_reference<
61 decltype(*(static_cast<T *>(NULL)->goal.MakeMessage().get()))>::type
62 GoalType;
63 typedef typename std::remove_reference<
64 decltype(*(static_cast<T *>(NULL)->position.MakeMessage().get()))>::type
65 PositionType;
66 typedef typename std::remove_reference<
67 decltype(*(static_cast<T *>(NULL)->status.MakeMessage().get()))>::type
68 StatusType;
69 typedef typename std::remove_reference<
70 decltype(*(static_cast<T *>(NULL)->output.MakeMessage().get()))>::type
71 OutputType;
72
73 // Constructs and sends a message on the output queue which will stop all the
74 // motors. Calls Zero to clear all the state.
75 void ZeroOutputs();
76
77 // Sets the output to zero.
78 // Over-ride if a value of zero is not "off" for this subsystem.
79 virtual void Zero(OutputType *output) { output->Zero(); }
80
81 // Runs the loop forever.
82 virtual void Run();
83
84 // Runs one cycle of the loop.
85 virtual void Iterate();
86
87 // Returns the name of the queue group.
88 const char *name() { return control_loop_->name(); }
89
90 // Methods to serialize all the data that should be sent over the network.
91 virtual size_t SeralizedSize() { return control_loop_->goal->Size(); }
92 virtual void Serialize(char *buffer) const {
93 control_loop_->goal->Serialize(buffer);
94 }
95 virtual void SerializeZeroMessage(char *buffer) const {
96 GoalType zero_goal;
97 zero_goal.Zero();
98 zero_goal.Serialize(buffer);
99 }
100
101 virtual void Deserialize(const char *buffer) {
102 ScopedMessagePtr<GoalType> new_msg = control_loop_->goal.MakeMessage();
103 new_msg->Deserialize(buffer);
104 new_msg.Send();
105 }
106
107 virtual uint32_t UniqueID() { return control_loop_->hash(); }
108
109 protected:
110 // Runs an iteration of the control loop.
111 // goal is the last goal that was sent. It might be any number of cycles old.
112 // position is the current position, or NULL if we didn't get a position this
113 // cycle.
114 // output is the values to be sent to the motors. This is NULL if the output
115 // is going to be ignored and set to 0.
116 // status is the status of the control loop.
117 // Both output and status should be filled in by the implementation.
118 virtual void RunIteration(const GoalType *goal,
119 const PositionType *position,
120 OutputType *output,
121 StatusType *status) = 0;
122
123 private:
124 // Pointer to the queue group
125 T *control_loop_;
126};
127
128} // namespace control_loops
129} // namespace aos
130
131#include "aos/common/control_loop/ControlLoop-tmpl.h" // IWYU pragma: export
132
133#endif