blob: ff822e4d7fdc44d0f843fb78dafaaba874396be3 [file]
#ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_THERMAL_CONTROLLER_SECOND_ORDER_ADRC_CONTROLLER_H_
#define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_THERMAL_CONTROLLER_SECOND_ORDER_ADRC_CONTROLLER_H_
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "absl/base/attributes.h"
#include "absl/base/nullability.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include <nlohmann/json_fwd.hpp>
#include "thermal_config.pb.h"
#include "thermal_controller_specification.pb.h"
#include "tlbmc/thermal/controller/algorithm/second_order_adrc.h"
#include "tlbmc/thermal/controller/controller.h"
#include "tlbmc/thermal/zone_manager.h"
namespace milotic_tlbmc {
namespace thermal {
constexpr double kDefaultSecondOrderAdrcSetpointValue = 0.0;
struct SecondOrderAdrcControllerParameters {
std::string id;
ZoneManager* absl_nonnull zone_manager ABSL_REQUIRE_EXPLICIT_INIT;
std::unique_ptr<SecondOrderAdrcThermalLoop> absl_nonnull
second_order_adrc_loop ABSL_REQUIRE_EXPLICIT_INIT;
double setpoint = kDefaultSecondOrderAdrcSetpointValue;
std::vector<std::string> input_sensors;
std::vector<std::vector<std::string>> disturbance_sensor_lists;
};
/**
* `SecondOrderAdrcController` provides a connection between the thermal zone
* manager and the 2nd-order ADRC thermal loop. It will handle the sensor
* reading & fan output process, and the 2nd-order ADRC thermal loop
* calculations.
*
* The 2nd-order ADRC loop and its controller is 1:1 in bi-jection relationship.
*
* This class is not thread-safe.
*/
class SecondOrderAdrcController : public ThermalController {
public:
~SecondOrderAdrcController() final = default;
static absl::StatusOr<std::unique_ptr<SecondOrderAdrcController>> Create(
SecondOrderAdrcControllerParameters params);
void ProcessThermalLoop() final;
double ProcessInput() final;
void ProcessOutput(double output) final;
std::string GetId() const final { return id_; }
bool IsFanController() const final { return false; }
bool IsSupportiveController() const final { return false; }
const std::vector<std::string>& GetAffectedControllerIds() const final {
return empty_affected_controller_ids_;
}
void AdjustSetpoint(double offset) final { setpoint_ += offset; }
double GetSetpoint() const { return setpoint_; }
ZoneManager* GetZoneManager() const { return zone_owner_; }
SecondOrderAdrcThermalLoop* GetSecondOrderAdrcLoop() const {
return second_order_adrc_loop_.get();
}
void AddInputSensor(const std::string& input_sensor) {
input_sensors_.push_back(input_sensor);
}
const std::vector<std::string>& GetInputSensors() const {
return input_sensors_;
}
nlohmann::json ToJson() const;
protected:
explicit SecondOrderAdrcController(
absl::string_view id, ZoneManager* zone_manager,
std::unique_ptr<SecondOrderAdrcThermalLoop> absl_nonnull
second_order_adrc_loop,
double setpoint, std::vector<std::string> input_sensors,
std::vector<std::vector<std::string>> disturbance_sensor_lists)
: ThermalController(),
id_(id),
zone_owner_(zone_manager),
second_order_adrc_loop_(std::move(second_order_adrc_loop)),
setpoint_(setpoint),
input_sensors_(std::move(input_sensors)),
disturbance_sensor_lists_(std::move(disturbance_sensor_lists)) {
input_disturbances_.resize(disturbance_sensor_lists_.size(), 0.0);
}
void ProcessInputDisturbances();
static std::optional<double> ProcessSensorInputs(
absl::Span<const std::string> sensors, ZoneManager* zone_manager);
private:
const std::string id_;
// Use a simple pointer here to avoid circular dependency.
// Every `ZoneManager` will be owned by the thermal control collector of
// tlBMC, and will live as long as the thermal control service is on.
ZoneManager* zone_owner_ = nullptr;
// Every `SecondOrderAdrcThermalLoop` will be owned by its thermal controller,
// and will live as long as the thermal control service is on.
std::unique_ptr<SecondOrderAdrcThermalLoop> second_order_adrc_loop_;
double setpoint_ = kDefaultSecondOrderAdrcSetpointValue;
std::vector<std::string> input_sensors_;
std::vector<std::vector<std::string>> disturbance_sensor_lists_;
std::vector<double> input_disturbances_;
// An empty vector to return by reference for `GetAffectedControllerIds`.
const std::vector<std::string> empty_affected_controller_ids_;
};
} // namespace thermal
} // namespace milotic_tlbmc
#endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_THERMAL_CONTROLLER_SECOND_ORDER_ADRC_CONTROLLER_H_