diff --git a/ground/openpilotgcs/src/plugins/config/airframe.ui b/ground/openpilotgcs/src/plugins/config/airframe.ui index 620faf6c5..47006a789 100644 --- a/ground/openpilotgcs/src/plugins/config/airframe.ui +++ b/ground/openpilotgcs/src/plugins/config/airframe.ui @@ -6,8 +6,8 @@ 0 0 - 730 - 602 + 796 + 618 @@ -74,7 +74,7 @@ - 1 + 0 diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp index 10b1d6bbf..a7e46eb83 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp @@ -25,7 +25,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "configccpmwidget.h" -//#include "mixersettings.h" #include #include @@ -555,7 +554,7 @@ void ConfigCcpmWidget::updateThrottleCurveValue(QList curveValues0,doubl for (i=0; iCurveSettings->item(i, 1 )->text().toDouble(); + CurrentValue=m_ccpm->CurveSettings->item(i, 0 )->text().toDouble(); if (CurrentValue!=internalCurveValues[i]) { m_ccpm->CurveSettings->item(i, 0)->setText(QString().sprintf("%.3f",internalCurveValues.at(i))); @@ -1225,11 +1224,10 @@ void ConfigCcpmWidget::setMixer() } //get the user data for the curve into the mixer settings - for (i=0;i<5;i++) + for (i=0;i<5;i++) { mixerSettingsData.ThrottleCurve1[i] = m_ccpm->CurveSettings->item(i, 0)->text().toDouble(); - - for (i=0;i<5;i++) mixerSettingsData.ThrottleCurve2[i] = m_ccpm->CurveSettings->item(i, 1)->text().toDouble(); + } //mapping of collective input to curve 2... //MixerSettings.Curve2Source = Throttle,Roll,Pitch,Yaw,Accessory0,Accessory1,Accessory2,Accessory3,Accessory4,Accessory5 diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp index b1354a447..cbb7f94cf 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp @@ -182,18 +182,16 @@ QString ConfigFixedWingWidget::updateConfigObjectsFromWidgets() QString airframeType = "FixedWing"; // Save the curve (common to all Fixed wing frames) - UAVDataObject *obj = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); - + UAVDataObject* mixer = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); + Q_ASSERT(mixer); + // Remove Feed Forward, it is pointless on a plane: - UAVObjectField* field = obj->getField(QString("FeedForward")); + UAVObjectField* field = mixer->getField(QString("FeedForward")); field->setDouble(0); - field = obj->getField("ThrottleCurve1"); - QList curve = m_aircraft->fixedWingThrottle->getCurve(); - for (int i=0;isetValue(curve.at(i),i); - } - + // Set the throttle curve + setThrottleCurve(mixer,VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->fixedWingThrottle->getCurve()); + //All airframe types must start with "FixedWing" if (m_aircraft->fixedWingType->currentText() == "Elevator aileron rudder" ) { airframeType = "FixedWing"; @@ -229,36 +227,26 @@ void ConfigFixedWingWidget::refreshWidgetsValues(QString frameType) setComboCurrentIndex(m_aircraft->fwRudder1ChannelBox, fixed.FixedWingYaw1); setComboCurrentIndex(m_aircraft->fwRudder2ChannelBox, fixed.FixedWingYaw2); - UAVDataObject* obj; - UAVObjectField *field; + UAVDataObject* mixer= dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); + Q_ASSERT(mixer); + int channel; if (frameType == "FixedWingElevon") { // If the airframe is elevon, restore the slider setting - // Find the channel number for Elevon1 (FixedWingRoll1) - obj = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); - Q_ASSERT(obj); - int chMixerNumber = m_aircraft->fwAileron1ChannelBox->currentIndex()-1; - if (chMixerNumber >= 0) { // If for some reason the actuators were incoherent, we might fail here, hence the check. - field = obj->getField(mixerVectors.at(chMixerNumber)); - int ti = field->getElementNames().indexOf("Roll"); - m_aircraft->elevonSlider1->setValue(field->getDouble(ti)*100); - ti = field->getElementNames().indexOf("Pitch"); - m_aircraft->elevonSlider2->setValue(field->getDouble(ti)*100); + // Find the channel number for Elevon1 (FixedWingRoll1) + channel = m_aircraft->fwAileron1ChannelBox->currentIndex()-1; + if (channel > -1) { // If for some reason the actuators were incoherent, we might fail here, hence the check. + m_aircraft->elevonSlider1->setValue(getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_ROLL)*100); + m_aircraft->elevonSlider2->setValue(getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_PITCH)*100); } } - if (frameType == "FixedWingVtail") { - obj = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); - Q_ASSERT(obj); - int chMixerNumber = m_aircraft->fwElevator1ChannelBox->currentIndex()-1; - if (chMixerNumber >=0) { - field = obj->getField(mixerVectors.at(chMixerNumber)); - int ti = field->getElementNames().indexOf("Yaw"); - m_aircraft->elevonSlider1->setValue(field->getDouble(ti)*100); - ti = field->getElementNames().indexOf("Pitch"); - m_aircraft->elevonSlider2->setValue(field->getDouble(ti)*100); - } - } - + if (frameType == "FixedWingVtail") { + channel = m_aircraft->fwElevator1ChannelBox->currentIndex()-1; + if (channel > -1) { // If for some reason the actuators were incoherent, we might fail here, hence the check. + m_aircraft->elevonSlider1->setValue(getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_YAW)*100); + m_aircraft->elevonSlider2->setValue(getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_PITCH)*100); + } + } } @@ -312,7 +300,10 @@ bool ConfigFixedWingWidget::setupFrameFixedWing(QString airframeType) int channel; //disable all for (channel=0; channelfwEngineChannelBox->currentIndex()-1; @@ -396,7 +387,10 @@ bool ConfigFixedWingWidget::setupFrameElevon(QString airframeType) double value; //disable all for (channel=0; channelfwEngineChannelBox->currentIndex()-1; @@ -478,7 +472,10 @@ bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType) double value; //disable all for (channel=0; channelfwEngineChannelBox->currentIndex()-1; diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp index 35044965d..5b390c0e3 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp @@ -25,7 +25,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "configmultirotorwidget.h" -#include "mixersettings.h" #include #include @@ -296,12 +295,8 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets() field = obj->getField(QString("MaxAccel")); field->setDouble(m_aircraft->maxAccelSlider->value()); - // Curve is also common to all quads: - field = obj->getField("ThrottleCurve1"); - QList curve = m_aircraft->multiThrottleCurve->getCurve(); - for (int i=0;isetValue(curve.at(i),i); - } + // Curve is also common to all quads: + setThrottleCurve(obj, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->multiThrottleCurve->getCurve() ); if (m_aircraft->multirotorFrameType->currentText() == "Quad +") { airframeType = "QuadP"; @@ -1036,20 +1031,22 @@ bool ConfigMultiRotorWidget::setupMultiRotorMixer(double mixerFactors[8][3]) qDebug()< mmList; mmList << m_aircraft->multiMotorChannelBox1 << m_aircraft->multiMotorChannelBox2 << m_aircraft->multiMotorChannelBox3 << m_aircraft->multiMotorChannelBox4 << m_aircraft->multiMotorChannelBox5 << m_aircraft->multiMotorChannelBox6 << m_aircraft->multiMotorChannelBox7 << m_aircraft->multiMotorChannelBox8; - UAVDataObject *obj = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); - // 1. Assign the servo/motor/none for each channel - // Disable all - foreach(QString mixer, mixerTypes) { - field = obj->getField(mixer); - Q_ASSERT(field); - field->setValue("Disabled"); + + UAVDataObject* mixer = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); + Q_ASSERT(mixer); + + //disable all + for (int channel=0; channelmrPitchMixLevel->value()/100; double rFactor = (double)m_aircraft->mrRollMixLevel->value()/100; diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.h b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.h index 7a275e401..3ccc0de6b 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.h +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.h @@ -29,6 +29,7 @@ #include "ui_airframe.h" #include "../uavobjectwidgetutils/configtaskwidget.h" +#include "cfg_vehicletypes/vehicleconfig.h" #include "extensionsystem/pluginmanager.h" #include "uavobjectmanager.h" diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.cpp index a5b1ac8b4..549778540 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.cpp @@ -233,6 +233,60 @@ void VehicleConfig::setMixerVectorValue(UAVDataObject* mixer, int channel, Mixer } } +void VehicleConfig::setThrottleCurve(UAVDataObject* mixer, MixerThrottleCurveElem curveType, QList curve) +{ + QPointer field; + + switch (curveType) + { + case MIXER_THROTTLECURVE1: + { + field = mixer->getField("ThrottleCurve1"); + break; + } + case MIXER_THROTTLECURVE2: + { + field = mixer->getField("ThrottleCurve2"); + break; + } + } + + if (field && field->getNumElements() == curve.length()) { + for (int i=0;isetValue(curve.at(i),i); + } + } +} + +void VehicleConfig::getThrottleCurve(UAVDataObject* mixer, MixerThrottleCurveElem curveType, QList* curve) +{ + Q_ASSERT(mixer); + Q_ASSERT(curve); + + QPointer field; + + switch (curveType) + { + case MIXER_THROTTLECURVE1: + { + field = mixer->getField("ThrottleCurve1"); + break; + } + case MIXER_THROTTLECURVE2: + { + field = mixer->getField("ThrottleCurve2"); + break; + } + } + + if (field) { + curve->clear(); + for (unsigned int i=0; i < field->getNumElements(); i++) { + curve->append(field->getValue(i).toDouble()); + } + } +} + /** Reset the contents of a field */ diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.h b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.h index 9700a8789..343cfcf0c 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.h +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.h @@ -111,6 +111,9 @@ class VehicleConfig: public ConfigTaskWidget VehicleConfig(QWidget *parent = 0); ~VehicleConfig(); + /* Enumeration options for ThrottleCurves */ + typedef enum { MIXER_THROTTLECURVE1=0, MIXER_THROTTLECURVE2=1 } MixerThrottleCurveElem; + /* Enumeration options for field MixerType */ typedef enum { MIXERTYPE_DISABLED=0, MIXERTYPE_MOTOR=1, MIXERTYPE_SERVO=2, MIXERTYPE_CAMERAROLL=3, MIXERTYPE_CAMERAPITCH=4, MIXERTYPE_CAMERAYAW=5, MIXERTYPE_ACCESSORY0=6, MIXERTYPE_ACCESSORY1=7, MIXERTYPE_ACCESSORY2=8, MIXERTYPE_ACCESSORY3=9, MIXERTYPE_ACCESSORY4=10, MIXERTYPE_ACCESSORY5=11 } MixerTypeElem; /* Array element names for field MixerVector */ @@ -127,6 +130,8 @@ class VehicleConfig: public ConfigTaskWidget void resetMixerVector(UAVDataObject* mixer, int channel); QString getMixerType(UAVDataObject* mixer, int channel); void setMixerType(UAVDataObject* mixer, int channel, MixerTypeElem mixerType); + void setThrottleCurve(UAVDataObject* mixer, MixerThrottleCurveElem curveType, QList curve); + void getThrottleCurve(UAVDataObject* mixer, MixerThrottleCurveElem curveType, QList* curve); virtual void ResetActuators(GUIConfigDataUnion* configData); virtual QStringList getChannelDescriptions(); diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index 4a2130b26..ba1dbb74e 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -46,7 +46,7 @@ #define STICK_MIN_MOVE -8 #define STICK_MAX_MOVE 8 -ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent),wizardStep(wizardNone),loop(NULL),skipflag(false),transmitterType(heli) +ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent),wizardStep(wizardNone),transmitterType(heli),loop(NULL),skipflag(false) { manualCommandObj = ManualControlCommand::GetInstance(getObjectManager()); manualSettingsObj = ManualControlSettings::GetInstance(getObjectManager()); diff --git a/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp b/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp index 45e4285e9..19047af55 100644 --- a/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp @@ -36,10 +36,11 @@ #include #include #include +#include + #include "systemsettings.h" #include "mixersettings.h" #include "actuatorsettings.h" -#include /** Helper delegate for the custom mixer editor table. @@ -119,7 +120,8 @@ ConfigVehicleTypeWidget::ConfigVehicleTypeWidget(QWidget *parent) : ConfigTaskWi airframeTypes << "Fixed Wing" << "Multirotor" << "Helicopter" << "Ground" << "Custom"; m_aircraft->aircraftType->addItems(airframeTypes); - m_aircraft->aircraftType->setCurrentIndex(0); //Set default vehicle to Fixed Wing + m_aircraft->aircraftType->setCurrentIndex(0); //Set default vehicle to Fixed Wing + m_aircraft->airframesWidget->setCurrentIndex(0); // Force the tab index to match QStringList fixedWingTypes; fixedWingTypes << "Elevator aileron rudder" << "Elevon" << "Vtail"; @@ -780,77 +782,65 @@ void ConfigVehicleTypeWidget::resetField(UAVObjectField * field) Note: does NOT ask for an object refresh itself! */ void ConfigVehicleTypeWidget::updateCustomAirframeUI() -{ +{ + UAVDataObject* mixer = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); + Q_ASSERT(mixer); + + VehicleConfig* vconfig = new VehicleConfig(); + QList curveValues; - UAVDataObject* obj = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); - Q_ASSERT(obj); + // setup throttlecurve 1 + vconfig->getThrottleCurve(mixer,VehicleConfig::MIXER_THROTTLECURVE1,&curveValues); - UAVObjectField* field = obj->getField(QString("ThrottleCurve1")); - if (field) - { - // If the 1st element of the curve is <= -10, then the curve - // is a straight line (that's how the mixer works on the mainboard): - if (field->getValue(0).toInt() <= -10) { - m_aircraft->customThrottle1Curve->initLinearCurve(field->getNumElements(),(double)1); - } else { - double temp=0; - double value; - for (unsigned int i=0; i < field->getNumElements(); i++) { - value=field->getValue(i).toDouble(); - temp+=value; - curveValues.append(value); - } - if(temp==0) - m_aircraft->customThrottle1Curve->initLinearCurve(field->getNumElements(),(double)1); - else - m_aircraft->customThrottle1Curve->initCurve(curveValues); - } + int total = 0; + for (int i=0; icustomThrottle1Curve->initLinearCurve(curveValues.length(),(double)1); + } + else { + m_aircraft->customThrottle1Curve->initCurve(curveValues); } - curveValues.clear(); + // setup throttlecurve 2 + vconfig->getThrottleCurve(mixer,VehicleConfig::MIXER_THROTTLECURVE2,&curveValues); - field = obj->getField(QString("ThrottleCurve2")); - if (field) - { - // If the 1st element of the curve is <= -10, then the curve - // is a straight line (that's how the mixer works on the mainboard): - if (field->getValue(0).toInt() <= -10) { - m_aircraft->customThrottle2Curve->initLinearCurve(field->getNumElements(),(double)1); - } else { - for (unsigned int i=0; i < field->getNumElements(); i++) { - curveValues.append(field->getValue(i).toDouble()); - } - m_aircraft->customThrottle2Curve->initCurve(curveValues); - } + total = 0; + for (int i=0; icustomThrottle2Curve->initLinearCurve(curveValues.length(),(double)1); + } + else { + m_aircraft->customThrottle2Curve->initCurve(curveValues); } - // Update the table: - for (int i=0; i<8; i++) { - field = obj->getField(mixerTypes.at(i)); + + // Update the mixer table: + for (int channel=0; channel<8; channel++) { + UAVObjectField* field = mixer->getField(mixerTypes.at(channel)); if (field) { - QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,i); + QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,channel); if (q) { QString s = field->getValue().toString(); setComboCurrentIndex(q, q->findText(s)); } - field = obj->getField(mixerVectors.at(i)); - if (field) - { - int ti = field->getElementNames().indexOf("ThrottleCurve1"); - m_aircraft->customMixerTable->item(1,i)->setText(field->getValue(ti).toString()); - ti = field->getElementNames().indexOf("ThrottleCurve2"); - m_aircraft->customMixerTable->item(2,i)->setText(field->getValue(ti).toString()); - ti = field->getElementNames().indexOf("Roll"); - m_aircraft->customMixerTable->item(3,i)->setText(field->getValue(ti).toString()); - ti = field->getElementNames().indexOf("Pitch"); - m_aircraft->customMixerTable->item(4,i)->setText(field->getValue(ti).toString()); - ti = field->getElementNames().indexOf("Yaw"); - m_aircraft->customMixerTable->item(5,i)->setText(field->getValue(ti).toString()); - } + m_aircraft->customMixerTable->item(1,channel)->setText( + QString::number(vconfig->getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE1))); + m_aircraft->customMixerTable->item(2,channel)->setText( + QString::number(vconfig->getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE2))); + m_aircraft->customMixerTable->item(3,channel)->setText( + QString::number(vconfig->getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_ROLL))); + m_aircraft->customMixerTable->item(4,channel)->setText( + QString::number(vconfig->getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_PITCH))); + m_aircraft->customMixerTable->item(5,channel)->setText( + QString::number(vconfig->getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_YAW))); } } } @@ -865,9 +855,6 @@ void ConfigVehicleTypeWidget::updateCustomAirframeUI() */ void ConfigVehicleTypeWidget::updateObjectsFromWidgets() { - UAVDataObject* obj; - UAVObjectField* field; - QString airframeType = "Custom"; //Sets airframe type default to "Custom" if (m_aircraft->aircraftType->currentText() == "Fixed Wing") { airframeType = m_fixedwing->updateConfigObjectsFromWidgets(); @@ -882,45 +869,42 @@ void ConfigVehicleTypeWidget::updateObjectsFromWidgets() airframeType = m_groundvehicle->updateConfigObjectsFromWidgets(); } else { - obj = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); - field = obj->getField(QString("FeedForward")); - // Curve is also common to all quads: - field = obj->getField("ThrottleCurve1"); - QList curve = m_aircraft->customThrottle1Curve->getCurve(); - for (int i=0;isetValue(curve.at(i),i); - } + UAVDataObject* mixer = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); + Q_ASSERT(mixer); - field = obj->getField("ThrottleCurve2"); - curve.clear(); - curve = m_aircraft->customThrottle2Curve->getCurve(); - for (int i=0;isetValue(curve.at(i),i); - } + VehicleConfig* vconfig = new VehicleConfig(); + + vconfig->setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->customThrottle1Curve->getCurve()); + vconfig->setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->customThrottle2Curve->getCurve()); // Update the table: - for (int i=0; i<8; i++) { - field = obj->getField(mixerTypes.at(i)); - QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,i); - field->setValue(q->currentText()); - field = obj->getField(mixerVectors.at(i)); - int ti = field->getElementNames().indexOf("ThrottleCurve1"); - field->setValue(m_aircraft->customMixerTable->item(1,i)->text(),ti); - ti = field->getElementNames().indexOf("ThrottleCurve2"); - field->setValue(m_aircraft->customMixerTable->item(2,i)->text(),ti); - ti = field->getElementNames().indexOf("Roll"); - field->setValue(m_aircraft->customMixerTable->item(3,i)->text(),ti); - ti = field->getElementNames().indexOf("Pitch"); - field->setValue(m_aircraft->customMixerTable->item(4,i)->text(),ti); - ti = field->getElementNames().indexOf("Yaw"); - field->setValue(m_aircraft->customMixerTable->item(5,i)->text(),ti); + for (int channel=0; channel<8; channel++) { + QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,channel); + + vconfig->setMixerType(mixer,channel, + q->currentText() == "Servo" ? VehicleConfig::MIXERTYPE_SERVO : VehicleConfig::MIXERTYPE_MOTOR); + + vconfig->setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE1, + m_aircraft->customMixerTable->item(1,channel)->text().toDouble()); + vconfig->setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE2, + m_aircraft->customMixerTable->item(2,channel)->text().toDouble()); + vconfig->setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_ROLL, + m_aircraft->customMixerTable->item(3,channel)->text().toDouble()); + vconfig->setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_PITCH, + m_aircraft->customMixerTable->item(4,channel)->text().toDouble()); + vconfig->setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_YAW, + m_aircraft->customMixerTable->item(5,channel)->text().toDouble()); } } + // set the airframe type - obj = dynamic_cast(getObjectManager()->getObject(QString("SystemSettings"))); - field = obj->getField(QString("AirframeType")); - field->setValue(airframeType); + UAVDataObject* system = dynamic_cast(getObjectManager()->getObject(QString("SystemSettings"))); + Q_ASSERT(system); + + QPointer field = system->getField(QString("AirframeType")); + if (field) + field->setValue(airframeType); updateCustomAirframeUI(); } diff --git a/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.h b/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.h index d128acaf5..3cca72ba1 100644 --- a/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.h +++ b/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.h @@ -38,6 +38,7 @@ #include "cfg_vehicletypes/configfixedwingwidget.h" #include "cfg_vehicletypes/configmultirotorwidget.h" #include "cfg_vehicletypes/configgroundvehiclewidget.h" +#include "cfg_vehicletypes/vehicleconfig.h" #include #include diff --git a/ground/openpilotgcs/src/plugins/config/stabilization.ui b/ground/openpilotgcs/src/plugins/config/stabilization.ui index fd6b01ca8..3f985a66e 100755 --- a/ground/openpilotgcs/src/plugins/config/stabilization.ui +++ b/ground/openpilotgcs/src/plugins/config/stabilization.ui @@ -495,7 +495,7 @@ 0 - -114 + 0 673 790 @@ -11797,7 +11797,7 @@ border-radius: 4; - + @@ -11850,7 +11850,7 @@ border-radius: 4; - + @@ -14693,6 +14693,19 @@ value as the Kp. + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -15272,7 +15285,7 @@ value as the Kp. false - + @@ -17936,7 +17949,7 @@ border-radius: 5; - + @@ -17999,6 +18012,19 @@ border-radius: 4; + + + + Qt::Horizontal + + + + 40 + 20 + + + + diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2.pro b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2.pro index f567fc401..58475b05f 100644 --- a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2.pro +++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2.pro @@ -1,5 +1,5 @@ TEMPLATE = lib -TARGET = HITLV2 +TARGET = HITLv2 QT += network include(../../openpilotgcsplugin.pri) include(hitlv2_dependencies.pri) diff --git a/ground/openpilotgcs/src/plugins/serialconnection/serialplugin.cpp b/ground/openpilotgcs/src/plugins/serialconnection/serialplugin.cpp index f83efe968..1f7a476f0 100644 --- a/ground/openpilotgcs/src/plugins/serialconnection/serialplugin.cpp +++ b/ground/openpilotgcs/src/plugins/serialconnection/serialplugin.cpp @@ -128,7 +128,7 @@ QList SerialConnection::availableDevices() foreach( QextPortInfo port, ports ) { device d; d.displayName=port.friendName; - d.name=port.friendName; + d.name=port.physName; list.append(d); } } @@ -143,7 +143,7 @@ QIODevice *SerialConnection::openDevice(const QString &deviceName) } QList ports = QextSerialEnumerator::getPorts(); foreach( QextPortInfo port, ports ) { - if(port.friendName == deviceName) + if(port.physName == deviceName) { //we need to handle port settings here... PortSettings set; diff --git a/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.cpp b/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.cpp index ced1bfcba..a6924e71d 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.cpp @@ -27,6 +27,77 @@ #include "treeitem.h" +/* Constructor */ +HighLightManager::HighLightManager(long checkingInterval) +{ + // Start the timer and connect it to the callback + m_expirationTimer.start(checkingInterval); + connect(&m_expirationTimer, SIGNAL(timeout()), this, SLOT(checkItemsExpired())); +} + +/* + * Called to add item to list. Item is only added if absent. + * Returns true if item was added, otherwise false. + */ +bool HighLightManager::add(TreeItem *itemToAdd) +{ + // Lock to ensure thread safety + QMutexLocker locker(&m_listMutex); + + // Check so that the item isn't already in the list + if(!m_itemsList.contains(itemToAdd)) + { + m_itemsList.append(itemToAdd); + return true; + } + return false; +} + +/* + * Called to remove item from list. + * Returns true if item was removed, otherwise false. + */ +bool HighLightManager::remove(TreeItem *itemToRemove) +{ + // Lock to ensure thread safety + QMutexLocker locker(&m_listMutex); + + // Remove item and return result + return m_itemsList.removeOne(itemToRemove); +} + +/* + * Callback called periodically by the timer. + * This method checks for expired highlights and + * removes them if they are expired. + * Expired highlights are restored. + */ +void HighLightManager::checkItemsExpired() +{ + // Lock to ensure thread safety + QMutexLocker locker(&m_listMutex); + + // Get a mutable iterator for the list + QMutableLinkedListIterator iter(m_itemsList); + + // This is the timestamp to compare with + QTime now = QTime::currentTime(); + + // Loop over all items, check if they expired. + while(iter.hasNext()) + { + TreeItem* item = iter.next(); + if(item->getHiglightExpires() < now) + { + // If expired, call removeHighlight + item->removeHighlight(); + + // Remove from list since it is restored. + iter.remove(); + } + } +} + int TreeItem::m_highlightTimeMs = 500; TreeItem::TreeItem(const QList &data, TreeItem *parent) : @@ -36,7 +107,6 @@ TreeItem::TreeItem(const QList &data, TreeItem *parent) : m_highlight(false), m_changed(false) { - connect(&m_timer, SIGNAL(timeout()), this, SLOT(removeHighlight())); } TreeItem::TreeItem(const QVariant &data, TreeItem *parent) : @@ -46,7 +116,6 @@ TreeItem::TreeItem(const QVariant &data, TreeItem *parent) : m_changed(false) { m_data << data << "" << ""; - connect(&m_timer, SIGNAL(timeout()), this, SLOT(removeHighlight())); } TreeItem::~TreeItem() @@ -108,21 +177,50 @@ void TreeItem::apply() { child->apply(); } +/* + * Called after a value has changed to trigger highlightning of tree item. + */ void TreeItem::setHighlight(bool highlight) { m_highlight = highlight; m_changed = false; if (highlight) { - if (m_timer.isActive()) { - m_timer.stop(); + // Update the expires timestamp + m_highlightExpires = QTime::currentTime().addMSecs(m_highlightTimeMs); + + // Add to highlightmanager + if(m_highlightManager->add(this)) + { + // Only emit signal if it was added + emit updateHighlight(this); } - m_timer.setSingleShot(true); - m_timer.start(m_highlightTimeMs); } - emit updateHighlight(this); + else if(m_highlightManager->remove(this)) + { + // Only emit signal if it was removed + emit updateHighlight(this); + } + + // If we have a parent, call recursively to update highlight status of parents. + // This will ensure that the root of a leaf that is changed also is highlighted. + // Only updates that really changes values will trigger highlight of parents. + if(m_parent) + { + m_parent->setHighlight(highlight); + } } void TreeItem::removeHighlight() { m_highlight = false; - update(); + //update(); emit updateHighlight(this); } + +void TreeItem::setHighlightManager(HighLightManager *mgr) +{ + m_highlightManager = mgr; +} + +QTime TreeItem::getHiglightExpires() +{ + return m_highlightExpires; +} diff --git a/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.h b/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.h index 937631b05..c4f8e0355 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.h +++ b/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.h @@ -32,10 +32,58 @@ #include "uavmetaobject.h" #include "uavobjectfield.h" #include +#include #include +#include #include #include +#include +class TreeItem; + +/* +* Small utility class that handles the higlighting of +* tree grid items. +* Basicly it maintains all items due to be restored to +* non highlighted state in a linked list. +* A timer traverses this list periodically to find out +* if any of the items should be restored. All items are +* updated withan expiration timestamp when they expires. +* An item that is beeing restored is removed from the +* list and its removeHighlight() method is called. Items +* that are not expired are left in the list til next time. +* Items that are updated during the expiration time are +* left untouched in the list. This reduces unwanted emits +* of signals to the repaint/update function. +*/ +class HighLightManager : public QObject +{ +Q_OBJECT +public: + // Constructor taking the checking interval in ms. + HighLightManager(long checkingInterval); + + // This is called when an item has been set to + // highlighted = true. + bool add(TreeItem* itemToAdd); + + //This is called when an item is set to highlighted = false; + bool remove(TreeItem* itemToRemove); + +private slots: + // Timer callback method. + void checkItemsExpired(); + +private: + // The timer checking highlight expiration. + QTimer m_expirationTimer; + + // The list holding all items due to be updated. + QLinkedList m_itemsList; + + //Mutex to lock when accessing list. + QMutex m_listMutex; +}; class TreeItem : public QObject { @@ -77,11 +125,16 @@ public: inline bool changed() { return m_changed; } inline void setChanged(bool changed) { m_changed = changed; } + virtual void setHighlightManager(HighLightManager* mgr); + + QTime getHiglightExpires(); + + virtual void removeHighlight(); + signals: void updateHighlight(TreeItem*); private slots: - void removeHighlight(); private: QList m_children; @@ -91,7 +144,8 @@ private: TreeItem *m_parent; bool m_highlight; bool m_changed; - QTimer m_timer; + QTime m_highlightExpires; + HighLightManager* m_highlightManager; public: static const int dataColumn = 1; private: diff --git a/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.cpp b/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.cpp index ac2e4bcee..9bd8b20b4 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.cpp @@ -47,6 +47,8 @@ UAVObjectTreeModel::UAVObjectTreeModel(QObject *parent) : ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); UAVObjectManager *objManager = pm->getObject(); + // Create highlight manager, let it run every 300 ms. + m_highlightManager = new HighLightManager(300); connect(objManager, SIGNAL(newObject(UAVObject*)), this, SLOT(newObject(UAVObject*))); connect(objManager, SIGNAL(newInstance(UAVObject*)), this, SLOT(newObject(UAVObject*))); @@ -56,6 +58,7 @@ UAVObjectTreeModel::UAVObjectTreeModel(QObject *parent) : UAVObjectTreeModel::~UAVObjectTreeModel() { + delete m_highlightManager; delete m_rootItem; } @@ -67,9 +70,12 @@ void UAVObjectTreeModel::setupModelData(UAVObjectManager *objManager) m_rootItem = new TreeItem(rootData); m_settingsTree = new TopTreeItem(tr("Settings"), m_rootItem); + m_settingsTree->setHighlightManager(m_highlightManager); m_rootItem->appendChild(m_settingsTree); m_nonSettingsTree = new TopTreeItem(tr("Data Objects"), m_rootItem); + m_nonSettingsTree->setHighlightManager(m_highlightManager); m_rootItem->appendChild(m_nonSettingsTree); + m_rootItem->setHighlightManager(m_highlightManager); connect(m_settingsTree, SIGNAL(updateHighlight(TreeItem*)), this, SLOT(updateHighlight(TreeItem*))); connect(m_nonSettingsTree, SIGNAL(updateHighlight(TreeItem*)), this, SLOT(updateHighlight(TreeItem*))); @@ -96,6 +102,7 @@ void UAVObjectTreeModel::addDataObject(UAVDataObject *obj) addInstance(obj, root->child(index)); } else { DataObjectTreeItem *data = new DataObjectTreeItem(obj->getName() + " (" + QString::number(obj->getNumBytes()) + " bytes)"); + data->setHighlightManager(m_highlightManager); connect(data, SIGNAL(updateHighlight(TreeItem*)), this, SLOT(updateHighlight(TreeItem*))); int index = root->nameIndex(obj->getName()); root->insert(index, data); @@ -110,6 +117,7 @@ void UAVObjectTreeModel::addMetaObject(UAVMetaObject *obj, TreeItem *parent) { connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(highlightUpdatedObject(UAVObject*))); MetaObjectTreeItem *meta = new MetaObjectTreeItem(obj, tr("Meta Data")); + meta->setHighlightManager(m_highlightManager); connect(meta, SIGNAL(updateHighlight(TreeItem*)), this, SLOT(updateHighlight(TreeItem*))); foreach (UAVObjectField *field, obj->getFields()) { if (field->getNumElements() > 1) { @@ -132,6 +140,7 @@ void UAVObjectTreeModel::addInstance(UAVObject *obj, TreeItem *parent) } else { QString name = tr("Instance") + " " + QString::number(obj->getInstID()); item = new InstanceTreeItem(obj, name); + item->setHighlightManager(m_highlightManager); connect(item, SIGNAL(updateHighlight(TreeItem*)), this, SLOT(updateHighlight(TreeItem*))); parent->appendChild(item); } @@ -148,6 +157,7 @@ void UAVObjectTreeModel::addInstance(UAVObject *obj, TreeItem *parent) void UAVObjectTreeModel::addArrayField(UAVObjectField *field, TreeItem *parent) { TreeItem *item = new ArrayFieldTreeItem(field->getName()); + item->setHighlightManager(m_highlightManager); connect(item, SIGNAL(updateHighlight(TreeItem*)), this, SLOT(updateHighlight(TreeItem*))); for (uint i = 0; i < field->getNumElements(); ++i) { addSingleField(i, field, item); @@ -192,6 +202,7 @@ void UAVObjectTreeModel::addSingleField(int index, UAVObjectField *field, TreeIt default: Q_ASSERT(false); } + item->setHighlightManager(m_highlightManager); connect(item, SIGNAL(updateHighlight(TreeItem*)), this, SLOT(updateHighlight(TreeItem*))); parent->appendChild(item); } @@ -352,7 +363,6 @@ void UAVObjectTreeModel::highlightUpdatedObject(UAVObject *obj) Q_ASSERT(obj); ObjectTreeItem *item = findObjectTreeItem(obj); Q_ASSERT(item); - item->setHighlight(true); item->update(); QModelIndex itemIndex = index(item); Q_ASSERT(itemIndex != QModelIndex()); diff --git a/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.h b/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.h index 17399611c..d9787e3a7 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.h +++ b/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.h @@ -97,6 +97,9 @@ private: int m_recentlyUpdatedTimeout; QColor m_recentlyUpdatedColor; QColor m_manuallyChangedColor; + + // Highlight manager to handle highlighting of tree items. + HighLightManager *m_highlightManager; }; #endif // UAVOBJECTTREEMODEL_H diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h index 76d6b55bd..3cac0abc0 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h @@ -84,7 +84,7 @@ public: }; ConfigTaskWidget(QWidget *parent = 0); - ~ConfigTaskWidget(); + virtual ~ConfigTaskWidget(); void disableMouseWheelEvents(); bool eventFilter( QObject * obj, QEvent * evt ); diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.cpp b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.cpp index 6eaa8f5ed..64b9912b1 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.cpp @@ -43,6 +43,7 @@ Node::Node(MixerCurveWidget *graphWidget) setCacheMode(DeviceCoordinateCache); setZValue(-1); vertical = false; + value = 0; } void Node::addEdge(Edge *edge) @@ -98,6 +99,15 @@ void Node::verticalMove(bool flag){ vertical = flag; } +double Node::getValue() { + return value; +} + +void Node::setValue(double val) { + value = val; +} + + QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value) { @@ -117,11 +127,19 @@ QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value) newPos.setY(h); return newPos; } - case ItemPositionHasChanged: + case ItemPositionHasChanged: { foreach (Edge *edge, edgeList) edge->adjust(); - graph->itemMoved((h-newPos.y())/h); + + double min = graph->getMin(); + double range = graph->getMax() - min; + double ratio = (h - newPos.y()) / h; + double val = (range * ratio ) + min; + setValue(val); + + graph->itemMoved(val); break; + } default: break; }; diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.h b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.h index 987875e32..19b940625 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.h +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.h @@ -48,12 +48,16 @@ public: enum { Type = UserType + 1 }; int type() const { return Type; } + void verticalMove(bool flag); QRectF boundingRect() const; QPainterPath shape() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + void setValue(double val); + double getValue(); + protected: QVariant itemChange(GraphicsItemChange change, const QVariant &value); @@ -61,6 +65,8 @@ protected: void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); private: + + double value; QList edgeList; QPointF newPos; MixerCurveWidget *graph; diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp index f21d782f6..56ed8bee9 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp @@ -32,8 +32,6 @@ #include #include - - /* * Initialize the widget */ @@ -74,11 +72,48 @@ MixerCurveWidget::MixerCurveWidget(QWidget *parent) : QGraphicsView(parent) scene->setSceneRect(plot->boundingRect()); setScene(scene); + initNodes(MixerCurveWidget::NODE_NUMELEM); } MixerCurveWidget::~MixerCurveWidget() { + for (int i=0; i= 0 && index < nodePool.count()) + { + node = nodePool.at(index); + } + else { + node = new Node(this); + nodePool.append(node); + } + return node; +} + +Edge* MixerCurveWidget::getEdge(int index, Node* sourceNode, Node* destNode) +{ + Edge* edge; + + if (index >= 0 && index < edgePool.count()) + { + edge = edgePool.at(index); + edge->setSourceNode(sourceNode); + edge->setDestNode(destNode); + } + else { + edge = new Edge(sourceNode,destNode); + edgePool.append(edge); + } + return edge; } /** @@ -89,60 +124,62 @@ MixerCurveWidget::~MixerCurveWidget() */ void MixerCurveWidget::initCurve(QList points) { - if (points.length() < 2) return; // We need at least 2 points on a curve! - // First of all, reset the list - // TODO: one edge might not get deleted properly, small mem leak maybe... + if (nodeList.count() != points.count()) + initNodes(points.count()); + + // finally, set node positions + setCurve(points); +} + +void MixerCurveWidget::initNodes(int numPoints) +{ + // First of all, clear any existing list + if (nodeList.count()) { foreach (Node *node, nodeList ) { QList edges = node->edges(); foreach(Edge *edge, edges) { - if (scene()->items().contains(edge)) - scene()->removeItem(edge); - else + if (edge->destNode() == node) { delete edge; + } + else { + scene()->removeItem(edge); + } } - scene()->removeItem(node); - delete node; - } - nodeList.clear(); + scene()->removeItem(node); + } + + nodeList.clear(); + } + + // Create the nodes and edges + Node* prevNode = 0; + for (int i=0; iboundingRect().width()/(points.length()-1); - qreal h = plot->boundingRect().height(); - for (int i=0; iaddItem(node); nodeList.append(node); - double val = points.at(i); - if (val>curveMax) - val=curveMax; - if (valsetPos(w*i,h-val*h); - node->verticalMove(true); - } + scene()->addItem(node); - // ... and link them together: - for (int i=0; i<(points.length()-1); i++) { - scene()->addItem(new Edge(nodeList.at(i),nodeList.at(i+1))); - } + if (prevNode) { + scene()->addItem(getEdge(i, prevNode, node)); + } + prevNode = node; + } } - /** Returns the current curve settings */ QList MixerCurveWidget::getCurve() { + QList list; - qreal h = plot->boundingRect().height(); foreach(Node *node, nodeList) { - list.append(((curveMax-curveMin)*(h-node->pos().y())/h)+curveMin); + list.append(node->getValue()); } return list; @@ -150,11 +187,15 @@ QList MixerCurveWidget::getCurve() { /** Sets a linear graph */ -void MixerCurveWidget::initLinearCurve(quint32 numPoints, double maxValue) +void MixerCurveWidget::initLinearCurve(quint32 numPoints, double maxValue, double minValue) { + Q_UNUSED(maxValue); + Q_UNUSED(minValue); + QList points; for (double i=0; i points) { - if (nodeList.length()<1) - { - initCurve(points); - } - else - { - qreal w = plot->boundingRect().width()/(points.length()-1); - qreal h = plot->boundingRect().height(); - for (int i=0; icurveMax) - val=curveMax; - if (valsetPos(w*i,h-val*h); - } + curveUpdating = true; + + if (nodeList.count() != points.count()) + initNodes(points.count()); + + double min = curveMin + 10; + double max = curveMax + 10; + + qreal w = plot->boundingRect().width()/(points.count()-1); + qreal h = plot->boundingRect().height(); + for (int i=0; i curveMax) + val = curveMax; + + val += 10; + val -= min; + val /= (max - min); + + nodeList.at(i)->setPos(w*i, h - (val*h)); + nodeList.at(i)->verticalMove(true); } + + curveUpdating = false; + + emit curveUpdated(points, (double)0); } @@ -205,8 +256,10 @@ void MixerCurveWidget::resizeEvent(QResizeEvent* event) void MixerCurveWidget::itemMoved(double itemValue) { - QList list = getCurve(); - emit curveUpdated(list, itemValue); + if (!curveUpdating) { + QList list = getCurve(); + emit curveUpdated(list, itemValue); + } } void MixerCurveWidget::setMin(double value) @@ -217,6 +270,14 @@ void MixerCurveWidget::setMax(double value) { curveMax = value; } +double MixerCurveWidget::getMin() +{ + return curveMin; +} +double MixerCurveWidget::getMax() +{ + return curveMax; +} void MixerCurveWidget::setRange(double min, double max) { curveMin = min; diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.h b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.h index 9a14123a7..92c9c3a8c 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.h +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.h @@ -31,6 +31,7 @@ #include #include #include +#include #include "mixercurvepoint.h" #include "mixercurveline.h" #include "uavobjectwidgetutils_global.h" @@ -45,12 +46,16 @@ public: void itemMoved(double itemValue); // Callback when a point is moved, to be updated void initCurve (QList points); QList getCurve(); - void initLinearCurve(quint32 numPoints, double maxValue); + void initLinearCurve(quint32 numPoints, double maxValue = 1, double minValue = 0); void setCurve(QList); void setMin(double value); + double getMin(); void setMax(double value); + double getMax(); void setRange(double min, double max); + static const int NODE_NUMELEM = 5; + signals: void curveUpdated(QList, double ); @@ -58,9 +63,19 @@ private slots: private: QGraphicsSvgItem *plot; + + QList nodePool; + QList edgePool; QList nodeList; + QList points; + double curveMin; double curveMax; + bool curveUpdating; + + void initNodes(int numPoints); + Node* getNode(int index); + Edge* getEdge(int index, Node* sourceNode, Node* destNode); protected: void showEvent(QShowEvent *event); diff --git a/ground/openpilotgcs/src/plugins/uavtalk/uavtalk.cpp b/ground/openpilotgcs/src/plugins/uavtalk/uavtalk.cpp index dd0fb21a7..d12d6d9fe 100644 --- a/ground/openpilotgcs/src/plugins/uavtalk/uavtalk.cpp +++ b/ground/openpilotgcs/src/plugins/uavtalk/uavtalk.cpp @@ -110,10 +110,12 @@ void UAVTalk::processInputStream() { quint8 tmp; - while (io->bytesAvailable() > 0) - { - io->read((char*)&tmp, 1); - processInputByte(tmp); + if (io && io->isReadable()) { + while (io->bytesAvailable() > 0) + { + io->read((char*)&tmp, 1); + processInputByte(tmp); + } } } @@ -731,9 +733,8 @@ bool UAVTalk::transmitNack(quint32 objId) qToLittleEndian(dataOffset, &txBuffer[2]); - // Send buffer, check that the transmit backlog does not grow above limit - if ( io->bytesToWrite() < TX_BUFFER_SIZE ) + if (io && io->isWritable() && io->bytesToWrite() < TX_BUFFER_SIZE ) { io->write((const char*)txBuffer, dataOffset+CHECKSUM_LENGTH); } @@ -823,7 +824,7 @@ bool UAVTalk::transmitSingleObject(UAVObject* obj, quint8 type, bool allInstance txBuffer[dataOffset+length] = updateCRC(0, txBuffer, dataOffset + length); // Send buffer, check that the transmit backlog does not grow above limit - if ( io->bytesToWrite() < TX_BUFFER_SIZE ) + if (io && io->isWritable() && io->bytesToWrite() < TX_BUFFER_SIZE ) { io->write((const char*)txBuffer, dataOffset+length+CHECKSUM_LENGTH); } diff --git a/ground/openpilotgcs/src/plugins/uavtalk/uavtalk.h b/ground/openpilotgcs/src/plugins/uavtalk/uavtalk.h index 217f110d9..6f0bf2e8d 100644 --- a/ground/openpilotgcs/src/plugins/uavtalk/uavtalk.h +++ b/ground/openpilotgcs/src/plugins/uavtalk/uavtalk.h @@ -27,6 +27,7 @@ #ifndef UAVTALK_H #define UAVTALK_H +#include #include #include #include @@ -100,7 +101,7 @@ private: typedef enum {STATE_SYNC, STATE_TYPE, STATE_SIZE, STATE_OBJID, STATE_INSTID, STATE_DATA, STATE_CS} RxStateType; // Variables - QIODevice* io; + QPointer io; UAVObjectManager* objMngr; QMutex* mutex; QMap transMap;