/** * @file closed_loop_controller.h */ #pragma once #include template class ClosedLoopController { public: expected update() { expected outputValue = getOutput(); setOutput(outputValue); return 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() = 0; // Get the current observation: what is the current state of the world? virtual expected observePlant() = 0; // Get the open-loop output: output state based on only the setpoint virtual expected getOpenLoop(TInput setpoint) = 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; };