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 void from_json(const json& j, ControllerInfo& c) 28 { 29 j.at("type").get_to(c.type); 30 j.at("inputs").get_to(c.inputs); 31 j.at("setpoint").get_to(c.setpoint); 32 33 /* TODO: We need to handle parsing other PID controller configurations. 34 * We can do that by checking for different keys and making the decision 35 * accordingly. 36 */ 37 auto p = j.at("pid"); 38 p.at("samplePeriod").get_to(c.pidInfo.ts); 39 p.at("proportionalCoeff").get_to(c.pidInfo.proportionalCoeff); 40 p.at("integralCoeff").get_to(c.pidInfo.integralCoeff); 41 p.at("feedFwdOffsetCoeff").get_to(c.pidInfo.feedFwdOffset); 42 p.at("feedFwdGainCoeff").get_to(c.pidInfo.feedFwdGain); 43 p.at("integralLimit_min").get_to(c.pidInfo.integralLimit.min); 44 p.at("integralLimit_max").get_to(c.pidInfo.integralLimit.max); 45 p.at("outLim_min").get_to(c.pidInfo.outLim.min); 46 p.at("outLim_max").get_to(c.pidInfo.outLim.max); 47 p.at("slewNeg").get_to(c.pidInfo.slewNeg); 48 p.at("slewPos").get_to(c.pidInfo.slewPos); 49 50 auto positiveHysteresis = p.find("positiveHysteresis"); 51 if (positiveHysteresis == p.end()) 52 { 53 c.pidInfo.positiveHysteresis = 0.0; 54 } 55 else 56 { 57 j.at("positiveHysteresis").get_to(c.pidInfo.positiveHysteresis); 58 } 59 60 auto negativeHysteresis = p.find("negativeHysteresis"); 61 if (negativeHysteresis == p.end()) 62 { 63 c.pidInfo.negativeHysteresis = 0.0; 64 } 65 else 66 { 67 j.at("negativeHysteresis").get_to(c.pidInfo.negativeHysteresis); 68 } 69 } 70 71 std::pair<std::map<int64_t, PIDConf>, std::map<int64_t, struct ZoneConfig>> 72 buildPIDsFromJson(const json& data) 73 { 74 // zone -> pids 75 std::map<int64_t, PIDConf> pidConfig; 76 // zone -> configs 77 std::map<int64_t, struct ZoneConfig> zoneConfig; 78 79 /* TODO: if zones is empty, that's invalid. */ 80 auto zones = data["zones"]; 81 for (const auto& zone : zones) 82 { 83 int64_t id; 84 PIDConf thisZone; 85 struct ZoneConfig thisZoneConfig; 86 87 /* TODO: using at() throws a specific exception we can catch */ 88 id = zone["id"]; 89 thisZoneConfig.minThermalOutput = zone["minThermalOutput"]; 90 thisZoneConfig.failsafePercent = zone["failsafePercent"]; 91 92 auto pids = zone["pids"]; 93 for (const auto& pid : pids) 94 { 95 auto name = pid["name"]; 96 auto item = pid.get<ControllerInfo>(); 97 98 thisZone[name] = item; 99 } 100 101 pidConfig[id] = thisZone; 102 zoneConfig[id] = thisZoneConfig; 103 } 104 105 return std::make_pair(pidConfig, zoneConfig); 106 } 107