| #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_ |