From f3667f3ff0a6ac52be1ff6d8123b090c8a0dad22 Mon Sep 17 00:00:00 2001 From: Mansard <nmansard@laas.fr> Date: Mon, 1 Sep 2014 15:22:30 +0200 Subject: [PATCH] Minor correction to improve computation time in Sym3. (error in the commit: unittest symmetric working, but tspatial is broken. Fixed in the following commit.) --- src/spatial/inertia.hpp | 71 ++++--- src/spatial/symmetric3.hpp | 139 +++++++------- unittest/symmetric.cpp | 25 ++- unittest/tspatial.cpp | 375 +++++++++++++++++++------------------ 4 files changed, 305 insertions(+), 305 deletions(-) diff --git a/src/spatial/inertia.hpp b/src/spatial/inertia.hpp index da6ec2433..e5a420039 100644 --- a/src/spatial/inertia.hpp +++ b/src/spatial/inertia.hpp @@ -1,6 +1,7 @@ #ifndef __se3_inertia_hpp__ #define __se3_inertia_hpp__ +#include "pinocchio/spatial/symmetric3.hpp" #include "pinocchio/spatial/force.hpp" #include "pinocchio/spatial/motion.hpp" @@ -22,33 +23,30 @@ namespace se3 typedef SE3Tpl<Scalar,Options> SE3; typedef InertiaTpl<Scalar,Options> Inertia; enum { LINEAR = 0, ANGULAR = 3 }; - typedef Eigen::SelfAdjointView<Matrix3,Eigen::Upper> Symmetric3; + typedef Symmetric3Tpl<Scalar,Options> Symmetric3; public: // Constructors - InertiaTpl() : m(), c(), dense_I(), I(dense_I) {} + InertiaTpl() : m(), c(), I() {} InertiaTpl(Scalar m_, const Vector3 &c_, const Matrix3 &I_) : m(m_), c(c_), - dense_I(I_), - I(dense_I) {} + I(I_) {} InertiaTpl(Scalar _m, const Vector3 &_c, const Symmetric3 &_I) : m(_m), c(_c), - dense_I(), - I(dense_I) { I = _I; } + I(_I) { } InertiaTpl(const InertiaTpl & clone) // Clone constructor for std::vector : m(clone.m), c(clone.c), - dense_I(clone.dense_I), - I(dense_I) {} + I(clone.I) {} InertiaTpl& operator= (const InertiaTpl& clone) // Copy operator for std::vector { - m=clone.m; c=clone.c; dense_I=clone.dense_I; + m=clone.m; c=clone.c; I=clone.I; return *this; } @@ -68,15 +66,9 @@ namespace se3 static Inertia Random() { /* We have to shoot "I" definite positive and not only symmetric. */ - Matrix3 M3 = Matrix3::Random(); // TODO clean that mess - Matrix3 D = Vector3::Random().cwiseAbs().asDiagonal(); - Matrix3 M3D2 = M3+2*D; - Matrix3 posdiag - = M3D2.template selfadjointView<Eigen::Upper>(); return InertiaTpl(Eigen::internal::random<Scalar>(), Vector3::Random(), - //Matrix3::Random().template selfadjointView<Eigen::Upper>()); - posdiag); + Symmetric3::RandomPositive()); } // Getters @@ -84,32 +76,40 @@ namespace se3 const Vector3 & lever() const { return c; } const Symmetric3 & inertia() const { return I; } - Matrix6 toMatrix() const + Matrix6 matrix() const { Matrix6 M; M.template block<3,3>(LINEAR, LINEAR ) = m*Matrix3::Identity(); M.template block<3,3>(LINEAR, ANGULAR) = -m*skew(c); M.template block<3,3>(ANGULAR,LINEAR ) = m*skew(c); - M.template block<3,3>(ANGULAR,ANGULAR) = (Matrix3)I - m*skew(c)*skew(c); + M.template block<3,3>(ANGULAR,ANGULAR) = (Matrix3)(I - typename Symmetric3::SkewSquare(c)); return M; } - operator Matrix6 () const { return toMatrix(); } + operator Matrix6 () const { return matrix(); } // Arithmetic operators - Inertia operator+(const InertiaTpl &other) const + friend Inertia operator+(const InertiaTpl &Ya, const InertiaTpl &Yb) { - const double & mm = m+other.m; - const Matrix3 & X = skew((c-other.c).eval()); - Matrix3 mmmXX = (m*other.m/mm*X*X).eval(); // TODO clean this mess - return InertiaTpl(mm, (m*c+other.m*other.c)/mm, dense_I+other.dense_I-mmmXX); // TODO: += in Eigen::Symmetric? + /* Y_{a+b} = ( m_a+m_b, + * (m_a*c_a + m_b*c_b ) / (m_a + m_b), + * I_a + I_b - (m_a*m_b)/(m_a+m_b) * AB_x * AB_x ) + */ + + const double & mab = Ya.m+Yb.m; + const Vector3 & mmmAB = ( ((Ya.m*Yb.m)/mab)*(Ya.c-Yb.c) ).eval(); + return InertiaTpl( mab, + (Ya.m*Ya.c+Yb.m*Yb.c)/mab, + Ya.I+Yb.I - typename Symmetric3::SkewSquare(mmmAB)); } - Inertia& operator+=(const InertiaTpl &other) + + Inertia& operator+=(const InertiaTpl &Yb) { - const Matrix3 & X = skew((c-other.c).eval()); - Matrix3 mmXX = (m*other.m*X*X).eval(); // TODO: clean this mess - c *=m; c+=other.m*other.c; - m+=other.m; c/=m; - dense_I+=other.dense_I-mmXX/m; // TODO: += in Eigen::Symmetric? + const Inertia& Ya = *this; + const double & mab = Ya.m+Yb.m; + const Vector3 & mmmAB = ( ((Ya.m*Yb.m)/mab)*(Ya.c-Yb.c) ).eval(); + c *= m; c += Yb.m*Yb.c; c /= mab; + I += Yb.I; I -= typename Symmetric3::SkewSquare(mmmAB); + m += Yb.m; return *this; } @@ -128,22 +128,21 @@ namespace se3 * 13215467/eigen-best-way-to-evaluate-asa-transpose-and-store-the-result-in-a-symmetric .*/ return Inertia( m, M.translation()+M.rotation()*c, - //dense_I); - M.rotation()*I*M.rotation().transpose()); + I.rotate(M.rotation()) ); } /// bI = aXb.actInv(aI) Inertia se3ActionInverse(const SE3 & M) const { return Inertia( m, M.rotation().transpose()*(c-M.translation()), - M.rotation().transpose()*I*M.rotation()); + I.rotate(M.rotation().transpose()) ); } // Force vxiv( const Motion& v ) const { - Vector3 mcxw = m*c.cross(v.angular()); - Vector3 mv_mcxw = m*v.linear()-mcxw; + const Vector3 & mcxw = m*c.cross(v.angular()); + const Vector3 & mv_mcxw = m*v.linear()-mcxw; return Force( v.angular().cross(mv_mcxw), v.angular().cross(c.cross(mv_mcxw)+I*v.angular())-v.linear().cross(mcxw) ); } @@ -160,11 +159,9 @@ namespace se3 private: Scalar m; Vector3 c; - Matrix3 dense_I; Symmetric3 I; }; - typedef InertiaTpl<double,0> Inertia; } // namespace se3 diff --git a/src/spatial/symmetric3.hpp b/src/spatial/symmetric3.hpp index f6845d1ed..1dffb9cd1 100644 --- a/src/spatial/symmetric3.hpp +++ b/src/spatial/symmetric3.hpp @@ -48,13 +48,42 @@ namespace se3 static Symmetric3Tpl Zero() { return Symmetric3Tpl(Vector6::Zero() ); } static Symmetric3Tpl Random() { return Symmetric3Tpl(Vector6::Random().eval()); } static Symmetric3Tpl Identity() { return Symmetric3Tpl( 1, 0, 1, 0, 0, 1); } - static Symmetric3Tpl SkewSq( const Vector3 & v ) - { - const double & x = v[0], & y = v[1], & z = v[2]; - return Symmetric3Tpl( -y*y-z*z, - x*y , -x*x-z*z, - x*z , y*z , -x*x-y*y ); + + struct SkewSquare + { + const Vector3 & v; + SkewSquare( const Vector3 & v ) : v(v) {} + operator Symmetric3Tpl () const + { + const double & x = v[0], & y = v[1], & z = v[2]; + return Symmetric3Tpl( -y*y-z*z, + x*y , -x*x-z*z, + x*z , y*z , -x*x-y*y ); + } + }; // struct SkewSquare + Symmetric3Tpl operator- (const SkewSquare & v) const + { + const double & x = v.v[0], & y = v.v[1], & z = v.v[2]; + return Symmetric3Tpl( data[0]+y*y+z*z, + data[1]-x*y , data[2]+x*x+z*z, + data[3]-x*z , data[4]-y*z , data[5]+x*x+y*y ); + } + Symmetric3Tpl& operator-= (const SkewSquare & v) + { + const double & x = v.v[0], & y = v.v[1], & z = v.v[2]; + data[0]+=y*y+z*z; + data[1]-=x*y ; data[2]+=x*x+z*z; + data[3]-=x*z ; data[4]-=y*z ; data[5]+=x*x+y*y; + return *this; } + // static Symmetric3Tpl SkewSq( const Vector3 & v ) + // { + // const double & x = v[0], & y = v[1], & z = v[2]; + // return Symmetric3Tpl( -y*y-z*z, + // x*y , -x*x-z*z, + // x*z , y*z , -x*x-y*y ); + // } + /* Shoot a positive definite matrix. */ static Symmetric3Tpl RandomPositive() { @@ -82,7 +111,7 @@ namespace se3 Symmetric3Tpl operator+(const Symmetric3Tpl & s2) const { - return Symmetric3Tpl(data+s2.data); + return Symmetric3Tpl((data+s2.data).eval()); } Symmetric3Tpl & operator+=(const Symmetric3Tpl & s2) @@ -147,84 +176,42 @@ namespace se3 return L; } - - /* R*S*R' */ - Symmetric3Tpl rotate(const Matrix3 & R) const - { - assert( (R.cols()==3) && (R.rows()==3) ); - assert( (R.transpose()*R).isApprox(Matrix3::Identity()) ); - - Symmetric3Tpl Sres; - Matrix2 Y; - Matrix32 L; - - // 4 a - L = decomposeltI(); - - // Y = R' L ===> (12 m + 8 a) - Y = R.template block<2,3>(1,0) * L; - - // Sres= Y R ===> (16 m + 8a) - Sres.data(1) = Y(0,0)*R(0,0) + Y(0,1)*R(0,1); - Sres.data(2) = Y(0,0)*R(1,0) + Y(0,1)*R(1,1); - Sres.data(3) = Y(1,0)*R(0,0) + Y(1,1)*R(0,1); - Sres.data(4) = Y(1,0)*R(1,0) + Y(1,1)*R(1,1); - Sres.data(5) = Y(1,0)*R(2,0) + Y(1,1)*R(2,1); - - // r=R' v ( 6m + 3a) - const Vector3 r( -R(0,0)*data(4) + R(0,1)*data(3), - -R(1,0)*data(4) + R(1,1)*data(3), - -R(2,0)*data(4) + R(2,1)*data(3) ); - - // Sres_11 (3a) - Sres.data(0) = L(0,0) + L(1,1) - Sres.data(2) - Sres.data(5); - - // Sres + D + (Ev)x ( 9a) - Sres.data(0) += data(5); - Sres.data(1) += r(2); Sres.data(2)+= data(5); - Sres.data(3) +=-r(1); Sres.data(4)+= r(0); Sres.data(5) += data(5); - - return Sres; - } - /* R*S*R' */ template<typename D> - Symmetric3Tpl rotateTpl(const Eigen::MatrixBase<D> & R) const + Symmetric3Tpl rotate(const Eigen::MatrixBase<D> & R) const { assert( (R.cols()==3) && (R.rows()==3) ); assert( (R.transpose()*R).isApprox(Matrix3::Identity()) ); - Symmetric3Tpl Sres; - Matrix2 Y; - Matrix32 L; - - // 4 a - L = decomposeltI(); + Symmetric3Tpl Sres; + + // 4 a + const Matrix32 & L = decomposeltI(); + + // Y = R' L ===> (12 m + 8 a) + const Matrix2 & Y = R.template block<2,3>(1,0) * L; - // Y = R' L ===> (12 m + 8 a) - Y = R.template block<2,3>(1,0) * L; - - // Sres= Y R ===> (16 m + 8a) - Sres.data(1) = Y(0,0)*R(0,0) + Y(0,1)*R(0,1); - Sres.data(2) = Y(0,0)*R(1,0) + Y(0,1)*R(1,1); - Sres.data(3) = Y(1,0)*R(0,0) + Y(1,1)*R(0,1); - Sres.data(4) = Y(1,0)*R(1,0) + Y(1,1)*R(1,1); - Sres.data(5) = Y(1,0)*R(2,0) + Y(1,1)*R(2,1); - - // r=R' v ( 6m + 3a) - const Vector3 r( -R(0,0)*data(4) + R(0,1)*data(3), - -R(1,0)*data(4) + R(1,1)*data(3), - -R(2,0)*data(4) + R(2,1)*data(3) ); - - // Sres_11 (3a) - Sres.data(0) = L(0,0) + L(1,1) - Sres.data(2) - Sres.data(5); + // Sres= Y R ===> (16 m + 8a) + Sres.data(1) = Y(0,0)*R(0,0) + Y(0,1)*R(0,1); + Sres.data(2) = Y(0,0)*R(1,0) + Y(0,1)*R(1,1); + Sres.data(3) = Y(1,0)*R(0,0) + Y(1,1)*R(0,1); + Sres.data(4) = Y(1,0)*R(1,0) + Y(1,1)*R(1,1); + Sres.data(5) = Y(1,0)*R(2,0) + Y(1,1)*R(2,1); + + // r=R' v ( 6m + 3a) + const Vector3 r( -R(0,0)*data(4) + R(0,1)*data(3), + -R(1,0)*data(4) + R(1,1)*data(3), + -R(2,0)*data(4) + R(2,1)*data(3) ); + + // Sres_11 (3a) + Sres.data(0) = L(0,0) + L(1,1) - Sres.data(2) - Sres.data(5); - // Sres + D + (Ev)x ( 9a) - Sres.data(0) += data(5); - Sres.data(1) += r(2); Sres.data(2)+= data(5); - Sres.data(3) +=-r(1); Sres.data(4)+= r(0); Sres.data(5) += data(5); + // Sres + D + (Ev)x ( 9a) + Sres.data(0) += data(5); + Sres.data(1) += r(2); Sres.data(2)+= data(5); + Sres.data(3) +=-r(1); Sres.data(4)+= r(0); Sres.data(5) += data(5); - return Sres; + return Sres; } diff --git a/unittest/symmetric.cpp b/unittest/symmetric.cpp index 836d7e611..b5fcbafc3 100644 --- a/unittest/symmetric.cpp +++ b/unittest/symmetric.cpp @@ -2,7 +2,6 @@ #include "pinocchio/spatial/fwd.hpp" #include "pinocchio/spatial/se3.hpp" -#include "pinocchio/spatial/inertia.hpp" #include "pinocchio/tools/timer.hpp" #include <boost/random.hpp> @@ -82,7 +81,7 @@ void testSym3() // Skew2 { Vector3 v = Vector3::Random(); - Symmetric3 vxvx = Symmetric3::SkewSq(v); + Symmetric3 vxvx = Symmetric3::SkewSquare(v); Vector3 p = Vector3::UnitX(); assert( (vxvx*p).isApprox( v.cross(v.cross(p)) )); @@ -90,6 +89,17 @@ void testSym3() assert( (vxvx*p).isApprox( v.cross(v.cross(p)) )); p = Vector3::UnitZ(); assert( (vxvx*p).isApprox( v.cross(v.cross(p)) )); + + Matrix3 vx = skew(v); + Matrix3 vxvx2 = (vx*vx).eval(); + assert( vxvx.matrix().isApprox(vxvx2) ); + + Symmetric3 S = Symmetric3::RandomPositive(); + assert( (S-Symmetric3::SkewSquare(v)).matrix() + .isApprox( S.matrix()-vxvx2 ) ); + Symmetric3 S2 = S; + S -= Symmetric3::SkewSquare(v); + assert(S.matrix().isApprox( S2.matrix()-vxvx2 ) ); } // (i,j) @@ -112,7 +122,6 @@ void testSym3() Symmetric3 RtSR = S.rotate(R.transpose()); assert( RtSR.matrix().isApprox( R.transpose()*S.matrix()*R )); - } // Time test @@ -182,7 +191,7 @@ void timeSelfAdj( const Eigen::Matrix3d & A, const Eigen::Matrix3d & Sdense, Eigen::Matrix3d & ASA ) { - typedef se3::Inertia::Symmetric3 Sym3; + typedef Eigen::SelfAdjointView<Eigen::Matrix3d,Eigen::Upper> Sym3; Sym3 S(Sdense); ASA.triangularView<Eigen::Upper>() = A * S * A.transpose(); @@ -191,17 +200,17 @@ void timeSelfAdj( const Eigen::Matrix3d & A, void testSelfAdj() { using namespace se3; - typedef Inertia::Matrix3 Matrix3; - typedef Inertia::Symmetric3 Sym3; + typedef Eigen::Matrix3d Matrix3; + typedef Eigen::SelfAdjointView<Matrix3,Eigen::Upper> Sym3; - Matrix3 M = Inertia::Matrix3::Random(); + Matrix3 M = Matrix3::Random(); Sym3 S(M); { Matrix3 Scp = S; assert( Scp-Scp.transpose()==Matrix3::Zero()); } - Matrix3 M2 = Inertia::Matrix3::Random(); + Matrix3 M2 = Matrix3::Random(); M.triangularView<Eigen::Upper>() = M2; Matrix3 A = Matrix3::Random(), ASA1, ASA2; diff --git a/unittest/tspatial.cpp b/unittest/tspatial.cpp index 554b7e3c8..1effe7e71 100644 --- a/unittest/tspatial.cpp +++ b/unittest/tspatial.cpp @@ -5,180 +5,180 @@ #include "pinocchio/spatial/se3.hpp" #include "pinocchio/spatial/inertia.hpp" -bool testSE3() -{ - using namespace se3; - typedef Eigen::Matrix<double,4,4> Matrix4; - typedef SE3::Matrix6 Matrix6; - typedef SE3::Vector3 Vector3; - - SE3 amb = SE3::Random(); - SE3 bmc = SE3::Random(); - SE3 amc = amb*bmc; - - Matrix4 aMb = amb; - Matrix4 bMc = bmc; - - // Test internal product - Matrix4 aMc = amc; - assert(aMc.isApprox(aMb*bMc)); - - Matrix4 bMa = amb.inverse(); - assert(bMa.isApprox(aMb.inverse())); - - { // Test point action - Vector3 p = Vector3::Random(); - Eigen::Matrix<double,4,1> p4; p4.head(3) = p; p4[3] = 1; - - Vector3 Mp = (aMb*p4).head(3); - assert(amb.act(p).isApprox(Mp)); - Vector3 Mip = (aMb.inverse()*p4).head(3); - assert(amb.actInv(p).isApprox(Mip)); - } - - { // Test action matrix - Matrix6 aXb = amb; - Matrix6 bXc = bmc; - Matrix6 aXc = amc; - assert(aXc.isApprox(aXb*bXc)); - - Matrix6 bXa = amb.inverse(); - assert(bXa.isApprox(aXb.inverse())); - } - - - return true; -} - -bool testMotion() -{ - using namespace se3; - typedef Eigen::Matrix<double,4,4> Matrix4; - typedef SE3::Matrix6 Matrix6; - typedef SE3::Vector3 Vector3; - typedef Motion::Vector6 Vector6; - - SE3 amb = SE3::Random(); - SE3 bmc = SE3::Random(); - SE3 amc = amb*bmc; - - Motion bv = Motion::Random(); - Motion bv2 = Motion::Random(); - - Vector6 bv_vec = bv; - Vector6 bv2_vec = bv2; +// bool testSE3() +// { +// using namespace se3; +// typedef Eigen::Matrix<double,4,4> Matrix4; +// typedef SE3::Matrix6 Matrix6; +// typedef SE3::Vector3 Vector3; + +// SE3 amb = SE3::Random(); +// SE3 bmc = SE3::Random(); +// SE3 amc = amb*bmc; + +// Matrix4 aMb = amb; +// Matrix4 bMc = bmc; + +// // Test internal product +// Matrix4 aMc = amc; +// assert(aMc.isApprox(aMb*bMc)); + +// Matrix4 bMa = amb.inverse(); +// assert(bMa.isApprox(aMb.inverse())); + +// { // Test point action +// Vector3 p = Vector3::Random(); +// Eigen::Matrix<double,4,1> p4; p4.head(3) = p; p4[3] = 1; + +// Vector3 Mp = (aMb*p4).head(3); +// assert(amb.act(p).isApprox(Mp)); +// Vector3 Mip = (aMb.inverse()*p4).head(3); +// assert(amb.actInv(p).isApprox(Mip)); +// } + +// { // Test action matrix +// Matrix6 aXb = amb; +// Matrix6 bXc = bmc; +// Matrix6 aXc = amc; +// assert(aXc.isApprox(aXb*bXc)); + +// Matrix6 bXa = amb.inverse(); +// assert(bXa.isApprox(aXb.inverse())); +// } + + +// return true; +// } + +// bool testMotion() +// { +// using namespace se3; +// typedef Eigen::Matrix<double,4,4> Matrix4; +// typedef SE3::Matrix6 Matrix6; +// typedef SE3::Vector3 Vector3; +// typedef Motion::Vector6 Vector6; + +// SE3 amb = SE3::Random(); +// SE3 bmc = SE3::Random(); +// SE3 amc = amb*bmc; + +// Motion bv = Motion::Random(); +// Motion bv2 = Motion::Random(); + +// Vector6 bv_vec = bv; +// Vector6 bv2_vec = bv2; - // Test .+. - Vector6 bvPbv2_vec = bv+bv2; - assert( bvPbv2_vec.isApprox(bv_vec+bv2_vec) ); - // Test -. - Vector6 Mbv_vec = -bv; - assert( Mbv_vec.isApprox(-bv_vec) ); - // Test .+=. - Motion bv3 = bv; bv3 += bv2; - assert(bv3.toVector().isApprox(bv_vec+bv2_vec)); - // Test .=V6 - bv3 = bv2_vec; - assert(bv3.toVector().isApprox(bv2_vec)); - // Test constructor from V6 - Motion bv4(bv2_vec); - assert(bv4.toVector().isApprox(bv2_vec)); - - // Test action - Matrix6 aXb = amb; - assert( amb.act(bv).toVector().isApprox(aXb*bv_vec)); - // Test action inverse - Matrix6 bXc = bmc; - assert( bmc.actInv(bv).toVector().isApprox(bXc.inverse()*bv_vec)); - - // Test double action - Motion cv = Motion::Random(); - bv = bmc.act(cv); - assert( amb.act(bv).toVector().isApprox(amc.act(cv).toVector()) ); - - // Simple test for cross product vxv - Motion vxv = bv.cross(bv); - assert(vxv.toVector().tail(3).isMuchSmallerThan(1e-3)); - - // Simple test for cross product vxf - Force f = bv.toVector(); - Force vxf = bv.cross(f); - assert( vxf.linear().isApprox( bv.angular().cross(f.linear()))); - assert( vxf.angular().isMuchSmallerThan(1e-3)); - - // Test frame change for vxf - Motion av = Motion::Random(); - Force af = Force::Random(); - bv = amb.actInv(av); - Force bf = amb.actInv(af); - Force avxf = av.cross(af); - Force bvxf = bv.cross(bf); - assert( avxf.toVector().isApprox( amb.act(bvxf).toVector()) ); - - // Test frame change for vxv - av = Motion::Random(); - Motion aw = Motion::Random(); - bv = amb.actInv(av); - Motion bw = amb.actInv(aw); - Motion avxw = av.cross(aw); - Motion bvxw = bv.cross(bw); - assert( avxw.toVector().isApprox( amb.act(bvxw).toVector()) ); - - return true; -} - - -bool testForce() -{ - using namespace se3; - typedef Eigen::Matrix<double,4,4> Matrix4; - typedef SE3::Matrix6 Matrix6; - typedef SE3::Vector3 Vector3; - typedef Force::Vector6 Vector6; - - SE3 amb = SE3::Random(); - SE3 bmc = SE3::Random(); - SE3 amc = amb*bmc; - - Force bf = Force::Random(); - Force bf2 = Force::Random(); - - Vector6 bf_vec = bf; - Vector6 bf2_vec = bf2; +// // Test .+. +// Vector6 bvPbv2_vec = bv+bv2; +// assert( bvPbv2_vec.isApprox(bv_vec+bv2_vec) ); +// // Test -. +// Vector6 Mbv_vec = -bv; +// assert( Mbv_vec.isApprox(-bv_vec) ); +// // Test .+=. +// Motion bv3 = bv; bv3 += bv2; +// assert(bv3.toVector().isApprox(bv_vec+bv2_vec)); +// // Test .=V6 +// bv3 = bv2_vec; +// assert(bv3.toVector().isApprox(bv2_vec)); +// // Test constructor from V6 +// Motion bv4(bv2_vec); +// assert(bv4.toVector().isApprox(bv2_vec)); + +// // Test action +// Matrix6 aXb = amb; +// assert( amb.act(bv).toVector().isApprox(aXb*bv_vec)); +// // Test action inverse +// Matrix6 bXc = bmc; +// assert( bmc.actInv(bv).toVector().isApprox(bXc.inverse()*bv_vec)); + +// // Test double action +// Motion cv = Motion::Random(); +// bv = bmc.act(cv); +// assert( amb.act(bv).toVector().isApprox(amc.act(cv).toVector()) ); + +// // Simple test for cross product vxv +// Motion vxv = bv.cross(bv); +// assert(vxv.toVector().tail(3).isMuchSmallerThan(1e-3)); + +// // Simple test for cross product vxf +// Force f = bv.toVector(); +// Force vxf = bv.cross(f); +// assert( vxf.linear().isApprox( bv.angular().cross(f.linear()))); +// assert( vxf.angular().isMuchSmallerThan(1e-3)); + +// // Test frame change for vxf +// Motion av = Motion::Random(); +// Force af = Force::Random(); +// bv = amb.actInv(av); +// Force bf = amb.actInv(af); +// Force avxf = av.cross(af); +// Force bvxf = bv.cross(bf); +// assert( avxf.toVector().isApprox( amb.act(bvxf).toVector()) ); + +// // Test frame change for vxv +// av = Motion::Random(); +// Motion aw = Motion::Random(); +// bv = amb.actInv(av); +// Motion bw = amb.actInv(aw); +// Motion avxw = av.cross(aw); +// Motion bvxw = bv.cross(bw); +// assert( avxw.toVector().isApprox( amb.act(bvxw).toVector()) ); + +// return true; +// } + + +// bool testForce() +// { +// using namespace se3; +// typedef Eigen::Matrix<double,4,4> Matrix4; +// typedef SE3::Matrix6 Matrix6; +// typedef SE3::Vector3 Vector3; +// typedef Force::Vector6 Vector6; + +// SE3 amb = SE3::Random(); +// SE3 bmc = SE3::Random(); +// SE3 amc = amb*bmc; + +// Force bf = Force::Random(); +// Force bf2 = Force::Random(); + +// Vector6 bf_vec = bf; +// Vector6 bf2_vec = bf2; - // Test .+. - Vector6 bfPbf2_vec = bf+bf2; - assert( bfPbf2_vec.isApprox(bf_vec+bf2_vec) ); - // Test -. - Vector6 Mbf_vec = -bf; - assert( Mbf_vec.isApprox(-bf_vec) ); - // Test .+=. - Force bf3 = bf; bf3 += bf2; - assert(bf3.toVector().isApprox(bf_vec+bf2_vec)); - // Test .= V6 - bf3 = bf2_vec; - assert(bf3.toVector().isApprox(bf2_vec)); - // Test constructor from V6 - Force bf4(bf2_vec); - assert(bf4.toVector().isApprox(bf2_vec)); - - // Test action - Matrix6 aXb = amb; - assert( amb.act(bf).toVector().isApprox(aXb.inverse().transpose()*bf_vec)); - // Test action inverse - Matrix6 bXc = bmc; - assert( bmc.actInv(bf).toVector().isApprox(bXc.transpose()*bf_vec)); - // Test double action - Force cf = Force::Random(); - bf = bmc.act(cf); - assert( amb.act(bf).toVector().isApprox(amc.act(cf).toVector()) ); - - // Simple test for cross product - // Force vxv = bf.cross(bf); - // assert(vxv.toVector().isMuchSmallerThan(bf.toVector())); - - return true; -} +// // Test .+. +// Vector6 bfPbf2_vec = bf+bf2; +// assert( bfPbf2_vec.isApprox(bf_vec+bf2_vec) ); +// // Test -. +// Vector6 Mbf_vec = -bf; +// assert( Mbf_vec.isApprox(-bf_vec) ); +// // Test .+=. +// Force bf3 = bf; bf3 += bf2; +// assert(bf3.toVector().isApprox(bf_vec+bf2_vec)); +// // Test .= V6 +// bf3 = bf2_vec; +// assert(bf3.toVector().isApprox(bf2_vec)); +// // Test constructor from V6 +// Force bf4(bf2_vec); +// assert(bf4.toVector().isApprox(bf2_vec)); + +// // Test action +// Matrix6 aXb = amb; +// assert( amb.act(bf).toVector().isApprox(aXb.inverse().transpose()*bf_vec)); +// // Test action inverse +// Matrix6 bXc = bmc; +// assert( bmc.actInv(bf).toVector().isApprox(bXc.transpose()*bf_vec)); +// // Test double action +// Force cf = Force::Random(); +// bf = bmc.act(cf); +// assert( amb.act(bf).toVector().isApprox(amc.act(cf).toVector()) ); + +// // Simple test for cross product +// // Force vxv = bf.cross(bf); +// // assert(vxv.toVector().isMuchSmallerThan(bf.toVector())); + +// return true; +// } bool testInertia() { @@ -197,7 +197,7 @@ bool testInertia() assert( (matI.topRightCorner<3,3>()*aI.lever()).isMuchSmallerThan(aI.lever()) ); Inertia I1 = Inertia::Identity(); - assert( I1.toMatrix() == Matrix6::Identity() ); + assert( I1.matrix() == Matrix6::Identity() ); // Test motion-to-force map Motion v = Motion::Random(); @@ -208,11 +208,20 @@ bool testInertia() SE3 bma = SE3::Random(); Inertia bI = bma.act(aI); Matrix6 bXa = bma; - assert( (bma.rotation()*aI.inertia()*bma.rotation().transpose()).isApprox((Matrix3)bI.inertia()) ); - assert( (bXa.transpose().inverse() * aI.toMatrix() * bXa.inverse()).isApprox( bI.toMatrix()) ); + assert( (bma.rotation()*aI.inertia().matrix()*bma.rotation().transpose()) + .isApprox((Matrix3)bI.inertia()) ); + std::cout << "bXa = [" << bma.toActionMatrix() << std::endl; + std::cout << "bY = [" << bI.matrix() << std::endl; + std::cout << "aY = [" << aI.matrix() << std::endl; + std::cout << "ac = [" << aI.lever() << std::endl; + std::cout << "bc = [" << bI.lever() << std::endl; + std::cout << "am = [" << aI.mass() << std::endl; + std::cout << "bm = [" << bI.mass() << std::endl; + + assert( (bXa.transpose().inverse() * aI.matrix() * bXa.inverse()).isApprox( bI.matrix()) ); // Test inverse action - assert( (bXa.transpose() * bI.toMatrix() * bXa).isApprox( bma.actInv(bI).toMatrix()) ); + assert( (bXa.transpose() * bI.matrix() * bXa).isApprox( bma.actInv(bI).matrix()) ); // Test vxIv cross product v = Motion::Random(); @@ -224,22 +233,20 @@ bool testInertia() // Test operator+ I1 = Inertia::Random(); Inertia I2 = Inertia::Random(); - assert( (I1.toMatrix()+I2.toMatrix()).isApprox((I1+I2).toMatrix()) ); - + assert( (I1.matrix()+I2.matrix()).isApprox((I1+I2).matrix()) ); + // operator += Inertia I12 = I1; I12 += I2; - assert( (I1.toMatrix()+I2.toMatrix()).isApprox(I12.toMatrix()) ); - - + assert( (I1.matrix()-I2.matrix()).isApprox(I12.matrix()) ); return true; } int main() { - testSE3(); - testMotion(); - testForce(); + // testSE3(); + // testMotion(); + // testForce(); testInertia(); return 1; } -- GitLab