14 #include <pinocchio/algorithm/frames.hpp>    15 #include <pinocchio/algorithm/jacobian.hpp>    16 #include <pinocchio/algorithm/joint-configuration.hpp>    17 #include <pinocchio/algorithm/kinematics.hpp>    18 #include <pinocchio/multibody/data.hpp>    19 #include <pinocchio/multibody/liegroup/liegroup.hpp>    20 #include <pinocchio/multibody/model.hpp>    21 #include <pinocchio/parsers/sample-models.hpp>    23 #define BOOST_TEST_MODULE features    24 #include <dynamic-graph/factory.h>    28 #include <boost/test/unit_test.hpp>    48 template <Representation_t representation>
    61 #define EIGEN_VECTOR_IS_APPROX(Va, Vb, precision)         \    62   BOOST_CHECK_MESSAGE((Va).isApprox(Vb, precision),       \    63                       "check " #Va ".isApprox(" #Vb       \    66                           << (Va).transpose() << "\n!=\n" \    67                           << (Vb).transpose() << "\n]")    68 #define EIGEN_MATRIX_IS_APPROX(Va, Vb, precision)                           \    69   BOOST_CHECK_MESSAGE((Va).isApprox(Vb, precision), "check " #Va            \    83       : task_(
"task" + name), time_(0) {
    84     expectedTaskOutput_.resize(dim);
    93                                  const Vector &errorDrift) {
    95     expectedTaskOutput_ = -gain * error - errorDrift;
    98   template <
typename LG_t>
   100                                  const Vector &sDesDot, 
const LG_t &lg) {
   102     lg.difference(sdes, s, s_sd);
   104     Eigen::Matrix<typename LG_t::Scalar, LG_t::NV, LG_t::NV> Jminus(lg.nv(),
   106     lg.template dDifference<pinocchio::ARG0>(sdes, s, Jminus);
   108     computeExpectedTaskOutput(s_sd, Jminus * sDesDot);
   113                         expectedTaskOutput_.size());
   114     Vector taskOutput(expectedTaskOutput_.size());
   115     for (
int i = 0; 
i < expectedTaskOutput_.size(); ++
i)
   126   template <
typename SignalType, 
typename ValueType>
   135   virtual void setInputs() = 0;
   171         feature_(
"feature" + name),
   172         featureDes_(
"featureDes" + name),
   192         BOOST_TEST_MESSAGE(
" ----- Test Velocity -----");
   199         BOOST_TEST_MESSAGE(
" ----- Test Position -----");
   206         BOOST_TEST_MESSAGE(
" ----- Test both -----");
   235     BOOST_TEST_MESSAGE(
"----- inputs -----");
   237         "feature_.errorSIN: " << feature_.
errorSIN(time_).transpose());
   239         "featureDes_.errorSIN: " << featureDes_.
errorSIN(time_).transpose());
   240     BOOST_TEST_MESSAGE(
"featureDes_.errordotSIN: "   242     BOOST_TEST_MESSAGE(
"task.controlGain: " << task_.controlGainSIN(time_));
   252     computeExpectedTaskOutput(s - sd, -vd);
   258     BOOST_TEST_MESSAGE(
"----- output -----");
   259     BOOST_TEST_MESSAGE(
"time: " << time_);
   261         "feature.errorSOUT: " << feature_.
errorSOUT(time_).transpose());
   263         "feature.errordotSOUT: " << feature_.
errordotSOUT(time_).transpose());
   264     BOOST_TEST_MESSAGE(
"task.taskSOUT: " << task_.taskSOUT(time_));
   269         "Expected task output: " << expectedTaskOutput_.transpose());
   273 BOOST_AUTO_TEST_SUITE(feature_generic)
   276   std::string srobot(
"test");
   277   unsigned int dim = 6;
   281   for (
int i = 0; 
i < 10; ++
i) testFeatureGeneric.
checkValue();
   288   M.translation().setRandom();
   289   Eigen::Vector3d 
w(Eigen::Vector3d::Random());
   290   M.linear() = Eigen::AngleAxisd(w.norm(), w.normalized()).matrix();
   298   v.head<3>() = M.translation();
   305   for (
int i = 0; 
i < (int)in.size(); ++
i) out[
i] = in[
i].getSingleBound();
   309 template <Representation_t representation>
   312   typedef typename dg::sot::internal::LG_t<representation>::type 
