rotation_property.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2016, Bielefeld University, CITEC
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  *
00029  * Author: Robert Haschke <rhaschke@techfak.uni-bielefeld.de>
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   // forward status signal from EulerProperty
00056   connect(euler_property_, SIGNAL(statusUpdate(int,QString,QString)),
00057           this, SIGNAL(statusUpdate(int,QString,QString)));
00058   // forward quaternion updates
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   // EulerProperty is considered "master".
00074   // EulerProperty update will trigger QuaternionProperty update too
00075   euler_property_->setQuaternion(qn);
00076 }
00077 
00078 void RotationProperty::updateFromEuler()
00079 {
00080   const Eigen::Quaterniond q = euler_property_->getQuaternion();
00081   // do not update QuaternionProperty
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   // protect from infinite update loop
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   // only update if changes are within accuracy range
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   // forward parsing to either Quaternion- or EulerProperty
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   // save/load from EulerProperty. This handles both, quaternion and euler axes.
00151   euler_property_->load(config);
00152 }
00153 
00154 void RotationProperty::save(Config config) const
00155 {
00156   // save/load from EulerProperty. This handles both, quaternion and euler axes.
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 } // end namespace rviz


agni_tf_tools
Author(s): Robert Haschke
autogenerated on Sat Jun 8 2019 21:01:20