1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-27 16:54:15 +01:00

OP-347 Implement the option to reverse the input controls on the config gadget: this is mostly useful for people with TX which do not offer this option. Tested on my small hex.

git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@3121 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
edouard 2011-04-03 06:47:07 +00:00 committed by edouard
parent 7ab0789f85
commit da6530537b
3 changed files with 293 additions and 140 deletions

View File

@ -84,6 +84,16 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent)
<< m_config->inSlider6 << m_config->inSlider6
<< m_config->inSlider7; << m_config->inSlider7;
inRevCheckboxes << m_config->ch0Rev
<< m_config->ch1Rev
<< m_config->ch2Rev
<< m_config->ch3Rev
<< m_config->ch4Rev
<< m_config->ch5Rev
<< m_config->ch6Rev
<< m_config->ch7Rev;
// Now connect the widget to the ManualControlCommand / Channel UAVObject // Now connect the widget to the ManualControlCommand / Channel UAVObject
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ManualControlCommand"))); UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ManualControlCommand")));
@ -157,31 +167,38 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent)
connect(parent, SIGNAL(autopilotConnected()),this, SLOT(requestRCInputUpdate())); connect(parent, SIGNAL(autopilotConnected()),this, SLOT(requestRCInputUpdate()));
connect(m_config->inSlider0, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged0(int))); connect(m_config->inSlider0, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged0(int)));
connect(m_config->inSlider1, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged1(int))); connect(m_config->inSlider1, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged1(int)));
connect(m_config->inSlider2, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged2(int))); connect(m_config->inSlider2, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged2(int)));
connect(m_config->inSlider3, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged3(int))); connect(m_config->inSlider3, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged3(int)));
connect(m_config->inSlider4, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged4(int))); connect(m_config->inSlider4, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged4(int)));
connect(m_config->inSlider5, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged5(int))); connect(m_config->inSlider5, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged5(int)));
connect(m_config->inSlider6, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged6(int))); connect(m_config->inSlider6, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged6(int)));
connect(m_config->inSlider7, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged7(int))); connect(m_config->inSlider7, SIGNAL(valueChanged(int)),this, SLOT(onInSliderValueChanged7(int)));
connect(m_config->ch0Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
connect(m_config->ch1Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
connect(m_config->ch2Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
connect(m_config->ch3Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
connect(m_config->ch4Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
connect(m_config->ch5Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
connect(m_config->ch6Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
connect(m_config->ch7Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
firstUpdate = true; firstUpdate = true;
enableControls(false); enableControls(false);
// Listen to telemetry connection events // Listen to telemetry connection events
if (pm) if (pm) {
{ TelemetryManager *tm = pm->getObject<TelemetryManager>();
TelemetryManager *tm = pm->getObject<TelemetryManager>(); if (tm) {
if (tm) connect(tm, SIGNAL(myStart()), this, SLOT(onTelemetryStart()));
{ connect(tm, SIGNAL(myStop()), this, SLOT(onTelemetryStop()));
connect(tm, SIGNAL(myStart()), this, SLOT(onTelemetryStart())); connect(tm, SIGNAL(connected()), this, SLOT(onTelemetryConnect()));
connect(tm, SIGNAL(myStop()), this, SLOT(onTelemetryStop())); connect(tm, SIGNAL(disconnected()), this, SLOT(onTelemetryDisconnect()));
connect(tm, SIGNAL(connected()), this, SLOT(onTelemetryConnect())); }
connect(tm, SIGNAL(disconnected()), this, SLOT(onTelemetryDisconnect())); }
}
}
} }
ConfigInputWidget::~ConfigInputWidget() ConfigInputWidget::~ConfigInputWidget()
@ -189,6 +206,24 @@ ConfigInputWidget::~ConfigInputWidget()
// Do nothing // Do nothing
} }
/**
Slot called whenever we revert a signal
*/
void ConfigInputWidget::reverseCheckboxClicked(bool state)
{
QObject* obj = sender();
int i = inRevCheckboxes.indexOf((QCheckBox*)obj);
inSliders[i]->setInvertedAppearance(state);
int max = inMaxLabels[i]->text().toInt();
int min = inMinLabels[i]->text().toInt();
if ((state && (max>min)) ||
(!state && (max < min))) {
inMaxLabels[i]->setText(QString::number(min));
inMinLabels[i]->setText(QString::number(max));
}
}
// ************************************ // ************************************
// slider value changed signals // slider value changed signals
@ -296,31 +331,36 @@ void ConfigInputWidget::requestRCInputUpdate()
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlSettings"))); UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlSettings")));
Q_ASSERT(obj); Q_ASSERT(obj);
obj->requestUpdate(); obj->requestUpdate();
UAVObjectField *field;
UAVObjectField *field;
// Now update all the slider values: // Now update all the slider values:
UAVObjectField *field_max = obj->getField(QString("ChannelMax")); UAVObjectField *field_max = obj->getField(QString("ChannelMax"));
UAVObjectField *field_min = obj->getField(QString("ChannelMin")); UAVObjectField *field_min = obj->getField(QString("ChannelMin"));
UAVObjectField *field_neu = obj->getField(QString("ChannelNeutral")); UAVObjectField *field_neu = obj->getField(QString("ChannelNeutral"));
Q_ASSERT(field_max); Q_ASSERT(field_max);
Q_ASSERT(field_min); Q_ASSERT(field_min);
Q_ASSERT(field_neu); Q_ASSERT(field_neu);
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++) {
{ QVariant max = field_max->getValue(i);
QVariant max = field_max->getValue(i); QVariant min = field_min->getValue(i);
QVariant min = field_min->getValue(i); QVariant neutral = field_neu->getValue(i);
QVariant neutral = field_neu->getValue(i); inMaxLabels[i]->setText(max.toString());
inMaxLabels[i]->setText(max.toString()); inMinLabels[i]->setText(min.toString());
inMinLabels[i]->setText(min.toString()); if (max.toInt()> min.toInt()) {
inSliders[i]->setMaximum(max.toInt()); inRevCheckboxes[i]->setChecked(false);
inSliders[i]->setMinimum(min.toInt()); inSliders[i]->setMaximum(max.toInt());
inSliders[i]->setValue(neutral.toInt()); inSliders[i]->setMinimum(min.toInt());
} } else {
inRevCheckboxes[i]->setChecked(true);
inSliders[i]->setMaximum(min.toInt());
inSliders[i]->setMinimum(max.toInt());
}
inSliders[i]->setValue(neutral.toInt());
}
// Update receiver type // Update receiver type
field = obj->getField(QString("InputMode")); field = obj->getField(QString("InputMode"));
m_config->receiverType->setCurrentIndex(m_config->receiverType->findText(field->getValue().toString())); m_config->receiverType->setCurrentIndex(m_config->receiverType->findText(field->getValue().toString()));
// Reset all channel assignement dropdowns: // Reset all channel assignement dropdowns:
@ -334,10 +374,9 @@ void ConfigInputWidget::requestRCInputUpdate()
m_config->ch7Assign->setCurrentIndex(0); m_config->ch7Assign->setCurrentIndex(0);
// Update all channels assignements // Update all channels assignements
QList<UAVObjectField *> fieldList = obj->getFields(); QList<UAVObjectField *> fieldList = obj->getFields();
foreach (UAVObjectField *field, fieldList) foreach (UAVObjectField *field, fieldList) {
{ if (field->getUnits().contains("channel"))
if (field->getUnits().contains("channel"))
assignChannel(obj, field->getName()); assignChannel(obj, field->getName());
} }
@ -380,18 +419,20 @@ void ConfigInputWidget::sendRCInputUpdate()
// Now update all fields from the sliders: // Now update all fields from the sliders:
QString fieldName = QString("ChannelMax"); QString fieldName = QString("ChannelMax");
UAVObjectField * field = obj->getField(fieldName); UAVObjectField * field = obj->getField(fieldName);
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++) {
field->setValue(inMaxLabels[i]->text().toInt(), i); field->setValue(inMaxLabels[i]->text().toInt(), i);
}
fieldName = QString("ChannelMin"); fieldName = QString("ChannelMin");
field = obj->getField(fieldName); field = obj->getField(fieldName);
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++) {
field->setValue(inMinLabels[i]->text().toInt(), i); field->setValue(inMinLabels[i]->text().toInt(), i);
}
fieldName = QString("ChannelNeutral"); fieldName = QString("ChannelNeutral");
field = obj->getField(fieldName); field = obj->getField(fieldName);
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
field->setValue(inSliders[i]->value(), i); field->setValue(inSliders[i]->value(), i);
// Set RC Receiver type: // Set RC Receiver type:
fieldName = QString("InputMode"); fieldName = QString("InputMode");
@ -474,7 +515,6 @@ void ConfigInputWidget::sendRCInputUpdate()
} }
/** /**
Sends the config to the board and request saving into the SD card Sends the config to the board and request saving into the SD card
*/ */
@ -534,47 +574,42 @@ void ConfigInputWidget::updateChannels(UAVObject* controlCommand)
QString fieldName = QString("Connected"); QString fieldName = QString("Connected");
UAVObjectField *field = controlCommand->getField(fieldName); UAVObjectField *field = controlCommand->getField(fieldName);
if (field->getValue().toBool()) if (field->getValue().toBool())
m_config->RCInputConnected->setText("RC Receiver Connected"); m_config->RCInputConnected->setText("RC Receiver Connected");
else else
m_config->RCInputConnected->setText("RC Receiver Not Connected"); m_config->RCInputConnected->setText("RC Receiver Not Connected");
if (m_config->doRCInputCalibration->isChecked()) if (m_config->doRCInputCalibration->isChecked()) {
{ if (firstUpdate) {
if (firstUpdate) // Increase the data rate from the board so that the sliders
{ // move faster
// Increase the data rate from the board so that the sliders UAVObject::Metadata mdata = controlCommand->getMetadata();
// move faster mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
UAVObject::Metadata mdata = controlCommand->getMetadata(); mccDataRate = mdata.flightTelemetryUpdatePeriod;
mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC; mdata.flightTelemetryUpdatePeriod = 150;
mccDataRate = mdata.flightTelemetryUpdatePeriod; controlCommand->setMetadata(mdata);
mdata.flightTelemetryUpdatePeriod = 150;
controlCommand->setMetadata(mdata); // Also protect the user by setting all values to zero
// and making the ActuatorCommand object readonly
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorCommand")));
mdata = obj->getMetadata();
mdata.flightAccess = UAVObject::ACCESS_READONLY;
obj->setMetadata(mdata);
UAVObjectField *field = obj->getField("Channel");
for (int i=0; i< field->getNumElements(); i++) {
field->setValue(0,i);
}
obj->updated();
// Also protect the user by setting all values to zero
// and making the ActuatorCommand object readonly
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorCommand")));
mdata = obj->getMetadata();
mdata.flightAccess = UAVObject::ACCESS_READONLY;
obj->setMetadata(mdata);
UAVObjectField *field = obj->getField("Channel");
for (int i=0; i< field->getNumElements(); i++) {
field->setValue(0,i);
} }
obj->updated();
}
field = controlCommand->getField(QString("Channel"));
for (int i = 0; i < 8; i++)
updateChannelInSlider(inSliders[i], inMinLabels[i], inMaxLabels[i], field->getValue(i).toInt());
field = controlCommand->getField(QString("Channel"));
for (int i = 0; i < 8; i++)
updateChannelInSlider(inSliders[i], inMinLabels[i], inMaxLabels[i], field->getValue(i).toInt(),inRevCheckboxes[i]->isChecked());
firstUpdate = false; firstUpdate = false;
} }
else else {
{ if (!firstUpdate) {
if (!firstUpdate)
{
// Restore original data rate from the board: // Restore original data rate from the board:
UAVObject::Metadata mdata = controlCommand->getMetadata(); UAVObject::Metadata mdata = controlCommand->getMetadata();
mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC; mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
@ -585,7 +620,6 @@ void ConfigInputWidget::updateChannels(UAVObject* controlCommand)
mdata = obj->getMetadata(); mdata = obj->getMetadata();
mdata.flightAccess = UAVObject::ACCESS_READWRITE; mdata.flightAccess = UAVObject::ACCESS_READWRITE;
obj->setMetadata(mdata); obj->setMetadata(mdata);
} }
firstUpdate = true; firstUpdate = true;
} }
@ -594,28 +628,27 @@ void ConfigInputWidget::updateChannels(UAVObject* controlCommand)
// Find the channel currently assigned to flightmode // Find the channel currently assigned to flightmode
field = obj->getField("FlightMode"); field = obj->getField("FlightMode");
int chIndex = field->getOptions().indexOf(field->getValue().toString()); int chIndex = field->getOptions().indexOf(field->getValue().toString());
if (chIndex < field->getOptions().length() - 1) if (chIndex < field->getOptions().length() - 1) {
{ float valueScaled;
float valueScaled;
int chMin = inSliders[chIndex]->minimum(); int chMin = inSliders[chIndex]->minimum();
int chMax = inSliders[chIndex]->maximum(); int chMax = inSliders[chIndex]->maximum();
int chNeutral = inSliders[chIndex]->value(); int chNeutral = inSliders[chIndex]->value();
int value = controlCommand->getField("Channel")->getValue(chIndex).toInt(); int value = controlCommand->getField("Channel")->getValue(chIndex).toInt();
if ((chMax > chMin && value >= chNeutral) || (chMin > chMax && value <= chNeutral)) if ((chMax > chMin && value >= chNeutral) || (chMin > chMax && value <= chNeutral))
{ {
if (chMax != chNeutral) if (chMax != chNeutral)
valueScaled = (float)(value - chNeutral) / (float)(chMax - chNeutral); valueScaled = (float)(value - chNeutral) / (float)(chMax - chNeutral);
else else
valueScaled = 0; valueScaled = 0;
} }
else else
{ {
if (chMin != chNeutral) if (chMin != chNeutral)
valueScaled = (float)(value - chNeutral) / (float)(chNeutral - chMin); valueScaled = (float)(value - chNeutral) / (float)(chNeutral - chMin);
else else
valueScaled = 0; valueScaled = 0;
} }
// Bound // Bound
@ -627,36 +660,37 @@ void ConfigInputWidget::updateChannels(UAVObject* controlCommand)
} }
} }
void ConfigInputWidget::updateChannelInSlider(QSlider *slider, QLabel *min, QLabel *max, int value) void ConfigInputWidget::updateChannelInSlider(QSlider *slider, QLabel *min, QLabel *max, int value, bool reversed)
{ {
if (!slider || !min || !max) if (!slider || !min || !max)
return; return;
if (firstUpdate) if (firstUpdate) {
{ // Reset all the min/max values of the progress bar since we are starting the calibration. // Reset all the min/max values of the progress bar since we are starting the calibration.
slider->setMaximum(value);
slider->setMinimum(value);
slider->setValue(value);
max->setText(QString::number(value));
min->setText(QString::number(value));
return;
}
slider->setMaximum(value); if (value > 0) {
slider->setMinimum(value); // avoids glitches...
slider->setValue(value); if (value > slider->maximum()) {
slider->setMaximum(value);
max->setText(QString::number(value)); if (reversed)
min->setText(QString::number(value)); min->setText(QString::number(value));
else
return; max->setText(QString::number(value));
} }
if (value < slider->minimum()) {
if (value > 0) slider->setMinimum(value);
{ // avoids glitches... if (reversed)
if (value > slider->maximum()) max->setText(QString::number(value));
{ else
slider->setMaximum(value); min->setText(QString::number(value));
max->setText(QString::number(value)); }
} slider->setValue(value);
if (value < slider->minimum()) }
{
slider->setMinimum(value);
min->setText(QString::number(value));
}
slider->setValue(value);
}
} }

