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 }