blob: e078fdb83a10e96303ddd040255c86bf9b36f56e [file] [log] [blame]
Patrick Ventured1491722019-02-08 14:37:45 -08001/**
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
Patrick Ventured1491722019-02-08 14:37:45 -080021#include <nlohmann/json.hpp>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070022
23#include <map>
Patrick Ventured1491722019-02-08 14:37:45 -080024#include <tuple>
25
Patrick Venturea0764872020-08-08 07:48:43 -070026namespace pid_control
27{
28
Patrick Ventured1491722019-02-08 14:37:45 -080029using json = nlohmann::json;
30
James Feistf81f2882019-02-26 11:26:36 -080031namespace conf
32{
33void from_json(const json& j, conf::ControllerInfo& c)
Patrick Ventured1491722019-02-08 14:37:45 -080034{
35 j.at("type").get_to(c.type);
36 j.at("inputs").get_to(c.inputs);
37 j.at("setpoint").get_to(c.setpoint);
38
39 /* TODO: We need to handle parsing other PID controller configurations.
40 * We can do that by checking for different keys and making the decision
41 * accordingly.
42 */
43 auto p = j.at("pid");
Patrick Ventured1491722019-02-08 14:37:45 -080044
45 auto positiveHysteresis = p.find("positiveHysteresis");
Hank Liou375f7092019-03-29 20:15:42 +080046 auto negativeHysteresis = p.find("negativeHysteresis");
47 auto positiveHysteresisValue = 0.0;
48 auto negativeHysteresisValue = 0.0;
49 if (positiveHysteresis != p.end())
Patrick Ventured1491722019-02-08 14:37:45 -080050 {
Hank Liou375f7092019-03-29 20:15:42 +080051 p.at("positiveHysteresis").get_to(positiveHysteresisValue);
Patrick Ventured1491722019-02-08 14:37:45 -080052 }
Hank Liou375f7092019-03-29 20:15:42 +080053 if (negativeHysteresis != p.end())
Patrick Ventured1491722019-02-08 14:37:45 -080054 {
Hank Liou375f7092019-03-29 20:15:42 +080055 p.at("negativeHysteresis").get_to(negativeHysteresisValue);
Patrick Ventured1491722019-02-08 14:37:45 -080056 }
57
Hank Liou375f7092019-03-29 20:15:42 +080058 if (c.type != "stepwise")
Patrick Ventured1491722019-02-08 14:37:45 -080059 {
Hank Liou375f7092019-03-29 20:15:42 +080060 p.at("samplePeriod").get_to(c.pidInfo.ts);
61 p.at("proportionalCoeff").get_to(c.pidInfo.proportionalCoeff);
62 p.at("integralCoeff").get_to(c.pidInfo.integralCoeff);
63 p.at("feedFwdOffsetCoeff").get_to(c.pidInfo.feedFwdOffset);
64 p.at("feedFwdGainCoeff").get_to(c.pidInfo.feedFwdGain);
65 p.at("integralLimit_min").get_to(c.pidInfo.integralLimit.min);
66 p.at("integralLimit_max").get_to(c.pidInfo.integralLimit.max);
67 p.at("outLim_min").get_to(c.pidInfo.outLim.min);
68 p.at("outLim_max").get_to(c.pidInfo.outLim.max);
69 p.at("slewNeg").get_to(c.pidInfo.slewNeg);
70 p.at("slewPos").get_to(c.pidInfo.slewPos);
71
72 c.pidInfo.positiveHysteresis = positiveHysteresisValue;
73 c.pidInfo.negativeHysteresis = negativeHysteresisValue;
Patrick Ventured1491722019-02-08 14:37:45 -080074 }
75 else
76 {
Hank Liou375f7092019-03-29 20:15:42 +080077 p.at("samplePeriod").get_to(c.stepwiseInfo.ts);
78 p.at("isCeiling").get_to(c.stepwiseInfo.isCeiling);
79
80 for (size_t i = 0; i < ec::maxStepwisePoints; i++)
81 {
82 c.stepwiseInfo.reading[i] =
83 std::numeric_limits<double>::quiet_NaN();
84 c.stepwiseInfo.output[i] = std::numeric_limits<double>::quiet_NaN();
85 }
86
87 auto reading = p.find("reading");
88 if (reading != p.end())
89 {
90 auto r = p.at("reading");
91 for (size_t i = 0; i < ec::maxStepwisePoints; i++)
92 {
93 auto n = r.find(std::to_string(i));
94 if (n != r.end())
95 {
96 r.at(std::to_string(i)).get_to(c.stepwiseInfo.reading[i]);
97 }
98 }
99 }
100
101 auto output = p.find("output");
102 if (output != p.end())
103 {
104 auto o = p.at("output");
105 for (size_t i = 0; i < ec::maxStepwisePoints; i++)
106 {
107 auto n = o.find(std::to_string(i));
108 if (n != o.end())
109 {
110 o.at(std::to_string(i)).get_to(c.stepwiseInfo.output[i]);
111 }
112 }
113 }
114
115 c.stepwiseInfo.positiveHysteresis = positiveHysteresisValue;
116 c.stepwiseInfo.negativeHysteresis = negativeHysteresisValue;
Patrick Ventured1491722019-02-08 14:37:45 -0800117 }
118}
James Feistf81f2882019-02-26 11:26:36 -0800119} // namespace conf
Patrick Ventured1491722019-02-08 14:37:45 -0800120
Patrick Venture1df9e872020-10-08 15:35:01 -0700121std::pair<std::map<int64_t, conf::PIDConf>, std::map<int64_t, conf::ZoneConfig>>
Patrick Ventured1491722019-02-08 14:37:45 -0800122 buildPIDsFromJson(const json& data)
123{
124 // zone -> pids
James Feistf81f2882019-02-26 11:26:36 -0800125 std::map<int64_t, conf::PIDConf> pidConfig;
Patrick Ventured1491722019-02-08 14:37:45 -0800126 // zone -> configs
Patrick Venture1df9e872020-10-08 15:35:01 -0700127 std::map<int64_t, conf::ZoneConfig> zoneConfig;
Patrick Ventured1491722019-02-08 14:37:45 -0800128
129 /* TODO: if zones is empty, that's invalid. */
130 auto zones = data["zones"];
131 for (const auto& zone : zones)
132 {
133 int64_t id;
James Feistf81f2882019-02-26 11:26:36 -0800134 conf::PIDConf thisZone;
Patrick Venture1df9e872020-10-08 15:35:01 -0700135 conf::ZoneConfig thisZoneConfig;
Patrick Ventured1491722019-02-08 14:37:45 -0800136
137 /* TODO: using at() throws a specific exception we can catch */
138 id = zone["id"];
James Feist3484bed2019-02-25 13:28:18 -0800139 thisZoneConfig.minThermalOutput = zone["minThermalOutput"];
Patrick Ventured1491722019-02-08 14:37:45 -0800140 thisZoneConfig.failsafePercent = zone["failsafePercent"];
141
142 auto pids = zone["pids"];
143 for (const auto& pid : pids)
144 {
145 auto name = pid["name"];
James Feistf81f2882019-02-26 11:26:36 -0800146 auto item = pid.get<conf::ControllerInfo>();
Patrick Ventured1491722019-02-08 14:37:45 -0800147
148 thisZone[name] = item;
149 }
150
151 pidConfig[id] = thisZone;
152 zoneConfig[id] = thisZoneConfig;
153 }
154
155 return std::make_pair(pidConfig, zoneConfig);
156}
Patrick Venturea0764872020-08-08 07:48:43 -0700157
158} // namespace pid_control