1 /** 2 * Copyright 2019 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "pid/buildjson.hpp" 18 19 #include "conf.hpp" 20 21 #include <map> 22 #include <nlohmann/json.hpp> 23 #include <tuple> 24 25 using json = nlohmann::json; 26 27 namespace conf 28 { 29 void from_json(const json& j, conf::ControllerInfo& c) 30 { 31 j.at("type").get_to(c.type); 32 j.at("inputs").get_to(c.inputs); 33 j.at("setpoint").get_to(c.setpoint); 34 35 /* TODO: We need to handle parsing other PID controller configurations. 36 * We can do that by checking for different keys and making the decision 37 * accordingly. 38 */ 39 auto p = j.at("pid"); 40 p.at("samplePeriod").get_to(c.pidInfo.ts); 41 p.at("proportionalCoeff").get_to(c.pidInfo.proportionalCoeff); 42 p.at("integralCoeff").get_to(c.pidInfo.integralCoeff); 43 p.at("feedFwdOffsetCoeff").get_to(c.pidInfo.feedFwdOffset); 44 p.at("feedFwdGainCoeff").get_to(c.pidInfo.feedFwdGain); 45 p.at("integralLimit_min").get_to(c.pidInfo.integralLimit.min); 46 p.at("integralLimit_max").get_to(c.pidInfo.integralLimit.max); 47 p.at("outLim_min").get_to(c.pidInfo.outLim.min); 48 p.at("outLim_max").get_to(c.pidInfo.outLim.max); 49 p.at("slewNeg").get_to(c.pidInfo.slewNeg); 50 p.at("slewPos").get_to(c.pidInfo.slewPos); 51 52 auto positiveHysteresis = p.find("positiveHysteresis"); 53 if (positiveHysteresis == p.end()) 54 { 55 c.pidInfo.positiveHysteresis = 0.0; 56 } 57 else 58 { 59 j.at("positiveHysteresis").get_to(c.pidInfo.positiveHysteresis); 60 } 61 62 auto negativeHysteresis = p.find("negativeHysteresis"); 63 if (negativeHysteresis == p.end()) 64 { 65 c.pidInfo.negativeHysteresis = 0.0; 66 } 67 else 68 { 69 j.at("negativeHysteresis").get_to(c.pidInfo.negativeHysteresis); 70 } 71 } 72 } // namespace conf 73 74 std::pair<std::map<int64_t, conf::PIDConf>, 75 std::map<int64_t, struct conf::ZoneConfig>> 76 buildPIDsFromJson(const json& data) 77 { 78 // zone -> pids 79 std::map<int64_t, conf::PIDConf> pidConfig; 80 // zone -> configs 81 std::map<int64_t, struct conf::ZoneConfig> zoneConfig; 82 83 /* TODO: if zones is empty, that's invalid. */ 84 auto zones = data["zones"]; 85 for (const auto& zone : zones) 86 { 87 int64_t id; 88 conf::PIDConf thisZone; 89 struct conf::ZoneConfig thisZoneConfig; 90 91 /* TODO: using at() throws a specific exception we can catch */ 92 id = zone["id"]; 93 thisZoneConfig.minThermalOutput = zone["minThermalOutput"]; 94 thisZoneConfig.failsafePercent = zone["failsafePercent"]; 95 96 auto pids = zone["pids"]; 97 for (const auto& pid : pids) 98 { 99 auto name = pid["name"]; 100 auto item = pid.get<conf::ControllerInfo>(); 101 102 thisZone[name] = item; 103 } 104 105 pidConfig[id] = thisZone; 106 zoneConfig[id] = thisZoneConfig; 107 } 108 109 return std::make_pair(pidConfig, zoneConfig); 110 } 111