diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp index a7e46eb83..e7ca51fd1 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp @@ -132,16 +132,11 @@ ConfigCcpmWidget::ConfigCcpmWidget(QWidget *parent) : VehicleConfig(parent) } - m_ccpm->PitchCurve->setMin(-1); - - resetMixer(m_ccpm->PitchCurve, 5); - resetMixer(m_ccpm->ThrottleCurve, 5); - - MixerSettings * mixerSettings = MixerSettings::GetInstance(getObjectManager()); - Q_ASSERT(mixerSettings); - UAVObjectField * curve2source = mixerSettings->getField("Curve2Source"); - Q_ASSERT(curve2source); + //initialize our two mixer curves + m_ccpm->PitchCurve->initLinearCurve(5, 1.0, -1.0); + m_ccpm->ThrottleCurve->initLinearCurve(5, 1.0); + //initialize channel names m_ccpm->ccpmEngineChannel->addItems(channelNames); m_ccpm->ccpmEngineChannel->setCurrentIndex(0); m_ccpm->ccpmTailChannel->addItems(channelNames); @@ -474,14 +469,6 @@ void ConfigCcpmWidget::UpdateType() } -/** - Resets a mixer curve - */ -void ConfigCcpmWidget::resetMixer(MixerCurveWidget *mixer, int numElements) -{ - mixer->initLinearCurve(numElements,(double)1); -} - void ConfigCcpmWidget::UpdateCurveWidgets() { int NumCurvePoints,i,Changed; @@ -501,7 +488,8 @@ void ConfigCcpmWidget::UpdateCurveWidgets() if (ThisValue!=OldCurveValues.at(i))Changed=1; } // Setup all Throttle1 curves for all types of airframes - if (Changed==1)m_ccpm->ThrottleCurve->setCurve(curveValues); + if (Changed==1) + m_ccpm->ThrottleCurve->setCurve(&curveValues); curveValues.clear(); Changed=0; @@ -513,7 +501,8 @@ void ConfigCcpmWidget::UpdateCurveWidgets() if (ThisValue!=OldCurveValues.at(i))Changed=1; } // Setup all Throttle1 curves for all types of airframes - if (Changed==1)m_ccpm->PitchCurve->setCurve(curveValues); + if (Changed==1) + m_ccpm->PitchCurve->setCurve(&curveValues); } void ConfigCcpmWidget::updatePitchCurveValue(QList curveValues0,double Value0) @@ -606,50 +595,40 @@ void ConfigCcpmWidget::UpdateCurveSettings() m_ccpm->CurveValue2->setCorrectionMode(QAbstractSpinBox::CorrectToNearestValue); m_ccpm->CurveValue3->setCorrectionMode(QAbstractSpinBox::CorrectToNearestValue); + //set default visible + m_ccpm->CurveLabel1->setVisible(true); + m_ccpm->CurveValue1->setVisible(true); + m_ccpm->CurveLabel2->setVisible(false); + m_ccpm->CurveValue2->setVisible(false); + m_ccpm->CurveLabel3->setVisible(false); + m_ccpm->CurveValue3->setVisible(false); + m_ccpm->ccpmGenerateCurve->setVisible(true); + m_ccpm->CurveToGenerate->setVisible(true); + if ( CurveType.compare("Flat")==0) { m_ccpm->CurveLabel1->setText("Value"); - m_ccpm->CurveLabel1->setVisible(true); - m_ccpm->CurveValue1->setVisible(true); - m_ccpm->CurveLabel2->setVisible(false); - m_ccpm->CurveValue2->setVisible(false); - m_ccpm->CurveLabel3->setVisible(false); - m_ccpm->CurveValue3->setVisible(false); - m_ccpm->ccpmGenerateCurve->setVisible(true); - m_ccpm->CurveToGenerate->setVisible(true); } if ( CurveType.compare("Linear")==0) { m_ccpm->CurveLabel1->setText("Min"); - m_ccpm->CurveLabel1->setVisible(true); - m_ccpm->CurveValue1->setVisible(true); m_ccpm->CurveLabel2->setText("Max"); m_ccpm->CurveLabel2->setVisible(true); m_ccpm->CurveValue2->setVisible(true); - m_ccpm->CurveLabel3->setVisible(false); - m_ccpm->CurveValue3->setVisible(false); - m_ccpm->ccpmGenerateCurve->setVisible(true); - m_ccpm->CurveToGenerate->setVisible(true); } if ( CurveType.compare("Step")==0) { m_ccpm->CurveLabel1->setText("Min"); - m_ccpm->CurveLabel1->setVisible(true); - m_ccpm->CurveValue1->setVisible(true); m_ccpm->CurveLabel2->setText("Max"); m_ccpm->CurveLabel2->setVisible(true); m_ccpm->CurveValue2->setVisible(true); m_ccpm->CurveLabel3->setText("Step at"); m_ccpm->CurveLabel3->setVisible(true); m_ccpm->CurveValue3->setVisible(true); - m_ccpm->ccpmGenerateCurve->setVisible(true); - m_ccpm->CurveToGenerate->setVisible(true); } if ( CurveType.compare("Exp")==0) { m_ccpm->CurveLabel1->setText("Min"); - m_ccpm->CurveLabel1->setVisible(true); - m_ccpm->CurveValue1->setVisible(true); m_ccpm->CurveLabel2->setText("Max"); m_ccpm->CurveLabel2->setVisible(true); m_ccpm->CurveValue2->setVisible(true); @@ -660,14 +639,10 @@ void ConfigCcpmWidget::UpdateCurveSettings() m_ccpm->CurveValue3->setMaximum(100.0); m_ccpm->CurveValue3->setSingleStep(1.0); m_ccpm->CurveValue3->setCorrectionMode(QAbstractSpinBox::CorrectToNearestValue);; - m_ccpm->ccpmGenerateCurve->setVisible(true); - m_ccpm->CurveToGenerate->setVisible(true); } if ( CurveType.compare("Log")==0) { m_ccpm->CurveLabel1->setText("Min"); - m_ccpm->CurveLabel1->setVisible(true); - m_ccpm->CurveValue1->setVisible(true); m_ccpm->CurveLabel2->setText("Max"); m_ccpm->CurveLabel2->setVisible(true); m_ccpm->CurveValue2->setVisible(true); @@ -677,22 +652,17 @@ void ConfigCcpmWidget::UpdateCurveSettings() m_ccpm->CurveValue3->setMinimum(1.0); m_ccpm->CurveValue3->setMaximum(100.0); m_ccpm->CurveValue3->setSingleStep(1.0); - m_ccpm->CurveValue3->setCorrectionMode(QAbstractSpinBox::CorrectToNearestValue);; - m_ccpm->ccpmGenerateCurve->setVisible(true); - m_ccpm->CurveToGenerate->setVisible(true); + m_ccpm->CurveValue3->setCorrectionMode(QAbstractSpinBox::CorrectToNearestValue); } if ( CurveType.compare("Custom")==0) { m_ccpm->CurveLabel1->setVisible(false); m_ccpm->CurveValue1->setVisible(false); - m_ccpm->CurveLabel2->setVisible(false); - m_ccpm->CurveValue2->setVisible(false); - m_ccpm->CurveLabel3->setVisible(false); - m_ccpm->CurveValue3->setVisible(false); m_ccpm->ccpmGenerateCurve->setVisible(false); m_ccpm->CurveToGenerate->setVisible(false); } -UpdateCurveWidgets(); + + UpdateCurveWidgets(); } void ConfigCcpmWidget::GenerateCurve() @@ -881,7 +851,8 @@ void ConfigCcpmWidget::UpdateMixer() float CollectiveConstant,PitchConstant,RollConstant,ThisAngle[6]; QString Channel; - throwConfigError(QString("HeliCP")); + if (throwConfigError(QString("HeliCP"))) + return; GUIConfigDataUnion config = GetConfigData(); @@ -1744,13 +1715,16 @@ void ConfigCcpmWidget::SwashLvlSpinBoxChanged(int value) /** This function displays text and color formatting in order to help the user understand what channels have not yet been configured. */ -void ConfigCcpmWidget::throwConfigError(QString airframeType) +bool ConfigCcpmWidget::throwConfigError(QString airframeType) { Q_UNUSED(airframeType); + bool error = false; + if((m_ccpm->ccpmServoWChannel->currentIndex()==0)&&(m_ccpm->ccpmServoWChannel->isEnabled())) { m_ccpm->ccpmServoWLabel->setText("Servo W"); + error = true; } else { @@ -1759,6 +1733,7 @@ void ConfigCcpmWidget::throwConfigError(QString airframeType) if((m_ccpm->ccpmServoXChannel->currentIndex()==0)&&(m_ccpm->ccpmServoXChannel->isEnabled())) { m_ccpm->ccpmServoXLabel->setText("Servo X"); + error = true; } else { @@ -1767,6 +1742,7 @@ void ConfigCcpmWidget::throwConfigError(QString airframeType) if((m_ccpm->ccpmServoYChannel->currentIndex()==0)&&(m_ccpm->ccpmServoYChannel->isEnabled())) { m_ccpm->ccpmServoYLabel->setText("Servo Y"); + error = true; } else { @@ -1775,6 +1751,7 @@ void ConfigCcpmWidget::throwConfigError(QString airframeType) if((m_ccpm->ccpmServoZChannel->currentIndex()==0)&&(m_ccpm->ccpmServoZChannel->isEnabled())) { m_ccpm->ccpmServoZLabel->setText("Servo Z"); + error = true; } else { @@ -1793,10 +1770,12 @@ void ConfigCcpmWidget::throwConfigError(QString airframeType) if((m_ccpm->ccpmTailChannel->currentIndex()==0)&&(m_ccpm->ccpmTailChannel->isEnabled())) { m_ccpm->ccpmTailLabel->setText("Tail Rotor"); + error = true; } else { m_ccpm->ccpmTailLabel->setText("Tail Rotor"); } + return error; } diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.h b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.h index 3dceadcda..56161c36f 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.h +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configccpmwidget.h @@ -95,7 +95,7 @@ private: virtual void setupUI(QString airframeType); virtual void refreshWidgetsValues(QString frameType); virtual QString updateConfigObjectsFromWidgets(); - virtual void throwConfigError(QString airframeType); + virtual bool throwConfigError(QString airframeType); void ccpmSwashplateUpdate(); void ccpmSwashplateRedraw(); @@ -103,7 +103,6 @@ private: void GenerateCurve(); void UpdateMixer(); void UpdateType(); - void resetMixer(MixerCurveWidget *mixer, int numElements); void UpdateCurveWidgets(); void updatePitchCurveValue(QList,double); void updateThrottleCurveValue(QList,double); diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp index cbb7f94cf..7ed667828 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.cpp @@ -262,15 +262,7 @@ bool ConfigFixedWingWidget::setupFrameFixedWing(QString airframeType) { // Check coherence: //Show any config errors in GUI - throwConfigError(airframeType); - - // - At least Pitch and either Roll or Yaw - if (m_aircraft->fwEngineChannelBox->currentText() == "None" || - m_aircraft->fwElevator1ChannelBox->currentText() == "None" || - ((m_aircraft->fwAileron1ChannelBox->currentText() == "None") && - (m_aircraft->fwRudder1ChannelBox->currentText() == "None"))) { - // TODO: explain the problem in the UI -// m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment"); + if (throwConfigError(airframeType)) { return false; } @@ -351,14 +343,7 @@ bool ConfigFixedWingWidget::setupFrameElevon(QString airframeType) { // Check coherence: //Show any config errors in GUI - throwConfigError(airframeType); - - // - At least Aileron1 and Aileron 2, and engine - if (m_aircraft->fwEngineChannelBox->currentText() == "None" || - m_aircraft->fwAileron1ChannelBox->currentText() == "None" || - m_aircraft->fwAileron2ChannelBox->currentText() == "None") { - // TODO: explain the problem in the UI -// m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment"); + if (throwConfigError(airframeType)) { return false; } @@ -436,14 +421,7 @@ bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType) { // Check coherence: //Show any config errors in GUI - throwConfigError(airframeType); - - // - At least Pitch1 and Pitch2, and engine - if (m_aircraft->fwEngineChannelBox->currentText() == "None" || - m_aircraft->fwElevator1ChannelBox->currentText() == "None" || - m_aircraft->fwElevator2ChannelBox->currentText() == "None") { - // TODO: explain the problem in the UI -// m_aircraft->fwStatusLabel->setText("WARNING: check channel assignment"); + if (throwConfigError(airframeType)) { return false; } @@ -526,7 +504,7 @@ bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType) /** This function displays text and color formatting in order to help the user understand what channels have not yet been configured. */ -void ConfigFixedWingWidget::throwConfigError(QString airframeType) +bool ConfigFixedWingWidget::throwConfigError(QString airframeType) { //Initialize configuration error flag bool error=false; @@ -618,4 +596,6 @@ void ConfigFixedWingWidget::throwConfigError(QString airframeType) if (error){ m_aircraft->fwStatusLabel->setText(QString("ERROR: Assign all necessary channels")); } + + return error; } diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.h b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.h index 8a39715f0..99eab5c06 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.h +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configfixedwingwidget.h @@ -63,7 +63,7 @@ private slots: virtual void setupUI(QString airframeType); virtual void refreshWidgetsValues(QString frameType); virtual QString updateConfigObjectsFromWidgets(); - virtual void throwConfigError(QString airframeType); + virtual bool throwConfigError(QString airframeType); protected: diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configgroundvehiclewidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configgroundvehiclewidget.cpp index 1fc17cea0..2309ed872 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configgroundvehiclewidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configgroundvehiclewidget.cpp @@ -289,16 +289,9 @@ void ConfigGroundVehicleWidget::refreshWidgetsValues(QString frameType) bool ConfigGroundVehicleWidget::setupGroundVehicleMotorcycle(QString airframeType){ // Check coherence: //Show any config errors in GUI - throwConfigError(airframeType); - - // - Motor, steering, and balance - if (m_aircraft->gvMotor2ChannelBox->currentText() == "None" || - (m_aircraft->gvSteering1ChannelBox->currentText() == "None" || - m_aircraft->gvSteering2ChannelBox->currentText() == "None") ) - { + if (throwConfigError(airframeType)) { return false; - } - + } // Now setup the channels: GUIConfigDataUnion config = GetConfigData(); @@ -352,16 +345,11 @@ bool ConfigGroundVehicleWidget::setupGroundVehicleMotorcycle(QString airframeTyp bool ConfigGroundVehicleWidget::setupGroundVehicleDifferential(QString airframeType){ // Check coherence: //Show any config errors in GUI - throwConfigError(airframeType); - - // - Left and right steering - if ( m_aircraft->gvMotor2ChannelBox->currentText() == "None" || - m_aircraft->gvSteering1ChannelBox->currentText() == "None") - { + + if (throwConfigError(airframeType)) { return false; } - // Now setup the channels: GUIConfigDataUnion config = GetConfigData(); ResetActuators(&config); @@ -411,14 +399,7 @@ bool ConfigGroundVehicleWidget::setupGroundVehicleCar(QString airframeType) { // Check coherence: //Show any config errors in GUI - throwConfigError(airframeType); - - // - At least one motor and one steering servo - if ((m_aircraft->gvMotor1ChannelBox->currentText() == "None" && - m_aircraft->gvMotor2ChannelBox->currentText() == "None") || - (m_aircraft->gvSteering1ChannelBox->currentText() == "None" && - m_aircraft->gvSteering2ChannelBox->currentText() == "None")) - { + if (throwConfigError(airframeType)) { return false; } @@ -468,7 +449,7 @@ bool ConfigGroundVehicleWidget::setupGroundVehicleCar(QString airframeType) /** This function displays text and color formatting in order to help the user understand what channels have not yet been configured. */ -void ConfigGroundVehicleWidget::throwConfigError(QString airframeType) +bool ConfigGroundVehicleWidget::throwConfigError(QString airframeType) { //Initialize configuration error flag bool error=false; @@ -558,5 +539,6 @@ void ConfigGroundVehicleWidget::throwConfigError(QString airframeType) if (error){ m_aircraft->gvStatusLabel->setText(QString("ERROR: Assign all necessary channels")); } + return error; } diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configgroundvehiclewidget.h b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configgroundvehiclewidget.h index 1e7b378e4..b2b447e6e 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configgroundvehiclewidget.h +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configgroundvehiclewidget.h @@ -63,7 +63,7 @@ private slots: virtual void setupUI(QString airframeType); virtual void refreshWidgetsValues(QString frameType); virtual QString updateConfigObjectsFromWidgets(); - virtual void throwConfigError(QString airframeType); + virtual bool throwConfigError(QString airframeType); protected: diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp index 5b390c0e3..3f1b9a074 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp @@ -93,6 +93,10 @@ void ConfigMultiRotorWidget::setupUI(QString frameType) enableComboBox(uiowner, QString("multiMotorChannelBox%0").arg(i), true); } + m_aircraft->mrRollMixLevel->setValue(100); + m_aircraft->mrPitchMixLevel->setValue(100); + m_aircraft->mrYawMixLevel->setValue(50); + m_aircraft->triYawChannelBox->setEnabled(true); } else if (frameType == "QuadX" || frameType == "Quad X") { @@ -104,6 +108,7 @@ void ConfigMultiRotorWidget::setupUI(QString frameType) enableComboBox(uiowner, QString("multiMotorChannelBox%0").arg(i), true); } + // init mixer levels m_aircraft->mrRollMixLevel->setValue(50); m_aircraft->mrPitchMixLevel->setValue(50); m_aircraft->mrYawMixLevel->setValue(50); @@ -283,20 +288,12 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets() { QString airframeType; QList motorList; - - // We can already setup the feedforward here, as it is common to all platforms - UAVDataObject* obj = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); - UAVObjectField* field = obj->getField(QString("FeedForward")); - field->setDouble((double)m_aircraft->feedForwardSlider->value()/100); - field = obj->getField(QString("AccelTime")); - field->setDouble(m_aircraft->accelTime->value()); - field = obj->getField(QString("DecelTime")); - field->setDouble(m_aircraft->decelTime->value()); - field = obj->getField(QString("MaxAccel")); - field->setDouble(m_aircraft->maxAccelSlider->value()); - + + UAVDataObject* mixerObj = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); + Q_ASSERT(mixerObj); + // Curve is also common to all quads: - setThrottleCurve(obj, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->multiThrottleCurve->getCurve() ); + setThrottleCurve(mixerObj, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->multiThrottleCurve->getCurve() ); if (m_aircraft->multirotorFrameType->currentText() == "Quad +") { airframeType = "QuadP"; @@ -314,15 +311,7 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets() airframeType = "HexaCoax"; //Show any config errors in GUI - throwConfigError(6); - - if (m_aircraft->multiMotorChannelBox1->currentText() == "None" || - m_aircraft->multiMotorChannelBox2->currentText() == "None" || - m_aircraft->multiMotorChannelBox3->currentText() == "None" || - m_aircraft->multiMotorChannelBox4->currentText() == "None" || - m_aircraft->multiMotorChannelBox5->currentText() == "None" || - m_aircraft->multiMotorChannelBox6->currentText() == "None" ) { - + if (throwConfigError(6)) { return airframeType; } motorList << "VTOLMotorNW" << "VTOLMotorW" << "VTOLMotorNE" << "VTOLMotorE" @@ -348,18 +337,9 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets() airframeType = "Octo"; //Show any config errors in GUI - throwConfigError(8); - - if (m_aircraft->multiMotorChannelBox1->currentText() == "None" || - m_aircraft->multiMotorChannelBox2->currentText() == "None" || - m_aircraft->multiMotorChannelBox3->currentText() == "None" || - m_aircraft->multiMotorChannelBox4->currentText() == "None" || - m_aircraft->multiMotorChannelBox5->currentText() == "None" || - m_aircraft->multiMotorChannelBox6->currentText() == "None" || - m_aircraft->multiMotorChannelBox7->currentText() == "None" || - m_aircraft->multiMotorChannelBox8->currentText() == "None") { - + if (throwConfigError(8)) { return airframeType; + } motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW"; @@ -383,17 +363,7 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets() airframeType = "OctoV"; //Show any config errors in GUI - throwConfigError(8); - - if (m_aircraft->multiMotorChannelBox1->currentText() == "None" || - m_aircraft->multiMotorChannelBox2->currentText() == "None" || - m_aircraft->multiMotorChannelBox3->currentText() == "None" || - m_aircraft->multiMotorChannelBox4->currentText() == "None" || - m_aircraft->multiMotorChannelBox5->currentText() == "None" || - m_aircraft->multiMotorChannelBox6->currentText() == "None" || - m_aircraft->multiMotorChannelBox7->currentText() == "None" || - m_aircraft->multiMotorChannelBox8->currentText() == "None") { - + if (throwConfigError(8)) { return airframeType; } motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" @@ -419,17 +389,7 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets() airframeType = "OctoCoaxP"; //Show any config errors in GUI - throwConfigError(8); - - if (m_aircraft->multiMotorChannelBox1->currentText() == "None" || - m_aircraft->multiMotorChannelBox2->currentText() == "None" || - m_aircraft->multiMotorChannelBox3->currentText() == "None" || - m_aircraft->multiMotorChannelBox4->currentText() == "None" || - m_aircraft->multiMotorChannelBox5->currentText() == "None" || - m_aircraft->multiMotorChannelBox6->currentText() == "None" || - m_aircraft->multiMotorChannelBox7->currentText() == "None" || - m_aircraft->multiMotorChannelBox8->currentText() == "None") { - + if (throwConfigError(8)) { return airframeType; } motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" @@ -454,17 +414,7 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets() airframeType = "OctoCoaxX"; //Show any config errors in GUI - throwConfigError(8); - - if (m_aircraft->multiMotorChannelBox1->currentText() == "None" || - m_aircraft->multiMotorChannelBox2->currentText() == "None" || - m_aircraft->multiMotorChannelBox3->currentText() == "None" || - m_aircraft->multiMotorChannelBox4->currentText() == "None" || - m_aircraft->multiMotorChannelBox5->currentText() == "None" || - m_aircraft->multiMotorChannelBox6->currentText() == "None" || - m_aircraft->multiMotorChannelBox7->currentText() == "None" || - m_aircraft->multiMotorChannelBox8->currentText() == "None") { - + if (throwConfigError(8)) { return airframeType; } motorList << "VTOLMotorNW" << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" @@ -489,12 +439,9 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets() airframeType = "Tri"; //Show any config errors in GUI - throwConfigError(3); - if (m_aircraft->multiMotorChannelBox1->currentText() == "None" || - m_aircraft->multiMotorChannelBox2->currentText() == "None" || - m_aircraft->multiMotorChannelBox3->currentText() == "None" ) { - + if (throwConfigError(3)) { return airframeType; + } if (m_aircraft->triYawChannelBox->currentText() == "None") { m_aircraft->mrStatusLabel->setText("Error: Assign a Yaw channel"); @@ -523,8 +470,6 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets() setupMultiRotorMixer(mixer); //tell the mixer about tricopter yaw channel - UAVDataObject* mixerObj = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); - Q_ASSERT(mixerObj); int channel = m_aircraft->triYawChannelBox->currentIndex()-1; if (channel > -1){ @@ -868,14 +813,7 @@ bool ConfigMultiRotorWidget::setupQuad(bool pLayout) // Check coherence: //Show any config errors in GUI - throwConfigError(4); - - // - Four engines have to be defined - if (m_aircraft->multiMotorChannelBox1->currentText() == "None" || - m_aircraft->multiMotorChannelBox2->currentText() == "None" || - m_aircraft->multiMotorChannelBox3->currentText() == "None" || - m_aircraft->multiMotorChannelBox4->currentText() == "None") { - + if (throwConfigError(4)) { return false; } @@ -943,19 +881,9 @@ bool ConfigMultiRotorWidget::setupHexa(bool pLayout) { // Check coherence: //Show any config errors in GUI - throwConfigError(6); - - // - Four engines have to be defined - if (m_aircraft->multiMotorChannelBox1->currentText() == "None" || - m_aircraft->multiMotorChannelBox2->currentText() == "None" || - m_aircraft->multiMotorChannelBox3->currentText() == "None" || - m_aircraft->multiMotorChannelBox4->currentText() == "None" || - m_aircraft->multiMotorChannelBox5->currentText() == "None" || - m_aircraft->multiMotorChannelBox6->currentText() == "None") { - + if (throwConfigError(6)) return false; - } - + QList motorList; if (pLayout) { motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorSE" @@ -1069,7 +997,7 @@ bool ConfigMultiRotorWidget::setupMultiRotorMixer(double mixerFactors[8][3]) /** This function displays text and color formatting in order to help the user understand what channels have not yet been configured. */ -void ConfigMultiRotorWidget::throwConfigError(int numMotors) +bool ConfigMultiRotorWidget::throwConfigError(int numMotors) { //Initialize configuration error flag bool error=false; @@ -1096,6 +1024,7 @@ void ConfigMultiRotorWidget::throwConfigError(int numMotors) if (error){ m_aircraft->mrStatusLabel->setText(QString("ERROR: Assign all %1 motor channels").arg(numMotors)); } + return error; } diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.h b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.h index 3ccc0de6b..69b1e1712 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.h +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.h @@ -71,7 +71,7 @@ private slots: virtual void setupUI(QString airframeType); virtual void refreshWidgetsValues(QString frameType); virtual QString updateConfigObjectsFromWidgets(); - void throwConfigError(int numMotors); + virtual bool throwConfigError(int numMotors); protected: diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.cpp index 549778540..94c3111b3 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.cpp @@ -233,6 +233,30 @@ void VehicleConfig::setMixerVectorValue(UAVDataObject* mixer, int channel, Mixer } } +double VehicleConfig::getMixerValue(UAVDataObject* mixer, QString elementName) +{ + Q_ASSERT(mixer); + + double value = 0.0; + + QPointer field = mixer->getField(elementName); + if (field) { + value = field->getDouble(); + } + return value; +} + +void VehicleConfig::setMixerValue(UAVDataObject* mixer, QString elementName, double value) +{ + Q_ASSERT(mixer); + + QPointer field = mixer->getField(elementName); + if (field) { + field->setDouble(value); + } +} + + void VehicleConfig::setThrottleCurve(UAVDataObject* mixer, MixerThrottleCurveElem curveType, QList curve) { QPointer field; @@ -287,6 +311,36 @@ void VehicleConfig::getThrottleCurve(UAVDataObject* mixer, MixerThrottleCurveEle } } +bool VehicleConfig::isValidThrottleCurve(QList* curve) +{ + Q_ASSERT(curve); + + if (curve) { + for (int i=0; i < curve->count(); i++) { + if (curve->at(i) != 0) + return true; + } + } + return false; +} + +double VehicleConfig::getCurveMin(QList* curve) +{ + double min = 0; + for (int i=0; icount(); i++) + min = std::min(min, curve->at(i)); + + return min; +} + +double VehicleConfig::getCurveMax(QList* curve) +{ + double max = 0; + for (int i=0; icount(); i++) + max = std::max(max, curve->at(i)); + + return max; +} /** 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 343cfcf0c..31447f3f8 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.h +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.h @@ -130,9 +130,13 @@ class VehicleConfig: public ConfigTaskWidget void resetMixerVector(UAVDataObject* mixer, int channel); QString getMixerType(UAVDataObject* mixer, int channel); void setMixerType(UAVDataObject* mixer, int channel, MixerTypeElem mixerType); + double getMixerValue(UAVDataObject* mixer, QString elementName); + void setMixerValue(UAVDataObject* mixer, QString elementName, double value); void setThrottleCurve(UAVDataObject* mixer, MixerThrottleCurveElem curveType, QList curve); void getThrottleCurve(UAVDataObject* mixer, MixerThrottleCurveElem curveType, QList* curve); - + bool isValidThrottleCurve(QList* curve); + double getCurveMin(QList* curve); + double getCurveMax(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 19047af55..84b531d6b 100644 --- a/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp @@ -274,7 +274,7 @@ QStringList ConfigVehicleTypeWidget::getChannelDescriptions() case SystemSettings::AIRFRAMETYPE_FIXEDWINGELEVON: case SystemSettings::AIRFRAMETYPE_FIXEDWINGVTAIL: { - ConfigFixedWingWidget* fixedwing = new ConfigFixedWingWidget(); + QPointer fixedwing = new ConfigFixedWingWidget(); channelDesc = fixedwing->getChannelDescriptions(); } break; @@ -282,7 +282,7 @@ QStringList ConfigVehicleTypeWidget::getChannelDescriptions() // helicp case SystemSettings::AIRFRAMETYPE_HELICP: { - ConfigCcpmWidget* heli = new ConfigCcpmWidget(); + QPointer heli = new ConfigCcpmWidget(); channelDesc = heli->getChannelDescriptions(); } break; @@ -300,7 +300,7 @@ QStringList ConfigVehicleTypeWidget::getChannelDescriptions() case SystemSettings::AIRFRAMETYPE_HEXACOAX: case SystemSettings::AIRFRAMETYPE_HEXA: { - ConfigMultiRotorWidget* multi = new ConfigMultiRotorWidget(); + QPointer multi = new ConfigMultiRotorWidget(); channelDesc = multi->getChannelDescriptions(); } break; @@ -310,7 +310,7 @@ QStringList ConfigVehicleTypeWidget::getChannelDescriptions() case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIAL: case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEMOTORCYCLE: { - ConfigGroundVehicleWidget* ground = new ConfigGroundVehicleWidget(); + QPointer ground = new ConfigGroundVehicleWidget(); channelDesc = ground->getChannelDescriptions(); } break; @@ -444,16 +444,17 @@ void ConfigVehicleTypeWidget::enableFFTest() // Depending on phase, either move actuator or send FF settings: if (ffTuningPhase) { // Send FF settings to the board - UAVDataObject* obj = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); - UAVObjectField* field = obj->getField(QString("FeedForward")); - field->setDouble((double)m_aircraft->feedForwardSlider->value()/100); - field = obj->getField(QString("AccelTime")); - field->setDouble(m_aircraft->accelTime->value()); - field = obj->getField(QString("DecelTime")); - field->setDouble(m_aircraft->decelTime->value()); - field = obj->getField(QString("MaxAccel")); - field->setDouble(m_aircraft->maxAccelSlider->value()); - obj->updated(); + UAVDataObject* mixer = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); + Q_ASSERT(mixer); + + QPointer vconfig = new VehicleConfig(); + + // Update feed forward settings + vconfig->setMixerValue(mixer, "FeedForward", m_aircraft->feedForwardSlider->value() / 100.0); + vconfig->setMixerValue(mixer, "AccelTime", m_aircraft->accelTime->value()); + vconfig->setMixerValue(mixer, "DecelTime", m_aircraft->decelTime->value()); + vconfig->setMixerValue(mixer, "MaxAccel", m_aircraft->maxAccelSlider->value()); + mixer->updated(); } else { // Toggle motor state UAVDataObject* obj = dynamic_cast(getObjectManager()->getObject(QString("ManualControlCommand"))); @@ -614,84 +615,55 @@ void ConfigVehicleTypeWidget::refreshWidgetsValues(UAVObject * o) { Q_UNUSED(o); - if(!allObjectsUpdated()) - return; + //if(!allObjectsUpdated()) + // return; //WHAT DOES THIS DO? bool dirty=isDirty(); //WHY IS THIS CALLED HERE AND THEN AGAIN SEVERAL LINES LATER IN setupAirframeUI() // Get the Airframe type from the system settings: - UAVDataObject* obj = dynamic_cast(getObjectManager()->getObject(QString("SystemSettings"))); - Q_ASSERT(obj); - UAVObjectField *field = obj->getField(QString("AirframeType")); + UAVDataObject* system = dynamic_cast(getObjectManager()->getObject(QString("SystemSettings"))); + Q_ASSERT(system); + + UAVObjectField *field = system->getField(QString("AirframeType")); Q_ASSERT(field); // At this stage, we will need to have some hardcoded settings in this code, this // is not ideal, but here you go. QString frameType = field->getValue().toString(); setupAirframeUI(frameType); - obj = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); - Q_ASSERT(obj); - field = obj->getField(QString("ThrottleCurve1")); - Q_ASSERT(field); - QList curveValues; - // 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->multiThrottleCurve->initLinearCurve(field->getNumElements(),(double)1); - m_aircraft->fixedWingThrottle->initLinearCurve(field->getNumElements(),(double)1); - m_aircraft->groundVehicleThrottle1->initLinearCurve(field->getNumElements(),(double)1); + UAVDataObject* mixer = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); + Q_ASSERT(mixer); + + QPointer vconfig = new VehicleConfig(); + + QList curveValues; + vconfig->getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues); + + // is at least one of the curve values != 0? + if (vconfig->isValidThrottleCurve(&curveValues)) { + // yes, use the curve we just read from mixersettings + m_aircraft->multiThrottleCurve->initCurve(&curveValues); + m_aircraft->fixedWingThrottle->initCurve(&curveValues); + m_aircraft->groundVehicleThrottle1->initCurve(&curveValues); } 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->multiThrottleCurve->initLinearCurve(field->getNumElements(),0.9); - m_aircraft->fixedWingThrottle->initLinearCurve(field->getNumElements(),(double)1); - m_aircraft->groundVehicleThrottle1->initLinearCurve(field->getNumElements(),(double)1); - } - else - { - m_aircraft->multiThrottleCurve->initCurve(curveValues); - m_aircraft->fixedWingThrottle->initCurve(curveValues); - m_aircraft->groundVehicleThrottle1->initCurve(curveValues); - } + // no, init a straight curve + m_aircraft->multiThrottleCurve->initLinearCurve(curveValues.count(), 0.9); + m_aircraft->fixedWingThrottle->initLinearCurve(curveValues.count(), 1.0); + m_aircraft->groundVehicleThrottle1->initLinearCurve(curveValues.count(), 1.0); } // Setup all Throttle2 curves for all types of airframes //AT THIS MOMENT, THAT MEANS ONLY GROUND VEHICLES - Q_ASSERT(obj); - field = obj->getField(QString("ThrottleCurve2")); - Q_ASSERT(field); - curveValues.clear(); - // 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->groundVehicleThrottle2->initLinearCurve(field->getNumElements(),(double)1); + vconfig->getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, &curveValues); + + if (vconfig->isValidThrottleCurve(&curveValues)) { + m_aircraft->groundVehicleThrottle2->initCurve(&curveValues); } 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->groundVehicleThrottle2->initLinearCurve(field->getNumElements(),(double)1); - } - else - { - m_aircraft->groundVehicleThrottle2->initCurve(curveValues); - } + m_aircraft->groundVehicleThrottle2->initLinearCurve(curveValues.count(), 1.0); } - + // Load the Settings for fixed wing frames: if (frameType.startsWith("FixedWing")) { @@ -716,8 +688,7 @@ void ConfigVehicleTypeWidget::refreshWidgetsValues(UAVObject * o) } else if (frameType == "Custom") { setComboCurrentIndex(m_aircraft->aircraftType, m_aircraft->aircraftType->findText("Custom")); - } - + } updateCustomAirframeUI(); setDirty(dirty); @@ -786,39 +757,35 @@ void ConfigVehicleTypeWidget::updateCustomAirframeUI() UAVDataObject* mixer = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); Q_ASSERT(mixer); - VehicleConfig* vconfig = new VehicleConfig(); + QPointer vconfig = new VehicleConfig(); QList curveValues; + vconfig->getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues); - // setup throttlecurve 1 - vconfig->getThrottleCurve(mixer,VehicleConfig::MIXER_THROTTLECURVE1,&curveValues); - - int total = 0; - for (int i=0; icustomThrottle1Curve->initLinearCurve(curveValues.length(),(double)1); + // is at least one of the curve values != 0? + if (vconfig->isValidThrottleCurve(&curveValues)) { + // yes, use the curve we just read from mixersettings + m_aircraft->customThrottle1Curve->setMin(vconfig->getCurveMin(&curveValues)); + m_aircraft->customThrottle1Curve->setMax(vconfig->getCurveMax(&curveValues)); + m_aircraft->customThrottle1Curve->initCurve(&curveValues); } else { - m_aircraft->customThrottle1Curve->initCurve(curveValues); + // no, init a straight curve + m_aircraft->customThrottle1Curve->initLinearCurve(curveValues.count(),(double)1); } - // setup throttlecurve 2 - vconfig->getThrottleCurve(mixer,VehicleConfig::MIXER_THROTTLECURVE2,&curveValues); + // Setup all Throttle2 curves for all types of airframes //AT THIS MOMENT, THAT MEANS ONLY GROUND VEHICLES + vconfig->getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, &curveValues); - total = 0; - for (int i=0; icustomThrottle2Curve->initLinearCurve(curveValues.length(),(double)1); + if (vconfig->isValidThrottleCurve(&curveValues)) { + m_aircraft->customThrottle2Curve->setMin(vconfig->getCurveMin(&curveValues)); + m_aircraft->customThrottle2Curve->setMax(vconfig->getCurveMax(&curveValues)); + m_aircraft->customThrottle2Curve->initCurve(&curveValues); } else { - m_aircraft->customThrottle2Curve->initCurve(curveValues); + m_aircraft->customThrottle2Curve->initLinearCurve(curveValues.count(),(double)1); } - // Update the mixer table: for (int channel=0; channel<8; channel++) { UAVObjectField* field = mixer->getField(mixerTypes.at(channel)); @@ -843,6 +810,12 @@ void ConfigVehicleTypeWidget::updateCustomAirframeUI() QString::number(vconfig->getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_YAW))); } } + + // Update feed forward settings + m_aircraft->feedForwardSlider->setValue(vconfig->getMixerValue(mixer,"FeedForward") * 100); + m_aircraft->accelTime->setValue(vconfig->getMixerValue(mixer,"AccelTime")); + m_aircraft->decelTime->setValue(vconfig->getMixerValue(mixer,"DecelTime")); + m_aircraft->maxAccelSlider->setValue(vconfig->getMixerValue(mixer,"MaxAccel")); } @@ -855,6 +828,17 @@ void ConfigVehicleTypeWidget::updateCustomAirframeUI() */ void ConfigVehicleTypeWidget::updateObjectsFromWidgets() { + UAVDataObject* mixer = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); + Q_ASSERT(mixer); + + QPointer vconfig = new VehicleConfig(); + + // Update feed forward settings + vconfig->setMixerValue(mixer, "FeedForward", m_aircraft->feedForwardSlider->value() / 100.0); + vconfig->setMixerValue(mixer, "AccelTime", m_aircraft->accelTime->value()); + vconfig->setMixerValue(mixer, "DecelTime", m_aircraft->decelTime->value()); + vconfig->setMixerValue(mixer, "MaxAccel", m_aircraft->maxAccelSlider->value()); + QString airframeType = "Custom"; //Sets airframe type default to "Custom" if (m_aircraft->aircraftType->currentText() == "Fixed Wing") { airframeType = m_fixedwing->updateConfigObjectsFromWidgets(); @@ -869,12 +853,6 @@ void ConfigVehicleTypeWidget::updateObjectsFromWidgets() airframeType = m_groundvehicle->updateConfigObjectsFromWidgets(); } else { - - UAVDataObject* mixer = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); - Q_ASSERT(mixer); - - VehicleConfig* vconfig = new VehicleConfig(); - vconfig->setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->customThrottle1Curve->getCurve()); vconfig->setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->customThrottle2Curve->getCurve()); diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.cpp b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.cpp index 64b9912b1..5996eb7d3 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.cpp @@ -43,7 +43,6 @@ Node::Node(MixerCurveWidget *graphWidget) setCacheMode(DeviceCoordinateCache); setZValue(-1); vertical = false; - value = 0; } void Node::addEdge(Edge *edge) @@ -61,14 +60,14 @@ QList Node::edges() const QRectF Node::boundingRect() const { qreal adjust = 2; - return QRectF(-10 - adjust, -10 - adjust, - 23 + adjust, 23 + adjust); + return QRectF(-12 - adjust, -12 - adjust, + 28 + adjust, 28 + adjust); } QPainterPath Node::shape() const { QPainterPath path; - path.addEllipse(-10, -10, 20, 20); + path.addEllipse(-12, -12, 25, 25); return path; } @@ -92,59 +91,60 @@ void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid } painter->setBrush(gradient); painter->setPen(QPen(Qt::black, 0)); - painter->drawEllipse(-10, -10, 20, 20); + painter->drawEllipse(-12, -12, 25, 25); + + painter->setPen(QPen(Qt::white, 0)); + painter->drawText(-10, 3, QString().sprintf("%.2f", value())); } 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) -{ - - QPointF newPos = value.toPointF(); +double Node::value() { double h = graph->sceneRect().height(); + double ratio = (h - pos().y()) / h; + return ((graph->getMax() - graph->getMin()) * ratio ) + graph->getMin(); +} + + +QVariant Node::itemChange(GraphicsItemChange change, const QVariant &val) +{ + QPointF newPos = val.toPointF(); + double h = graph->sceneRect().height(); + switch (change) { case ItemPositionChange: { - if (!vertical) - break; - // Force node to move vertically - newPos.setX(pos().x()); - // Stay inside graph - if (newPos.y() < 0) - newPos.setY(0); - //qDebug() << h << " - " << newPos.y(); - if (newPos.y() > h) - newPos.setY(h); - return newPos; + + if (!vertical) + break; + + // Force node to move vertically + newPos.setX(pos().x()); + + // Stay inside graph + if (newPos.y() < 0) + newPos.setY(0); + //qDebug() << h << " - " << newPos.y(); + if (newPos.y() > h) + newPos.setY(h); + + return newPos; } case ItemPositionHasChanged: { foreach (Edge *edge, edgeList) edge->adjust(); - double min = graph->getMin(); - double range = graph->getMax() - min; - double ratio = (h - newPos.y()) / h; - double val = (range * ratio ) + min; - setValue(val); + update(); - graph->itemMoved(val); + graph->itemMoved(value()); break; } default: break; }; - return QGraphicsItem::itemChange(change, value); + return QGraphicsItem::itemChange(change, val); } void Node::mousePressEvent(QGraphicsSceneMouseEvent *event) diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.h b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.h index 19b940625..eca445d32 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.h +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvepoint.h @@ -55,22 +55,21 @@ public: QPainterPath shape() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - void setValue(double val); - double getValue(); + double value(); protected: - QVariant itemChange(GraphicsItemChange change, const QVariant &value); + QVariant itemChange(GraphicsItemChange change, const QVariant &val); void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); private: - double value; QList edgeList; QPointF newPos; MixerCurveWidget *graph; bool vertical; + }; #endif // MIXERCURVEPOINT_H diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp index 56ed8bee9..a19692ff9 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.cpp @@ -69,6 +69,7 @@ MixerCurveWidget::MixerCurveWidget(QWidget *parent) : QGraphicsView(parent) //plot->setElementId("map"); scene->addItem(plot); plot->setZValue(-1); + scene->setSceneRect(plot->boundingRect()); setScene(scene); @@ -77,11 +78,11 @@ MixerCurveWidget::MixerCurveWidget(QWidget *parent) : QGraphicsView(parent) MixerCurveWidget::~MixerCurveWidget() { - for (int i=0; i points) +void MixerCurveWidget::initCurve(const QList* points) { - if (points.length() < 2) + 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); } @@ -139,12 +137,8 @@ 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 (edge->destNode() == node) { - delete edge; - } - else { + foreach(Edge *edge, node->edges()) { + if (edge->sourceNode() == node) { scene()->removeItem(edge); } } @@ -163,6 +157,8 @@ void MixerCurveWidget::initNodes(int numPoints) nodeList.append(node); scene()->addItem(node); + node->setPos(0,0); + if (prevNode) { scene()->addItem(getEdge(i, prevNode, node)); } @@ -179,7 +175,7 @@ QList MixerCurveWidget::getCurve() { QList list; foreach(Node *node, nodeList) { - list.append(node->getValue()); + list.append(node->value()); } return list; @@ -187,51 +183,48 @@ QList MixerCurveWidget::getCurve() { /** Sets a linear graph */ -void MixerCurveWidget::initLinearCurve(quint32 numPoints, double maxValue, double minValue) +void MixerCurveWidget::initLinearCurve(int numPoints, double maxValue, double minValue) { - Q_UNUSED(maxValue); - Q_UNUSED(minValue); + double range = setRange(minValue, maxValue); QList points; - for (double i=0; i points) +void MixerCurveWidget::setCurve(const QList* points) { curveUpdating = true; - if (nodeList.count() != points.count()) - initNodes(points.count()); + int ptCnt = points->count(); + if (nodeList.count() != ptCnt) + initNodes(ptCnt); - double min = curveMin + 10; - double max = curveMax + 10; + double range = curveMax - curveMin; - qreal w = plot->boundingRect().width()/(points.count()-1); + qreal w = plot->boundingRect().width()/(ptCnt-1); qreal h = plot->boundingRect().height(); - for (int i=0; i curveMax) - val = curveMax; + double val = (points->at(i) < curveMin) ? curveMin : (points->at(i) > curveMax) ? curveMax : points->at(i); - val += 10; - val -= min; - val /= (max - min); + val += range; + val -= (curveMin + range); + val /= range; - nodeList.at(i)->setPos(w*i, h - (val*h)); - nodeList.at(i)->verticalMove(true); + Node* node = nodeList.at(i); + node->setPos(w*i, h - (val*h)); + node->verticalMove(true); } - curveUpdating = false; + update(); + emit curveUpdated(points, (double)0); } @@ -252,13 +245,11 @@ void MixerCurveWidget::resizeEvent(QResizeEvent* event) fitInView(plot, Qt::KeepAspectRatio); } - - void MixerCurveWidget::itemMoved(double itemValue) { if (!curveUpdating) { - QList list = getCurve(); - emit curveUpdated(list, itemValue); + QList curve = getCurve(); + emit curveUpdated(&curve, itemValue); } } @@ -278,8 +269,9 @@ double MixerCurveWidget::getMax() { return curveMax; } -void MixerCurveWidget::setRange(double min, double max) +double MixerCurveWidget::setRange(double min, double max) { curveMin = min; curveMax = max; + return curveMax - curveMin; } diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.h b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.h index 92c9c3a8c..031a70733 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.h +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/mixercurvewidget.h @@ -44,20 +44,20 @@ public: MixerCurveWidget(QWidget *parent = 0); ~MixerCurveWidget(); void itemMoved(double itemValue); // Callback when a point is moved, to be updated - void initCurve (QList points); + void initCurve (const QList* points); QList getCurve(); - void initLinearCurve(quint32 numPoints, double maxValue = 1, double minValue = 0); - void setCurve(QList); + void initLinearCurve(int numPoints, double maxValue = 1, double minValue = 0); + void setCurve(const QList* points); void setMin(double value); double getMin(); void setMax(double value); double getMax(); - void setRange(double min, double max); + double setRange(double min, double max); static const int NODE_NUMELEM = 5; signals: - void curveUpdated(QList, double ); + void curveUpdated(const QList* points, const double value); private slots: