Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "EulerWidget.h"
00033 #include "ui_euler.h"
00034
00035 #include <angles/angles.h>
00036 #include <QStandardItemModel>
00037 #include <iostream>
00038
00039
00040 static void disableAxis(QComboBox *w, unsigned int axis) {
00041 const QStandardItemModel* model = qobject_cast<const QStandardItemModel*>(w->model());
00042 for (unsigned int i=0; i < 3; ++i) {
00043 QStandardItem* item = model->item(i);
00044 if (i == axis) {
00045 item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
00046 if (w->currentIndex() == static_cast<int>(axis)) w->setCurrentIndex((axis+1) % 3);
00047 } else {
00048 item->setFlags(item->flags() | Qt::ItemIsEnabled);
00049 }
00050 }
00051 }
00052
00053 EulerWidget::EulerWidget(QWidget *parent) :
00054 QWidget(parent), ui_(new Ui::EulerWidget)
00055 {
00056 qRegisterMetaType<Eigen::Quaterniond>("Eigen::Quaterniond");
00057
00058 ui_->setupUi(this);
00059 ui_->a1->setCurrentIndex(0);
00060 ui_->a2->setCurrentIndex(1); disableAxis(ui_->a2, 0);
00061 ui_->a3->setCurrentIndex(2); disableAxis(ui_->a3, 1);
00062
00063 q_ = Eigen::Quaterniond::Identity();
00064 updateAngles();
00065
00066
00067 connect(ui_->a1, SIGNAL(currentIndexChanged(int)),
00068 this, SLOT(axisChanged(int)));
00069 connect(ui_->a2, SIGNAL(currentIndexChanged(int)),
00070 this, SLOT(axisChanged(int)));
00071 connect(ui_->a3, SIGNAL(currentIndexChanged(int)),
00072 this, SLOT(axisChanged(int)));
00073
00074
00075 connect(ui_->e1, SIGNAL(valueChanged(double)),
00076 this, SLOT(angleChanged(double)));
00077 connect(ui_->e2, SIGNAL(valueChanged(double)),
00078 this, SLOT(angleChanged(double)));
00079 connect(ui_->e3, SIGNAL(valueChanged(double)),
00080 this, SLOT(angleChanged(double)));
00081 }
00082
00083 void EulerWidget::getGuiAxes(uint a[]) const {
00084 a[0] = ui_->a1->currentIndex();
00085 a[1] = ui_->a2->currentIndex();
00086 a[2] = ui_->a3->currentIndex();
00087 }
00088
00089 void EulerWidget::getGuiAngles(double e[3]) const {
00090 e[0] = angles::from_degrees(ui_->e1->value());
00091 e[1] = angles::from_degrees(ui_->e2->value());
00092 e[2] = angles::from_degrees(ui_->e3->value());
00093 }
00094
00095
00096 void EulerWidget::axisChanged(int axis) {
00097 bool bFirstCall = !this->signalsBlocked();
00098 this->blockSignals(true);
00099
00100
00101 QComboBox* origin = dynamic_cast<QComboBox*>(sender());
00102 if (origin == ui_->a1) disableAxis(ui_->a2, axis);
00103 if (origin == ui_->a2) disableAxis(ui_->a3, axis);
00104
00105 if (bFirstCall) {
00106 updateAngles();
00107 this->blockSignals(false);
00108
00109 emit axesChanged(ui_->a1->currentIndex(),
00110 ui_->a2->currentIndex(),
00111 ui_->a3->currentIndex());
00112 }
00113 }
00114
00115 void EulerWidget::angleChanged(double angle) {
00116 double e[3]; getGuiAngles(e);
00117 setEulerAngles(e[0], e[1], e[2], false);
00118 }
00119
00120 void EulerWidget::setEulerAngles(double e1, double e2, double e3, bool normalize) {
00121 uint a[3]; getGuiAxes(a);
00122 Eigen::Quaterniond q =
00123 Eigen::AngleAxisd(e1, Eigen::Vector3d::Unit(a[0])) *
00124 Eigen::AngleAxisd(e2, Eigen::Vector3d::Unit(a[1])) *
00125 Eigen::AngleAxisd(e3, Eigen::Vector3d::Unit(a[2]));
00126 if (normalize)
00127 setValue(q);
00128 else {
00129
00130 ui_->e1->blockSignals(true);
00131 ui_->e2->blockSignals(true);
00132 ui_->e3->blockSignals(true);
00133
00134 ui_->e1->setValue(angles::to_degrees(e1));
00135 ui_->e2->setValue(angles::to_degrees(e2));
00136 ui_->e3->setValue(angles::to_degrees(e3));
00137
00138 ui_->e1->blockSignals(false);
00139 ui_->e2->blockSignals(false);
00140 ui_->e3->blockSignals(false);
00141
00142 if (q_.isApprox(q)) return;
00143 q_ = q;
00144 emit valueChanged(q);
00145 }
00146 }
00147
00148 void EulerWidget::setEulerAxes(uint a1, uint a2, uint a3)
00149 {
00150 if (a1 > 2 || a2 > 2 || a3 > 2) return;
00151 if (static_cast<int>(a1) == ui_->a1->currentIndex() &&
00152 static_cast<int>(a2) == ui_->a2->currentIndex() &&
00153 static_cast<int>(a3) == ui_->a3->currentIndex()) return;
00154
00155 this->blockSignals(true);
00156 ui_->a3->setCurrentIndex(a3);
00157 ui_->a2->setCurrentIndex(a2);
00158 ui_->a1->setCurrentIndex(a1);
00159 this->blockSignals(false);
00160 updateAngles();
00161
00162 emit axesChanged(a1, a2, a3);
00163 }
00164
00165
00166 void EulerWidget::setValue(const Eigen::Quaterniond &q) {
00167 if (q_.isApprox(q)) return;
00168 q_ = q;
00169 updateAngles();
00170 emit valueChanged(q);
00171 }
00172
00173 const Eigen::Quaterniond& EulerWidget::value() const {
00174 return q_;
00175 }
00176
00177
00178 void EulerWidget::updateAngles() {
00179
00180 uint a[3]; getGuiAxes(a);
00181 Eigen::Vector3d e = q_.matrix().eulerAngles(a[0], a[1], a[2]);
00182 setEulerAngles(e[0], e[1], e[2], false);
00183 }