blob: d89da92022905bb495660a48eee5db8b35da8cce [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
21#include <map>
22#include <nlohmann/json.hpp>
23#include <tuple>
24
25using json = nlohmann::json;
26
27void 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("feedFwdOffOffsetCoeff").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
71std::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.minThermalRpm = zone["minThermalRpm"];
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}