mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-12-02 10:24:11 +01:00
Merge remote-tracking branch 'origin/next' into laurent/OP-1337_French_translations_updates
This commit is contained in:
commit
7ca288901f
@ -138,6 +138,12 @@
|
|||||||
<property name="columnCount">
|
<property name="columnCount">
|
||||||
<number>12</number>
|
<number>12</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::NoSelection</enum>
|
||||||
|
</property>
|
||||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||||
<number>50</number>
|
<number>50</number>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
@ -101,7 +101,7 @@ SixPointCalibrationModel::SixPointCalibrationModel(QObject *parent) :
|
|||||||
revoCalibration = RevoCalibration::GetInstance(getObjectManager());
|
revoCalibration = RevoCalibration::GetInstance(getObjectManager());
|
||||||
Q_ASSERT(revoCalibration);
|
Q_ASSERT(revoCalibration);
|
||||||
|
|
||||||
auxMagSettings = AuxMagSettings::GetInstance(getObjectManager());
|
auxMagSettings = AuxMagSettings::GetInstance(getObjectManager());
|
||||||
Q_ASSERT(auxMagSettings);
|
Q_ASSERT(auxMagSettings);
|
||||||
|
|
||||||
accelGyroSettings = AccelGyroSettings::GetInstance(getObjectManager());
|
accelGyroSettings = AccelGyroSettings::GetInstance(getObjectManager());
|
||||||
@ -440,7 +440,7 @@ void SixPointCalibrationModel::compute()
|
|||||||
double Be_length;
|
double Be_length;
|
||||||
|
|
||||||
RevoCalibration::DataFields revoCalibrationData = revoCalibration->getData();
|
RevoCalibration::DataFields revoCalibrationData = revoCalibration->getData();
|
||||||
AuxMagSettings::DataFields auxCalibrationData = auxMagSettings->getData();
|
AuxMagSettings::DataFields auxCalibrationData = auxMagSettings->getData();
|
||||||
AccelGyroSettings::DataFields accelGyroSettingsData = accelGyroSettings->getData();
|
AccelGyroSettings::DataFields accelGyroSettingsData = accelGyroSettings->getData();
|
||||||
|
|
||||||
HomeLocation::DataFields homeLocationData = homeLocation->getData();
|
HomeLocation::DataFields homeLocationData = homeLocation->getData();
|
||||||
@ -521,8 +521,8 @@ void SixPointCalibrationModel::compute()
|
|||||||
if (good_calibration) {
|
if (good_calibration) {
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
if (calibratingMag) {
|
if (calibratingMag) {
|
||||||
result.revoCalibrationData = revoCalibrationData;
|
result.revoCalibrationData = revoCalibrationData;
|
||||||
result.auxMagSettingsData = auxCalibrationData;
|
result.auxMagSettingsData = auxCalibrationData;
|
||||||
displayInstructions(tr("Magnetometer calibration completed successfully."), WizardModel::Success);
|
displayInstructions(tr("Magnetometer calibration completed successfully."), WizardModel::Success);
|
||||||
}
|
}
|
||||||
if (calibratingAccel) {
|
if (calibratingAccel) {
|
||||||
|
@ -92,14 +92,14 @@ public:
|
|||||||
UAVObject::Metadata accelStateMetadata;
|
UAVObject::Metadata accelStateMetadata;
|
||||||
UAVObject::Metadata magSensorMetadata;
|
UAVObject::Metadata magSensorMetadata;
|
||||||
UAVObject::Metadata auxMagSensorMetadata;
|
UAVObject::Metadata auxMagSensorMetadata;
|
||||||
AuxMagSettings::DataFields auxMagSettings;
|
AuxMagSettings::DataFields auxMagSettings;
|
||||||
RevoCalibration::DataFields revoCalibrationData;
|
RevoCalibration::DataFields revoCalibrationData;
|
||||||
AccelGyroSettings::DataFields accelGyroSettingsData;
|
AccelGyroSettings::DataFields accelGyroSettingsData;
|
||||||
} Memento;
|
} Memento;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
RevoCalibration::DataFields revoCalibrationData;
|
RevoCalibration::DataFields revoCalibrationData;
|
||||||
AuxMagSettings::DataFields auxMagSettingsData;
|
AuxMagSettings::DataFields auxMagSettingsData;
|
||||||
AccelGyroSettings::DataFields accelGyroSettingsData;
|
AccelGyroSettings::DataFields accelGyroSettingsData;
|
||||||
} Result;
|
} Result;
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*
|
*
|
||||||
* @file configmultirotorwidget.cpp
|
* @file configcustomwidget.cpp
|
||||||
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
||||||
* @addtogroup GCSPlugins GCS Plugins
|
* @addtogroup GCSPlugins GCS Plugins
|
||||||
* @{
|
* @{
|
||||||
* @addtogroup ConfigPlugin Config Plugin
|
* @addtogroup ConfigPlugin Config Plugin
|
||||||
* @{
|
* @{
|
||||||
* @brief ccpm configuration panel
|
* @brief custom configuration panel
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/*
|
/*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -45,6 +45,84 @@ QStringList ConfigCustomWidget::getChannelDescriptions()
|
|||||||
for (int i = 0; i < (int)VehicleConfig::CHANNEL_NUMELEM; i++) {
|
for (int i = 0; i < (int)VehicleConfig::CHANNEL_NUMELEM; i++) {
|
||||||
channelDesc.append(QString("-"));
|
channelDesc.append(QString("-"));
|
||||||
}
|
}
|
||||||
|
// get the gui config data
|
||||||
|
GUIConfigDataUnion configData = getConfigData();
|
||||||
|
customGUISettingsStruct custom = configData.custom;
|
||||||
|
|
||||||
|
if (custom.Motor1 > 0 && custom.Motor1 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Motor1 - 1] = QString("Motor1");
|
||||||
|
}
|
||||||
|
if (custom.Motor2 > 0 && custom.Motor2 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Motor2 - 1] = QString("Motor2");
|
||||||
|
}
|
||||||
|
if (custom.Motor3 > 0 && custom.Motor3 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Motor3 - 1] = QString("Motor3");
|
||||||
|
}
|
||||||
|
if (custom.Motor4 > 0 && custom.Motor4 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Motor4 - 1] = QString("Motor4");
|
||||||
|
}
|
||||||
|
if (custom.Motor5 > 0 && custom.Motor5 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Motor5 - 1] = QString("Motor5");
|
||||||
|
}
|
||||||
|
if (custom.Motor6 > 0 && custom.Motor6 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Motor6 - 1] = QString("Motor6");
|
||||||
|
}
|
||||||
|
if (custom.Motor7 > 0 && custom.Motor7 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Motor7 - 1] = QString("Motor7");
|
||||||
|
}
|
||||||
|
if (custom.Motor8 > 0 && custom.Motor8 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Motor8 - 1] = QString("Motor8");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (custom.RevMotor1 > 0 && custom.RevMotor1 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.RevMotor1 - 1] = QString("RevMotor1");
|
||||||
|
}
|
||||||
|
if (custom.RevMotor2 > 0 && custom.RevMotor2 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.RevMotor2 - 1] = QString("RevMotor2");
|
||||||
|
}
|
||||||
|
if (custom.RevMotor3 > 0 && custom.RevMotor3 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.RevMotor3 - 1] = QString("RevMotor3");
|
||||||
|
}
|
||||||
|
if (custom.RevMotor4 > 0 && custom.RevMotor4 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.RevMotor4 - 1] = QString("RevMotor4");
|
||||||
|
}
|
||||||
|
if (custom.RevMotor5 > 0 && custom.RevMotor5 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.RevMotor5 - 1] = QString("RevMotor5");
|
||||||
|
}
|
||||||
|
if (custom.RevMotor6 > 0 && custom.RevMotor6 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.RevMotor6 - 1] = QString("RevMotor6");
|
||||||
|
}
|
||||||
|
if (custom.RevMotor7 > 0 && custom.RevMotor7 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.RevMotor7 - 1] = QString("RevMotor7");
|
||||||
|
}
|
||||||
|
if (custom.RevMotor8 > 0 && custom.RevMotor8 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.RevMotor8 - 1] = QString("RevMotor8");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (custom.Servo1 > 0 && custom.Servo1 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Servo1 - 1] = QString("Servo1");
|
||||||
|
}
|
||||||
|
if (custom.Servo2 > 0 && custom.Servo2 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Servo2 - 1] = QString("Servo2");
|
||||||
|
}
|
||||||
|
if (custom.Servo3 > 0 && custom.Servo3 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Servo3 - 1] = QString("Servo3");
|
||||||
|
}
|
||||||
|
if (custom.Servo4 > 0 && custom.Servo4 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Servo4 - 1] = QString("Servo4");
|
||||||
|
}
|
||||||
|
if (custom.Servo5 > 0 && custom.Servo5 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Servo5 - 1] = QString("Servo5");
|
||||||
|
}
|
||||||
|
if (custom.Servo6 > 0 && custom.Servo6 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Servo6 - 1] = QString("Servo6");
|
||||||
|
}
|
||||||
|
if (custom.Servo7 > 0 && custom.Servo7 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Servo7 - 1] = QString("Servo7");
|
||||||
|
}
|
||||||
|
if (custom.Servo8 > 0 && custom.Servo8 <= VehicleConfig::CHANNEL_NUMELEM) {
|
||||||
|
channelDesc[custom.Servo8 - 1] = QString("Servo8");
|
||||||
|
}
|
||||||
return channelDesc;
|
return channelDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +130,7 @@ ConfigCustomWidget::ConfigCustomWidget(QWidget *parent) :
|
|||||||
VehicleConfig(parent), m_aircraft(new Ui_CustomConfigWidget())
|
VehicleConfig(parent), m_aircraft(new Ui_CustomConfigWidget())
|
||||||
{
|
{
|
||||||
m_aircraft->setupUi(this);
|
m_aircraft->setupUi(this);
|
||||||
|
m_aircraft->customMixerTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
|
|
||||||
// Put combo boxes in line one of the custom mixer table:
|
// Put combo boxes in line one of the custom mixer table:
|
||||||
UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
|
UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
@ -93,7 +172,30 @@ void ConfigCustomWidget::registerWidgets(ConfigTaskWidget &parent)
|
|||||||
|
|
||||||
void ConfigCustomWidget::resetActuators(GUIConfigDataUnion *configData)
|
void ConfigCustomWidget::resetActuators(GUIConfigDataUnion *configData)
|
||||||
{
|
{
|
||||||
Q_UNUSED(configData);
|
configData->custom.Motor1 = 0;
|
||||||
|
configData->custom.Motor2 = 0;
|
||||||
|
configData->custom.Motor3 = 0;
|
||||||
|
configData->custom.Motor4 = 0;
|
||||||
|
configData->custom.Motor5 = 0;
|
||||||
|
configData->custom.Motor6 = 0;
|
||||||
|
configData->custom.Motor7 = 0;
|
||||||
|
configData->custom.Motor8 = 0;
|
||||||
|
configData->custom.RevMotor1 = 0;
|
||||||
|
configData->custom.RevMotor2 = 0;
|
||||||
|
configData->custom.RevMotor3 = 0;
|
||||||
|
configData->custom.RevMotor4 = 0;
|
||||||
|
configData->custom.RevMotor5 = 0;
|
||||||
|
configData->custom.RevMotor6 = 0;
|
||||||
|
configData->custom.RevMotor7 = 0;
|
||||||
|
configData->custom.RevMotor8 = 0;
|
||||||
|
configData->custom.Servo1 = 0;
|
||||||
|
configData->custom.Servo2 = 0;
|
||||||
|
configData->custom.Servo3 = 0;
|
||||||
|
configData->custom.Servo4 = 0;
|
||||||
|
configData->custom.Servo5 = 0;
|
||||||
|
configData->custom.Servo6 = 0;
|
||||||
|
configData->custom.Servo7 = 0;
|
||||||
|
configData->custom.Servo8 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,9 +207,23 @@ void ConfigCustomWidget::refreshWidgetsValues(QString frameType)
|
|||||||
|
|
||||||
setupUI(frameType);
|
setupUI(frameType);
|
||||||
|
|
||||||
|
UAVDataObject *system = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("SystemSettings")));
|
||||||
|
Q_ASSERT(system);
|
||||||
|
QPointer<UAVObjectField> field = system->getField(QString("AirframeType"));
|
||||||
|
|
||||||
|
// Do not allow table edit until AirframeType == Custom
|
||||||
|
// First save set AirframeType to 'Custom' and next modify.
|
||||||
|
if (field->getValue().toString() != "Custom") {
|
||||||
|
m_aircraft->customMixerTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
|
} else {
|
||||||
|
m_aircraft->customMixerTable->setEditTriggers(QAbstractItemView::AllEditTriggers);
|
||||||
|
}
|
||||||
|
|
||||||
UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
|
UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
Q_ASSERT(mixer);
|
Q_ASSERT(mixer);
|
||||||
|
|
||||||
|
getChannelDescriptions();
|
||||||
|
|
||||||
QList<double> curveValues;
|
QList<double> curveValues;
|
||||||
getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues);
|
getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues);
|
||||||
|
|
||||||
@ -162,60 +278,125 @@ void ConfigCustomWidget::refreshWidgetsValues(QString frameType)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Helper function to
|
Helper function to
|
||||||
*/
|
*/
|
||||||
QString ConfigCustomWidget::updateConfigObjectsFromWidgets()
|
QString ConfigCustomWidget::updateConfigObjectsFromWidgets()
|
||||||
{
|
{
|
||||||
UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
|
UAVDataObject *system = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("SystemSettings")));
|
||||||
|
|
||||||
Q_ASSERT(mixer);
|
Q_ASSERT(system);
|
||||||
|
|
||||||
setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->customThrottle1Curve->getCurve());
|
QPointer<UAVObjectField> field = system->getField(QString("AirframeType"));
|
||||||
setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->customThrottle2Curve->getCurve());
|
|
||||||
|
|
||||||
// Update the table:
|
// Do not allow changes until AirframeType == Custom
|
||||||
for (int channel = 0; channel < (int)VehicleConfig::CHANNEL_NUMELEM; channel++) {
|
// If user want to save custom mixer : first set AirframeType to 'Custom' without changes and next modify.
|
||||||
QComboBox *q = (QComboBox *)m_aircraft->customMixerTable->cellWidget(0, channel);
|
if (field->getValue().toString() == "Custom") {
|
||||||
if (q->currentText() == "Disabled") {
|
UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_DISABLED);
|
|
||||||
} else if (q->currentText() == "Motor") {
|
Q_ASSERT(mixer);
|
||||||
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
|
|
||||||
} else if (q->currentText() == "ReversableMotor") {
|
setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->customThrottle1Curve->getCurve());
|
||||||
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
|
setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->customThrottle2Curve->getCurve());
|
||||||
} else if (q->currentText() == "Servo") {
|
|
||||||
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
|
GUIConfigDataUnion configData = getConfigData();
|
||||||
} else if (q->currentText() == "CameraRoll") {
|
resetActuators(&configData);
|
||||||
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAROLL);
|
|
||||||
} else if (q->currentText() == "CameraPitch") {
|
// Update the table:
|
||||||
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAPITCH);
|
for (int channel = 0; channel < (int)VehicleConfig::CHANNEL_NUMELEM; channel++) {
|
||||||
} else if (q->currentText() == "CameraYaw") {
|
QComboBox *q = (QComboBox *)m_aircraft->customMixerTable->cellWidget(0, channel);
|
||||||
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAYAW);
|
if (q->currentText() == "Disabled") {
|
||||||
} else if (q->currentText() == "Accessory0") {
|
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_DISABLED);
|
||||||
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY0);
|
} else if (q->currentText() == "Motor") {
|
||||||
} else if (q->currentText() == "Accessory1") {
|
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
|
||||||
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY1);
|
if (configData.custom.Motor1 == 0) {
|
||||||
} else if (q->currentText() == "Accessory2") {
|
configData.custom.Motor1 = channel + 1;
|
||||||
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY2);
|
} else if (configData.custom.Motor2 == 0) {
|
||||||
} else if (q->currentText() == "Accessory3") {
|
configData.custom.Motor2 = channel + 1;
|
||||||
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY3);
|
} else if (configData.custom.Motor3 == 0) {
|
||||||
} else if (q->currentText() == "Accessory4") {
|
configData.custom.Motor3 = channel + 1;
|
||||||
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY4);
|
} else if (configData.custom.Motor4 == 0) {
|
||||||
} else if (q->currentText() == "Accessory5") {
|
configData.custom.Motor4 = channel + 1;
|
||||||
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY5);
|
} else if (configData.custom.Motor5 == 0) {
|
||||||
|
configData.custom.Motor5 = channel + 1;
|
||||||
|
} else if (configData.custom.Motor6 == 0) {
|
||||||
|
configData.custom.Motor6 = channel + 1;
|
||||||
|
} else if (configData.custom.Motor7 == 0) {
|
||||||
|
configData.custom.Motor7 = channel + 1;
|
||||||
|
} else if (configData.custom.Motor8 == 0) {
|
||||||
|
configData.custom.Motor8 = channel + 1;
|
||||||
|
}
|
||||||
|
} else if (q->currentText() == "ReversableMotor") {
|
||||||
|
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
|
||||||
|
if (configData.custom.RevMotor1 == 0) {
|
||||||
|
configData.custom.RevMotor1 = channel + 1;
|
||||||
|
} else if (configData.custom.RevMotor2 == 0) {
|
||||||
|
configData.custom.RevMotor2 = channel + 1;
|
||||||
|
} else if (configData.custom.RevMotor3 == 0) {
|
||||||
|
configData.custom.RevMotor3 = channel + 1;
|
||||||
|
} else if (configData.custom.RevMotor4 == 0) {
|
||||||
|
configData.custom.RevMotor4 = channel + 1;
|
||||||
|
} else if (configData.custom.RevMotor5 == 0) {
|
||||||
|
configData.custom.RevMotor5 = channel + 1;
|
||||||
|
} else if (configData.custom.RevMotor6 == 0) {
|
||||||
|
configData.custom.RevMotor6 = channel;
|
||||||
|
} else if (configData.custom.RevMotor7 == 0) {
|
||||||
|
configData.custom.RevMotor7 = channel;
|
||||||
|
} else if (configData.custom.RevMotor8 == 0) {
|
||||||
|
configData.custom.RevMotor8 = channel;
|
||||||
|
}
|
||||||
|
} else if (q->currentText() == "Servo") {
|
||||||
|
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
|
||||||
|
if (configData.custom.Servo1 == 0) {
|
||||||
|
configData.custom.Servo1 = channel + 1;
|
||||||
|
} else if (configData.custom.Servo2 == 0) {
|
||||||
|
configData.custom.Servo2 = channel + 1;
|
||||||
|
} else if (configData.custom.Servo3 == 0) {
|
||||||
|
configData.custom.Servo3 = channel + 1;
|
||||||
|
} else if (configData.custom.Servo4 == 0) {
|
||||||
|
configData.custom.Servo4 = channel + 1;
|
||||||
|
} else if (configData.custom.Servo5 == 0) {
|
||||||
|
configData.custom.Servo5 = channel + 1;
|
||||||
|
} else if (configData.custom.Servo6 == 0) {
|
||||||
|
configData.custom.Servo6 = channel + 1;
|
||||||
|
} else if (configData.custom.Servo7 == 0) {
|
||||||
|
configData.custom.Servo7 = channel + 1;
|
||||||
|
} else if (configData.custom.Servo8 == 0) {
|
||||||
|
configData.custom.Servo8 = channel + 1;
|
||||||
|
}
|
||||||
|
} else if (q->currentText() == "CameraRoll") {
|
||||||
|
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAROLL);
|
||||||
|
} else if (q->currentText() == "CameraPitch") {
|
||||||
|
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAPITCH);
|
||||||
|
} else if (q->currentText() == "CameraYaw") {
|
||||||
|
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAYAW);
|
||||||
|
} else if (q->currentText() == "Accessory0") {
|
||||||
|
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY0);
|
||||||
|
} else if (q->currentText() == "Accessory1") {
|
||||||
|
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY1);
|
||||||
|
} else if (q->currentText() == "Accessory2") {
|
||||||
|
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY2);
|
||||||
|
} else if (q->currentText() == "Accessory3") {
|
||||||
|
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY3);
|
||||||
|
} else if (q->currentText() == "Accessory4") {
|
||||||
|
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY4);
|
||||||
|
} else if (q->currentText() == "Accessory5") {
|
||||||
|
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY5);
|
||||||
|
}
|
||||||
|
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1,
|
||||||
|
m_aircraft->customMixerTable->item(1, channel)->text().toDouble());
|
||||||
|
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2,
|
||||||
|
m_aircraft->customMixerTable->item(2, channel)->text().toDouble());
|
||||||
|
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL,
|
||||||
|
m_aircraft->customMixerTable->item(3, channel)->text().toDouble());
|
||||||
|
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH,
|
||||||
|
m_aircraft->customMixerTable->item(4, channel)->text().toDouble());
|
||||||
|
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW,
|
||||||
|
m_aircraft->customMixerTable->item(5, channel)->text().toDouble());
|
||||||
}
|
}
|
||||||
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1,
|
setConfigData(configData);
|
||||||
m_aircraft->customMixerTable->item(1, channel)->text().toDouble());
|
|
||||||
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2,
|
|
||||||
m_aircraft->customMixerTable->item(2, channel)->text().toDouble());
|
|
||||||
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL,
|
|
||||||
m_aircraft->customMixerTable->item(3, channel)->text().toDouble());
|
|
||||||
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH,
|
|
||||||
m_aircraft->customMixerTable->item(4, channel)->text().toDouble());
|
|
||||||
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW,
|
|
||||||
m_aircraft->customMixerTable->item(5, channel)->text().toDouble());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Custom";
|
return "Custom";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*
|
*
|
||||||
* @file configairframetwidget.h
|
* @file configcustomwidget.h
|
||||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
||||||
* @addtogroup GCSPlugins GCS Plugins
|
* @addtogroup GCSPlugins GCS Plugins
|
||||||
* @{
|
* @{
|
||||||
* @addtogroup ConfigPlugin Config Plugin
|
* @addtogroup ConfigPlugin Config Plugin
|
||||||
* @{
|
* @{
|
||||||
* @brief Airframe configuration panel
|
* @brief custom configuration panel
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/*
|
/*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*
|
*
|
||||||
* @file configfixedwidget.cpp
|
* @file configfixedwingwidget.cpp
|
||||||
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
||||||
* @addtogroup GCSPlugins GCS Plugins
|
* @addtogroup GCSPlugins GCS Plugins
|
||||||
* @{
|
* @{
|
||||||
* @addtogroup ConfigPlugin Config Plugin
|
* @addtogroup ConfigPlugin Config Plugin
|
||||||
* @{
|
* @{
|
||||||
* @brief ccpm configuration panel
|
* @brief fixed wing configuration panel
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/*
|
/*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*
|
*
|
||||||
* @file configairframetwidget.h
|
* @file configfixedwingwidget.h
|
||||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
||||||
* @addtogroup GCSPlugins GCS Plugins
|
* @addtogroup GCSPlugins GCS Plugins
|
||||||
* @{
|
* @{
|
||||||
* @addtogroup ConfigPlugin Config Plugin
|
* @addtogroup ConfigPlugin Config Plugin
|
||||||
* @{
|
* @{
|
||||||
* @brief Airframe configuration panel
|
* @brief fixed wing configuration panel
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/*
|
/*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* @{
|
* @{
|
||||||
* @addtogroup ConfigPlugin Config Plugin
|
* @addtogroup ConfigPlugin Config Plugin
|
||||||
* @{
|
* @{
|
||||||
* @brief ccpm configuration panel
|
* @brief ground vehicle configuration panel
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/*
|
/*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*
|
*
|
||||||
* @file configairframetwidget.h
|
* @file configgroundvehiclewidget.h
|
||||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
||||||
* @addtogroup GCSPlugins GCS Plugins
|
* @addtogroup GCSPlugins GCS Plugins
|
||||||
* @{
|
* @{
|
||||||
* @addtogroup ConfigPlugin Config Plugin
|
* @addtogroup ConfigPlugin Config Plugin
|
||||||
* @{
|
* @{
|
||||||
* @brief Airframe configuration panel
|
* @brief ground vehicle configuration panel
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/*
|
/*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -50,11 +50,10 @@ typedef struct {
|
|||||||
uint VTOLMotorSSW : 4;
|
uint VTOLMotorSSW : 4;
|
||||||
uint VTOLMotorWSW : 4;
|
uint VTOLMotorWSW : 4;
|
||||||
uint VTOLMotorWNW : 4;
|
uint VTOLMotorWNW : 4;
|
||||||
uint VTOLMotorNNW : 4; // 32 bits
|
uint VTOLMotorNNW : 4; // 64 bits
|
||||||
uint TRIYaw : 4;
|
uint TRIYaw : 4;
|
||||||
quint32 padding : 28; // 64 bits
|
quint32 padding : 28; // 96 bits
|
||||||
quint32 padding1;
|
quint32 padding1; // 128 bits
|
||||||
quint32 padding2; // 128 bits
|
|
||||||
} __attribute__((packed)) multiGUISettingsStruct;
|
} __attribute__((packed)) multiGUISettingsStruct;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -102,12 +101,42 @@ typedef struct {
|
|||||||
quint32 padding3; // 128 bits
|
quint32 padding3; // 128 bits
|
||||||
} __attribute__((packed)) groundGUISettingsStruct;
|
} __attribute__((packed)) groundGUISettingsStruct;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint Motor1 : 4;
|
||||||
|
uint Motor2 : 4;
|
||||||
|
uint Motor3 : 4;
|
||||||
|
uint Motor4 : 4;
|
||||||
|
uint Motor5 : 4;
|
||||||
|
uint Motor6 : 4;
|
||||||
|
uint Motor7 : 4;
|
||||||
|
uint Motor8 : 4; // 32 bits
|
||||||
|
uint Servo1 : 4;
|
||||||
|
uint Servo2 : 4;
|
||||||
|
uint Servo3 : 4;
|
||||||
|
uint Servo4 : 4;
|
||||||
|
uint Servo5 : 4;
|
||||||
|
uint Servo6 : 4;
|
||||||
|
uint Servo7 : 4;
|
||||||
|
uint Servo8 : 4; // 64 bits
|
||||||
|
uint RevMotor1 : 4;
|
||||||
|
uint RevMotor2 : 4;
|
||||||
|
uint RevMotor3 : 4;
|
||||||
|
uint RevMotor4 : 4;
|
||||||
|
uint RevMotor5 : 4;
|
||||||
|
uint RevMotor6 : 4;
|
||||||
|
uint RevMotor7 : 4;
|
||||||
|
uint RevMotor8 : 4; // 96 bits
|
||||||
|
quint32 padding; // 128 bits
|
||||||
|
} __attribute__((packed)) customGUISettingsStruct;
|
||||||
|
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
uint UAVObject[4]; // 32 bits * 4
|
uint UAVObject[5]; // 32 bits * 5
|
||||||
heliGUISettingsStruct heli; // 128 bits
|
heliGUISettingsStruct heli; // 128 bits
|
||||||
fixedGUISettingsStruct fixedwing;
|
fixedGUISettingsStruct fixedwing;
|
||||||
multiGUISettingsStruct multi;
|
multiGUISettingsStruct multi;
|
||||||
groundGUISettingsStruct ground;
|
groundGUISettingsStruct ground;
|
||||||
|
customGUISettingsStruct custom;
|
||||||
} GUIConfigDataUnion;
|
} GUIConfigDataUnion;
|
||||||
|
|
||||||
class ConfigTaskWidget;
|
class ConfigTaskWidget;
|
||||||
|
@ -55,7 +55,10 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) :
|
|||||||
transmitterType(acro),
|
transmitterType(acro),
|
||||||
//
|
//
|
||||||
loop(NULL),
|
loop(NULL),
|
||||||
skipflag(false)
|
skipflag(false),
|
||||||
|
nextDelayedTimer(),
|
||||||
|
nextDelayedTick(0),
|
||||||
|
nextDelayedLatestActivityTick(0)
|
||||||
{
|
{
|
||||||
manualCommandObj = ManualControlCommand::GetInstance(getObjectManager());
|
manualCommandObj = ManualControlCommand::GetInstance(getObjectManager());
|
||||||
manualSettingsObj = ManualControlSettings::GetInstance(getObjectManager());
|
manualSettingsObj = ManualControlSettings::GetInstance(getObjectManager());
|
||||||
@ -395,6 +398,13 @@ void ConfigInputWidget::goToWizard()
|
|||||||
flightModeSettingsData.Arming = FlightModeSettings::ARMING_ALWAYSDISARMED;
|
flightModeSettingsData.Arming = FlightModeSettings::ARMING_ALWAYSDISARMED;
|
||||||
flightModeSettingsObj->setData(flightModeSettingsData);
|
flightModeSettingsObj->setData(flightModeSettingsData);
|
||||||
|
|
||||||
|
accessoryDesiredObj0 = AccessoryDesired::GetInstance(getObjectManager(), 0);
|
||||||
|
accessoryDesiredObj1 = AccessoryDesired::GetInstance(getObjectManager(), 1);
|
||||||
|
accessoryDesiredObj2 = AccessoryDesired::GetInstance(getObjectManager(), 2);
|
||||||
|
|
||||||
|
// Use faster input update rate.
|
||||||
|
fastMdata();
|
||||||
|
|
||||||
// start the wizard
|
// start the wizard
|
||||||
wizardSetUpStep(wizardWelcome);
|
wizardSetUpStep(wizardWelcome);
|
||||||
ui->graphicsView->fitInView(m_txBackground, Qt::KeepAspectRatio);
|
ui->graphicsView->fitInView(m_txBackground, Qt::KeepAspectRatio);
|
||||||
@ -412,7 +422,13 @@ void ConfigInputWidget::disableWizardButton(int value)
|
|||||||
void ConfigInputWidget::wzCancel()
|
void ConfigInputWidget::wzCancel()
|
||||||
{
|
{
|
||||||
dimOtherControls(false);
|
dimOtherControls(false);
|
||||||
manualCommandObj->setMetadata(manualCommandObj->getDefaultMetadata());
|
|
||||||
|
// Cancel any ongoing delayd next trigger.
|
||||||
|
wzNextDelayedCancel();
|
||||||
|
|
||||||
|
// Restore original input update rate.
|
||||||
|
restoreMdata();
|
||||||
|
|
||||||
ui->stackedWidget->setCurrentIndex(0);
|
ui->stackedWidget->setCurrentIndex(0);
|
||||||
|
|
||||||
if (wizardStep != wizardNone) {
|
if (wizardStep != wizardNone) {
|
||||||
@ -426,8 +442,45 @@ void ConfigInputWidget::wzCancel()
|
|||||||
flightModeSettingsObj->setData(previousFlightModeSettingsData);
|
flightModeSettingsObj->setData(previousFlightModeSettingsData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::registerControlActivity()
|
||||||
|
{
|
||||||
|
nextDelayedLatestActivityTick = nextDelayedTick;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::wzNextDelayed()
|
||||||
|
{
|
||||||
|
nextDelayedTick++;
|
||||||
|
|
||||||
|
// Call next after the full 2500 ms timeout has been reached,
|
||||||
|
// or if no input activity has occurred the last 500 ms.
|
||||||
|
if (nextDelayedTick == 25 ||
|
||||||
|
nextDelayedTick - nextDelayedLatestActivityTick >= 5) {
|
||||||
|
wzNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::wzNextDelayedStart()
|
||||||
|
{
|
||||||
|
// Call wzNextDelayed every 100 ms, to see if it's time to go to the next page.
|
||||||
|
connect(&nextDelayedTimer, SIGNAL(timeout()), this, SLOT(wzNextDelayed()));
|
||||||
|
nextDelayedTimer.start(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel the delayed next timer, if it's active.
|
||||||
|
void ConfigInputWidget::wzNextDelayedCancel()
|
||||||
|
{
|
||||||
|
nextDelayedTick = 0;
|
||||||
|
nextDelayedLatestActivityTick = 0;
|
||||||
|
if (nextDelayedTimer.isActive()) {
|
||||||
|
nextDelayedTimer.stop();
|
||||||
|
disconnect(&nextDelayedTimer, SIGNAL(timeout()), this, SLOT(wzNextDelayed()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ConfigInputWidget::wzNext()
|
void ConfigInputWidget::wzNext()
|
||||||
{
|
{
|
||||||
|
wzNextDelayedCancel();
|
||||||
|
|
||||||
// In identify sticks mode the next button can indicate
|
// In identify sticks mode the next button can indicate
|
||||||
// channel advance
|
// channel advance
|
||||||
if (wizardStep != wizardNone &&
|
if (wizardStep != wizardNone &&
|
||||||
@ -464,6 +517,10 @@ void ConfigInputWidget::wzNext()
|
|||||||
break;
|
break;
|
||||||
case wizardFinish:
|
case wizardFinish:
|
||||||
wizardStep = wizardNone;
|
wizardStep = wizardNone;
|
||||||
|
|
||||||
|
// Restore original input update rate.
|
||||||
|
restoreMdata();
|
||||||
|
|
||||||
// Leave setting the throttle neutral until the final Next press,
|
// Leave setting the throttle neutral until the final Next press,
|
||||||
// else the throttle scaling causes the graphical stick movement to not
|
// else the throttle scaling causes the graphical stick movement to not
|
||||||
// match the tx stick
|
// match the tx stick
|
||||||
@ -492,6 +549,8 @@ void ConfigInputWidget::wzNext()
|
|||||||
|
|
||||||
void ConfigInputWidget::wzBack()
|
void ConfigInputWidget::wzBack()
|
||||||
{
|
{
|
||||||
|
wzNextDelayedCancel();
|
||||||
|
|
||||||
if (wizardStep != wizardNone &&
|
if (wizardStep != wizardNone &&
|
||||||
wizardStep != wizardIdentifySticks) {
|
wizardStep != wizardIdentifySticks) {
|
||||||
wizardTearDownStep(wizardStep);
|
wizardTearDownStep(wizardStep);
|
||||||
@ -623,12 +682,8 @@ void ConfigInputWidget::wizardSetUpStep(enum wizardSteps step)
|
|||||||
break;
|
break;
|
||||||
case wizardIdentifyLimits:
|
case wizardIdentifyLimits:
|
||||||
{
|
{
|
||||||
accessoryDesiredObj0 = AccessoryDesired::GetInstance(getObjectManager(), 0);
|
|
||||||
accessoryDesiredObj1 = AccessoryDesired::GetInstance(getObjectManager(), 1);
|
|
||||||
accessoryDesiredObj2 = AccessoryDesired::GetInstance(getObjectManager(), 2);
|
|
||||||
setTxMovement(nothing);
|
setTxMovement(nothing);
|
||||||
ui->wzText->setText(QString(tr("Please move all controls to their maximum extents on both directions.\n\nPress Next when ready.")));
|
ui->wzText->setText(QString(tr("Please move all controls to their maximum extents on both directions.\n\nPress Next when ready.")));
|
||||||
fastMdata();
|
|
||||||
manualSettingsData = manualSettingsObj->getData();
|
manualSettingsData = manualSettingsObj->getData();
|
||||||
for (uint i = 0; i < ManualControlSettings::CHANNELMAX_NUMELEM; ++i) {
|
for (uint i = 0; i < ManualControlSettings::CHANNELMAX_NUMELEM; ++i) {
|
||||||
// Preserve the inverted status
|
// Preserve the inverted status
|
||||||
@ -665,7 +720,6 @@ void ConfigInputWidget::wizardSetUpStep(enum wizardSteps step)
|
|||||||
}
|
}
|
||||||
connect(manualCommandObj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(moveSticks()));
|
connect(manualCommandObj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(moveSticks()));
|
||||||
ui->wzText->setText(QString(tr("Please check the picture below and correct all the sticks which show an inverted movement. Press Next when ready.")));
|
ui->wzText->setText(QString(tr("Please check the picture below and correct all the sticks which show an inverted movement. Press Next when ready.")));
|
||||||
fastMdata();
|
|
||||||
break;
|
break;
|
||||||
case wizardFinish:
|
case wizardFinish:
|
||||||
dimOtherControls(false);
|
dimOtherControls(false);
|
||||||
@ -675,7 +729,6 @@ void ConfigInputWidget::wizardSetUpStep(enum wizardSteps step)
|
|||||||
ui->wzText->setText(QString(tr("You have completed this wizard, please check below if the picture mimics your sticks movement.\n\n"
|
ui->wzText->setText(QString(tr("You have completed this wizard, please check below if the picture mimics your sticks movement.\n\n"
|
||||||
"IMPORTANT: These new settings have not been saved to the board yet. After pressing Next you will go to the Arming Settings "
|
"IMPORTANT: These new settings have not been saved to the board yet. After pressing Next you will go to the Arming Settings "
|
||||||
"tab where you can set your desired arming sequence and save the configuration.")));
|
"tab where you can set your desired arming sequence and save the configuration.")));
|
||||||
fastMdata();
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Q_ASSERT(0);
|
Q_ASSERT(0);
|
||||||
@ -732,7 +785,6 @@ void ConfigInputWidget::wizardTearDownStep(enum wizardSteps step)
|
|||||||
disconnect(flightStatusObj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(moveSticks()));
|
disconnect(flightStatusObj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(moveSticks()));
|
||||||
disconnect(accessoryDesiredObj0, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(moveSticks()));
|
disconnect(accessoryDesiredObj0, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(moveSticks()));
|
||||||
manualSettingsObj->setData(manualSettingsData);
|
manualSettingsObj->setData(manualSettingsData);
|
||||||
restoreMdata();
|
|
||||||
setTxMovement(nothing);
|
setTxMovement(nothing);
|
||||||
break;
|
break;
|
||||||
case wizardIdentifyInverted:
|
case wizardIdentifyInverted:
|
||||||
@ -747,7 +799,6 @@ void ConfigInputWidget::wizardTearDownStep(enum wizardSteps step)
|
|||||||
}
|
}
|
||||||
extraWidgets.clear();
|
extraWidgets.clear();
|
||||||
disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(moveSticks()));
|
disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(moveSticks()));
|
||||||
restoreMdata();
|
|
||||||
break;
|
break;
|
||||||
case wizardFinish:
|
case wizardFinish:
|
||||||
dimOtherControls(false);
|
dimOtherControls(false);
|
||||||
@ -755,23 +806,33 @@ void ConfigInputWidget::wizardTearDownStep(enum wizardSteps step)
|
|||||||
disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(moveSticks()));
|
disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(moveSticks()));
|
||||||
disconnect(flightStatusObj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(moveSticks()));
|
disconnect(flightStatusObj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(moveSticks()));
|
||||||
disconnect(accessoryDesiredObj0, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(moveSticks()));
|
disconnect(accessoryDesiredObj0, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(moveSticks()));
|
||||||
restoreMdata();
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Q_ASSERT(0);
|
Q_ASSERT(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fastMdataSingle(UAVDataObject *object, UAVObject::Metadata *savedMdata)
|
||||||
|
{
|
||||||
|
*savedMdata = object->getMetadata();
|
||||||
|
UAVObject::Metadata mdata = *savedMdata;
|
||||||
|
UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_PERIODIC);
|
||||||
|
mdata.flightTelemetryUpdatePeriod = 150;
|
||||||
|
object->setMetadata(mdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void restoreMdataSingle(UAVDataObject *object, UAVObject::Metadata *savedMdata)
|
||||||
|
{
|
||||||
|
object->setMetadata(*savedMdata);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set manual control command to fast updates
|
* Set manual control command to fast updates
|
||||||
*/
|
*/
|
||||||
void ConfigInputWidget::fastMdata()
|
void ConfigInputWidget::fastMdata()
|
||||||
{
|
{
|
||||||
manualControlMdata = manualCommandObj->getMetadata();
|
fastMdataSingle(manualCommandObj, &manualControlMdata);
|
||||||
UAVObject::Metadata mdata = manualControlMdata;
|
fastMdataSingle(accessoryDesiredObj0, &accessoryDesiredMdata0);
|
||||||
UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_PERIODIC);
|
|
||||||
mdata.flightTelemetryUpdatePeriod = 150;
|
|
||||||
manualCommandObj->setMetadata(mdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -779,7 +840,8 @@ void ConfigInputWidget::fastMdata()
|
|||||||
*/
|
*/
|
||||||
void ConfigInputWidget::restoreMdata()
|
void ConfigInputWidget::restoreMdata()
|
||||||
{
|
{
|
||||||
manualCommandObj->setMetadata(manualControlMdata);
|
restoreMdataSingle(manualCommandObj, &manualControlMdata);
|
||||||
|
restoreMdataSingle(accessoryDesiredObj0, &accessoryDesiredMdata0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -849,7 +911,7 @@ void ConfigInputWidget::prevChannel()
|
|||||||
for (int i = 1; i < order.length(); i++) {
|
for (int i = 1; i < order.length(); i++) {
|
||||||
if (order[i] == currentChannelNum) {
|
if (order[i] == currentChannelNum) {
|
||||||
if (!usedChannels.isEmpty() &&
|
if (!usedChannels.isEmpty() &&
|
||||||
usedChannels.back().channelIndex == currentChannelNum) {
|
usedChannels.back().channelIndex == order[i - 1]) {
|
||||||
usedChannels.removeLast();
|
usedChannels.removeLast();
|
||||||
}
|
}
|
||||||
setChannel(order[i - 1]);
|
setChannel(order[i - 1]);
|
||||||
@ -861,41 +923,66 @@ void ConfigInputWidget::prevChannel()
|
|||||||
|
|
||||||
void ConfigInputWidget::identifyControls()
|
void ConfigInputWidget::identifyControls()
|
||||||
{
|
{
|
||||||
|
static const int DEBOUNCE_COUNT = 4;
|
||||||
static int debounce = 0;
|
static int debounce = 0;
|
||||||
|
|
||||||
receiverActivityData = receiverActivityObj->getData();
|
receiverActivityData = receiverActivityObj->getData();
|
||||||
|
|
||||||
if (receiverActivityData.ActiveChannel == 255) {
|
if (receiverActivityData.ActiveChannel == 255) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channelDetected) {
|
if (channelDetected) {
|
||||||
|
registerControlActivity();
|
||||||
return;
|
return;
|
||||||
} else {
|
}
|
||||||
receiverActivityData = receiverActivityObj->getData();
|
|
||||||
currentChannel.group = receiverActivityData.ActiveGroup;
|
receiverActivityData = receiverActivityObj->getData();
|
||||||
currentChannel.number = receiverActivityData.ActiveChannel;
|
currentChannel.group = receiverActivityData.ActiveGroup;
|
||||||
if (currentChannel == lastChannel) {
|
currentChannel.number = receiverActivityData.ActiveChannel;
|
||||||
++debounce;
|
|
||||||
}
|
if (debounce == 0) {
|
||||||
|
// Register a channel to be debounced.
|
||||||
lastChannel.group = currentChannel.group;
|
lastChannel.group = currentChannel.group;
|
||||||
lastChannel.number = currentChannel.number;
|
lastChannel.number = currentChannel.number;
|
||||||
lastChannel.channelIndex = currentChannelNum;
|
lastChannel.channelIndex = currentChannelNum;
|
||||||
if (!usedChannels.contains(lastChannel) && debounce > 1) {
|
++debounce;
|
||||||
channelDetected = true;
|
return;
|
||||||
debounce = 0;
|
|
||||||
usedChannels.append(lastChannel);
|
|
||||||
manualSettingsData = manualSettingsObj->getData();
|
|
||||||
manualSettingsData.ChannelGroups[currentChannelNum] = currentChannel.group;
|
|
||||||
manualSettingsData.ChannelNumber[currentChannelNum] = currentChannel.number;
|
|
||||||
manualSettingsObj->setData(manualSettingsData);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentChannel != lastChannel) {
|
||||||
|
// A new channel was seen. Only register it if we count down to 0.
|
||||||
|
--debounce;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debounce < DEBOUNCE_COUNT) {
|
||||||
|
// We still haven't seen enough enough activity on this channel yet.
|
||||||
|
++debounce;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Channel has been debounced and it's enough record it.
|
||||||
|
|
||||||
|
if (usedChannels.contains(lastChannel)) {
|
||||||
|
// Channel is already recorded.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the channel.
|
||||||
|
|
||||||
|
channelDetected = true;
|
||||||
|
debounce = 0;
|
||||||
|
usedChannels.append(lastChannel);
|
||||||
|
manualSettingsData = manualSettingsObj->getData();
|
||||||
|
manualSettingsData.ChannelGroups[currentChannelNum] = currentChannel.group;
|
||||||
|
manualSettingsData.ChannelNumber[currentChannelNum] = currentChannel.number;
|
||||||
|
manualSettingsObj->setData(manualSettingsData);
|
||||||
|
|
||||||
// m_config->wzText->clear();
|
// m_config->wzText->clear();
|
||||||
setTxMovement(nothing);
|
setTxMovement(nothing);
|
||||||
|
|
||||||
QTimer::singleShot(2500, this, SLOT(wzNext()));
|
wzNextDelayedStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigInputWidget::identifyLimits()
|
void ConfigInputWidget::identifyLimits()
|
||||||
|
@ -82,6 +82,10 @@ private:
|
|||||||
{
|
{
|
||||||
return (group == rhs.group) && (number == rhs.number);
|
return (group == rhs.group) && (number == rhs.number);
|
||||||
}
|
}
|
||||||
|
bool operator !=(const channelsStruct & rhs) const
|
||||||
|
{
|
||||||
|
return !operator==(rhs);
|
||||||
|
}
|
||||||
int group;
|
int group;
|
||||||
int number;
|
int number;
|
||||||
int channelIndex;
|
int channelIndex;
|
||||||
@ -92,24 +96,34 @@ private:
|
|||||||
QEventLoop *loop;
|
QEventLoop *loop;
|
||||||
bool skipflag;
|
bool skipflag;
|
||||||
|
|
||||||
|
// Variables to support delayed transitions when detecting input controls.
|
||||||
|
QTimer nextDelayedTimer;
|
||||||
|
int nextDelayedTick;
|
||||||
|
int nextDelayedLatestActivityTick;
|
||||||
|
|
||||||
int currentChannelNum;
|
int currentChannelNum;
|
||||||
QList<int> heliChannelOrder;
|
QList<int> heliChannelOrder;
|
||||||
QList<int> acroChannelOrder;
|
QList<int> acroChannelOrder;
|
||||||
|
|
||||||
|
UAVObject::Metadata manualControlMdata;
|
||||||
ManualControlCommand *manualCommandObj;
|
ManualControlCommand *manualCommandObj;
|
||||||
ManualControlCommand::DataFields manualCommandData;
|
ManualControlCommand::DataFields manualCommandData;
|
||||||
|
|
||||||
FlightStatus *flightStatusObj;
|
FlightStatus *flightStatusObj;
|
||||||
FlightStatus::DataFields flightStatusData;
|
FlightStatus::DataFields flightStatusData;
|
||||||
|
|
||||||
|
UAVObject::Metadata accessoryDesiredMdata0;
|
||||||
AccessoryDesired *accessoryDesiredObj0;
|
AccessoryDesired *accessoryDesiredObj0;
|
||||||
AccessoryDesired *accessoryDesiredObj1;
|
AccessoryDesired *accessoryDesiredObj1;
|
||||||
AccessoryDesired *accessoryDesiredObj2;
|
AccessoryDesired *accessoryDesiredObj2;
|
||||||
AccessoryDesired::DataFields accessoryDesiredData0;
|
AccessoryDesired::DataFields accessoryDesiredData0;
|
||||||
AccessoryDesired::DataFields accessoryDesiredData1;
|
AccessoryDesired::DataFields accessoryDesiredData1;
|
||||||
AccessoryDesired::DataFields accessoryDesiredData2;
|
AccessoryDesired::DataFields accessoryDesiredData2;
|
||||||
UAVObject::Metadata manualControlMdata;
|
|
||||||
ManualControlSettings *manualSettingsObj;
|
ManualControlSettings *manualSettingsObj;
|
||||||
ManualControlSettings::DataFields manualSettingsData;
|
ManualControlSettings::DataFields manualSettingsData;
|
||||||
ManualControlSettings::DataFields previousManualSettingsData;
|
ManualControlSettings::DataFields previousManualSettingsData;
|
||||||
|
|
||||||
FlightModeSettings *flightModeSettingsObj;
|
FlightModeSettings *flightModeSettingsObj;
|
||||||
FlightModeSettings::DataFields flightModeSettingsData;
|
FlightModeSettings::DataFields flightModeSettingsData;
|
||||||
FlightModeSettings::DataFields previousFlightModeSettingsData;
|
FlightModeSettings::DataFields previousFlightModeSettingsData;
|
||||||
@ -152,8 +166,14 @@ private:
|
|||||||
void wizardSetUpStep(enum wizardSteps);
|
void wizardSetUpStep(enum wizardSteps);
|
||||||
void wizardTearDownStep(enum wizardSteps);
|
void wizardTearDownStep(enum wizardSteps);
|
||||||
|
|
||||||
|
void registerControlActivity();
|
||||||
|
|
||||||
|
void wzNextDelayedStart();
|
||||||
|
void wzNextDelayedCancel();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void wzNext();
|
void wzNext();
|
||||||
|
void wzNextDelayed();
|
||||||
void wzBack();
|
void wzBack();
|
||||||
void wzCancel();
|
void wzCancel();
|
||||||
void goToWizard();
|
void goToWizard();
|
||||||
|
@ -57,7 +57,6 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa
|
|||||||
// Set up fake tab widget stuff for pid banks support
|
// Set up fake tab widget stuff for pid banks support
|
||||||
m_pidTabBars.append(ui->basicPIDBankTabBar);
|
m_pidTabBars.append(ui->basicPIDBankTabBar);
|
||||||
m_pidTabBars.append(ui->advancedPIDBankTabBar);
|
m_pidTabBars.append(ui->advancedPIDBankTabBar);
|
||||||
m_pidTabBars.append(ui->expertPIDBankTabBar);
|
|
||||||
foreach(QTabBar * tabBar, m_pidTabBars) {
|
foreach(QTabBar * tabBar, m_pidTabBars) {
|
||||||
for (int i = 0; i < m_pidBankCount; i++) {
|
for (int i = 0; i < m_pidBankCount; i++) {
|
||||||
tabBar->addTab(tr("PID Bank %1").arg(i + 1));
|
tabBar->addTab(tr("PID Bank %1").arg(i + 1));
|
||||||
@ -94,8 +93,6 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa
|
|||||||
addWidget(ui->realTimeUpdates_12);
|
addWidget(ui->realTimeUpdates_12);
|
||||||
connect(ui->realTimeUpdates_7, SIGNAL(toggled(bool)), this, SLOT(realtimeUpdatesSlot(bool)));
|
connect(ui->realTimeUpdates_7, SIGNAL(toggled(bool)), this, SLOT(realtimeUpdatesSlot(bool)));
|
||||||
addWidget(ui->realTimeUpdates_7);
|
addWidget(ui->realTimeUpdates_7);
|
||||||
connect(ui->realTimeUpdates_9, SIGNAL(toggled(bool)), this, SLOT(realtimeUpdatesSlot(bool)));
|
|
||||||
addWidget(ui->realTimeUpdates_9);
|
|
||||||
|
|
||||||
connect(ui->checkBox_7, SIGNAL(toggled(bool)), this, SLOT(linkCheckBoxes(bool)));
|
connect(ui->checkBox_7, SIGNAL(toggled(bool)), this, SLOT(linkCheckBoxes(bool)));
|
||||||
addWidget(ui->checkBox_7);
|
addWidget(ui->checkBox_7);
|
||||||
@ -111,7 +108,11 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa
|
|||||||
addWidget(ui->pushButton_4);
|
addWidget(ui->pushButton_4);
|
||||||
addWidget(ui->pushButton_5);
|
addWidget(ui->pushButton_5);
|
||||||
addWidget(ui->pushButton_6);
|
addWidget(ui->pushButton_6);
|
||||||
|
addWidget(ui->pushButton_7);
|
||||||
|
addWidget(ui->pushButton_8);
|
||||||
addWidget(ui->pushButton_9);
|
addWidget(ui->pushButton_9);
|
||||||
|
addWidget(ui->pushButton_10);
|
||||||
|
addWidget(ui->pushButton_11);
|
||||||
addWidget(ui->pushButton_20);
|
addWidget(ui->pushButton_20);
|
||||||
addWidget(ui->pushButton_22);
|
addWidget(ui->pushButton_22);
|
||||||
addWidget(ui->pushButton_23);
|
addWidget(ui->pushButton_23);
|
||||||
@ -150,7 +151,6 @@ void ConfigStabilizationWidget::realtimeUpdatesSlot(bool value)
|
|||||||
ui->realTimeUpdates_8->setChecked(value);
|
ui->realTimeUpdates_8->setChecked(value);
|
||||||
ui->realTimeUpdates_12->setChecked(value);
|
ui->realTimeUpdates_12->setChecked(value);
|
||||||
ui->realTimeUpdates_7->setChecked(value);
|
ui->realTimeUpdates_7->setChecked(value);
|
||||||
ui->realTimeUpdates_9->setChecked(value);
|
|
||||||
|
|
||||||
if (value && !realtimeUpdates->isActive()) {
|
if (value && !realtimeUpdates->isActive()) {
|
||||||
realtimeUpdates->start(AUTOMATIC_UPDATE_RATE);
|
realtimeUpdates->start(AUTOMATIC_UPDATE_RATE);
|
||||||
@ -193,14 +193,10 @@ void ConfigStabilizationWidget::processLinkedWidgets(QWidget *widget)
|
|||||||
ui->RatePitchKp->setValue(ui->RateRollKp_2->value());
|
ui->RatePitchKp->setValue(ui->RateRollKp_2->value());
|
||||||
} else if (widget == ui->RateRollKi_2) {
|
} else if (widget == ui->RateRollKi_2) {
|
||||||
ui->RatePitchKi->setValue(ui->RateRollKi_2->value());
|
ui->RatePitchKi->setValue(ui->RateRollKi_2->value());
|
||||||
} else if (widget == ui->RateRollILimit_2) {
|
|
||||||
ui->RatePitchILimit->setValue(ui->RateRollILimit_2->value());
|
|
||||||
} else if (widget == ui->RatePitchKp) {
|
} else if (widget == ui->RatePitchKp) {
|
||||||
ui->RateRollKp_2->setValue(ui->RatePitchKp->value());
|
ui->RateRollKp_2->setValue(ui->RatePitchKp->value());
|
||||||
} else if (widget == ui->RatePitchKi) {
|
} else if (widget == ui->RatePitchKi) {
|
||||||
ui->RateRollKi_2->setValue(ui->RatePitchKi->value());
|
ui->RateRollKi_2->setValue(ui->RatePitchKi->value());
|
||||||
} else if (widget == ui->RatePitchILimit) {
|
|
||||||
ui->RateRollILimit_2->setValue(ui->RatePitchILimit->value());
|
|
||||||
} else if (widget == ui->RollRateKd) {
|
} else if (widget == ui->RollRateKd) {
|
||||||
ui->PitchRateKd->setValue(ui->RollRateKd->value());
|
ui->PitchRateKd->setValue(ui->RollRateKd->value());
|
||||||
} else if (widget == ui->PitchRateKd) {
|
} else if (widget == ui->PitchRateKd) {
|
||||||
@ -213,14 +209,10 @@ void ConfigStabilizationWidget::processLinkedWidgets(QWidget *widget)
|
|||||||
ui->AttitudePitchKp_2->setValue(ui->AttitudeRollKp->value());
|
ui->AttitudePitchKp_2->setValue(ui->AttitudeRollKp->value());
|
||||||
} else if (widget == ui->AttitudeRollKi) {
|
} else if (widget == ui->AttitudeRollKi) {
|
||||||
ui->AttitudePitchKi_2->setValue(ui->AttitudeRollKi->value());
|
ui->AttitudePitchKi_2->setValue(ui->AttitudeRollKi->value());
|
||||||
} else if (widget == ui->AttitudeRollILimit) {
|
|
||||||
ui->AttitudePitchILimit_2->setValue(ui->AttitudeRollILimit->value());
|
|
||||||
} else if (widget == ui->AttitudePitchKp_2) {
|
} else if (widget == ui->AttitudePitchKp_2) {
|
||||||
ui->AttitudeRollKp->setValue(ui->AttitudePitchKp_2->value());
|
ui->AttitudeRollKp->setValue(ui->AttitudePitchKp_2->value());
|
||||||
} else if (widget == ui->AttitudePitchKi_2) {
|
} else if (widget == ui->AttitudePitchKi_2) {
|
||||||
ui->AttitudeRollKi->setValue(ui->AttitudePitchKi_2->value());
|
ui->AttitudeRollKi->setValue(ui->AttitudePitchKi_2->value());
|
||||||
} else if (widget == ui->AttitudePitchILimit_2) {
|
|
||||||
ui->AttitudeRollILimit->setValue(ui->AttitudePitchILimit_2->value());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +232,7 @@ void ConfigStabilizationWidget::onBoardConnected()
|
|||||||
|
|
||||||
Q_ASSERT(utilMngr);
|
Q_ASSERT(utilMngr);
|
||||||
boardModel = utilMngr->getBoardModel();
|
boardModel = utilMngr->getBoardModel();
|
||||||
// If Revolution board enable misc tab, otherwise disable it
|
// If Revolution board enable Althold tab, otherwise disable it
|
||||||
ui->AltitudeHold->setEnabled((boardModel & 0xff00) == 0x0900);
|
ui->AltitudeHold->setEnabled((boardModel & 0xff00) == 0x0900);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,12 +198,27 @@ void ConfigVehicleTypeWidget::refreshWidgetsValues(UAVObject *o)
|
|||||||
// is not ideal, but there you go.
|
// is not ideal, but there you go.
|
||||||
QString frameType = field->getValue().toString();
|
QString frameType = field->getValue().toString();
|
||||||
|
|
||||||
int category = frameCategory(frameType);
|
// Always update custom tab from others airframe settings : debug/learn hardcoded mixers
|
||||||
|
int category = frameCategory("Custom");
|
||||||
m_aircraft->aircraftType->setCurrentIndex(category);
|
m_aircraft->aircraftType->setCurrentIndex(category);
|
||||||
|
|
||||||
VehicleConfig *vehicleConfig = getVehicleConfigWidget(category);
|
VehicleConfig *vehicleConfig = getVehicleConfigWidget(category);
|
||||||
|
|
||||||
if (vehicleConfig) {
|
if (vehicleConfig) {
|
||||||
vehicleConfig->refreshWidgetsValues(frameType);
|
vehicleConfig->refreshWidgetsValues("Custom");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch to Airframe currently used
|
||||||
|
category = frameCategory(frameType);
|
||||||
|
|
||||||
|
if (frameType != "Custom") {
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(category);
|
||||||
|
|
||||||
|
VehicleConfig *vehicleConfig = getVehicleConfigWidget(category);
|
||||||
|
|
||||||
|
if (vehicleConfig) {
|
||||||
|
vehicleConfig->refreshWidgetsValues(frameType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFeedForwardUI();
|
updateFeedForwardUI();
|
||||||
@ -252,7 +267,8 @@ void ConfigVehicleTypeWidget::updateObjectsFromWidgets()
|
|||||||
vconfig->setMixerValue(mixer, "DecelTime", m_aircraft->decelTime->value());
|
vconfig->setMixerValue(mixer, "DecelTime", m_aircraft->decelTime->value());
|
||||||
vconfig->setMixerValue(mixer, "MaxAccel", m_aircraft->maxAccelSlider->value());
|
vconfig->setMixerValue(mixer, "MaxAccel", m_aircraft->maxAccelSlider->value());
|
||||||
|
|
||||||
// TODO call refreshWidgetsValues() to reflect actual saved values ?
|
// call refreshWidgetsValues() to reflect actual saved values
|
||||||
|
refreshWidgetsValues();
|
||||||
updateFeedForwardUI();
|
updateFeedForwardUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -26,7 +26,9 @@
|
|||||||
*/
|
*/
|
||||||
#include "modeluavoproxy.h"
|
#include "modeluavoproxy.h"
|
||||||
#include "extensionsystem/pluginmanager.h"
|
#include "extensionsystem/pluginmanager.h"
|
||||||
|
#include "uavobjecthelper.h"
|
||||||
|
|
||||||
|
#include <QProgressDialog>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
ModelUavoProxy::ModelUavoProxy(QObject *parent, flightDataModel *model) : QObject(parent), myModel(model)
|
ModelUavoProxy::ModelUavoProxy(QObject *parent, flightDataModel *model) : QObject(parent), myModel(model)
|
||||||
@ -37,91 +39,126 @@ ModelUavoProxy::ModelUavoProxy(QObject *parent, flightDataModel *model) : QObjec
|
|||||||
|
|
||||||
objMngr = pm->getObject<UAVObjectManager>();
|
objMngr = pm->getObject<UAVObjectManager>();
|
||||||
Q_ASSERT(objMngr != NULL);
|
Q_ASSERT(objMngr != NULL);
|
||||||
|
|
||||||
completionCountdown = 0;
|
|
||||||
successCountdown = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelUavoProxy::sendPathPlan()
|
void ModelUavoProxy::sendPathPlan()
|
||||||
{
|
{
|
||||||
modelToObjects();
|
modelToObjects();
|
||||||
|
|
||||||
PathPlan *pathPlan = PathPlan::GetInstance(objMngr, 0);
|
PathPlan *pathPlan = PathPlan::GetInstance(objMngr);
|
||||||
connect(pathPlan, SIGNAL(transactionCompleted(UAVObject *, bool)),
|
|
||||||
this, SLOT(pathPlanElementSent(UAVObject *, bool)), Qt::UniqueConnection);
|
|
||||||
|
|
||||||
Waypoint *waypoint = Waypoint::GetInstance(objMngr, 0);
|
const int waypointCount = pathPlan->getWaypointCount();
|
||||||
connect(waypoint, SIGNAL(transactionCompleted(UAVObject *, bool)),
|
const int actionCount = pathPlan->getPathActionCount();
|
||||||
this, SLOT(pathPlanElementSent(UAVObject *, bool)), Qt::UniqueConnection);
|
|
||||||
|
|
||||||
PathAction *action = PathAction::GetInstance(objMngr, 0);
|
QProgressDialog progress(tr("Sending the path plan to the board... "), "", 0, 1 + waypointCount + actionCount);
|
||||||
connect(action, SIGNAL(transactionCompleted(UAVObject *, bool)),
|
progress.setWindowModality(Qt::WindowModal);
|
||||||
this, SLOT(pathPlanElementSent(UAVObject *, bool)), Qt::UniqueConnection);
|
progress.setCancelButton(NULL);
|
||||||
|
progress.show();
|
||||||
|
|
||||||
// we will start 3 update all
|
UAVObjectUpdaterHelper updateHelper;
|
||||||
completionCountdown = 3;
|
|
||||||
successCountdown = completionCountdown;
|
|
||||||
|
|
||||||
pathPlan->updated();
|
// send PathPlan
|
||||||
waypoint->updatedAll();
|
bool success = (updateHelper.doObjectAndWait(pathPlan) == UAVObjectUpdaterHelper::SUCCESS);
|
||||||
action->updatedAll();
|
progress.setValue(1);
|
||||||
}
|
|
||||||
|
|
||||||
void ModelUavoProxy::pathPlanElementSent(UAVObject *obj, bool success)
|
if (success) {
|
||||||
{
|
// send Waypoint instances
|
||||||
obj->disconnect(this);
|
qDebug() << "sending" << waypointCount << "waypoints";
|
||||||
|
for (int i = 0; i < waypointCount; ++i) {
|
||||||
completionCountdown--;
|
Waypoint *waypoint = Waypoint::GetInstance(objMngr, i);
|
||||||
successCountdown -= success ? 1 : 0;
|
success = (updateHelper.doObjectAndWait(waypoint) == UAVObjectUpdaterHelper::SUCCESS);
|
||||||
|
if (!success) {
|
||||||
if (completionCountdown == 0) {
|
break;
|
||||||
qDebug() << "ModelUavoProxy::pathPlanSent - completed" << (successCountdown == 0);
|
}
|
||||||
if (successCountdown == 0) {
|
progress.setValue(progress.value() + 1);
|
||||||
QMessageBox::information(NULL, tr("Path Plan Upload Successful"), tr("Path plan upload was successful."));
|
|
||||||
} else {
|
|
||||||
QMessageBox::critical(NULL, tr("Path Plan Upload Failed"), tr("Failed to upload the path plan !"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
// send PathAction instances
|
||||||
|
qDebug() << "sending" << actionCount << "path actions";
|
||||||
|
for (int i = 0; i < actionCount; ++i) {
|
||||||
|
PathAction *action = PathAction::GetInstance(objMngr, i);
|
||||||
|
success = (updateHelper.doObjectAndWait(action) == UAVObjectUpdaterHelper::SUCCESS);
|
||||||
|
if (!success) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
progress.setValue(progress.value() + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "ModelUavoProxy::pathPlanSent - completed" << success;
|
||||||
|
if (!success) {
|
||||||
|
QMessageBox::critical(NULL, tr("Sending Path Plan Failed!"), tr("Failed to send the path plan to the board."));
|
||||||
|
}
|
||||||
|
|
||||||
|
progress.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelUavoProxy::receivePathPlan()
|
void ModelUavoProxy::receivePathPlan()
|
||||||
{
|
{
|
||||||
PathPlan *pathPlan = PathPlan::GetInstance(objMngr, 0);
|
QProgressDialog progress(tr("Receiving the path plan from the board... "), "", 0, 0);
|
||||||
|
progress.setWindowModality(Qt::WindowModal);
|
||||||
|
progress.setCancelButton(NULL);
|
||||||
|
progress.show();
|
||||||
|
|
||||||
connect(pathPlan, SIGNAL(transactionCompleted(UAVObject *, bool)), this, SLOT(pathPlanElementReceived(UAVObject *, bool)));
|
UAVObjectRequestHelper requestHelper;
|
||||||
|
|
||||||
Waypoint *waypoint = Waypoint::GetInstance(objMngr, 0);
|
PathPlan *pathPlan = PathPlan::GetInstance(objMngr);
|
||||||
connect(waypoint, SIGNAL(transactionCompleted(UAVObject *, bool)), this, SLOT(pathPlanElementReceived(UAVObject *, bool)));
|
bool success = (requestHelper.doObjectAndWait(pathPlan) == UAVObjectUpdaterHelper::SUCCESS);
|
||||||
|
|
||||||
PathAction *action = PathAction::GetInstance(objMngr, 0);
|
const int waypointCount = pathPlan->getWaypointCount();
|
||||||
connect(action, SIGNAL(transactionCompleted(UAVObject *, bool)), this, SLOT(pathPlanElementReceived(UAVObject *, bool)));
|
const int actionCount = pathPlan->getPathActionCount();
|
||||||
|
|
||||||
// we will start 3 update requests
|
progress.setMaximum(1 + waypointCount + actionCount);
|
||||||
completionCountdown = 3;
|
progress.setValue(1);
|
||||||
successCountdown = completionCountdown;
|
|
||||||
|
|
||||||
pathPlan->requestUpdate();
|
if (success && (waypointCount > objMngr->getNumInstances(Waypoint::OBJID))) {
|
||||||
waypoint->requestUpdateAll();
|
// allocate needed Waypoint instances
|
||||||
action->requestUpdateAll();
|
Waypoint *waypoint = new Waypoint;
|
||||||
}
|
waypoint->initialize(waypointCount - 1, waypoint->getMetaObject());
|
||||||
|
success = objMngr->registerObject(waypoint);
|
||||||
void ModelUavoProxy::pathPlanElementReceived(UAVObject *obj, bool success)
|
}
|
||||||
{
|
if (success) {
|
||||||
obj->disconnect(this);
|
// request Waypoint instances
|
||||||
|
qDebug() << "requesting" << waypointCount << "waypoints";
|
||||||
completionCountdown--;
|
for (int i = 0; i < waypointCount; ++i) {
|
||||||
successCountdown -= success ? 1 : 0;
|
Waypoint *waypoint = Waypoint::GetInstance(objMngr, i);
|
||||||
|
success = (requestHelper.doObjectAndWait(waypoint) == UAVObjectRequestHelper::SUCCESS);
|
||||||
if (completionCountdown == 0) {
|
if (!success) {
|
||||||
qDebug() << "ModelUavoProxy::pathPlanReceived - completed" << (successCountdown == 0);
|
break;
|
||||||
if (successCountdown == 0) {
|
|
||||||
if (objectsToModel()) {
|
|
||||||
QMessageBox::information(NULL, tr("Path Plan Download Successful"), tr("Path plan download was successful."));
|
|
||||||
}
|
}
|
||||||
} else {
|
progress.setValue(progress.value() + 1);
|
||||||
QMessageBox::critical(NULL, tr("Path Plan Download Failed"), tr("Failed to download the path plan !"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (success && (actionCount > objMngr->getNumInstances(PathAction::OBJID))) {
|
||||||
|
// allocate needed PathAction instances
|
||||||
|
PathAction *action = new PathAction;
|
||||||
|
action->initialize(actionCount - 1, action->getMetaObject());
|
||||||
|
success = objMngr->registerObject(action);
|
||||||
|
}
|
||||||
|
if (success) {
|
||||||
|
// request PathAction isntances
|
||||||
|
qDebug() << "requesting" << actionCount << "path actions";
|
||||||
|
for (int i = 0; i < actionCount; ++i) {
|
||||||
|
PathAction *action = PathAction::GetInstance(objMngr, i);
|
||||||
|
success = (requestHelper.doObjectAndWait(action) == UAVObjectRequestHelper::SUCCESS);
|
||||||
|
if (!success) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
progress.setValue(progress.value() + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "ModelUavoProxy::pathPlanReceived - completed" << success;
|
||||||
|
if (success) {
|
||||||
|
objectsToModel();
|
||||||
|
} else {
|
||||||
|
QMessageBox::critical(NULL, tr("Receiving Path Plan Failed!"), tr("Failed to receive the path plan from the board."));
|
||||||
|
}
|
||||||
|
|
||||||
|
progress.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// update waypoint and path actions UAV objects
|
// update waypoint and path actions UAV objects
|
||||||
|
@ -49,9 +49,6 @@ private:
|
|||||||
UAVObjectManager *objMngr;
|
UAVObjectManager *objMngr;
|
||||||
flightDataModel *myModel;
|
flightDataModel *myModel;
|
||||||
|
|
||||||
uint completionCountdown;
|
|
||||||
uint successCountdown;
|
|
||||||
|
|
||||||
bool modelToObjects();
|
bool modelToObjects();
|
||||||
bool objectsToModel();
|
bool objectsToModel();
|
||||||
|
|
||||||
@ -67,10 +64,6 @@ private:
|
|||||||
void pathActionToModel(int i, PathAction::DataFields &data);
|
void pathActionToModel(int i, PathAction::DataFields &data);
|
||||||
|
|
||||||
quint8 computePathPlanCrc(int waypointCount, int actionCount);
|
quint8 computePathPlanCrc(int waypointCount, int actionCount);
|
||||||
|
|
||||||
private slots:
|
|
||||||
void pathPlanElementSent(UAVObject *, bool success);
|
|
||||||
void pathPlanElementReceived(UAVObject *, bool success);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MODELUAVOPROXY_H
|
#endif // MODELUAVOPROXY_H
|
||||||
|
@ -43,7 +43,10 @@ public:
|
|||||||
virtual ~AbstractUAVObjectHelper();
|
virtual ~AbstractUAVObjectHelper();
|
||||||
|
|
||||||
enum Result { SUCCESS, FAIL, TIMEOUT };
|
enum Result { SUCCESS, FAIL, TIMEOUT };
|
||||||
Result doObjectAndWait(UAVObject *object, int timeout);
|
|
||||||
|
// default timeout = 3 x 250ms + 50ms safety margin = 800ms
|
||||||
|
// where 3 is the number of UAVTalk retries and 250ms is the UAVTalk timeout
|
||||||
|
Result doObjectAndWait(UAVObject *object, int timeout = 800);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void doObjectAndWaitImpl() = 0;
|
virtual void doObjectAndWaitImpl() = 0;
|
||||||
|
@ -48,10 +48,12 @@ Telemetry::Telemetry(UAVTalk *utalk, UAVObjectManager *objMngr) : objMngr(objMng
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Listen to new object creations
|
// Listen to new object creations
|
||||||
connect(objMngr, SIGNAL(newObject(UAVObject *)), this, SLOT(newObject(UAVObject *)));
|
// connection must be direct, if not, it is not possible to create and send (or request) an object in one go
|
||||||
connect(objMngr, SIGNAL(newInstance(UAVObject *)), this, SLOT(newInstance(UAVObject *)));
|
connect(objMngr, SIGNAL(newObject(UAVObject *)), this, SLOT(newObject(UAVObject *)), Qt::DirectConnection);
|
||||||
|
connect(objMngr, SIGNAL(newInstance(UAVObject *)), this, SLOT(newInstance(UAVObject *)), Qt::DirectConnection);
|
||||||
|
|
||||||
// Listen to transaction completions
|
// Listen to transaction completions
|
||||||
|
// these slots will be executed in the telemetry thread
|
||||||
// TODO should send a status (SUCCESS, FAILED, TIMEOUT)
|
// TODO should send a status (SUCCESS, FAILED, TIMEOUT)
|
||||||
connect(utalk, SIGNAL(transactionCompleted(UAVObject *, bool)), this, SLOT(transactionCompleted(UAVObject *, bool)));
|
connect(utalk, SIGNAL(transactionCompleted(UAVObject *, bool)), this, SLOT(transactionCompleted(UAVObject *, bool)));
|
||||||
|
|
||||||
@ -568,6 +570,10 @@ void Telemetry::newObject(UAVObject *obj)
|
|||||||
{
|
{
|
||||||
QMutexLocker locker(mutex);
|
QMutexLocker locker(mutex);
|
||||||
|
|
||||||
|
#ifdef VERBOSE_TELEMETRY
|
||||||
|
qDebug() << "Telemetry - new object" << obj->toStringBrief();
|
||||||
|
#endif
|
||||||
|
|
||||||
registerObject(obj);
|
registerObject(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,6 +581,10 @@ void Telemetry::newInstance(UAVObject *obj)
|
|||||||
{
|
{
|
||||||
QMutexLocker locker(mutex);
|
QMutexLocker locker(mutex);
|
||||||
|
|
||||||
|
#ifdef VERBOSE_TELEMETRY
|
||||||
|
qDebug() << "Telemetry - new object instance" << obj->toStringBrief();
|
||||||
|
#endif
|
||||||
|
|
||||||
registerObject(obj);
|
registerObject(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<field name="RollRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
<field name="RollRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
||||||
<field name="PitchRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
<field name="PitchRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
||||||
<field name="YawRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.00620,0.01000,0.00005,0.3" limits="%BE:0:0.01; %BE:0:0.01 ; ; "/>
|
<field name="YawRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.00620,0.01000,0.00005,0.3" limits="%BE:0:0.01; %BE:0:0.015 ; ; "/>
|
||||||
<field name="RollPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
<field name="RollPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||||
<field name="PitchPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
<field name="PitchPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||||
<field name="YawPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
<field name="YawPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<field name="RollRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
<field name="RollRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
||||||
<field name="PitchRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
<field name="PitchRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
||||||
<field name="YawRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.00620,0.01000,0.00005,0.3" limits="%BE:0:0.01; %BE:0:0.01 ; ; "/>
|
<field name="YawRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.00620,0.01000,0.00005,0.3" limits="%BE:0:0.01; %BE:0:0.015 ; ; "/>
|
||||||
<field name="RollPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
<field name="RollPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||||
<field name="PitchPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
<field name="PitchPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||||
<field name="YawPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
<field name="YawPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<field name="RollRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
<field name="RollRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
||||||
<field name="PitchRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
<field name="PitchRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
||||||
<field name="YawRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.00620,0.01000,0.00005,0.3" limits="%BE:0:0.01; %BE:0:0.01 ; ; "/>
|
<field name="YawRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.00620,0.01000,0.00005,0.3" limits="%BE:0:0.01; %BE:0:0.015 ; ; "/>
|
||||||
<field name="RollPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
<field name="RollPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||||
<field name="PitchPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
<field name="PitchPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||||
<field name="YawPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
<field name="YawPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||||
|
Loading…
Reference in New Issue
Block a user