From b60978be864854ade73c5d550f2776b0faa0f85a Mon Sep 17 00:00:00 2001 From: Mansard <nmansard@laas.fr> Date: Fri, 5 Sep 2014 10:37:06 +0200 Subject: [PATCH] IVIGIT Cholesky. --- CMakeLists.txt | 5 + src/algorithm/chol.m | 55 ++++++ src/algorithm/cholesky.hpp | 232 ++++++++++++++++++++++++++ src/multibody/joint/joint-variant.hpp | 4 +- unittest/cholesky.cpp | 79 +++++++++ 5 files changed, 373 insertions(+), 2 deletions(-) create mode 100644 src/algorithm/chol.m create mode 100644 src/algorithm/cholesky.hpp create mode 100644 unittest/cholesky.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9caa4619d..1993ab0f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,7 @@ SET(${PROJECT_NAME}_HEADERS algorithm/rnea.hpp algorithm/crba.hpp algorithm/crba2.hpp + algorithm/cholesky.hpp algorithm/kinematics.hpp ) @@ -100,6 +101,10 @@ ADD_EXECUTABLE(crba EXCLUDE_FROM_ALL unittest/crba.cpp) PKG_CONFIG_USE_DEPENDENCY(crba eigenpy) PKG_CONFIG_USE_DEPENDENCY(crba urdfdom) +ADD_EXECUTABLE(cholesky EXCLUDE_FROM_ALL unittest/cholesky.cpp) +PKG_CONFIG_USE_DEPENDENCY(cholesky eigenpy) +PKG_CONFIG_USE_DEPENDENCY(cholesky urdfdom) + ADD_EXECUTABLE(dg EXCLUDE_FROM_ALL unittest/dg.cpp) PKG_CONFIG_USE_DEPENDENCY(dg eigenpy) diff --git a/src/algorithm/chol.m b/src/algorithm/chol.m new file mode 100644 index 000000000..2455d50e7 --- /dev/null +++ b/src/algorithm/chol.m @@ -0,0 +1,55 @@ +clear U L M parent tree + +parent = [ 0 1 2 3 2 5 2 7 8 9 8 11 ]; +n=12; +M = zeros(n); +for i=1:n + j=i; + while j>0 + M(i,j) = rand; + M(j,i) = M(i,j); + L(i,j) = 1; + U(j,i) = 1; + j=parent(j); + end +end + +tree = zeros(1,n); +for i=n:-1:2 + if(tree(i)==0) tree(i) = i; end + tree(parent(i)) = max(tree(parent(i)), tree(i) ); +end + +D = zeros(n,1); +U = eye(n); +for i=n:-1:1 + for j=n:-1:i+1 + subtree = j+1:tree(j); + U(i,j) = inv(D(j)) * (M(i,j) - U(i,subtree)*diag(D(subtree))*U(j,subtree)'); + end + subtree = i+1:tree(i); + D(i) = M(i,i) - U(i,subtree)*diag(D(subtree))*U(i,subtree)'; +end + +Msav = M; +D = zeros(n,1); +U = eye(n); +for k=n:-1:1 + i=parent(k); + while i>0 + a = M(i,k) / M(k,k); + M(i,i) = M(i,i) - a * M(i,k); + j = parent(i); + while j>0 + M(j,i) = M(j,i) - a * M(j,k); + j=parent(j); + end + M(i,k) = a; + i=parent(i); + end +end + +U = triu(M,1) + eye(n); +D = diag(M); +M = Msav; +norm(U*diag(D)*U' - M) \ No newline at end of file diff --git a/src/algorithm/cholesky.hpp b/src/algorithm/cholesky.hpp new file mode 100644 index 000000000..1b938db3e --- /dev/null +++ b/src/algorithm/cholesky.hpp @@ -0,0 +1,232 @@ +#ifndef __se3_cholesky_hpp__ +#define __se3_cholesky_hpp__ + +#include "pinocchio/multibody/visitor.hpp" +#include "pinocchio/multibody/model.hpp" +#include <iostream> + +namespace se3 +{ + inline const Eigen::MatrixXd& + cholesky(const Model & model, + Data& data ); + + + template<typename D> + void multSqrt( const Model & model, + Data& data , + const Eigen::MatrixBase<D> & v); + +} // namespace se3 + +/* --- Details -------------------------------------------------------------------- */ +namespace se3 +{ + template<typename JointModel,typename D> + void udut( Eigen::MatrixBase<D> & U, + const JointModel& ) + { + /* TODO */ + } + + + // struct CholeskyInnerStep : public fusion::JointVisitor<CholeskyInnerStep> + // { + // typedef boost::fusion::vector<const Model&, + // Data&, + // const int &, + // const int &> ArgsType; + + // JOINT_VISITOR_INIT(CholeskyOuterStep); + + // template<typename JointModel> + // static void algo(const JointModelBase<JointModel> & jmodel, + // JointDataBase<typename JointModel::JointData> & , + // const Model& model, + // Data& data, + // int j) + // { + + // } + // }; + + // struct CholeskyOuterStep : public fusion::JointVisitor<CholeskyOuterStep> + // { + // typedef boost::fusion::vector<const Model&, + // Data&, + // const int &> ArgsType; + + // JOINT_VISITOR_INIT(CholeskyOuterStep); + + // template<typename JointModel> + // static void algo(const JointModelBase<JointModel> & jmodel, + // JointDataBase<typename JointModel::JointData> & , + // const Model& model, + // Data& data, + // int j) + // { + // typename Model::Index parent = jmodel.parents[j]; + // while( parent>0 ) + // { + + // } + + // const int + // idx = jmodel.idx_v(), + // nv = JointModel::nv, + // idx_tree = idx+nv, + // nv_tree = data.nvSubtree[j]; + + // data.U.template block<nv,nv>(j,j) + // -= data.U.block(idx,idx_tree,nv,nv_tree) + // * data.D.segment(idx_tree,nv_tree).asDiagonal() + // * data.U.block(idx,idx_tree,nv,nv_tree).transpose(); + + // Eigen::Block<Eigen::MatrixXd,nv,nv> Ujj = data.U.template block<nv,nv>(j,j); + // udut(Ujj,jmodel); + // } + // }; + + + template<typename JointModel_k,typename JointModel_i> + struct CholeskyLoopJStep : public fusion::JointVisitor< CholeskyLoopJStep<JointModel_k,JointModel_i> > + { + typedef boost::fusion::vector<const JointModelBase<JointModel_k>&, + const JointModelBase<JointModel_i>&, + const Model&, + Data&, + const int &, + const int &, + const double &> ArgsType; + + CholeskyLoopJStep( JointDataVariant & jdata,ArgsType args ) : jdata(jdata),args(args) {} + using fusion::JointVisitor< CholeskyLoopJStep<JointModel_k,JointModel_i> >::run; + JointDataVariant & jdata; + ArgsType args; + + template<typename JointModel_j> + static void algo(const JointModelBase<JointModel_j> & jj_model, + JointDataBase<typename JointModel_j::JointData> &, + const JointModelBase<JointModel_k> & jk_model, + const JointModelBase<JointModel_i> & ji_model, + const Model& model, + Data& data, + const int & k, + const int & i, + const int & j) + { + } + }; + + + template<typename JointModel_k> + struct CholeskyLoopIStep : public fusion::JointVisitor< CholeskyLoopIStep<JointModel_k> > + { + typedef boost::fusion::vector<const JointModelBase<JointModel_k>&, + const Model&, + Data&, + const int &, + const int &> ArgsType; + + //JOINT_VISITOR_INIT(CholeskyLoopIStep); + CholeskyLoopIStep( JointDataVariant & jdata,ArgsType args ) : jdata(jdata),args(args) {} + using fusion::JointVisitor< CholeskyLoopIStep<JointModel_k> >::run; + JointDataVariant & jdata; + ArgsType args; + + + template<typename JointModel_i> + static void algo(const JointModelBase<JointModel_i> & ji_model, + JointDataBase<typename JointModel_i::JointData> &, + const JointModelBase<JointModel_k> & jk_model, + const Model& model, + Data& data, + const int & k, + const int & i) + { + + double a = data.M( jk_model.idx_v(),ji_model.idx_v() )/data.M(k,k); + typedef typename Model::Index Index; + for( Index j=i;j>0;j=model.parents[j]) + { + CholeskyLoopJStep<JointModel_k,JointModel_i> + ::run(model.joints[j],data.joints[j], + typename CholeskyLoopJStep<JointModel_k,JointModel_i> + ::ArgsType(jk_model,ji_model,model,data,k,i,a) ); + } + } + }; + + struct CholeskyLoopKStep : public fusion::JointVisitor<CholeskyLoopKStep> + { + typedef boost::fusion::vector<const Model&, + Data&, + const int &> ArgsType; + + JOINT_VISITOR_INIT(CholeskyLoopKStep); + + template<typename JointModel> + static void algo(const JointModelBase<JointModel> & jk_model, + JointDataBase<typename JointModel::JointData> & jk_data, + const Model& model, + Data& data, + const int & k ) + { + typedef typename Model::Index Index; + for( Index i=model.parents[k];i>0;i=model.parents[i]) + { + CholeskyLoopIStep<JointModel> + ::run(model.joints[i],data.joints[i], + typename CholeskyLoopIStep<JointModel> + ::ArgsType(jk_model,model,data,k,i) ); + } + } + }; + + /* + * U=zeros(n,n); D=zeros(n,1); + * for j=n:-1:1 + * for k=n:-1:j+1 + * subtree = k+1:n; + * U(j,k) = inv(D(k)) * (A(j,k) - U(k,subtree)*diag(D(subtree))*U(j,subtree)'); + * end + * subtree = j+1:n; + * D(j) = A(j,j) - U(j,subtree)*diag(D(subtree))*U(j,subtree)'; + * end + * U = U + diag(ones(n,1)); + */ + inline const Eigen::MatrixXd& + cholesky(const Model & model, + Data& data ) + { + data.U = data.M; + for( int j=model.nbody-1;j>=0;--j ) + { + CholeskyLoopKStep::run(model.joints[j],data.joints[j], + CholeskyLoopKStep::ArgsType(model,data,j)); + + } + + return data.U; + } + + template<typename D> + void multSqrt( const Model & model, + Data& data , + const Eigen::MatrixBase<D> & v) + { + /* for i = n:1 + * res[i] = L(i,i) x[i] + * while j>0 + * y[i] += L(i,j) x[j] + */ + + + + + } + + + +} // namespace se3 +#endif // ifndef __se3_cholesky_hpp__ diff --git a/src/multibody/joint/joint-variant.hpp b/src/multibody/joint/joint-variant.hpp index 311719750..17010c35f 100644 --- a/src/multibody/joint/joint-variant.hpp +++ b/src/multibody/joint/joint-variant.hpp @@ -6,8 +6,8 @@ namespace se3 { - typedef boost::variant< JointModelRX,JointModelRY,JointModelRZ,JointModelFreeFlyer> JointModelVariant; - typedef boost::variant< JointDataRX, JointDataRY, JointDataRZ, JointDataFreeFlyer > JointDataVariant; + typedef boost::variant< JointModelRX,JointModelRY,JointModelRZ /*,JointModelFreeFlyer*/> JointModelVariant; + typedef boost::variant< JointDataRX, JointDataRY, JointDataRZ /*, JointDataFreeFlyer*/ > JointDataVariant; typedef std::vector<JointModelVariant> JointModelVector; typedef std::vector<JointDataVariant> JointDataVector; diff --git a/unittest/cholesky.cpp b/unittest/cholesky.cpp new file mode 100644 index 000000000..1ced4990f --- /dev/null +++ b/unittest/cholesky.cpp @@ -0,0 +1,79 @@ +#include "pinocchio/spatial/fwd.hpp" +#include "pinocchio/spatial/se3.hpp" +#include "pinocchio/multibody/joint.hpp" +#include "pinocchio/multibody/visitor.hpp" +#include "pinocchio/multibody/model.hpp" +#include "pinocchio/algorithm/crba.hpp" +#include "pinocchio/algorithm/crba2.hpp" +#include "pinocchio/algorithm/cholesky.hpp" +//#include "pinocchio/multibody/parser/urdf.hpp" + +#include <iostream> + +#include "pinocchio/tools/timer.hpp" + + +//#define __SSE3__ +#include <fenv.h> +#ifdef __SSE3__ +#include <pmmintrin.h> +#endif + +int main(int argc, const char ** argv) +{ +#ifdef __SSE3__ + _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); +#endif + + + using namespace Eigen; + using namespace se3; + + SE3::Matrix3 I3 = SE3::Matrix3::Identity(); + + se3::Model model; + + // std::string filename = "/home/nmansard/src/metapod/data/simple_arm.urdf"; + // if(argc>1) filename = argv[1]; + // model = se3::buildModel(filename,false); + + + model.addBody(model.getBodyId("universe"),JointModelRX(),SE3::Random(),Inertia::Random(),"ff1"); + model.addBody(model.getBodyId("ff1"),JointModelRX(),SE3::Random(),Inertia::Random(),"root"); + + model.addBody(model.getBodyId("root"),JointModelRX(),SE3::Random(),Inertia::Random(),"lleg1"); + model.addBody(model.getBodyId("lleg1"),JointModelRX(),SE3::Random(),Inertia::Random(),"lleg2"); + + model.addBody(model.getBodyId("root"),JointModelRX(),SE3::Random(),Inertia::Random(),"rleg1"); + model.addBody(model.getBodyId("rleg1"),JointModelRX(),SE3::Random(),Inertia::Random(),"rleg2"); + + model.addBody(model.getBodyId("root"),JointModelRX(),SE3::Random(),Inertia::Random(),"torso1"); + model.addBody(model.getBodyId("torso1"),JointModelRX(),SE3::Random(),Inertia::Random(),"chest"); + + model.addBody(model.getBodyId("chest"),JointModelRX(),SE3::Random(),Inertia::Random(),"rarm1"); + model.addBody(model.getBodyId("rarm1"),JointModelRX(),SE3::Random(),Inertia::Random(),"rarm2"); + model.addBody(model.getBodyId("rarm2"),JointModelRX(),SE3::Random(),Inertia::Random(),"rarm3"); + + model.addBody(model.getBodyId("chest"),JointModelRX(),SE3::Random(),Inertia::Random(),"larm1"); + model.addBody(model.getBodyId("larm1"),JointModelRX(),SE3::Random(),Inertia::Random(),"larm2"); + model.addBody(model.getBodyId("larm2"),JointModelRX(),SE3::Random(),Inertia::Random(),"larm3"); + + std::cout << model << std::endl; + + se3::Data data(model); + VectorXd q = VectorXd::Zero(model.nq); + crba2(model,data,q); + + std::cout << "M = [\n" << data.M << "];" << std::endl; + for(int i=0;i<model.nv;++i) + for(int j=i;j<model.nv;++j) + { + data.M(i,j) = round(data.M(i,j))+1; + data.M(j,i) = data.M(i,j); + } + std::cout << "M = [\n" << data.M << "];" << std::endl; + + //cholesky(model,data) + + return 0; +} -- GitLab