1d1491724SPatrick Venture /** 2d1491724SPatrick Venture * Copyright 2019 Google Inc. 3d1491724SPatrick Venture * 4d1491724SPatrick Venture * Licensed under the Apache License, Version 2.0 (the "License"); 5d1491724SPatrick Venture * you may not use this file except in compliance with the License. 6d1491724SPatrick Venture * You may obtain a copy of the License at 7d1491724SPatrick Venture * 8d1491724SPatrick Venture * http://www.apache.org/licenses/LICENSE-2.0 9d1491724SPatrick Venture * 10d1491724SPatrick Venture * Unless required by applicable law or agreed to in writing, software 11d1491724SPatrick Venture * distributed under the License is distributed on an "AS IS" BASIS, 12d1491724SPatrick Venture * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d1491724SPatrick Venture * See the License for the specific language governing permissions and 14d1491724SPatrick Venture * limitations under the License. 15d1491724SPatrick Venture */ 16d1491724SPatrick Venture 17d1491724SPatrick Venture #include "pid/buildjson.hpp" 18d1491724SPatrick Venture 19d1491724SPatrick Venture #include "conf.hpp" 20d1491724SPatrick Venture 21d1491724SPatrick Venture #include <nlohmann/json.hpp> 22a83a3eccSPatrick Venture 23a83a3eccSPatrick Venture #include <map> 24d1491724SPatrick Venture #include <tuple> 25d1491724SPatrick Venture 26a076487aSPatrick Venture namespace pid_control 27a076487aSPatrick Venture { 28a076487aSPatrick Venture 29d1491724SPatrick Venture using json = nlohmann::json; 30d1491724SPatrick Venture 31f81f2886SJames Feist namespace conf 32f81f2886SJames Feist { 33f81f2886SJames Feist void from_json(const json& j, conf::ControllerInfo& c) 34d1491724SPatrick Venture { 35d1491724SPatrick Venture j.at("type").get_to(c.type); 36d1491724SPatrick Venture j.at("inputs").get_to(c.inputs); 37d1491724SPatrick Venture j.at("setpoint").get_to(c.setpoint); 38d1491724SPatrick Venture 39d1491724SPatrick Venture /* TODO: We need to handle parsing other PID controller configurations. 40d1491724SPatrick Venture * We can do that by checking for different keys and making the decision 41d1491724SPatrick Venture * accordingly. 42d1491724SPatrick Venture */ 43d1491724SPatrick Venture auto p = j.at("pid"); 44375f7098SHank Liou 45375f7098SHank Liou auto positiveHysteresis = p.find("positiveHysteresis"); 46375f7098SHank Liou auto negativeHysteresis = p.find("negativeHysteresis"); 47375f7098SHank Liou auto positiveHysteresisValue = 0.0; 48375f7098SHank Liou auto negativeHysteresisValue = 0.0; 49375f7098SHank Liou if (positiveHysteresis != p.end()) 50375f7098SHank Liou { 51375f7098SHank Liou p.at("positiveHysteresis").get_to(positiveHysteresisValue); 52375f7098SHank Liou } 53375f7098SHank Liou if (negativeHysteresis != p.end()) 54375f7098SHank Liou { 55375f7098SHank Liou p.at("negativeHysteresis").get_to(negativeHysteresisValue); 56375f7098SHank Liou } 57375f7098SHank Liou 58375f7098SHank Liou if (c.type != "stepwise") 59375f7098SHank Liou { 60d1491724SPatrick Venture p.at("samplePeriod").get_to(c.pidInfo.ts); 61d1491724SPatrick Venture p.at("proportionalCoeff").get_to(c.pidInfo.proportionalCoeff); 62d1491724SPatrick Venture p.at("integralCoeff").get_to(c.pidInfo.integralCoeff); 63903b0427SPatrick Venture p.at("feedFwdOffsetCoeff").get_to(c.pidInfo.feedFwdOffset); 64d1491724SPatrick Venture p.at("feedFwdGainCoeff").get_to(c.pidInfo.feedFwdGain); 65d1491724SPatrick Venture p.at("integralLimit_min").get_to(c.pidInfo.integralLimit.min); 66d1491724SPatrick Venture p.at("integralLimit_max").get_to(c.pidInfo.integralLimit.max); 67d1491724SPatrick Venture p.at("outLim_min").get_to(c.pidInfo.outLim.min); 68d1491724SPatrick Venture p.at("outLim_max").get_to(c.pidInfo.outLim.max); 69d1491724SPatrick Venture p.at("slewNeg").get_to(c.pidInfo.slewNeg); 70d1491724SPatrick Venture p.at("slewPos").get_to(c.pidInfo.slewPos); 71d1491724SPatrick Venture 72375f7098SHank Liou c.pidInfo.positiveHysteresis = positiveHysteresisValue; 73375f7098SHank Liou c.pidInfo.negativeHysteresis = negativeHysteresisValue; 74d1491724SPatrick Venture } 75d1491724SPatrick Venture else 76d1491724SPatrick Venture { 77375f7098SHank Liou p.at("samplePeriod").get_to(c.stepwiseInfo.ts); 78375f7098SHank Liou p.at("isCeiling").get_to(c.stepwiseInfo.isCeiling); 79375f7098SHank Liou 80375f7098SHank Liou for (size_t i = 0; i < ec::maxStepwisePoints; i++) 81375f7098SHank Liou { 82375f7098SHank Liou c.stepwiseInfo.reading[i] = 83375f7098SHank Liou std::numeric_limits<double>::quiet_NaN(); 84375f7098SHank Liou c.stepwiseInfo.output[i] = std::numeric_limits<double>::quiet_NaN(); 85d1491724SPatrick Venture } 86d1491724SPatrick Venture 87375f7098SHank Liou auto reading = p.find("reading"); 88375f7098SHank Liou if (reading != p.end()) 89d1491724SPatrick Venture { 90375f7098SHank Liou auto r = p.at("reading"); 91375f7098SHank Liou for (size_t i = 0; i < ec::maxStepwisePoints; i++) 92375f7098SHank Liou { 93375f7098SHank Liou auto n = r.find(std::to_string(i)); 94375f7098SHank Liou if (n != r.end()) 95375f7098SHank Liou { 96375f7098SHank Liou r.at(std::to_string(i)).get_to(c.stepwiseInfo.reading[i]); 97d1491724SPatrick Venture } 98375f7098SHank Liou } 99375f7098SHank Liou } 100375f7098SHank Liou 101375f7098SHank Liou auto output = p.find("output"); 102375f7098SHank Liou if (output != p.end()) 103d1491724SPatrick Venture { 104375f7098SHank Liou auto o = p.at("output"); 105375f7098SHank Liou for (size_t i = 0; i < ec::maxStepwisePoints; i++) 106375f7098SHank Liou { 107375f7098SHank Liou auto n = o.find(std::to_string(i)); 108375f7098SHank Liou if (n != o.end()) 109375f7098SHank Liou { 110375f7098SHank Liou o.at(std::to_string(i)).get_to(c.stepwiseInfo.output[i]); 111375f7098SHank Liou } 112375f7098SHank Liou } 113375f7098SHank Liou } 114375f7098SHank Liou 115375f7098SHank Liou c.stepwiseInfo.positiveHysteresis = positiveHysteresisValue; 116375f7098SHank Liou c.stepwiseInfo.negativeHysteresis = negativeHysteresisValue; 117d1491724SPatrick Venture } 118d1491724SPatrick Venture } 119f81f2886SJames Feist } // namespace conf 120d1491724SPatrick Venture 121*1df9e879SPatrick Venture std::pair<std::map<int64_t, conf::PIDConf>, std::map<int64_t, conf::ZoneConfig>> 122d1491724SPatrick Venture buildPIDsFromJson(const json& data) 123d1491724SPatrick Venture { 124d1491724SPatrick Venture // zone -> pids 125f81f2886SJames Feist std::map<int64_t, conf::PIDConf> pidConfig; 126d1491724SPatrick Venture // zone -> configs 127*1df9e879SPatrick Venture std::map<int64_t, conf::ZoneConfig> zoneConfig; 128d1491724SPatrick Venture 129d1491724SPatrick Venture /* TODO: if zones is empty, that's invalid. */ 130d1491724SPatrick Venture auto zones = data["zones"]; 131d1491724SPatrick Venture for (const auto& zone : zones) 132d1491724SPatrick Venture { 133d1491724SPatrick Venture int64_t id; 134f81f2886SJames Feist conf::PIDConf thisZone; 135*1df9e879SPatrick Venture conf::ZoneConfig thisZoneConfig; 136d1491724SPatrick Venture 137d1491724SPatrick Venture /* TODO: using at() throws a specific exception we can catch */ 138d1491724SPatrick Venture id = zone["id"]; 1393484bedaSJames Feist thisZoneConfig.minThermalOutput = zone["minThermalOutput"]; 140d1491724SPatrick Venture thisZoneConfig.failsafePercent = zone["failsafePercent"]; 141d1491724SPatrick Venture 142d1491724SPatrick Venture auto pids = zone["pids"]; 143d1491724SPatrick Venture for (const auto& pid : pids) 144d1491724SPatrick Venture { 145d1491724SPatrick Venture auto name = pid["name"]; 146f81f2886SJames Feist auto item = pid.get<conf::ControllerInfo>(); 147d1491724SPatrick Venture 148d1491724SPatrick Venture thisZone[name] = item; 149d1491724SPatrick Venture } 150d1491724SPatrick Venture 151d1491724SPatrick Venture pidConfig[id] = thisZone; 152d1491724SPatrick Venture zoneConfig[id] = thisZoneConfig; 153d1491724SPatrick Venture } 154d1491724SPatrick Venture 155d1491724SPatrick Venture return std::make_pair(pidConfig, zoneConfig); 156d1491724SPatrick Venture } 157a076487aSPatrick Venture 158a076487aSPatrick Venture } // namespace pid_control 159