From 37e5e0d2a227106277260fab1b955cd1e80a1848 Mon Sep 17 00:00:00 2001 From: a*morale Date: Sun, 3 Jun 2012 20:31:48 +0200 Subject: [PATCH 01/16] Fixes a problem in OSX that prevent to use two serial ports with the same displayed name (for example from USB multiple serial adapter) Now serial ports are internally referred using their physName instead of friendName --- .../src/plugins/serialconnection/serialplugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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; From 1fad5c9fc2dfd3cee7b06a0b2e5fd903abf156c1 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 12 Jun 2012 01:51:57 -0500 Subject: [PATCH 02/16] Fix the stabilization expert UI so the label is in the right place --- .../src/plugins/config/stabilization.ui | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) 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 + + + + From 295fa4a8f34773142a05edf3cae28be1afa66bcf Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 12 Jun 2012 23:12:53 -0500 Subject: [PATCH 03/16] Fix bug where the aircraft gadget initially shows the quad tab but the selector says plane. --- ground/openpilotgcs/src/plugins/config/airframe.ui | 6 +++--- .../src/plugins/config/configvehicletypewidget.cpp | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) 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/configvehicletypewidget.cpp b/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp index 45e4285e9..613ca5ae0 100644 --- a/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp @@ -119,7 +119,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"; From 8283d4280e6577d57b6a68868b8e793e10fe1088 Mon Sep 17 00:00:00 2001 From: Mike LaBranche Date: Wed, 13 Jun 2012 14:57:43 -0700 Subject: [PATCH 04/16] UAVTalk, change private member QIODevice* io to smart pointer QPointer --- .../openpilotgcs/src/plugins/uavtalk/uavtalk.cpp | 15 ++++++++------- ground/openpilotgcs/src/plugins/uavtalk/uavtalk.h | 3 ++- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/uavtalk/uavtalk.cpp b/ground/openpilotgcs/src/plugins/uavtalk/uavtalk.cpp index 4c218379d..03da96a6f 100644 --- a/ground/openpilotgcs/src/plugins/uavtalk/uavtalk.cpp +++ b/ground/openpilotgcs/src/plugins/uavtalk/uavtalk.cpp @@ -112,10 +112,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); + } } } @@ -719,9 +721,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); } @@ -811,7 +812,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 163fb9fa3..de7ca8542 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 @@ -93,7 +94,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; UAVObject* respObj; From 8de40c7847c24becca400a27d38745dcc7067578 Mon Sep 17 00:00:00 2001 From: Mike LaBranche Date: Wed, 13 Jun 2012 15:09:54 -0700 Subject: [PATCH 05/16] BugFix: ConfigFixedWing reset the mixer vectors to zero prior to writing anew. --- .../plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp index b1354a447..8b2e428e2 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp @@ -312,7 +312,10 @@ bool ConfigFixedWingWidget::setupFrameFixedWing(QString airframeType) int channel; //disable all for (channel=0; channelfwEngineChannelBox->currentIndex()-1; From a7ae258bc8c0c66cbba5a68cc5b6ac577bf7e68c Mon Sep 17 00:00:00 2001 From: Mike LaBranche Date: Wed, 13 Jun 2012 15:14:18 -0700 Subject: [PATCH 06/16] Bugfix, oops: missed a couple resetMixerVector opportunities. --- .../config/cfg_vehicletypes/configfixedwingwidget.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp index 8b2e428e2..dc1f6bbcc 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp @@ -399,7 +399,10 @@ bool ConfigFixedWingWidget::setupFrameElevon(QString airframeType) double value; //disable all for (channel=0; channelfwEngineChannelBox->currentIndex()-1; @@ -481,7 +484,10 @@ bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType) double value; //disable all for (channel=0; channelfwEngineChannelBox->currentIndex()-1; From c1689b220546985eeb4e305dca5e509a5e95e3bd Mon Sep 17 00:00:00 2001 From: Mike LaBranche Date: Thu, 14 Jun 2012 15:40:17 -0700 Subject: [PATCH 07/16] VehicleConfig: add set/getThrottleCurve, enhance configwidgets to consume; add resetMixerVector call in multirotor; ConfigVehicleType now VehicleConfig aware --- .../cfg_vehicletypes/configccpmwidget.cpp | 1 - .../configfixedwingwidget.cpp | 56 +++--- .../configmultirotorwidget.cpp | 29 ++- .../cfg_vehicletypes/configmultirotorwidget.h | 1 + .../config/cfg_vehicletypes/vehicleconfig.cpp | 54 ++++++ .../config/cfg_vehicletypes/vehicleconfig.h | 5 + .../config/configvehicletypewidget.cpp | 165 ++++++++---------- .../plugins/config/configvehicletypewidget.h | 1 + 8 files changed, 170 insertions(+), 142 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp index 10b1d6bbf..4a6ca62a9 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 diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp index dc1f6bbcc..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); + } + } } 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/configvehicletypewidget.cpp b/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp index 613ca5ae0..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. @@ -781,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))); } } } @@ -866,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(); @@ -883,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 From d03282d9b0177c6b19a6157ed768d7a9a482cffe Mon Sep 17 00:00:00 2001 From: Fredrik Arvidsson Date: Sat, 16 Jun 2012 17:38:05 +0200 Subject: [PATCH 08/16] Changed the way change hilight of three cells works to bring down the number of QTimer instances and the number of redraws to hopefully increase performance. Changed so that when a child gets hilighted it will hilight its parent. --- .../src/plugins/uavobjectbrowser/treeitem.cpp | 70 ++++++++++++++++--- .../src/plugins/uavobjectbrowser/treeitem.h | 31 +++++++- .../uavobjectbrowser/uavobjecttreemodel.cpp | 12 +++- .../uavobjectbrowser/uavobjecttreemodel.h | 1 + 4 files changed, 102 insertions(+), 12 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.cpp b/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.cpp index ced1bfcba..b8cea004f 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.cpp @@ -27,6 +27,45 @@ #include "treeitem.h" +HighLightManager::HighLightManager(long checkingInterval) +{ + m_expirationTimer.start(checkingInterval); + connect(&m_expirationTimer, SIGNAL(timeout()), this, SLOT(checkItemsExpired())); +} + +bool HighLightManager::add(TreeItem *itemToAdd) +{ + QMutexLocker locker(&m_listMutex); + if(!m_itemsList.contains(itemToAdd)) + { + m_itemsList.append(itemToAdd); + return true; + } + return false; +} + +bool HighLightManager::remove(TreeItem *itemToRemove) +{ + QMutexLocker locker(&m_listMutex); + return m_itemsList.removeOne(itemToRemove); +} + +void HighLightManager::checkItemsExpired() +{ + QMutexLocker locker(&m_listMutex); + QMutableLinkedListIterator iter(m_itemsList); + QTime now = QTime::currentTime(); + while(iter.hasNext()) + { + TreeItem* item = iter.next(); + if(item->getHiglightExpires() < now) + { + item->removeHighlight(); + iter.remove(); + } + } +} + int TreeItem::m_highlightTimeMs = 500; TreeItem::TreeItem(const QList &data, TreeItem *parent) : @@ -36,7 +75,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 +84,6 @@ TreeItem::TreeItem(const QVariant &data, TreeItem *parent) : m_changed(false) { m_data << data << "" << ""; - connect(&m_timer, SIGNAL(timeout()), this, SLOT(removeHighlight())); } TreeItem::~TreeItem() @@ -112,17 +149,34 @@ void TreeItem::setHighlight(bool highlight) { m_highlight = highlight; m_changed = false; if (highlight) { - if (m_timer.isActive()) { - m_timer.stop(); + m_highlightExpires = QTime::currentTime().addMSecs(m_highlightTimeMs); + if(m_highlightManager->add(this)) + { + emit updateHighlight(this); } - m_timer.setSingleShot(true); - m_timer.start(m_highlightTimeMs); } - emit updateHighlight(this); + else if(m_highlightManager->remove(this)) + { + emit updateHighlight(this); + } + 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..494fb9a0b 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.h +++ b/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.h @@ -32,10 +32,31 @@ #include "uavmetaobject.h" #include "uavobjectfield.h" #include +#include #include +#include #include #include +#include +class TreeItem; + +class HighLightManager : public QObject +{ +Q_OBJECT +public: + HighLightManager(long checkingInterval); + bool add(TreeItem* itemToAdd); + bool remove(TreeItem* itemToRemove); + +private slots: + void checkItemsExpired(); + +private: + QTimer m_expirationTimer; + QLinkedList m_itemsList; + QMutex m_listMutex; +}; class TreeItem : public QObject { @@ -77,11 +98,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 +117,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..e2377da9a 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.cpp @@ -46,7 +46,7 @@ UAVObjectTreeModel::UAVObjectTreeModel(QObject *parent) : { ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); UAVObjectManager *objManager = pm->getObject(); - + 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 +56,7 @@ UAVObjectTreeModel::UAVObjectTreeModel(QObject *parent) : UAVObjectTreeModel::~UAVObjectTreeModel() { + delete m_highlightManager; delete m_rootItem; } @@ -67,9 +68,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 +100,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 +115,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 +138,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 +155,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 +200,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 +361,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..5e67840cd 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.h +++ b/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.h @@ -97,6 +97,7 @@ private: int m_recentlyUpdatedTimeout; QColor m_recentlyUpdatedColor; QColor m_manuallyChangedColor; + HighLightManager *m_highlightManager; }; #endif // UAVOBJECTTREEMODEL_H From 4120eb300c726e11bd7f039e687698823ca43cbb Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 16 Jun 2012 20:13:41 +0300 Subject: [PATCH 09/16] HITLv2: fix shared object name captitalization --- ground/openpilotgcs/src/plugins/hitlv2/hitlv2.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) From 4807eb730fb8140cc2195a1c42aba93705c109df Mon Sep 17 00:00:00 2001 From: Mike LaBranche Date: Sat, 16 Jun 2012 13:38:05 -0700 Subject: [PATCH 10/16] Compiler Warning kill: rearrange ctor member init order in ConfigInputWidget --- ground/openpilotgcs/src/plugins/config/configinputwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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()); From 4650d4909d0d2285548c1628f2136eb773e64ca4 Mon Sep 17 00:00:00 2001 From: Mike LaBranche Date: Sat, 16 Jun 2012 13:39:58 -0700 Subject: [PATCH 11/16] Add virtual keyword ConfigTaskWidget:: dtor; assures correct child deletion --- .../src/plugins/uavobjectwidgetutils/configtaskwidget.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ); From c8b4abc71fa05ed2c9d8dba0cb898fc40be9588c Mon Sep 17 00:00:00 2001 From: Fredrik Arvidsson Date: Sun, 17 Jun 2012 12:46:45 +0200 Subject: [PATCH 12/16] Added comments to the code. --- .../src/plugins/uavobjectbrowser/treeitem.cpp | 44 +++++++++++++++++++ .../src/plugins/uavobjectbrowser/treeitem.h | 27 ++++++++++++ .../uavobjectbrowser/uavobjecttreemodel.cpp | 2 + .../uavobjectbrowser/uavobjecttreemodel.h | 2 + 4 files changed, 75 insertions(+) diff --git a/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.cpp b/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.cpp index b8cea004f..a6924e71d 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.cpp @@ -27,15 +27,24 @@ #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); @@ -44,23 +53,46 @@ bool HighLightManager::add(TreeItem *itemToAdd) 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(); } } @@ -145,20 +177,32 @@ 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) { + // 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); } } 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); diff --git a/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.h b/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.h index 494fb9a0b..c4f8e0355 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.h +++ b/ground/openpilotgcs/src/plugins/uavobjectbrowser/treeitem.h @@ -41,20 +41,47 @@ 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; }; diff --git a/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.cpp b/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.cpp index e2377da9a..9bd8b20b4 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.cpp @@ -46,6 +46,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*))); diff --git a/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.h b/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.h index 5e67840cd..d9787e3a7 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.h +++ b/ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.h @@ -97,6 +97,8 @@ private: int m_recentlyUpdatedTimeout; QColor m_recentlyUpdatedColor; QColor m_manuallyChangedColor; + + // Highlight manager to handle highlighting of tree items. HighLightManager *m_highlightManager; }; From fe2aed328ee9dc30440229894bc9a3d236c49580 Mon Sep 17 00:00:00 2001 From: Mike LaBranche Date: Tue, 19 Jun 2012 10:27:08 -0700 Subject: [PATCH 13/16] bugfix: configccpmwidget, updatethrottlecurvevalue using wrong table index --- .../plugins/config/cfg_vehicletypes/configccpmwidget.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp index 4a6ca62a9..a7e46eb83 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp @@ -554,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))); @@ -1224,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 From 04ea5f24fa516e44caa7c0a53d5355ad2371fb07 Mon Sep 17 00:00:00 2001 From: Mike LaBranche Date: Tue, 19 Jun 2012 10:28:42 -0700 Subject: [PATCH 14/16] MixerCurveWidget: first pass refactoring for performance; bugfix for negative values --- .../uavobjectwidgetutils/mixercurvewidget.cpp | 145 ++++++++++++------ .../uavobjectwidgetutils/mixercurvewidget.h | 15 +- 2 files changed, 110 insertions(+), 50 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp index f21d782f6..f97c9e296 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,51 +124,50 @@ MixerCurveWidget::~MixerCurveWidget() */ void MixerCurveWidget::initCurve(QList points) { - if (points.length() < 2) return; // We need at least 2 points on a curve! + if (nodeList.count() != points.count()) + initNodes(points.count()); + + // finally, set node positions + setCurve(points); +} + +void MixerCurveWidget::initNodes(int numPoints) +{ // First of all, reset the list // TODO: one edge might not get deleted properly, small mem leak maybe... + + if (nodeList.count()) { foreach (Node *node, nodeList ) { QList edges = node->edges(); foreach(Edge *edge, edges) { if (scene()->items().contains(edge)) scene()->removeItem(edge); - else - delete edge; } - scene()->removeItem(node); - delete node; + scene()->removeItem(node); + } + + nodeList.clear(); } - nodeList.clear(); // Create the nodes - qreal w = plot->boundingRect().width()/(points.length()-1); - qreal h = plot->boundingRect().height(); - for (int i=0; iaddItem(node); + + for (int i=0; icurveMax) - 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))); + for (int i=0; i<(numPoints-1); i++) { + scene()->addItem(getEdge(i, nodeList.at(i),nodeList.at(i+1))); } - } - /** Returns the current curve settings */ @@ -142,7 +176,8 @@ QList MixerCurveWidget::getCurve() { qreal h = plot->boundingRect().height(); foreach(Node *node, nodeList) { - list.append(((curveMax-curveMin)*(h-node->pos().y())/h)+curveMin); + double val = ((curveMax-curveMin)*(h-node->pos().y())/h)+curveMin; + list.append(val); } return list; @@ -150,11 +185,11 @@ QList MixerCurveWidget::getCurve() { /** Sets a linear graph */ -void MixerCurveWidget::initLinearCurve(quint32 numPoints, double maxValue) +void MixerCurveWidget::initLinearCurve(quint32 numPoints, double maxValue, double 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 +250,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) diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.h b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.h index 9a14123a7..539755d2c 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,14 @@ 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); void setMax(double value); void setRange(double min, double max); + static const int NODE_NUMELEM = 5; + signals: void curveUpdated(QList, double ); @@ -58,9 +61,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); From 9da2ffff2fa73998d63dcba9f89cfa6d6791fb92 Mon Sep 17 00:00:00 2001 From: Mike LaBranche Date: Tue, 19 Jun 2012 15:22:11 -0700 Subject: [PATCH 15/16] MixerCurveWidget: incorporate m_thread's delete leak fix, combined node+edge init --- .../uavobjectwidgetutils/mixercurvewidget.cpp | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp index f97c9e296..89132407b 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp @@ -136,15 +136,17 @@ void MixerCurveWidget::initCurve(QList points) void MixerCurveWidget::initNodes(int numPoints) { - // First of all, reset the list - // TODO: one edge might not get deleted properly, small mem leak maybe... - + // 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); + if (edge->destNode() == node) { + delete edge; + } + else { + scene()->removeItem(edge); + } } scene()->removeItem(node); } @@ -152,19 +154,20 @@ void MixerCurveWidget::initNodes(int numPoints) nodeList.clear(); } - // Create the nodes - + // Create the nodes and edges + Node* prevNode = 0; for (int i=0; iaddItem(node); - } - // ... and link them together: - for (int i=0; i<(numPoints-1); i++) { - scene()->addItem(getEdge(i, nodeList.at(i),nodeList.at(i+1))); + if (prevNode) { + scene()->addItem(getEdge(i, prevNode, node)); + } + + prevNode = node; } } @@ -187,9 +190,13 @@ QList MixerCurveWidget::getCurve() { */ void MixerCurveWidget::initLinearCurve(quint32 numPoints, double maxValue, double minValue) { + Q_UNUSED(maxValue); + Q_UNUSED(minValue); + QList points; for (double i=0; i Date: Tue, 19 Jun 2012 16:51:22 -0700 Subject: [PATCH 16/16] MixerCurveWidget: make Node smarter by storing a value whenever pos changes; getCurve now reports back the list of node->getValue() --- .../uavobjectwidgetutils/mixercurvepoint.cpp | 22 +++++++++++++++++-- .../uavobjectwidgetutils/mixercurvepoint.h | 6 +++++ .../uavobjectwidgetutils/mixercurvewidget.cpp | 13 ++++++++--- .../uavobjectwidgetutils/mixercurvewidget.h | 2 ++ 4 files changed, 38 insertions(+), 5 deletions(-) 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 89132407b..56ed8bee9 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp @@ -175,12 +175,11 @@ void MixerCurveWidget::initNodes(int numPoints) Returns the current curve settings */ QList MixerCurveWidget::getCurve() { + QList list; - qreal h = plot->boundingRect().height(); foreach(Node *node, nodeList) { - double val = ((curveMax-curveMin)*(h-node->pos().y())/h)+curveMin; - list.append(val); + list.append(node->getValue()); } return list; @@ -271,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 539755d2c..92c9c3a8c 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.h +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.h @@ -49,7 +49,9 @@ public: 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;