Skip to content
Snippets Groups Projects
Commit c7f68315 authored by Joan Solà Ortega's avatar Joan Solà Ortega
Browse files

Merge branch 'LocalParamQuat_template' into 'master'

to discuss : made LocalParametrizationQuaternion template & use partial specialization

Since `LocalParametrizationQuaternion` private member `delta_reference_` is set at instantiation, does not change and is used to specialize computation it is better to use a template partial specialization scheme.

If having the empty template bracket when using the default value `DQ_GLOBAL` is a killer, we can always consider typedef.

See merge request !83
parents eb8d0430 caff6b08
No related branches found
No related tags found
1 merge request!83to discuss : made LocalParametrizationQuaternion template & use partial specialization
...@@ -37,8 +37,8 @@ int main(){ ...@@ -37,8 +37,8 @@ int main(){
cout << "q = " << q.transpose() << " with norm = " << q.norm() << "\nda = " << da.transpose() << endl; cout << "q = " << q.transpose() << " with norm = " << q.norm() << "\nda = " << da.transpose() << endl;
cout << "qo = " << qo.transpose() << " with norm = " << qo.norm() << endl; cout << "qo = " << qo.transpose() << " with norm = " << qo.norm() << endl;
LocalParametrizationQuaternion Qpar; LocalParametrizationQuaternion<DQ_GLOBAL> Qpar;
LocalParametrizationQuaternion Qpar_loc(DQ_LOCAL); LocalParametrizationQuaternion<DQ_LOCAL> Qpar_loc;
cout << "\nGLOBAL D_QUAT plus()" << endl; cout << "\nGLOBAL D_QUAT plus()" << endl;
Map<const VectorXs> q_const(q.data(),4); Map<const VectorXs> q_const(q.data(),4);
......
...@@ -2,19 +2,10 @@ ...@@ -2,19 +2,10 @@
namespace wolf { namespace wolf {
LocalParametrizationQuaternion::LocalParametrizationQuaternion(QuaternionDeltaReference _delta_ref) : template <>
LocalParametrizationBase(4, 3), bool LocalParametrizationQuaternion<wolf::DQ_LOCAL>::plus(const Eigen::Map<const Eigen::VectorXs>& _q,
delta_reference_(_delta_ref) const Eigen::Map<const Eigen::VectorXs>& _delta_theta,
{ Eigen::Map<Eigen::VectorXs>& _q_plus_delta_theta) const
}
LocalParametrizationQuaternion::~LocalParametrizationQuaternion()
{
}
bool LocalParametrizationQuaternion::plus(const Eigen::Map<const Eigen::VectorXs>& _q,
const Eigen::Map<const Eigen::VectorXs>& _delta_theta,
Eigen::Map<Eigen::VectorXs>& _q_plus_delta_theta) const
{ {
assert(_q.size() == global_size_ && "Wrong size of input quaternion."); assert(_q.size() == global_size_ && "Wrong size of input quaternion.");
...@@ -35,12 +26,8 @@ bool LocalParametrizationQuaternion::plus(const Eigen::Map<const Eigen::VectorXs ...@@ -35,12 +26,8 @@ bool LocalParametrizationQuaternion::plus(const Eigen::Map<const Eigen::VectorXs
Quaternions dq(AngleAxis<Scalar>(angle, axis)); Quaternions dq(AngleAxis<Scalar>(angle, axis));
// result as a quaternion // result as a quaternion
if (delta_reference_ == DQ_GLOBAL) // the delta is in local reference: q * dq
// the delta is in global reference: dq * q _q_plus_delta_theta = (Map<const Quaternions>(_q.data()) * dq).coeffs();
_q_plus_delta_theta = (dq * Map<const Quaternions>(_q.data())).coeffs();
else
// the delta is in local reference: q * dq
_q_plus_delta_theta = (Map<const Quaternions>(_q.data()) * dq).coeffs();
} }
else // Consider null rotation else // Consider null rotation
...@@ -50,30 +37,72 @@ bool LocalParametrizationQuaternion::plus(const Eigen::Map<const Eigen::VectorXs ...@@ -50,30 +37,72 @@ bool LocalParametrizationQuaternion::plus(const Eigen::Map<const Eigen::VectorXs
return true; return true;
} }
bool LocalParametrizationQuaternion::computeJacobian(const Eigen::Map<const Eigen::VectorXs>& _q, template <>
Eigen::Map<Eigen::MatrixXs>& _jacobian) const bool LocalParametrizationQuaternion<wolf::DQ_GLOBAL>::plus(const Eigen::Map<const Eigen::VectorXs>& _q,
const Eigen::Map<const Eigen::VectorXs>& _delta_theta,
Eigen::Map<Eigen::VectorXs>& _q_plus_delta_theta) const
{ {
assert(_q.size() == global_size_ && "Wrong size of input quaternion."); assert(_q.size() == global_size_ && "Wrong size of input quaternion.");
assert(_jacobian.rows() == global_size_ && _jacobian.cols() == local_size_ && "Wrong size of Jacobian matrix."); assert(_delta_theta.size() == local_size_ && "Wrong size of input delta_theta.");
assert(_q_plus_delta_theta.size() == global_size_ && "Wrong size of output quaternion.");
assert(fabs(1.0 - _q.norm()) < Constants::EPS && "Quaternion not normalized.");
using namespace Eigen; using namespace Eigen;
if (delta_reference_ == DQ_GLOBAL) // See comments in method plus()
double angle = _delta_theta.norm();
if (angle > Constants::EPS)
{ {
_jacobian << -_q(0), -_q(1), -_q(2), // compute rotation axis -- this guarantees unity norm
_q(3), _q(2), -_q(1), Vector3s axis = _delta_theta / angle;
-_q(2), _q(3), _q(0),
_q(1), -_q(0), _q(3); // express delta_theta as a quaternion using the angle-axis helper
_jacobian /= 2; Quaternions dq(AngleAxis<Scalar>(angle, axis));
// result as a quaternion
// the delta is in global reference: dq * q
_q_plus_delta_theta = (dq * Map<const Quaternions>(_q.data())).coeffs();
} }
else else // Consider null rotation
{ {
_jacobian << -_q(0), -_q(1), -_q(2), _q_plus_delta_theta = _q;
_q(3), -_q(2), _q(1),
_q(2), _q(3), -_q(0),
-_q(1), _q(0), _q(3);
_jacobian /= 2;
} }
return true; return true;
} }
template <>
bool LocalParametrizationQuaternion<wolf::DQ_LOCAL>::computeJacobian(const Eigen::Map<const Eigen::VectorXs>& _q,
Eigen::Map<Eigen::MatrixXs>& _jacobian) const
{
assert(_q.size() == global_size_ && "Wrong size of input quaternion.");
assert(_jacobian.rows() == global_size_ && _jacobian.cols() == local_size_ && "Wrong size of Jacobian matrix.");
using namespace Eigen;
_jacobian << -_q(0), -_q(1), -_q(2),
_q(3), -_q(2), _q(1),
_q(2), _q(3), -_q(0),
-_q(1), _q(0), _q(3);
_jacobian /= 2;
return true;
}
template <>
bool LocalParametrizationQuaternion<wolf::DQ_GLOBAL>::computeJacobian(const Eigen::Map<const Eigen::VectorXs>& _q,
Eigen::Map<Eigen::MatrixXs>& _jacobian) const
{
assert(_q.size() == global_size_ && "Wrong size of input quaternion.");
assert(_jacobian.rows() == global_size_ && _jacobian.cols() == local_size_ && "Wrong size of Jacobian matrix.");
using namespace Eigen;
_jacobian << -_q(0), -_q(1), -_q(2),
_q(3), _q(2), -_q(1),
-_q(2), _q(3), _q(0),
_q(1), -_q(0), _q(3);
_jacobian /= 2;
return true;
}
} // namespace wolf } // namespace wolf
...@@ -48,20 +48,38 @@ typedef enum { ...@@ -48,20 +48,38 @@ typedef enum {
* \f] * \f]
* *
*/ */
template <unsigned int DeltaReference/* = DQ_GLOBAL*/>
class LocalParametrizationQuaternion : public LocalParametrizationBase class LocalParametrizationQuaternion : public LocalParametrizationBase
{ {
private: protected:
QuaternionDeltaReference delta_reference_;
public:
LocalParametrizationQuaternion(QuaternionDeltaReference _delta_ref = DQ_GLOBAL);
virtual ~LocalParametrizationQuaternion();
virtual bool plus(const Eigen::Map<const Eigen::VectorXs>& _q, QuaternionDeltaReference delta_reference_;
const Eigen::Map<const Eigen::VectorXs>& _delta_theta,
Eigen::Map<Eigen::VectorXs>& _q_plus_delta_theta) const; public:
virtual bool computeJacobian(const Eigen::Map<const Eigen::VectorXs>& _q, Eigen::Map<Eigen::MatrixXs>& _jacobian) const;
LocalParametrizationQuaternion() :
LocalParametrizationBase(4, 3)
{
//
}
virtual ~LocalParametrizationQuaternion()
{
//
}
virtual bool plus(const Eigen::Map<const Eigen::VectorXs>& _q,
const Eigen::Map<const Eigen::VectorXs>& _delta_theta,
Eigen::Map<Eigen::VectorXs>& _q_plus_delta_theta) const;
virtual bool computeJacobian(const Eigen::Map<const Eigen::VectorXs>& _q,
Eigen::Map<Eigen::MatrixXs>& _jacobian) const;
}; };
// @TODO : considere typedef
// typedef LocalParametrizationQuaternion<DQ_GLOBAL> LocalParametrizationQuaternionG;
// typedef LocalParametrizationQuaternion<DQ_LOCAL> LocalParametrizationQuaternionL;
} // namespace wolf } // namespace wolf
#endif /* LOCAL_PARAMETRIZATION_QUATERNION_H_ */ #endif /* LOCAL_PARAMETRIZATION_QUATERNION_H_ */
...@@ -28,13 +28,13 @@ inline StateQuaternion::StateQuaternion(const Eigen::Quaternions _quaternion, bo ...@@ -28,13 +28,13 @@ inline StateQuaternion::StateQuaternion(const Eigen::Quaternions _quaternion, bo
} }
inline StateQuaternion::StateQuaternion(const Eigen::VectorXs _state, bool _fixed) : inline StateQuaternion::StateQuaternion(const Eigen::VectorXs _state, bool _fixed) :
StateBlock(_state, _fixed, new LocalParametrizationQuaternion) StateBlock(_state, _fixed, new LocalParametrizationQuaternion<DQ_GLOBAL>)
{ {
assert(_state.size() == 4 && "The quaternion state vector must be of size 4"); assert(_state.size() == 4 && "The quaternion state vector must be of size 4");
} }
inline StateQuaternion::StateQuaternion(bool _fixed) : inline StateQuaternion::StateQuaternion(bool _fixed) :
StateBlock(4, _fixed, new LocalParametrizationQuaternion) StateBlock(4, _fixed, new LocalParametrizationQuaternion<DQ_GLOBAL>)
{ {
state_ = Eigen::Quaternions::Identity().coeffs(); state_ = Eigen::Quaternions::Identity().coeffs();
// //
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment