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 "rotation_property.h"
00033 
00034 using namespace rviz;
00035 
00036 namespace agni_tf_tools
00037 {
00038 
00039 RotationProperty::RotationProperty(Property* parent, const QString& name,
00040                                    const Eigen::Quaterniond& value,
00041                                    const char *changed_slot,
00042                                    QObject* receiver)
00043    : StringProperty(name, "",
00044                     "Orientation specification using Euler angles or a quaternion.",
00045                     parent, changed_slot, receiver)
00046    , ignore_quaternion_property_updates_(false)
00047    , show_euler_string_(true)
00048 {
00049   euler_property_ = new EulerProperty(this, "Euler angles", value);
00050   quaternion_property_ = new rviz::QuaternionProperty("quaternion",
00051                                                       Ogre::Quaternion(value.w(), value.x(), value.y(), value.z()),
00052                                                       "order: x, y, z, w", this);
00053   connect(euler_property_, SIGNAL(changed()), this, SLOT(updateFromEuler()));
00054   connect(quaternion_property_, SIGNAL(changed()), this, SLOT(updateFromQuaternion()));
00055   
00056   connect(euler_property_, SIGNAL(statusUpdate(int,QString,QString)),
00057           this, SIGNAL(statusUpdate(int,QString,QString)));
00058   
00059   connect(euler_property_, SIGNAL(quaternionChanged(Eigen::Quaterniond)),
00060           this, SIGNAL(quaternionChanged(Eigen::Quaterniond)));
00061   updateString();
00062 }
00063 
00064 Eigen::Quaterniond RotationProperty::getQuaternion() const
00065 {
00066   return euler_property_->getQuaternion();
00067 }
00068 
00069 void RotationProperty::setQuaternion(const Eigen::Quaterniond& q)
00070 {
00071   Eigen::Quaterniond qn = q.normalized();
00072   if (getQuaternion().isApprox(qn)) return;
00073   
00074   
00075   euler_property_->setQuaternion(qn);
00076 }
00077 
00078 void RotationProperty::updateFromEuler()
00079 {
00080   const Eigen::Quaterniond q = euler_property_->getQuaternion();
00081   
00082   if (!ignore_quaternion_property_updates_) {
00083     quaternion_property_->setQuaternion(Ogre::Quaternion(q.w(), q.x(), q.y(), q.z()));
00084   }
00085   show_euler_string_ = true;
00086   updateString();
00087 }
00088 
00089 void RotationProperty::updateFromQuaternion()
00090 {
00091   
00092   if (ignore_quaternion_property_updates_) return;
00093 
00094   const Ogre::Quaternion &q = quaternion_property_->getQuaternion();
00095   Eigen::Quaternion<Ogre::Real> eigen_q(q.w, q.x, q.y, q.z);
00096 
00097   
00098   if (eigen_q.isApprox(getQuaternion().cast<Ogre::Real>())) return;
00099 
00100   ignore_quaternion_property_updates_ = true;
00101   setQuaternion(eigen_q.cast<double>());
00102   ignore_quaternion_property_updates_ = false;
00103 
00104   show_euler_string_ = false;
00105   updateString();
00106 }
00107 
00108 void RotationProperty::setEulerAngles(double euler[], bool normalize)
00109 {
00110   euler_property_->setEulerAngles(euler, normalize);
00111 }
00112 
00113 void RotationProperty::setEulerAngles(double e1, double e2, double e3, bool normalize)
00114 {
00115   euler_property_->setEulerAngles(e1, e2, e3, normalize);
00116 }
00117 
00118 void RotationProperty::setEulerAxes(const QString &axes_spec)
00119 {
00120   euler_property_->setEulerAxes(axes_spec);
00121 }
00122 
00123 bool RotationProperty::setValue(const QVariant& value)
00124 {
00125   
00126   const QRegExp quatSpec("\\s*(quat:)?([^;]+;){3}");
00127   QString s = value.toString();
00128   if (quatSpec.indexIn(s) != -1)
00129   {
00130     s = s.mid(quatSpec.cap(1).length());
00131     return quaternion_property_->setValue(s);
00132   }
00133   return euler_property_->setValue(value);
00134 }
00135 
00136 void RotationProperty::updateString()
00137 {
00138   QString euler = euler_property_->getValue().toString();
00139   QString quat  = QString("quat: ") + quaternion_property_->getValue().toString();
00140   QString s = show_euler_string_ ? euler : quat;
00141   if (getString() != s) {
00142     Q_EMIT aboutToChange();
00143     value_ = s;
00144     Q_EMIT changed();
00145   }
00146 }
00147 
00148 void RotationProperty::load(const Config& config)
00149 {
00150   
00151   euler_property_->load(config);
00152 }
00153 
00154 void RotationProperty::save(Config config) const
00155 {
00156   
00157   euler_property_->save(config);
00158 }
00159 
00160 void RotationProperty::setReadOnly(bool read_only)
00161 {
00162   euler_property_->setReadOnly(read_only);
00163   quaternion_property_->setReadOnly(read_only);
00164 }
00165 
00166 }