LieGroup_t;
   322         feature_(
"feature" + name),
   361     model_.
frames[fa_].placement.setIdentity();
   362     model_.
frames[fb_].placement.setIdentity();
   367     model_.
frames[fa_].placement.setRandom();
   368     model_.
frames[fb_].placement.setRandom();
   380     setSignal(feature_.
oMjb,
   383       setSignal(feature_.
oMja,
   391     setSignal(feature_.
jbJjb, J);
   395       setSignal(feature_.
jaJja, J);
   399     setSignal(feature_.
faMfbDes, randomM());
   400     setSignal(feature_.
faNufafbDes, Vector::Random(6));
   405     if (time_ % 2 != 0) gain = 1;
   410     BOOST_TEST_MESSAGE(
"----- inputs -----");
   413     BOOST_TEST_MESSAGE(
"task.controlGain: " << task_.controlGainSIN(time_));
   419     const SE3 oMfb = data_.oMf[fb_], oMfa = data_.oMf[fa_],
   424     computeExpectedTaskOutput(
   426         (boost::is_same<LieGroup_t, SE3_t>::value
   427              ? faMfbDes.toActionMatrixInverse() * nu
   428              : (Vector6d() << nu.head<3>() -
   429                                   faMfb.translation().cross(nu.tail<3>()),
   430                 faMfbDes.rotation().transpose() * nu.tail<3>())
   438     BOOST_TEST_MESSAGE(
"----- output -----");
   439     BOOST_TEST_MESSAGE(
"time: " << time_);
   441         "feature.errorSOUT: " << feature_.
errorSOUT(time_).transpose());
   443         "feature.errordotSOUT: " << feature_.
errordotSOUT(time_).transpose());
   444     BOOST_TEST_MESSAGE(
"task.taskSOUT: " << task_.taskSOUT(time_));
   449         "Expected task output: " << expectedTaskOutput_.transpose());
   463     setSignal(feature_.
oMjb,
   466       setSignal(feature_.
oMja,
   474     setSignal(feature_.
jbJjb, J);
   478       setSignal(feature_.
jaJja, J);
   482     setSignal(feature_.
faMfbDes, randomM());
   485     Vector e_q = task_.errorSOUT.access(time_);
   486     J = task_.jacobianSOUT.access(time_);
   488     Eigen::IOFormat PyVectorFmt(Eigen::FullPrecision, 0, 
", ", 
", ", 
"", 
"",
   490     Eigen::IOFormat PyMatrixFmt(Eigen::FullPrecision, 0, 
", ", 
",\n", 
"[", 
"]",
   493     Vector qdot(Vector::Zero(model_.
nv));
   496         data_.oMi[ja_].toHomogeneousMatrix().format(PyMatrixFmt)
   497         << data_.oMi[jb_].toHomogeneousMatrix().format(PyMatrixFmt)
   498         << model_.
frames[fa_].placement.toHomogeneousMatrix().format(
   500         << model_.
frames[fb_].placement.toHomogeneousMatrix().format(
   502         << J.format(PyMatrixFmt));
   504     for (
int i = 0; 
i < model_.
nv; ++
i) {
   511       setSignal(feature_.
oMjb,
   514         setSignal(feature_.
oMja,
   519       Vector e_q_dq = task_.errorSOUT.access(time_);
   521           (((e_q_dq - e_q) / eps) - J.col(
i)).maxCoeff() < 1e-4,
   522           "Jacobian col " << 
i << 
" does not match finite difference.\n"   523                           << ((e_q_dq - e_q) / eps).format(PyVectorFmt) << 
'\n'   524                           << J.col(
i).format(PyVectorFmt) << 
'\n');
   545     SE3 faMfb = data_.oMf[fa_].actInv(data_.oMf[fb_]);
   548     setSignal(feature_.
oMjb,
   551       setSignal(feature_.
oMja,
   559     setSignal(feature_.
jbJjb, J);
   563       setSignal(feature_.
jaJja, J);
   569     faJfafb = faMfb.toActionMatrix() * J;
   575     setSignal(feature_.
faMfbDes, randomM());
   578     task_.jacobianSOUT.recompute(time_);
   579     J = task_.jacobianSOUT.accessCopy();
   580     Eigen::JacobiSVD<Matrix> svd(J, Eigen::ComputeThinU | Eigen::ComputeThinV);
   582     Vector faNufafbDes(Vector::Zero(6));
   584     for (
int i = 0; 
i < 6; ++
i) {
   588       task_.taskSOUT.recompute(time_);
   592       Vector faNufafb = faJfafb * qdot;
   601 template <
typename TestClass>
   605   for (
int i = 0; 
i < 
N; ++
i) runner.checkValue();
   606   for (
int i = 0; 
i < N; ++
i) runner.checkJacobian();
   607   for (
int i = 0; 
i < N; ++
i) runner.checkFeedForward();
   610 BOOST_AUTO_TEST_SUITE(feature_pose)
   612 template <Representation_t representation>
   614   BOOST_TEST_MESSAGE(
"absolute " << repr);
   626   feature_pose_absolute_tpl<R3xSO3Representation>(
"R3xSO3");
   630   feature_pose_absolute_tpl<SE3Representation>(
"SE3");
   635 template <Representation_t representation>
   636 void feature_pose_relative_tpl(
const std::string &repr) {
   637   BOOST_TEST_MESSAGE(
"relative " << repr);
   645 BOOST_AUTO_TEST_SUITE(relative)
   648   feature_pose_relative_tpl<R3xSO3Representation>(
"R3xSO3");
   652   feature_pose_relative_tpl<SE3Representation>(
"SE3");
 
dynamicgraph::SignalPtr< MatrixHomogeneous, int > jaMfa
Input pose of Frame A wrt to Joint A. 
TestFeaturePose(bool relative, const std::string &name)
void computeExpectedTaskOutput(const Vector &s, const Vector &sdes, const Vector &sDesDot, const LG_t &lg)
dg::sot::internal::LG_t< representation >::type LieGroup_t
FeatureAbstract & featureAbstract()
BOOST_AUTO_TEST_CASE(check_value)
TestFeatureGeneric(unsigned dim, const std::string &name)
SignalTimeDependent< dynamicgraph::Vector, int > errordotSOUT
Derivative of the error with respect to time: . 
virtual void checkJacobian()
SignalPtr< Flags, int > selectionSIN
This vector specifies which dimension are used to perform the computation. For instance let us assume...
Eigen::Matrix< double, 7, 1 > Vector7
Eigen::Transform< double, 3, Eigen::Affine > MatrixHomogeneous
void setGain(double gain)
dynamicgraph::SignalTimeDependent< VectorMultiBound, int > taskSOUT
dynamicgraph::SignalPtr< double, int > controlGainSIN
void addFeature(FeatureAbstract &s)
virtual void setReference(const T *t, typename Signal< T, Time >::Mutex *m=NULL)
ConfigVectorType lowerPositionLimit
void computeExpectedTaskOutput(const Vector &error, const Vector &errorDrift)
Signal< dynamicgraph::Matrix, int > sig("matrix")
pinocchio::SpecialEuclideanOperationTpl< 3, double > SE3_t
pinocchio::JointIndex jb_
void setWithDerivative(const bool &s)
dynamicgraph::SignalPtr< MatrixHomogeneous, int > oMja
Input pose of Joint A wrt to world frame. 
virtual void printInputs()
dynamicgraph::SignalPtr< dynamicgraph::Matrix, int > jacobianSIN
Input for the Jacobian. 
void getJointJacobian(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const DataTpl< Scalar, Options, JointCollectionTpl > &data, const typename ModelTpl< Scalar, Options, JointCollectionTpl >::JointIndex jointId, const ReferenceFrame rf, const Eigen::MatrixBase< Matrix6Like > &J)
void integrate(const LieGroupGenericTpl< LieGroupCollection > &lg, const Eigen::MatrixBase< ConfigIn_t > &q, const Eigen::MatrixBase< Tangent_t > &v, const Eigen::MatrixBase< ConfigOut_t > &qout)
SignalTimeDependent< MatrixHomogeneous, int > faMfb
Pose of Frame B wrt to Frame A. 
dynamicgraph::SignalTimeDependent< dynamicgraph::Vector, int > errorSOUT
void humanoid(ModelTpl< Scalar, Options, JointCollectionTpl > &model, bool usingFF=true)
dynamicgraph::SignalPtr< MatrixHomogeneous, int > jbMfb
Input pose of Frame B wrt to Joint B. 
virtual void printOutputs()
SignalPtr< dynamicgraph::Vector, int > errordotSIN
Derivative of the reference value. 
pinocchio::CartesianProductOperation< pinocchio::VectorSpaceOperationTpl< 3, double >, pinocchio::SpecialOrthogonalOperationTpl< 3, double > > R3xSO3_t
void feature_pose_absolute_tpl(const std::string &repr)
void setSignal(SignalType &sig, const ValueType &v)
void runTest(TestClass &runner, int N=2)
boost::mpl::if_c< representation==SE3Representation, SE3_t, R3xSO3_t >::type type
FeatureAbstract & featureAbstract()
virtual void checkFeedForward()
pinocchio::FrameIndex fb_
virtual const T & access(const Time &t)
FeatureGeneric featureDes_
void randomConfiguration(const LieGroupGenericTpl< LieGroupCollection > &lg, const Eigen::MatrixBase< ConfigL_t > &q0, const Eigen::MatrixBase< ConfigR_t > &q1, const Eigen::MatrixBase< ConfigOut_t > &qout)
FrameIndex getFrameId(const std::string &name, const FrameType &type=(FrameType)(JOINT|FIXED_JOINT|BODY|OP_FRAME|SENSOR)) const
virtual void setReference(FeatureAbstract *sdes)=0
virtual const T & accessCopy() const
dynamicgraph::SignalPtr< Matrix, int > jaJja
Jacobian of the input Joint A, expressed in Joint A 
void init(bool compute_local_aabb=true)
virtual void recompute(const Time &t)
FeatureTestBase(unsigned dim, const std::string &name)
FrameIndex addFrame(const Frame &frame, const bool append_inertia=true)
JointIndex getJointId(const std::string &name) const
This class gives the abstract definition of a feature. 
const DataTpl< Scalar, Options, JointCollectionTpl >::Matrix6x & computeJointJacobians(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q)
BOOST_AUTO_TEST_SUITE_END() MatrixHomogeneous randomM()
Feature that controls the relative (or absolute) pose between two frames A (or world) and B...
dynamicgraph::SignalTimeDependent< dynamicgraph::Vector, int > errorTimeDerivativeSOUT
dynamicgraph::SignalPtr< Matrix, int > jbJjb
Jacobian of the input Joint B, expressed in Joint B 
Vector7 toVector(const pinocchio::SE3 &M)
ConfigVectorType upperPositionLimit
virtual void checkValue()
dynamicgraph::SignalPtr< MatrixHomogeneous, int > faMfbDes
The desired pose of Frame B wrt to Frame A. 
Class that defines the basic elements of a task. 
virtual const T & accessCopy() const
dynamicgraph::SignalPtr< MatrixHomogeneous, int > oMjb
Input pose of Joint B wrt to world frame. 
void setReady(const bool sready=true)
dynamicgraph::SignalPtr< dynamicgraph::Vector, int > errorSIN
Input for the error. 
dynamicgraph::SignalPtr< Vector, int > faNufafbDes
SignalTimeDependent< dynamicgraph::Vector, int > errorSOUT
This signal returns the error between the desired value and the current value : . ...
virtual const Time & getTime() const
#define EIGEN_VECTOR_IS_APPROX(Va, Vb, precision)
void getFrameJacobian(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const FrameIndex frame_id, const ReferenceFrame rf, const Eigen::MatrixBase< Matrix6xLike > &J)
dynamicgraph::Vector expectedTaskOutput_
FeaturePose< representation > feature_
Eigen::Map< Quaternion > SOT_CORE_EXPORT QuaternionMap
void framesForwardKinematics(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q)
Class that defines a generic implementation of the abstract interface for features.