QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
Common.cc
Go to the documentation of this file.
1#include "Common.h"
2#include "ParameterManager.h"
4
5QGC_LOGGING_CATEGORY(ActuatorsConfigLog, "Vehicle.ActuatorsConfig")
6
7
8void Parameter::parse(const QJsonValue& jsonValue)
9{
10 label = jsonValue["label"].toString();
11 name = jsonValue["name"].toString();
12 indexOffset = jsonValue["index-offset"].toInt(0);
13 QString displayOptionStr = jsonValue["show-as"].toString();
14 if (displayOptionStr == "true-if-positive") {
15 displayOption = DisplayOption::BoolTrueIfPositive;
16 } else if (displayOptionStr == "bitset") {
17 displayOption = DisplayOption::Bitset;
18 } else if (displayOptionStr != "") {
19 qCDebug(ActuatorsConfigLog) << "Unknown param display option (show-as):" << displayOptionStr;
20 }
21 advanced = jsonValue["advanced"].toBool(false);
22}
23
24FactBitset::FactBitset(QObject* parent, Fact* integerFact, int offset)
25 : Fact("", new FactMetaData(FactMetaData::valueTypeBool, "", parent), parent),
26 _integerFact(integerFact), _offset(offset)
27{
28 forceSetRawValue(false); // need to force set an initial bool value so the type is correct
29 onIntegerFactChanged();
30 connect(this, &Fact::rawValueChanged, this, &FactBitset::onThisFactChanged);
31 connect(_integerFact, &Fact::rawValueChanged, this, &FactBitset::onIntegerFactChanged);
32}
33
34void FactBitset::onIntegerFactChanged()
35{
36 if (_ignoreChange) {
37 return;
38 }
39 _ignoreChange = true;
40 // sync to this
41 setRawValue((_integerFact->rawValue().toInt() & (1 << _offset)) != 0);
42 _ignoreChange = false;
43}
44
45void FactBitset::onThisFactChanged()
46{
47 if (_ignoreChange) {
48 return;
49 }
50 _ignoreChange = true;
51 // sync to integer fact
52 int value = _integerFact->rawValue().toInt();
53 if (rawValue().toBool()) {
54 _integerFact->forceSetRawValue(value | (1u << _offset));
55 } else {
56 _integerFact->forceSetRawValue(value & ~(1u << _offset));
57 }
58 _ignoreChange = false;
59}
60
61
62FactFloatAsBool::FactFloatAsBool(QObject* parent, Fact* floatFact)
63 : Fact("", new FactMetaData(FactMetaData::valueTypeBool, "", parent), parent),
64 _floatFact(floatFact)
65{
66 onFloatFactChanged();
67 connect(this, &Fact::rawValueChanged, this, &FactFloatAsBool::onThisFactChanged);
68 connect(_floatFact, &Fact::rawValueChanged, this, &FactFloatAsBool::onFloatFactChanged);
69}
70
71void FactFloatAsBool::onFloatFactChanged()
72{
73 if (_ignoreChange) {
74 return;
75 }
76 _ignoreChange = true;
77 // sync to this
78 forceSetRawValue(_floatFact->rawValue().toFloat() > 0.f);
79 _ignoreChange = false;
80}
81
82void FactFloatAsBool::onThisFactChanged()
83{
84 if (_ignoreChange) {
85 return;
86 }
87 _ignoreChange = true;
88 // sync to float fact
89 float value = _floatFact->rawValue().toFloat();
90 if (rawValue().toBool()) {
91 _floatFact->forceSetRawValue(std::abs(value));
92 } else {
93 _floatFact->forceSetRawValue(-std::abs(value));
94 }
95 _ignoreChange = false;
96}
97
98Condition::Condition(const QString &condition, ParameterManager* parameterManager, const QString& label)
99{
100 _label = label;
101
102 const bool debugEnabled = ActuatorsConfigLog().isDebugEnabled();
103 QString logPrefix;
104 if (debugEnabled) {
105 logPrefix = QStringLiteral("Condition");
106 if (!label.isEmpty()) {
107 logPrefix += QStringLiteral(" [%1]").arg(label);
108 }
109 }
110
111 QRegularExpression re("^([0-9A-Za-z_-]+)([\\!=<>]+)(-?\\d+)$");
112 QRegularExpressionMatch match = re.match(condition);
113 if (condition.isEmpty()) {
114 _operation = Operation::AlwaysTrue;
115 _alwaysTrueReason = QStringLiteral("empty/default");
116 if (debugEnabled) {
117 qCDebug(ActuatorsConfigLog) << logPrefix + ": <empty> (defaults to true)";
118 }
119 } else if (condition == "true") {
120 _operation = Operation::AlwaysTrue;
121 _alwaysTrueReason = QStringLiteral("literal true");
122 if (debugEnabled) {
123 qCDebug(ActuatorsConfigLog) << logPrefix + ": true";
124 }
125 } else if (condition == "false") {
126 _operation = Operation::AlwaysFalse;
127 if (debugEnabled) {
128 qCDebug(ActuatorsConfigLog) << logPrefix + ": false";
129 }
130 } else if (match.hasMatch()) {
131 _parameter = match.captured(1);
132 QString operation = match.captured(2);
133 if (operation == ">") {
134 _operation = Operation::GreaterThan;
135 } else if (operation == ">=") {
136 _operation = Operation::GreaterEqual;
137 } else if (operation == "==") {
138 _operation = Operation::Equal;
139 } else if (operation == "!=") {
140 _operation = Operation::NotEqual;
141 } else if (operation == "<") {
142 _operation = Operation::LessThan;
143 } else if (operation == "<=") {
144 _operation = Operation::LessEqual;
145 } else {
146 _operation = Operation::AlwaysTrue;
147 _alwaysTrueReason = QStringLiteral("unknown operator '%1'").arg(operation);
148 qCWarning(ActuatorsConfigLog) << "Unknown condition operation: " << operation;
149 }
150 _value = match.captured(3).toInt();
151
152 if (debugEnabled) {
153 qCDebug(ActuatorsConfigLog) << logPrefix + QStringLiteral(": Param:%1 op:%2 value:%3").arg(_parameter, operation).arg(_value);
154 }
155
156 if (parameterManager->parameterExists(ParameterManager::defaultComponentId, _parameter)) {
157 Fact* param = parameterManager->getParameter(ParameterManager::defaultComponentId, _parameter);
158 if (param->type() == FactMetaData::ValueType_t::valueTypeBool ||
160 _fact = param;
161 } else if (debugEnabled) {
162 qCDebug(ActuatorsConfigLog) << logPrefix + QStringLiteral(": Unsupported param type:%1").arg((int)param->type());
163 }
164 } else if (debugEnabled) {
165 qCDebug(ActuatorsConfigLog) << logPrefix + QStringLiteral(": Param does not exist:%1").arg(_parameter);
166 }
167 } else {
168 _alwaysTrueReason = QStringLiteral("unrecognized '%1'").arg(condition);
169 qCWarning(ActuatorsConfigLog) << "Condition"
170 << (label.isEmpty() ? QString() : QStringLiteral(" [%1]").arg(label))
171 << QStringLiteral(": Unrecognized condition string '%1', defaulting to true").arg(condition);
172 }
173
174}
175
177{
178 if (_operation == Operation::AlwaysTrue) {
179 if (ActuatorsConfigLog().isDebugEnabled()) {
180 QString logPrefix = _label.isEmpty() ? QStringLiteral("Evaluating condition") : QStringLiteral("Evaluating [%1]").arg(_label);
181 qCDebug(ActuatorsConfigLog) << logPrefix << "-> true (" << _alwaysTrueReason << ")";
182 }
183 return true;
184 }
185
186 if (_operation == Operation::AlwaysFalse) {
187 if (ActuatorsConfigLog().isDebugEnabled()) {
188 QString logPrefix = _label.isEmpty() ? QStringLiteral("Evaluating condition") : QStringLiteral("Evaluating [%1]").arg(_label);
189 qCDebug(ActuatorsConfigLog) << logPrefix << "-> false (literal false)";
190 }
191 return false;
192 }
193
194 if (!_fact) {
195 if (ActuatorsConfigLog().isDebugEnabled()) {
196 QString logPrefix = _label.isEmpty() ? QStringLiteral("Evaluating condition") : QStringLiteral("Evaluating [%1]").arg(_label);
197 qCDebug(ActuatorsConfigLog) << logPrefix << "-> false (parameter" << _parameter << "unavailable for evaluation)";
198 }
199 return false;
200 }
201
202 int32_t paramValue = _fact->rawValue().toInt();
203 bool result = false;
204 QString operation;
205
206 switch (_operation) {
208 result = paramValue > _value;
209 operation = ">";
210 break;
212 result = paramValue >= _value;
213 operation = ">=";
214 break;
215 case Operation::Equal:
216 result = paramValue == _value;
217 operation = "==";
218 break;
220 result = paramValue != _value;
221 operation = "!=";
222 break;
224 result = paramValue < _value;
225 operation = "<";
226 break;
228 result = paramValue <= _value;
229 operation = "<=";
230 break;
231 default:
232 qCWarning(ActuatorsConfigLog) << "Unexpected operation type in condition evaluation";
233 break;
234 }
235
236 if (ActuatorsConfigLog().isDebugEnabled()) {
237 QString logPrefix = _label.isEmpty() ? QStringLiteral("Evaluating condition") : QStringLiteral("Evaluating [%1]").arg(_label);
238 qCDebug(ActuatorsConfigLog) << logPrefix << "->" << (result ? "true" : "false")
239 << "(" << _parameter << "=" << paramValue << operation << _value << ")";
240 }
241 return result;
242}
243
245{
246 if (type == "motor") {
248 } else if (type == "servo") {
250 }
252}
#define QGC_LOGGING_CATEGORY(name, categoryStr)
bool evaluate() const
Definition Common.cc:176
Condition()=default
FactBitset(QObject *parent, Fact *integerFact, int offset)
Definition Common.cc:24
FactFloatAsBool(QObject *parent, Fact *floatFact)
Definition Common.cc:62
A Fact is used to hold a single value within the system.
Definition Fact.h:19
void rawValueChanged(const QVariant &value)
bool parameterExists(int componentId, const QString &paramName) const
Fact * getParameter(int componentId, const QString &paramName)
static constexpr int defaultComponentId
static Type typeFromStr(const QString &type)
Definition Common.cc:244