| /* |
| // Copyright (c) 2018 Intel Corporation |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| */ |
| #include "util.hpp" |
| |
| #include "conf.hpp" |
| |
| #include <cstdint> |
| #include <iostream> |
| #include <map> |
| #include <string> |
| |
| namespace pid_control |
| { |
| |
| void debugPrint(const std::map<std::string, conf::SensorConfig>& sensorConfig, |
| const std::map<int64_t, conf::PIDConf>& zoneConfig, |
| const std::map<int64_t, conf::ZoneConfig>& zoneDetailsConfig) |
| { |
| if constexpr (!conf::DEBUG) |
| { |
| return; |
| } |
| // print sensor config |
| std::cout << "sensor config:\n"; |
| std::cout << "{\n"; |
| for (const auto& pair : sensorConfig) |
| { |
| std::cout << "\t{" << pair.first << ",\n\t\t{"; |
| std::cout << pair.second.type << ", "; |
| std::cout << pair.second.readPath << ", "; |
| std::cout << pair.second.writePath << ", "; |
| std::cout << pair.second.min << ", "; |
| std::cout << pair.second.max << ", "; |
| std::cout << pair.second.timeout << ", "; |
| std::cout << pair.second.unavailableAsFailed << "},\n\t},\n"; |
| } |
| std::cout << "}\n\n"; |
| std::cout << "ZoneDetailsConfig\n"; |
| std::cout << "{\n"; |
| for (const auto& zone : zoneDetailsConfig) |
| { |
| std::cout << "\t{" << zone.first << ",\n"; |
| std::cout << "\t\t{" << zone.second.minThermalOutput << ", "; |
| std::cout << zone.second.failsafePercent << "}\n\t},\n"; |
| } |
| std::cout << "}\n\n"; |
| std::cout << "ZoneConfig\n"; |
| std::cout << "{\n"; |
| for (const auto& zone : zoneConfig) |
| { |
| std::cout << "\t{" << zone.first << "\n"; |
| for (const auto& pidconf : zone.second) |
| { |
| std::cout << "\t\t{" << pidconf.first << ",\n"; |
| std::cout << "\t\t\t{" << pidconf.second.type << ",\n"; |
| std::cout << "\t\t\t{"; |
| for (const auto& input : pidconf.second.inputs) |
| { |
| std::cout << "\n\t\t\t" << input.name; |
| if (input.convertTempToMargin) |
| { |
| std::cout << "[" << input.convertMarginZero << "]"; |
| } |
| std::cout << ",\n"; |
| } |
| std::cout << "\t\t\t}\n"; |
| std::cout << "\t\t\t" << pidconf.second.setpoint << ",\n"; |
| std::cout << "\t\t\t{" << pidconf.second.pidInfo.ts << ",\n"; |
| std::cout << "\t\t\t" << pidconf.second.pidInfo.proportionalCoeff |
| << ",\n"; |
| std::cout << "\t\t\t" << pidconf.second.pidInfo.integralCoeff |
| << ",\n"; |
| std::cout << "\t\t\t" << pidconf.second.pidInfo.feedFwdOffset |
| << ",\n"; |
| std::cout << "\t\t\t" << pidconf.second.pidInfo.feedFwdGain |
| << ",\n"; |
| std::cout << "\t\t\t{" << pidconf.second.pidInfo.integralLimit.min |
| << "," << pidconf.second.pidInfo.integralLimit.max |
| << "},\n"; |
| std::cout << "\t\t\t{" << pidconf.second.pidInfo.outLim.min << "," |
| << pidconf.second.pidInfo.outLim.max << "},\n"; |
| std::cout << "\t\t\t" << pidconf.second.pidInfo.slewNeg << ",\n"; |
| std::cout << "\t\t\t" << pidconf.second.pidInfo.slewPos << ",\n"; |
| std::cout << "\t\t\t}\n\t\t}\n"; |
| } |
| std::cout << "\t},\n"; |
| } |
| std::cout << "}\n\n"; |
| } |
| |
| std::vector<conf::SensorInput> |
| spliceInputs(const std::vector<std::string>& inputNames, |
| const std::vector<double>& inputTempToMargin, |
| const std::vector<std::string>& missingAcceptableNames) |
| { |
| std::vector<conf::SensorInput> results; |
| |
| // Default to TempToMargin and MissingIsAcceptable disabled |
| for (const auto& inputName : inputNames) |
| { |
| conf::SensorInput newInput{ |
| inputName, std::numeric_limits<double>::quiet_NaN(), false, false}; |
| |
| results.emplace_back(newInput); |
| } |
| |
| size_t resultSize = results.size(); |
| size_t marginSize = inputTempToMargin.size(); |
| |
| for (size_t index = 0; index < resultSize; ++index) |
| { |
| // If fewer doubles than strings, and vice versa, ignore remainder |
| if (index >= marginSize) |
| { |
| break; |
| } |
| |
| // Both vectors have this index, combine both into SensorInput |
| results[index].convertMarginZero = inputTempToMargin[index]; |
| results[index].convertTempToMargin = true; |
| } |
| |
| std::set<std::string> acceptableSet; |
| |
| // Copy vector to set, to avoid O(n^2) runtime below |
| for (const auto& name : missingAcceptableNames) |
| { |
| acceptableSet.emplace(name); |
| } |
| |
| // Flag missingIsAcceptable true if name found in that set |
| for (auto& result : results) |
| { |
| if (acceptableSet.find(result.name) != acceptableSet.end()) |
| { |
| result.missingIsAcceptable = true; |
| } |
| } |
| |
| return results; |
| } |
| |
| std::vector<std::string> |
| splitNames(const std::vector<conf::SensorInput>& sensorInputs) |
| { |
| std::vector<std::string> results; |
| |
| for (const auto& sensorInput : sensorInputs) |
| { |
| results.emplace_back(sensorInput.name); |
| } |
| |
| return results; |
| } |
| |
| } // namespace pid_control |