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 <map> 22d1491724SPatrick Venture #include <nlohmann/json.hpp> 23d1491724SPatrick Venture #include <tuple> 24d1491724SPatrick Venture 25d1491724SPatrick Venture using json = nlohmann::json; 26d1491724SPatrick Venture 27f81f2886SJames Feist namespace conf 28f81f2886SJames Feist { 29f81f2886SJames Feist void from_json(const json& j, conf::ControllerInfo& c) 30d1491724SPatrick Venture { 31d1491724SPatrick Venture j.at("type").get_to(c.type); 32d1491724SPatrick Venture j.at("inputs").get_to(c.inputs); 33d1491724SPatrick Venture j.at("setpoint").get_to(c.setpoint); 34d1491724SPatrick Venture 35d1491724SPatrick Venture /* TODO: We need to handle parsing other PID controller configurations. 36d1491724SPatrick Venture * We can do that by checking for different keys and making the decision 37d1491724SPatrick Venture * accordingly. 38d1491724SPatrick Venture */ 39d1491724SPatrick Venture auto p = j.at("pid"); 40*375f7098SHank Liou 41*375f7098SHank Liou auto positiveHysteresis = p.find("positiveHysteresis"); 42*375f7098SHank Liou auto negativeHysteresis = p.find("negativeHysteresis"); 43*375f7098SHank Liou auto positiveHysteresisValue = 0.0; 44*375f7098SHank Liou auto negativeHysteresisValue = 0.0; 45*375f7098SHank Liou if (positiveHysteresis != p.end()) 46*375f7098SHank Liou { 47*375f7098SHank Liou p.at("positiveHysteresis").get_to(positiveHysteresisValue); 48*375f7098SHank Liou } 49*375f7098SHank Liou if (negativeHysteresis != p.end()) 50*375f7098SHank Liou { 51*375f7098SHank Liou p.at("negativeHysteresis").get_to(negativeHysteresisValue); 52*375f7098SHank Liou } 53*375f7098SHank Liou 54*375f7098SHank Liou if (c.type != "stepwise") 55*375f7098SHank Liou { 56d1491724SPatrick Venture p.at("samplePeriod").get_to(c.pidInfo.ts); 57d1491724SPatrick Venture p.at("proportionalCoeff").get_to(c.pidInfo.proportionalCoeff); 58d1491724SPatrick Venture p.at("integralCoeff").get_to(c.pidInfo.integralCoeff); 59903b0427SPatrick Venture p.at("feedFwdOffsetCoeff").get_to(c.pidInfo.feedFwdOffset); 60d1491724SPatrick Venture p.at("feedFwdGainCoeff").get_to(c.pidInfo.feedFwdGain); 61d1491724SPatrick Venture p.at("integralLimit_min").get_to(c.pidInfo.integralLimit.min); 62d1491724SPatrick Venture p.at("integralLimit_max").get_to(c.pidInfo.integralLimit.max); 63d1491724SPatrick Venture p.at("outLim_min").get_to(c.pidInfo.outLim.min); 64d1491724SPatrick Venture p.at("outLim_max").get_to(c.pidInfo.outLim.max); 65d1491724SPatrick Venture p.at("slewNeg").get_to(c.pidInfo.slewNeg); 66d1491724SPatrick Venture p.at("slewPos").get_to(c.pidInfo.slewPos); 67d1491724SPatrick Venture 68*375f7098SHank Liou c.pidInfo.positiveHysteresis = positiveHysteresisValue; 69*375f7098SHank Liou c.pidInfo.negativeHysteresis = negativeHysteresisValue; 70d1491724SPatrick Venture } 71d1491724SPatrick Venture else 72d1491724SPatrick Venture { 73*375f7098SHank Liou p.at("samplePeriod").get_to(c.stepwiseInfo.ts); 74*375f7098SHank Liou p.at("isCeiling").get_to(c.stepwiseInfo.isCeiling); 75*375f7098SHank Liou 76*375f7098SHank Liou for (size_t i = 0; i < ec::maxStepwisePoints; i++) 77*375f7098SHank Liou { 78*375f7098SHank Liou c.stepwiseInfo.reading[i] = 79*375f7098SHank Liou std::numeric_limits<double>::quiet_NaN(); 80*375f7098SHank Liou c.stepwiseInfo.output[i] = std::numeric_limits<double>::quiet_NaN(); 81d1491724SPatrick Venture } 82d1491724SPatrick Venture 83*375f7098SHank Liou auto reading = p.find("reading"); 84*375f7098SHank Liou if (reading != p.end()) 85d1491724SPatrick Venture { 86*375f7098SHank Liou auto r = p.at("reading"); 87*375f7098SHank Liou for (size_t i = 0; i < ec::maxStepwisePoints; i++) 88*375f7098SHank Liou { 89*375f7098SHank Liou auto n = r.find(std::to_string(i)); 90*375f7098SHank Liou if (n != r.end()) 91*375f7098SHank Liou { 92*375f7098SHank Liou r.at(std::to_string(i)).get_to(c.stepwiseInfo.reading[i]); 93d1491724SPatrick Venture } 94*375f7098SHank Liou } 95*375f7098SHank Liou } 96*375f7098SHank Liou 97*375f7098SHank Liou auto output = p.find("output"); 98*375f7098SHank Liou if (output != p.end()) 99d1491724SPatrick Venture { 100*375f7098SHank Liou auto o = p.at("output"); 101*375f7098SHank Liou for (size_t i = 0; i < ec::maxStepwisePoints; i++) 102*375f7098SHank Liou { 103*375f7098SHank Liou auto n = o.find(std::to_string(i)); 104*375f7098SHank Liou if (n != o.end()) 105*375f7098SHank Liou { 106*375f7098SHank Liou o.at(std::to_string(i)).get_to(c.stepwiseInfo.output[i]); 107*375f7098SHank Liou } 108*375f7098SHank Liou } 109*375f7098SHank Liou } 110*375f7098SHank Liou 111*375f7098SHank Liou c.stepwiseInfo.positiveHysteresis = positiveHysteresisValue; 112*375f7098SHank Liou c.stepwiseInfo.negativeHysteresis = negativeHysteresisValue; 113d1491724SPatrick Venture } 114d1491724SPatrick Venture } 115f81f2886SJames Feist } // namespace conf 116d1491724SPatrick Venture 117f81f2886SJames Feist std::pair<std::map<int64_t, conf::PIDConf>, 118f81f2886SJames Feist std::map<int64_t, struct conf::ZoneConfig>> 119d1491724SPatrick Venture buildPIDsFromJson(const json& data) 120d1491724SPatrick Venture { 121d1491724SPatrick Venture // zone -> pids 122f81f2886SJames Feist std::map<int64_t, conf::PIDConf> pidConfig; 123d1491724SPatrick Venture // zone -> configs 124f81f2886SJames Feist std::map<int64_t, struct conf::ZoneConfig> zoneConfig; 125d1491724SPatrick Venture 126d1491724SPatrick Venture /* TODO: if zones is empty, that's invalid. */ 127d1491724SPatrick Venture auto zones = data["zones"]; 128d1491724SPatrick Venture for (const auto& zone : zones) 129d1491724SPatrick Venture { 130d1491724SPatrick Venture int64_t id; 131f81f2886SJames Feist conf::PIDConf thisZone; 132f81f2886SJames Feist struct conf::ZoneConfig thisZoneConfig; 133d1491724SPatrick Venture 134d1491724SPatrick Venture /* TODO: using at() throws a specific exception we can catch */ 135d1491724SPatrick Venture id = zone["id"]; 1363484bedaSJames Feist thisZoneConfig.minThermalOutput = zone["minThermalOutput"]; 137d1491724SPatrick Venture thisZoneConfig.failsafePercent = zone["failsafePercent"]; 138d1491724SPatrick Venture 139d1491724SPatrick Venture auto pids = zone["pids"]; 140d1491724SPatrick Venture for (const auto& pid : pids) 141d1491724SPatrick Venture { 142d1491724SPatrick Venture auto name = pid["name"]; 143f81f2886SJames Feist auto item = pid.get<conf::ControllerInfo>(); 144d1491724SPatrick Venture 145d1491724SPatrick Venture thisZone[name] = item; 146d1491724SPatrick Venture } 147d1491724SPatrick Venture 148d1491724SPatrick Venture pidConfig[id] = thisZone; 149d1491724SPatrick Venture zoneConfig[id] = thisZoneConfig; 150d1491724SPatrick Venture } 151d1491724SPatrick Venture 152d1491724SPatrick Venture return std::make_pair(pidConfig, zoneConfig); 153d1491724SPatrick Venture } 154