Go to the documentation of this file.
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);
112 BOOST_REQUIRE_EQUAL(task_.
taskSOUT.accessCopy().size(),
113 expectedTaskOutput_.size());
114 Vector taskOutput(expectedTaskOutput_.size());
115 for (
int i = 0;
i < expectedTaskOutput_.size(); ++
i)
116 taskOutput[
i] = task_.
taskSOUT.accessCopy()[
i].getSingleBound();
126 template <
typename SignalType,
typename ValueType>
135 virtual void setInputs() = 0;
144 BOOST_CHECK_EQUAL(time_,
f.errorSOUT.getTime());
145 BOOST_CHECK_EQUAL(time_,
f.errordotSOUT.getTime());
146 BOOST_CHECK_EQUAL(time_, task_.
errorSOUT.getTime());
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_],
420 faMfb(feature_.
faMfb.accessCopy().matrix()),
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");
636 void feature_pose_relative_tpl(const std::
string &repr) {
637 BOOST_TEST_MESSAGE(
"relative " << repr);
641 testRelative.setRandomFrame();
645 BOOST_AUTO_TEST_SUITE(relative)
648 feature_pose_relative_tpl<R3xSO3Representation>(
"R3xSO3");
652 feature_pose_relative_tpl<SE3Representation>(
"SE3");
FeatureAbstract & featureAbstract()
Eigen::Map< Quaternion > SOT_CORE_EXPORT QuaternionMap
BOOST_AUTO_TEST_SUITE_END() MatrixHomogeneous randomM()
void init(bool compute_local_aabb=true)
pinocchio::JointIndex jb_
void feature_pose_absolute_tpl(const std::string &repr)
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)
virtual void checkFeedForward()
dynamicgraph::SignalTimeDependent< dynamicgraph::Vector, sigtime_t > errorTimeDerivativeSOUT
dynamicgraph::Vector expectedTaskOutput_
BOOST_AUTO_TEST_CASE(check_value)
TestFeatureGeneric(unsigned dim, const std::string &name)
virtual const T & accessCopy() const
dynamicgraph::SignalPtr< double, sigtime_t > controlGainSIN
void setWithDerivative(const bool &s)
ConfigVectorType lowerPositionLimit
dynamicgraph::SignalPtr< dynamicgraph::Matrix, sigtime_t > jacobianSIN
Input for the Jacobian.
void computeExpectedTaskOutput(const Vector &s, const Vector &sdes, const Vector &sDesDot, const LG_t &lg)
pinocchio::SpecialEuclideanOperationTpl< 3, double > SE3_t
PINOCCHIO_DEPRECATED void framesForwardKinematics(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data)
void randomConfiguration(const LieGroupGenericTpl< LieGroupCollection > &lg, const Eigen::MatrixBase< ConfigL_t > &q0, const Eigen::MatrixBase< ConfigR_t > &q1, const Eigen::MatrixBase< ConfigOut_t > &qout)
#define EIGEN_VECTOR_IS_APPROX(Va, Vb, precision)
virtual void setReference(FeatureAbstract *sdes)=0
dynamicgraph::SignalPtr< Matrix, sigtime_t > jaJja
Jacobian of the input Joint A, expressed in Joint A
SignalPtr< Flags, sigtime_t > selectionSIN
This vector specifies which dimension are used to perform the computation. For instance let us assume...
virtual void printInputs()
Class that defines a generic implementation of the abstract interface for features.
void setSignal(SignalType &sig, const ValueType &v)
SignalTimeDependent< MatrixHomogeneous, sigtime_t > faMfb
Pose of Frame B wrt to Frame A.
virtual void setReference(const T *t, typename Signal< T, Time >::Mutex *m=NULL)
void computeExpectedTaskOutput(const Vector &error, const Vector &errorDrift)
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)
boost::mpl::if_c< representation==SE3Representation, SE3_t, R3xSO3_t >::type type
void runTest(TestClass &runner, int N=2)
This class gives the abstract definition of a feature.
pinocchio::CartesianProductOperation< pinocchio::VectorSpaceOperationTpl< 3, double >, pinocchio::SpecialOrthogonalOperationTpl< 3, double > > R3xSO3_t
pinocchio::FrameIndex fb_
virtual const T & access(const Time &t)
void setGain(double gain)
SignalTimeDependent< dynamicgraph::Vector, sigtime_t > errordotSOUT
Derivative of the error with respect to time: .
Feature that controls the relative (or absolute) pose between two frames A (or world) and B.
FeatureAbstract & featureAbstract()
FrameIndex getFrameId(const std::string &name, const FrameType &type=(FrameType)(JOINT|FIXED_JOINT|BODY|OP_FRAME|SENSOR)) const
void integrate(const LieGroupGenericTpl< LieGroupCollection > &lg, const Eigen::MatrixBase< ConfigIn_t > &q, const Eigen::MatrixBase< Tangent_t > &v, const Eigen::MatrixBase< ConfigOut_t > &qout)
const DataTpl< Scalar, Options, JointCollectionTpl >::Matrix6x & computeJointJacobians(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data)
SignalTimeDependent< dynamicgraph::Vector, sigtime_t > errorSOUT
This signal returns the error between the desired value and the current value : .
dynamicgraph::SignalTimeDependent< dynamicgraph::Vector, sigtime_t > errorSOUT
virtual void checkJacobian()
Representation_t
Enum used to specify what difference operation is used in FeaturePose.
FrameIndex addFrame(const Frame &frame, const bool append_inertia=true)
dynamicgraph::SignalPtr< Vector, sigtime_t > faNufafbDes
dynamicgraph::SignalPtr< MatrixHomogeneous, sigtime_t > faMfbDes
The desired pose of Frame B wrt to Frame A.
FeaturePose< representation > feature_
virtual void checkValue()
dynamicgraph::SignalPtr< dynamicgraph::Vector, sigtime_t > errorSIN
Input for the error.
JointIndex getJointId(const std::string &name) const
FeatureTestBase(unsigned dim, const std::string &name)
dynamicgraph::SignalPtr< MatrixHomogeneous, sigtime_t > jaMfa
Input pose of Frame A wrt to Joint A.
void humanoid(ModelTpl< Scalar, Options, JointCollectionTpl > &model, bool usingFF=true)
FeatureGeneric featureDes_
dynamicgraph::SignalPtr< Matrix, sigtime_t > jbJjb
Jacobian of the input Joint B, expressed in Joint B
Eigen::Matrix< double, 7, 1 > Vector7
dg::sot::internal::LG_t< representation >::type LieGroup_t
dynamicgraph::SignalTimeDependent< VectorMultiBound, sigtime_t > taskSOUT
Class that defines the basic elements of a task.
dynamicgraph::SignalPtr< MatrixHomogeneous, sigtime_t > oMja
Input pose of Joint A wrt to world frame.
dynamicgraph::SignalPtr< MatrixHomogeneous, sigtime_t > oMjb
Input pose of Joint B wrt to world frame.
Vector7 toVector(const pinocchio::SE3 &M)
SignalTimeDependent< dynamicgraph::Vector, sigtime_t > errorSOUT
Publish the error between the desired and the current value of the feature.
Eigen::Transform< double, 3, Eigen::Affine > MatrixHomogeneous
SignalPtr< dynamicgraph::Vector, sigtime_t > errordotSIN
Derivative of the reference value.
Signal< dynamicgraph::Matrix, sigtime_t > sig("matrix")
dynamicgraph::SignalPtr< MatrixHomogeneous, sigtime_t > jbMfb
Input pose of Frame B wrt to Joint B.
void addFeature(FeatureAbstract &s)
TestFeaturePose(bool relative, const std::string &name)
ConfigVectorType upperPositionLimit
virtual void printOutputs()
sot-core
Author(s): Olivier Stasse, ostasse@laas.fr
autogenerated on Tue Oct 24 2023 02:26:32