#pragma once #include "expected.h" template class ClosedLoopController { public: void update() { expected outputValue = getOutput(); setOutput(outputValue); } private: expected getOutput() { expected setpoint = getSetpoint(); // If we don't know the setpoint, return failure. if (!setpoint) { return unexpected; } expected observation = observePlant(); // If we couldn't observe the plant, return failure. if (!observation) { return unexpected; } expected openLoopResult = getOpenLoop(setpoint.Value); // If we couldn't compute open loop, return failure. if (!openLoopResult) { return unexpected; } expected closedLoopResult = getClosedLoop(setpoint.Value, observation.Value); // If we couldn't compute closed loop, return failure. if (!closedLoopResult) { return unexpected; } return openLoopResult.Value + closedLoopResult.Value; } // Get the setpoint: where should the controller put the plant? virtual expected getSetpoint() const = 0; // Get the current observation: what is the current state of the world? virtual expected observePlant() const = 0; // Get the open-loop output: output state based on only the setpoint virtual expected getOpenLoop(TInput setpoint) const = 0; // Get the closed-loop output: output state based on setpoint and observation virtual expected getClosedLoop(TInput setpoint, TInput observation) = 0; // Set the output: Drive whatever output system will perturb the plant in the real world virtual void setOutput(expected outputValue) = 0; };