From 427acee559d91963345a8a5c66aced795e4ddb59 Mon Sep 17 00:00:00 2001 From: zedamota Date: Fri, 3 Feb 2012 20:29:28 +0000 Subject: [PATCH] Added support for objects value limits on the GCS to the GCS and generator. --- .../config/configstabilizationwidget.cpp | 1 + .../src/plugins/config/configtaskwidget.cpp | 220 ++++++++++++------ .../src/plugins/config/configtaskwidget.h | 38 +-- .../src/plugins/uavobjects/uavobjectfield.cpp | 47 +++- .../src/plugins/uavobjects/uavobjectfield.h | 17 +- .../generators/gcs/uavobjectgeneratorgcs.cpp | 10 +- ground/uavobjgenerator/uavobjectparser.cpp | 7 + ground/uavobjgenerator/uavobjectparser.h | 13 +- 8 files changed, 253 insertions(+), 100 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp b/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp index 991fcbf94..f2cb0f137 100644 --- a/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp @@ -48,6 +48,7 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa addDefaultButton(m_stabilization->defaultButton,0); addReloadButton(m_stabilization->reloadButton,0); addWidgetToDefaultReloadGroups(m_stabilization->rateRollKp,rateGroup); + addShadowWidget("StabilizationSettings","RollRatePID",m_stabilization->rateRollKi,0,1,false,rateGroup); } diff --git a/ground/openpilotgcs/src/plugins/config/configtaskwidget.cpp b/ground/openpilotgcs/src/plugins/config/configtaskwidget.cpp index 4057eb782..fce5966f8 100644 --- a/ground/openpilotgcs/src/plugins/config/configtaskwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configtaskwidget.cpp @@ -68,6 +68,9 @@ void ConfigTaskWidget::addUAVObjectToWidgetRelation(QString object, QString fiel } void ConfigTaskWidget::addUAVObjectToWidgetRelation(QString object, QString field, QWidget * widget, int index,float scale,bool isLimited,QList* defaultReloadGroups) { + if(addShadowWidget(object,field,widget,index,scale,isLimited,defaultReloadGroups)) + return; + UAVObject *obj=NULL; UAVObjectField *_field=NULL; if(!object.isEmpty()) @@ -100,16 +103,28 @@ void ConfigTaskWidget::addUAVObjectToWidgetRelation(QString object, QString fiel // do nothing } else + { connectWidgetUpdatesToSlot(widget,SLOT(widgetsContentsChanged())); if(defaultReloadGroups) addWidgetToDefaultReloadGroups(widget,defaultReloadGroups); + shadowsList.insert(widget,ow); + } } ConfigTaskWidget::~ConfigTaskWidget() { - delete smartsave; + if(smartsave) + delete smartsave; foreach(QList* pointer,defaultReloadGroups.values()) - delete pointer; + { + if(pointer) + delete pointer; + } + foreach (objectToWidget* oTw, objOfInterest) + { + if(oTw) + delete oTw; + } } void ConfigTaskWidget::saveObjectToSD(UAVObject *obj) @@ -230,6 +245,39 @@ void ConfigTaskWidget::enableControls(bool enable) void ConfigTaskWidget::widgetsContentsChanged() { + float scale; + qDebug()<<"sender:"<<(quint32)sender(); + foreach(QWidget * w,shadowsList.keys()) + qDebug()<<"in list:"<<(quint32)w; + objectToWidget * oTw= shadowsList.value((QWidget*)sender(),NULL); + if(oTw) + qDebug()<<"in oTw OK"<<(quint32)oTw->widget; + if(oTw) + { + if(oTw->widget==(QWidget*)sender()) + { + scale=oTw->scale; + qDebug()<<"sender was master"; + } + else + { + foreach (shadow * sh, oTw->shadowsList) + { + if(sh->widget==(QWidget*)sender()) + { + scale=sh->scale; + qDebug()<<"sender was shadow"; + } + } + } + if(oTw->widget!=(QWidget *)sender()) + setWidgetFromVariant(oTw->widget,getVariantFromWidget((QWidget*)sender(),scale),oTw->scale); + foreach (shadow * sh, oTw->shadowsList) + { + if(sh->widget!=(QWidget*)sender()) + setWidgetFromVariant(sh->widget,getVariantFromWidget((QWidget*)sender(),scale),sh->scale); + } + } setDirty(true); } @@ -249,10 +297,6 @@ bool ConfigTaskWidget::isDirty() return false; } -void ConfigTaskWidget::refreshValues() -{ -} - void ConfigTaskWidget::disableObjUpdates() { foreach(objectToWidget * obj,objOfInterest) @@ -323,15 +367,27 @@ void ConfigTaskWidget::invalidateObjects() } } -bool ConfigTaskWidget::addShadowWidget(QString object, QString field, QWidget *widget, int index, float scale, bool isLimited) +bool ConfigTaskWidget::addShadowWidget(QString object, QString field, QWidget *widget, int index, float scale, bool isLimited,QList* defaultReloadGroups) { - foreach(objectToWidget * oTw, objOfInterest) + foreach(objectToWidget * oTw,objOfInterest) { + if(!oTw->object || !oTw->widget) + continue; if(oTw->object->getName()==object && oTw->field->getName()==field && oTw->index==index) { - oTw->shadows.append(widget); + shadow * sh=new shadow; + sh->isLimited=isLimited; + sh->scale=scale; + sh->widget=widget; + oTw->shadowsList.append(sh); + shadowsList.insert(widget,oTw); + connectWidgetUpdatesToSlot(widget,SLOT(widgetsContentsChanged())); + if(defaultReloadGroups) + addWidgetToDefaultReloadGroups(widget,defaultReloadGroups); + return true; } } + return false; } void ConfigTaskWidget::autoLoadWidgets() @@ -442,9 +498,9 @@ void ConfigTaskWidget::addWidgetToDefaultReloadGroups(QWidget *widget, QListshadows) + foreach(shadow * sh, oTw->shadowsList) { - if(shadow==widget) + if(sh->widget==widget) addOTW=true; } } @@ -481,6 +537,8 @@ void ConfigTaskWidget::defaultButtonClicked() QList * list=defaultReloadGroups.value(group); foreach(objectToWidget * oTw,*list) { + if(!oTw->object) + continue; UAVDataObject * temp=((UAVDataObject*)oTw->object)->dirtyClone(); setWidgetFromField(oTw->widget,temp->getField(oTw->field->getName()),oTw->index,oTw->scale); } @@ -491,6 +549,10 @@ void ConfigTaskWidget::reloadButtonClicked() int group=sender()->property("group").toInt(); QList * list=defaultReloadGroups.value(group); ObjectPersistence* objper = dynamic_cast( getObjectManager()->getObject(ObjectPersistence::NAME) ); + QTimer * timeOut=new QTimer(this); + QEventLoop * eventLoop=new QEventLoop(this); + connect(timeOut, SIGNAL(timeout()),eventLoop,SLOT(quit())); + connect(objper, SIGNAL(objectUpdated(UAVObject*)), eventLoop, SLOT(quit())); foreach(objectToWidget * oTw,*list) { if (oTw->object != NULL) @@ -502,9 +564,19 @@ void ConfigTaskWidget::reloadButtonClicked() data.InstanceID = oTw->object->getInstID(); objper->setData(data); objper->updated(); + timeOut->start(500); + eventLoop->exec(); + if(timeOut->isActive()) + { + setWidgetFromField(oTw->widget,oTw->field,oTw->index,oTw->scale); + } + timeOut->stop(); } } + delete eventLoop; + delete timeOut; } + void ConfigTaskWidget::connectWidgetUpdatesToSlot(QWidget * widget,const char* function) { if(!widget) @@ -545,46 +617,87 @@ void ConfigTaskWidget::connectWidgetUpdatesToSlot(QWidget * widget,const char* f qDebug()<<__FUNCTION__<<"widget to uavobject relation not implemented"<metaObject()->className(); } + bool ConfigTaskWidget::setFieldFromWidget(QWidget * widget,UAVObjectField * field,int index,float scale) { if(!widget || !field) return false; - if(QComboBox * cb=qobject_cast(widget)) + QVariant ret=getVariantFromWidget(widget,scale); + if(ret.isValid()) { - field->setValue(cb->currentText(),index); + field->setValue(ret,index); return true; } - else if(QLabel * cb=qobject_cast(widget)) - { - field->setValue(cb->text(),index); - return true; - } - else if(QDoubleSpinBox * cb=qobject_cast(widget)) - { - field->setValue(cb->value()* scale,index); - return true; - } - else if(QSpinBox * cb=qobject_cast(widget)) - { - field->setValue(cb->value()* (int)scale,index); - return true; - } - else if(QSlider * cb=qobject_cast(widget)) - { - field->setValue(cb->value()* (int)scale,index); - return true; - } - else if(QCheckBox * cb=qobject_cast(widget)) - { - field->setValue((cb->isChecked()?"TRUE":"FALSE"),index); - return true; - } - else { qDebug()<<__FUNCTION__<<"widget to uavobject relation not implemented"<metaObject()->className(); return false; } } +QVariant ConfigTaskWidget::getVariantFromWidget(QWidget * widget,float scale) +{ + if(QComboBox * cb=qobject_cast(widget)) + { + return (QString)cb->currentText(); + } + else if(QLabel * cb=qobject_cast(widget)) + { + return (QString)cb->text(); + } + else if(QDoubleSpinBox * cb=qobject_cast(widget)) + { + return (double)(cb->value()* scale); + } + else if(QSpinBox * cb=qobject_cast(widget)) + { + return (int)(cb->value()* (int)scale); + } + else if(QSlider * cb=qobject_cast(widget)) + { + return(int)(cb->value()* (int)scale); + } + else if(QCheckBox * cb=qobject_cast(widget)) + { + return (bool)(cb->isChecked()?"TRUE":"FALSE"); + } + else + return QVariant(); +} + +bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, float scale) +{ + if(QComboBox * cb=qobject_cast(widget)) + { + cb->setCurrentIndex(cb->findText(value.toString())); + return true; + } + else if(QLabel * cb=qobject_cast(widget)) + { + cb->setText(value.toString()); + return true; + } + else if(QDoubleSpinBox * cb=qobject_cast(widget)) + { + cb->setValue(value.toDouble()/scale); + return true; + } + else if(QSpinBox * cb=qobject_cast(widget)) + { + cb->setValue(value.toInt()/(int)scale); + return true; + } + else if(QSlider * cb=qobject_cast(widget)) + { + cb->setValue(value.toInt()/(int)scale); + return true; + } + else if(QCheckBox * cb=qobject_cast(widget)) + { + cb->setChecked(value.toBool()); + return true; + } + else + return false; +} bool ConfigTaskWidget::setWidgetFromField(QWidget * widget,UAVObjectField * field,int index,float scale) { @@ -594,34 +707,11 @@ bool ConfigTaskWidget::setWidgetFromField(QWidget * widget,UAVObjectField * fiel { if(cb->count()==0) cb->addItems(field->getOptions()); - cb->setCurrentIndex(cb->findText(field->getValue(index).toString())); - return true; } - else if(QLabel * cb=qobject_cast(widget)) - { - cb->setText(field->getValue(index).toString()); + QVariant var=field->getValue(index); + bool ret=setWidgetFromVariant(widget,var,scale); + if(ret) return true; - } - else if(QDoubleSpinBox * cb=qobject_cast(widget)) - { - cb->setValue(field->getValue(index).toDouble()/scale); - return true; - } - else if(QSpinBox * cb=qobject_cast(widget)) - { - cb->setValue(field->getValue(index).toInt()/(int)scale); - return true; - } - else if(QSlider * cb=qobject_cast(widget)) - { - cb->setValue(field->getValue(index).toInt()/(int)scale); - return true; - } - else if(QCheckBox * cb=qobject_cast(widget)) - { - cb->setChecked(field->getValue(index).toBool()); - return true; - } else { qDebug()<<__FUNCTION__<<"widget to uavobject relation not implemented"<metaObject()->className(); diff --git a/ground/openpilotgcs/src/plugins/config/configtaskwidget.h b/ground/openpilotgcs/src/plugins/config/configtaskwidget.h index 809f58433..3f00c23b5 100644 --- a/ground/openpilotgcs/src/plugins/config/configtaskwidget.h +++ b/ground/openpilotgcs/src/plugins/config/configtaskwidget.h @@ -49,6 +49,12 @@ class ConfigTaskWidget: public QWidget Q_OBJECT public: + struct shadow + { + QWidget * widget; + float scale; + bool isLimited; + }; struct objectToWidget { UAVObject * object; @@ -57,15 +63,7 @@ public: int index; float scale; bool isLimited; - QList shadows; - }; - - struct shadows - { - QWidget * widget; - float scale; - bool isLimited; - QWidget * parent; + QList shadowsList; }; enum buttonTypeEnum {none,save_button,apply_button,reload_button,default_button}; @@ -83,30 +81,37 @@ public: ConfigTaskWidget(QWidget *parent = 0); ~ConfigTaskWidget(); + void saveObjectToSD(UAVObject *obj); UAVObjectManager* getObjectManager(); static double listMean(QList list); + void addUAVObject(QString objectName); void addWidget(QWidget * widget); + void addUAVObjectToWidgetRelation(QString object,QString field,QWidget * widget,int index=0,float scale=1,bool isLimited=false,QList* defaultReloadGroups=0); void addUAVObjectToWidgetRelation(QString object,QString field,QWidget * widget,QString element,float scale,bool isLimited=false,QList* defaultReloadGroups=0); +void addUAVObjectToWidgetRelation(QString object, QString field, QWidget *widget, QString index); + //BUTTONS// void addApplySaveButtons(QPushButton * update,QPushButton * save); - - void addReloadButton(QPushButton * button,int buttonGroup); void addDefaultButton(QPushButton * button,int buttonGroup); + ////////// + void addWidgetToDefaultReloadGroups(QWidget * widget, QList *groups); + bool addShadowWidget(QWidget * masterWidget, QWidget * shadowWidget,float shadowScale=1,bool shadowIsLimited=false); - bool addShadowWidget(QString object,QString field,QWidget * widget,int index=0,float scale=1,bool isLimited=false); + bool addShadowWidget(QString object,QString field,QWidget * widget,int index=0,float scale=1,bool isLimited=false, QList *defaultReloadGroups=NULL); void autoLoadWidgets(); bool isDirty(); void setDirty(bool value); - void addUAVObjectToWidgetRelation(QString object, QString field, QWidget *widget, QString index); + bool allObjectsUpdated(); + public slots: void onAutopilotDisconnect(); void onAutopilotConnect(); @@ -117,8 +122,6 @@ signals: void objectAdded(UAVObject*); void objectRemoved(UAVObject*); private slots: - virtual void refreshValues(); - virtual void updateObjectsFromWidgets(); void objectUpdated(UAVObject*); void defaultButtonClicked(); void reloadButtonClicked(); @@ -131,10 +134,12 @@ private: smartSaveButton *smartsave; QMap objectUpdates; QMap *> defaultReloadGroups; - QList shadowsList; + QMap shadowsList; bool dirty; bool setFieldFromWidget(QWidget *widget, UAVObjectField *field, int index, float scale); bool setWidgetFromField(QWidget *widget, UAVObjectField *field, int index, float scale); + QVariant getVariantFromWidget(QWidget *widget, float scale); + bool setWidgetFromVariant(QWidget *widget,QVariant value,float scale); void connectWidgetUpdatesToSlot(QWidget *widget, const char *function); protected slots: virtual void disableObjUpdates(); @@ -143,6 +148,7 @@ protected slots: virtual void widgetsContentsChanged(); virtual void populateWidgets(); virtual void refreshWidgetsValues(); + virtual void updateObjectsFromWidgets(); protected: virtual void enableControls(bool enable); diff --git a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp index da71fd943..6723daf04 100644 --- a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp @@ -29,7 +29,7 @@ #include #include -UAVObjectField::UAVObjectField(const QString& name, const QString& units, FieldType type, quint32 numElements, const QStringList& options) +UAVObjectField::UAVObjectField(const QString& name, const QString& units, FieldType type, quint32 numElements, const QStringList& options, const QString &limits) { QStringList elementNames; // Set element names @@ -38,16 +38,16 @@ UAVObjectField::UAVObjectField(const QString& name, const QString& units, FieldT elementNames.append(QString("%1").arg(n)); } // Initialize - constructorInitialize(name, units, type, elementNames, options); + constructorInitialize(name, units, type, elementNames, options,limits); } -UAVObjectField::UAVObjectField(const QString& name, const QString& units, FieldType type, const QStringList& elementNames, const QStringList& options) +UAVObjectField::UAVObjectField(const QString& name, const QString& units, FieldType type, const QStringList& elementNames, const QStringList& options, const QString &limits) { - constructorInitialize(name, units, type, elementNames, options); + constructorInitialize(name, units, type, elementNames, options,limits); } -void UAVObjectField::constructorInitialize(const QString& name, const QString& units, FieldType type, const QStringList& elementNames, const QStringList& options) +void UAVObjectField::constructorInitialize(const QString& name, const QString& units, FieldType type, const QStringList& elementNames, const QStringList& options,QString &limits) { // Copy params this->name = name; @@ -94,6 +94,43 @@ void UAVObjectField::constructorInitialize(const QString& name, const QString& u } } +void UAVObjectField::limitsInitialize(QString &limits) +{ + /// format + /// (TY)->type (EQ-equal;NE-not equal;BE-between;BI-bigger;SM-smaller) + /// (VALX)->value + /// %TY:VAL1:VAL2:VAL3,%TY,VAL1,VAL2,VAL3 + /// example: first element bigger than 3 and second element inside [2.3,5] + /// "%0BI:3,%1BE:2.3:5" + QStringList stringPerElement=limits.split(","); + foreach (QString str, stringPerElement) { + QStringList valuesPerElement=str.split(":"); + LimitStruct lstruc; + quint32 index=valuesPerElement.at(0).mid(1,valuesPerElement.at(0).length()-3).toULong(); + if(valuesPerElement.at(0).startsWith("%") && indexdata = data; diff --git a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.h b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.h index 3cefc25e6..0c4598598 100644 --- a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.h +++ b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.h @@ -32,6 +32,8 @@ #include "uavobject.h" #include #include +#include +#include class UAVObject; @@ -41,9 +43,15 @@ class UAVOBJECTS_EXPORT UAVObjectField: public QObject public: typedef enum { INT8 = 0, INT16, INT32, UINT8, UINT16, UINT32, FLOAT32, ENUM, STRING } FieldType; + typedef enum { EQUAL,NOT_EQUAL,BETWEEN,BIGGER,SMALLER } LimitType; + typedef struct + { + LimitType type; + QList values; + } LimitStruct; - UAVObjectField(const QString& name, const QString& units, FieldType type, quint32 numElements, const QStringList& options); - UAVObjectField(const QString& name, const QString& units, FieldType type, const QStringList& elementNames, const QStringList& options); + UAVObjectField(const QString& name, const QString& units, FieldType type, quint32 numElements, const QStringList& options,const QString& limits=QString::QString()); + UAVObjectField(const QString& name, const QString& units, FieldType type, const QStringList& elementNames, const QStringList& options,const QString& limits=QString::QString()); void initialize(quint8* data, quint32 dataOffset, UAVObject* obj); UAVObject* getObject(); FieldType getType(); @@ -81,9 +89,10 @@ protected: quint32 offset; quint8* data; UAVObject* obj; - + QMap elementLimits; void clear(); - void constructorInitialize(const QString& name, const QString& units, FieldType type, const QStringList& elementNames, const QStringList& options); + void constructorInitialize(const QString& name, const QString& units, FieldType type, const QStringList& elementNames, const QStringList& options, QString &limits); + void limitsInitialize(QString &limits); }; diff --git a/ground/uavobjgenerator/generators/gcs/uavobjectgeneratorgcs.cpp b/ground/uavobjgenerator/generators/gcs/uavobjectgeneratorgcs.cpp index aacb66a96..a8a5b8efe 100644 --- a/ground/uavobjgenerator/generators/gcs/uavobjectgeneratorgcs.cpp +++ b/ground/uavobjgenerator/generators/gcs/uavobjectgeneratorgcs.cpp @@ -131,19 +131,21 @@ bool UAVObjectGeneratorGCS::process_object(ObjectInfo* info) .arg(varOptionName) .arg(options[m]) ); } - finit.append( QString(" fields.append( new UAVObjectField(QString(\"%1\"), QString(\"%2\"), UAVObjectField::ENUM, %3, %4) );\n") + finit.append( QString(" fields.append( new UAVObjectField(QString(\"%1\"), QString(\"%2\"), UAVObjectField::ENUM, %3, %4, QString(\"%5\")));\n") .arg(info->fields[n]->name) .arg(info->fields[n]->units) .arg(varElemName) - .arg(varOptionName) ); + .arg(varOptionName) + .arg(info->fields[n]->limitValues)); } // For all other types else { - finit.append( QString(" fields.append( new UAVObjectField(QString(\"%1\"), QString(\"%2\"), UAVObjectField::%3, %4, QStringList()) );\n") + finit.append( QString(" fields.append( new UAVObjectField(QString(\"%1\"), QString(\"%2\"), UAVObjectField::%3, %4, QStringList(), QString(\"%5\")));\n") .arg(info->fields[n]->name) .arg(info->fields[n]->units) .arg(fieldTypeStrCPPClass[info->fields[n]->type]) - .arg(varElemName) ); + .arg(varElemName) + .arg(info->fields[n]->limitValues)); } } outCode.replace(QString("$(FIELDSINIT)"), finit); diff --git a/ground/uavobjgenerator/uavobjectparser.cpp b/ground/uavobjgenerator/uavobjectparser.cpp index 414712658..a0409f06f 100644 --- a/ground/uavobjgenerator/uavobjectparser.cpp +++ b/ground/uavobjgenerator/uavobjectparser.cpp @@ -469,6 +469,13 @@ QString UAVObjectParser::processObjectFields(QDomNode& childNode, ObjectInfo* in } field->defaultValues = defaults; } + elemAttr = elemAttributes.namedItem("limits"); + if ( elemAttr.isNull() ) { + field->limitValues=QString(); + } + else{ + field->limitValues=elemAttr.nodeValue(); + } // Add field to object info->fields.append(field); // Done diff --git a/ground/uavobjgenerator/uavobjectparser.h b/ground/uavobjgenerator/uavobjectparser.h index 6f8678930..f1e93d8f5 100644 --- a/ground/uavobjgenerator/uavobjectparser.h +++ b/ground/uavobjgenerator/uavobjectparser.h @@ -52,11 +52,12 @@ typedef struct { QString units; FieldType type; int numElements; - int numBytes; + int numBytes; QStringList elementNames; QStringList options; // for enums only bool defaultElementNames; QStringList defaultValues; + QString limitValues; } FieldInfo; /** @@ -69,13 +70,13 @@ typedef enum { UPDATEMODE_NEVER /** Object is never updated */ } UpdateMode; - + typedef enum { ACCESS_READWRITE = 0, ACCESS_READONLY = 1 } AccessMode; - - + + typedef struct { QString name; QString namelc; /** name in lowercase */ @@ -110,8 +111,8 @@ public: quint32 getObjectID(int objIndex); ObjectInfo* getObjectByIndex(int objIndex); - int getNumBytes(int objIndex); - QStringList all_units; + int getNumBytes(int objIndex); + QStringList all_units; private: QList objInfo;