Browse Source

actuators: update output function parameter metadata

- remove the mixer functions that are unused with the current configration
  (e.g. if 4 motors -> remove motors 5-N)
- use the specific labels
QGC4.4
Beat Küng 3 years ago
parent
commit
d78b21cb5e
  1. 83
      src/Vehicle/Actuators/Actuators.cc
  2. 3
      src/Vehicle/Actuators/Actuators.h
  3. 29
      src/Vehicle/Actuators/Mixer.cc
  4. 4
      src/Vehicle/Actuators/Mixer.h

83
src/Vehicle/Actuators/Actuators.cc

@ -239,7 +239,7 @@ void Actuators::parametersChanged()
_actuatorTest.updateFunctions(actuators); _actuatorTest.updateFunctions(actuators);
// check if there are required functions, but not set on any output // check if there are required functions, but not set on any output
QSet<int> requiredFunctions = _mixer.requiredFunctions(); QSet<int> requiredFunctions = _mixer.getFunctions(true);
_hasUnsetRequiredFunctions = false; _hasUnsetRequiredFunctions = false;
for (int requiredFunction : requiredFunctions) { for (int requiredFunction : requiredFunctions) {
if (uniqueConfiguredFunctions.find(requiredFunction) == uniqueConfiguredFunctions.end()) { if (uniqueConfiguredFunctions.find(requiredFunction) == uniqueConfiguredFunctions.end()) {
@ -248,11 +248,92 @@ void Actuators::parametersChanged()
} }
emit hasUnsetRequiredFunctionsChanged(); emit hasUnsetRequiredFunctionsChanged();
updateFunctionMetadata();
updateActuatorActions(); updateActuatorActions();
updateGeometryImage(); updateGeometryImage();
} }
void Actuators::updateFunctionMetadata()
{
// Update the function parameter metadata:
// - remove the mixer functions that are unused with the current configration (e.g. if 4 motors -> remove motors 5-N)
// - use the specific labels
QSet<int> usedMixerFunctions = _mixer.getFunctions(false);
QMap<int, QString> usedMixerLabels;
for (int usedMixerFunction : usedMixerFunctions) {
usedMixerLabels[usedMixerFunction] = _mixer.getSpecificLabelForFunction(usedMixerFunction);
}
if (_usedMixerLabels == usedMixerLabels) {
// no update required
return;
}
_usedMixerLabels = usedMixerLabels;
// Get the unused mixer functions
QSet<int> removedMixerFunctions;
for(Mixer::ActuatorTypes::const_iterator iter = _mixer.actuatorTypes().constBegin();
iter != _mixer.actuatorTypes().constEnd(); ++iter) {
if (iter.key() == "DEFAULT")
continue;
for (int i = iter.value().functionMin; i <= iter.value().functionMax; ++i) {
if (!usedMixerFunctions.contains(i)) {
removedMixerFunctions.insert(i);
}
}
}
// Now update all function facts (we need to treat them individually, as some might have extra functions)
for (int groupIdx = 0; groupIdx < _actuatorOutputs->count(); groupIdx++) {
ActuatorOutput* group = qobject_cast<ActuatorOutput*>(_actuatorOutputs->get(groupIdx));
group->forEachOutputFunction([&](ActuatorOutputSubgroup* subgroup, ChannelConfigInstance*, Fact* fact) {
QStringList enumStrings = fact->enumStrings();
if (!enumStrings.empty()) {
QVariantList enumValues = fact->enumValues();
// Replace or add
for (int usedMixerFunction : usedMixerFunctions) {
QString label = usedMixerLabels[usedMixerFunction];
int index = enumValues.indexOf(usedMixerFunction);
if (index == -1) {
// Insert at the right place
bool inserted = false;
for (index = 0; index < enumValues.count() && !inserted; ++index) {
if (enumValues[index].toInt() > usedMixerFunction) {
enumValues.insert(index, usedMixerFunction);
enumStrings.insert(index, label);
inserted = true;
}
}
if (!inserted) {
enumValues.append(usedMixerFunction);
enumStrings.append(label);
}
} else {
enumStrings[index] = label;
}
}
// Remove
for (int removedMixerFunction : removedMixerFunctions) {
int index = enumValues.indexOf(removedMixerFunction);
if (index != -1) {
enumValues.removeAt(index);
enumStrings.removeAt(index);
}
}
fact->setEnumInfo(enumStrings, enumValues);
}
});
}
}
void Actuators::updateActuatorActions() void Actuators::updateActuatorActions()
{ {
_actuatorActions->clearAndDeleteContents(); _actuatorActions->clearAndDeleteContents();

3
src/Vehicle/Actuators/Actuators.h

@ -106,6 +106,8 @@ private:
void highlightActuators(bool highlight); void highlightActuators(bool highlight);
void updateFunctionMetadata();
QSet<Fact*> _subscribedFacts{}; QSet<Fact*> _subscribedFacts{};
QJsonDocument _jsonMetadata; QJsonDocument _jsonMetadata;
bool _init{false}; bool _init{false};
@ -120,5 +122,6 @@ private:
bool _imageRefreshFlag{false}; ///< indicator to QML to reload the image bool _imageRefreshFlag{false}; ///< indicator to QML to reload the image
int _selectedActuatorOutput{0}; int _selectedActuatorOutput{0};
Vehicle* _vehicle{nullptr}; Vehicle* _vehicle{nullptr};
QMap<int, QString> _usedMixerLabels;
}; };

29
src/Vehicle/Actuators/Mixer.cc

@ -317,7 +317,7 @@ void Mixers::update()
} }
if (itemLabelPrefix != "") { if (itemLabelPrefix != "") {
label = itemLabelPrefix + " (" + label + ")"; label = itemLabelPrefix + " (" + label + ")";
_functionsSpecificLabel[actuatorFunction] = label; _functionsSpecificLabel[actuatorFunction] = itemLabelPrefix;
} }
} }
auto factAdded = [this](Function function, Fact* fact) { auto factAdded = [this](Function function, Fact* fact) {
@ -348,21 +348,38 @@ void Mixers::update()
QString Mixers::getSpecificLabelForFunction(int function) const QString Mixers::getSpecificLabelForFunction(int function) const
{ {
// Try to get it from the actuator type param // Try to get it from the actuator type param
for (int mixerGroupIdx = 0; mixerGroupIdx < _groups->count(); ++mixerGroupIdx) { Fact* typeFact = nullptr;
for (int mixerGroupIdx = 0; !typeFact && mixerGroupIdx < _groups->count(); ++mixerGroupIdx) {
Mixer::MixerConfigGroup* mixerGroup = _groups->value<Mixer::MixerConfigGroup*>(mixerGroupIdx); Mixer::MixerConfigGroup* mixerGroup = _groups->value<Mixer::MixerConfigGroup*>(mixerGroupIdx);
for (int mixerChannelIdx = 0; mixerChannelIdx < mixerGroup->channels()->count(); ++mixerChannelIdx) { for (int mixerChannelIdx = 0; !typeFact && mixerChannelIdx < mixerGroup->channels()->count(); ++mixerChannelIdx) {
Mixer::MixerChannel* mixerChannel = mixerGroup->channels()->value<Mixer::MixerChannel*>(mixerChannelIdx); Mixer::MixerChannel* mixerChannel = mixerGroup->channels()->value<Mixer::MixerChannel*>(mixerChannelIdx);
if (mixerChannel->actuatorFunction() != function) { if (mixerChannel->actuatorFunction() != function) {
continue; continue;
} }
Fact* typeFact = mixerChannel->getFact(Function::Type); typeFact = mixerChannel->getFact(Function::Type);
}
}
if (typeFact) { if (typeFact) {
// Now check if we have multiple functions configured with the same type.
// If so, add the function label to disambiguate
for (int mixerGroupIdx = 0; mixerGroupIdx < _groups->count(); ++mixerGroupIdx) {
Mixer::MixerConfigGroup* mixerGroup = _groups->value<Mixer::MixerConfigGroup*>(mixerGroupIdx);
for (int mixerChannelIdx = 0; mixerChannelIdx < mixerGroup->channels()->count(); ++mixerChannelIdx) {
Mixer::MixerChannel* mixerChannel = mixerGroup->channels()->value<Mixer::MixerChannel*>(mixerChannelIdx);
if (mixerChannel->actuatorFunction() == function) {
continue;
}
Fact* typeFactOther = mixerChannel->getFact(Function::Type);
if (typeFactOther && typeFactOther->rawValue() == typeFact->rawValue()) {
return typeFact->enumOrValueString() + " (" + _functions.value(function).label +")"; return typeFact->enumOrValueString() + " (" + _functions.value(function).label +")";
} }
} }
} }
return typeFact->enumOrValueString();
}
const auto iter = _functionsSpecificLabel.find(function); const auto iter = _functionsSpecificLabel.find(function);
if (iter == _functionsSpecificLabel.end()) { if (iter == _functionsSpecificLabel.end()) {
@ -371,12 +388,12 @@ QString Mixers::getSpecificLabelForFunction(int function) const
return *iter; return *iter;
} }
QSet<int> Mixers::requiredFunctions() const QSet<int> Mixers::getFunctions(bool requiredOnly) const
{ {
QSet<int> ret; QSet<int> ret;
for (int mixerGroupIdx = 0; mixerGroupIdx < _groups->count(); ++mixerGroupIdx) { for (int mixerGroupIdx = 0; mixerGroupIdx < _groups->count(); ++mixerGroupIdx) {
Mixer::MixerConfigGroup* mixerGroup = _groups->value<Mixer::MixerConfigGroup*>(mixerGroupIdx); Mixer::MixerConfigGroup* mixerGroup = _groups->value<Mixer::MixerConfigGroup*>(mixerGroupIdx);
if (mixerGroup->group().required) { if (!requiredOnly || mixerGroup->group().required) {
for (int mixerChannelIdx = 0; mixerChannelIdx < mixerGroup->channels()->count(); ++mixerChannelIdx) { for (int mixerChannelIdx = 0; mixerChannelIdx < mixerGroup->channels()->count(); ++mixerChannelIdx) {
const Mixer::MixerChannel* mixerChannel = mixerGroup->channels()->value<Mixer::MixerChannel*>(mixerChannelIdx); const Mixer::MixerChannel* mixerChannel = mixerGroup->channels()->value<Mixer::MixerChannel*>(mixerChannelIdx);
if (mixerChannel->actuatorFunction() != 0) { if (mixerChannel->actuatorFunction() != 0) {

4
src/Vehicle/Actuators/Mixer.h

@ -321,9 +321,9 @@ public:
QString getSpecificLabelForFunction(int function) const; QString getSpecificLabelForFunction(int function) const;
/** /**
* Get the set of all required actuator functions * Get the set of all (required) actuator functions
*/ */
QSet<int> requiredFunctions() const; QSet<int> getFunctions(bool requiredOnly) const;
QString configuredType() const; QString configuredType() const;

Loading…
Cancel
Save