View File

@ -65,7 +65,7 @@ private:
QList<QSlider> sliders; QList<QSlider> sliders;
void updateChannelInSlider(QSlider *slider, QLabel *min, QLabel *max, int value); void updateChannelInSlider(QSlider *slider, QLabel *min, QLabel *max, int value, bool reversed);
void assignChannel(UAVDataObject *obj, QString str); void assignChannel(UAVDataObject *obj, QString str);
void assignOutputChannel(UAVDataObject *obj, QString str); void assignOutputChannel(UAVDataObject *obj, QString str);
@ -78,6 +78,7 @@ private:
QList<QLabel*> inMaxLabels; QList<QLabel*> inMaxLabels;
QList<QLabel*> inMinLabels; QList<QLabel*> inMinLabels;
QList<QLabel*> inNeuLabels; QList<QLabel*> inNeuLabels;
QList<QCheckBox*> inRevCheckboxes;
bool firstUpdate; bool firstUpdate;
@ -88,6 +89,7 @@ private slots:
void requestRCInputUpdate(); void requestRCInputUpdate();
void sendRCInputUpdate(); void sendRCInputUpdate();
void saveRCInputObject(); void saveRCInputObject();
void reverseCheckboxClicked(bool state);
}; };
#endif #endif

View File

@ -226,7 +226,7 @@ p, li { white-space: pre-wrap; }
<widget class="QPushButton" name="getRCInputCurrent"> <widget class="QPushButton" name="getRCInputCurrent">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>250</x> <x>260</x>
<y>280</y> <y>280</y>
<width>93</width> <width>93</width>
<height>27</height> <height>27</height>
@ -353,7 +353,7 @@ p, li { white-space: pre-wrap; }
<widget class="QPushButton" name="saveRCInputToSD"> <widget class="QPushButton" name="saveRCInputToSD">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>430</x> <x>460</x>
<y>280</y> <y>280</y>
<width>93</width> <width>93</width>
<height>27</height> <height>27</height>
@ -428,7 +428,7 @@ p, li { white-space: pre-wrap; }
<widget class="QPushButton" name="saveRCInputToRAM"> <widget class="QPushButton" name="saveRCInputToRAM">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>340</x> <x>360</x>
<y>280</y> <y>280</y>
<width>93</width> <width>93</width>
<height>27</height> <height>27</height>
@ -1189,6 +1189,123 @@ p, li { white-space: pre-wrap; }
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
<widget class="QCheckBox" name="ch0Rev">
<property name="geometry">
<rect>
<x>560</x>
<y>40</y>
<width>21</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>560</x>
<y>20</y>
<width>31</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Rev.</string>
</property>
</widget>
<widget class="QCheckBox" name="ch1Rev">
<property name="geometry">
<rect>
<x>560</x>
<y>70</y>
<width>21</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QCheckBox" name="ch2Rev">
<property name="geometry">
<rect>
<x>560</x>
<y>100</y>
<width>21</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QCheckBox" name="ch3Rev">
<property name="geometry">
<rect>
<x>560</x>
<y>130</y>
<width>21</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QCheckBox" name="ch4Rev">
<property name="geometry">
<rect>
<x>560</x>
<y>160</y>
<width>21</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QCheckBox" name="ch5Rev">
<property name="geometry">
<rect>
<x>560</x>
<y>190</y>
<width>21</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QCheckBox" name="ch6Rev">
<property name="geometry">
<rect>
<x>560</x>
<y>220</y>
<width>21</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QCheckBox" name="ch7Rev">
<property name="geometry">
<rect>
<x>560</x>
<y>250</y>
<width>21</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
</widget> </widget>
<widget class="QWidget" name="tab_3"> <widget class="QWidget" name="tab_3">
<attribute name="title"> <attribute name="title">