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