From d3fb85788536f1008a62df8170361ed5655655fa Mon Sep 17 00:00:00 2001
From: Mansard <nmansard@laas.fr>
Date: Mon, 29 Aug 2011 16:41:34 +0200
Subject: [PATCH] Unified the QR and pseudo inversion.

---
 python/dynreduced.py            |  9 ++---
 src/col-piv-qr-solve-in-place.h | 16 +++++++--
 src/solver-dyn-reduced.cpp      | 63 +++++++++++++++++++++------------
 src/solver-dyn-reduced.h        |  5 ++-
 4 files changed, 60 insertions(+), 33 deletions(-)

diff --git a/python/dynreduced.py b/python/dynreduced.py
index 176d9a7..dda7edf 100644
--- a/python/dynreduced.py
+++ b/python/dynreduced.py
@@ -169,7 +169,7 @@ featureCom.sdes.value = 'featureComDes'
 taskCom = TaskDynPD('taskCom')
 taskCom.add('featureCom')
 plug(dyn.velocity,taskCom.qdot)
-taskCom.dt.value = 1e-3
+taskCom.dt.value = dt
 
 gCom = GainAdaptive('gCom')
 plug(taskCom.error,gCom.error)
@@ -185,11 +185,13 @@ gCom.set(1050,45,125e3)
 contactLF = MetaTaskDyn6d('contact_lleg',dyn,'lf','left-ankle')
 contactLF.support = ((0.11,-0.08,-0.08,0.11),(-0.045,-0.045,0.07,0.07),(-0.105,-0.105,-0.105,-0.105))
 contactLF.feature.frame('desired')
+contactLF.task.dt.value=dt
 
 # Right foot contact
 contactRF = MetaTaskDyn6d('contact_rleg',dyn,'rf','right-ankle')
 contactRF.support = ((0.11,-0.08,-0.08,0.11),(-0.07,-0.07,0.045,0.045),(-0.105,-0.105,-0.105,-0.105))
 contactRF.feature.frame('desired')
+contactLF.task.dt.value=dt
 
 # --- SOT Dyn OpSpaceH --------------------------------------
 
@@ -237,6 +239,7 @@ robot.after.addSignal('sot.acceleration')
 tr.add('taskCom.error','com')
 tr.add('taskCom.task','')
 tr.add(contactLF.task.name+'.error','lf')
+tr.add(contactRF.task.name+'.error','rf')
 
 if not rs: tr.add('sot.solution','')
 
@@ -287,10 +290,9 @@ attime(500,stop,'stop')
 
 
 
-go()
+#go()
 
 # --- DEBUG ----------------------------------------------
-'''
 for i in range(50):    inc()
 
 print sot.velocity.m
@@ -331,7 +333,6 @@ else:
     print "u=x(1:24); psi=x(25:end); "
 
     print "ddq2= ddq; phi2=phi; f2=f; fn2=f(3:3:end);"
-'''
 
 '''
 if 0: # double check
diff --git a/src/col-piv-qr-solve-in-place.h b/src/col-piv-qr-solve-in-place.h
index 2779c07..77773de 100644
--- a/src/col-piv-qr-solve-in-place.h
+++ b/src/col-piv-qr-solve-in-place.h
@@ -18,6 +18,7 @@
 #define __sot_dyninv_ColPivQRSolveInPlace_H__
 
 #include <Eigen/QR>
+#include <iostream>
 
 namespace Eigen
 {
@@ -43,7 +44,7 @@ namespace Eigen
       assert( r==m );
       assert( Gp.rows() == m ); // TODO: if not proper size, resize.
 
-      VectorXd workspace( n );
+      VectorXd workspace( Gp.rows() ); // Size of Gtp number of rows.
       /* P2*P1*P0 ... */
       for (int k = r-1; k >= 0 ; --k)
 	{
@@ -96,11 +97,20 @@ namespace Eigen
 
       /* Compute Q R^+T E'*X. */
       /* Q = P1*P2* ... *Pn */
-      VectorXd workspace( n );
+      VectorXd workspace( Gtp.cols() ); // size of Gtp number of cols.
       for (int k = r-1; k >= 0 ; --k)
 	{
 	  int remainingSize = m-k;
-	  Gtp.bottomRows( Gtp.rows()-k )
+	  /* std::cout << " ---------------------------" << std::endl; */
+	  /* std::cout << remainingSize << std::endl; */
+	  /* std::cout << " ---------------------------" << std::endl; */
+	  /* std::cout << Gtp.bottomRows( Gtp.rows()-k ) << std::endl; */
+	  /* std::cout << " ---------------------------" << std::endl; */
+	  /* std::cout << matrixQR().col(k).transpose() << std::endl; */
+	  /* std::cout << " ---------------------------" << std::endl; */
+	  /* std::cout << matrixQR().col(k).tail(remainingSize-1).transpose() << std::endl; */
+	  /* std::cout << " ---------------------------" << std::endl; */
+	  Gtp.bottomRows( remainingSize )
 	    .applyHouseholderOnTheLeft(matrixQR().col(k).tail(remainingSize-1),
 				       hCoeffs().coeff(k), &workspace.coeffRef(0));
 	}
diff --git a/src/solver-dyn-reduced.cpp b/src/solver-dyn-reduced.cpp
index 17ae8cf..55e366b 100644
--- a/src/solver-dyn-reduced.cpp
+++ b/src/solver-dyn-reduced.cpp
@@ -744,7 +744,7 @@ namespace dynamicgraph
 	  V = Q [ 0 ; I ].
 	 */
 	EIGEN_MATRIX_FROM_MATRIX(V,mlV,nq,freeRank);
-	assert( freeRank == J.rows() );
+	assert( G_rank == J.rows() );
 	assert( Gt_qr.householderQ().cols()==nq && Gt_qr.householderQ().rows()==nq );
 	V.topRows(nq-freeRank).fill(0);
 	V.bottomRows(freeRank) = MatrixXd::Identity(freeRank,freeRank);
@@ -764,17 +764,21 @@ namespace dynamicgraph
 	const int & nf = sizeForcePointSOUT(t);
 	assert( X.rows()==nf );
 
-	X_qr.compute( (MatrixXd)((X*Jc).leftCols(6)));
+	/* J[:,1:6] = [ R_1  X_1 ; ... ; R_N X_N ]
+	 * with R_i the rotation of the frame where contact point i is expressed
+	 * and X_i the skew of the vector from waist to contact point. */
+	X_qr.compute( X*(Jc.leftCols(6)) );
 	X_qr.setThreshold(1e-3);
 	const unsigned int freeRank = nf-X_qr.rank();
 	assert( X_qr.rank()==6 );
-	//assert( X_qr.rank()==X.cols() );
 
 	sotDEBUG(5) << "JSb = " << (MATLAB)( (MatrixXd)((X*Jc).leftCols(6)) ) << endl;
-	sotDEBUG(5) << "Q = " << (MATLAB)X_qr.matrixQ()  << endl;
+	sotDEBUG(5) << "Q = " << (MATLAB)(MatrixXd)X_qr.householderQ()  << endl;
 
 	EIGEN_MATRIX_FROM_MATRIX(K,mlK,nf,freeRank);
-	K = X_qr.matrixQ().rightCols(freeRank);
+	K.topRows(X_qr.rank()).fill(0);
+	K.bottomRows(freeRank) = MatrixXd::Identity(freeRank,freeRank);
+	K.applyOnTheLeft( X_qr.householderQ() );
 
 	return mlK;
       }
@@ -945,27 +949,30 @@ namespace dynamicgraph
 
 	/* -1- */
 	{
-	  MatrixXd XJS = Xc*Jc.leftCols(6);
-	  sotDEBUG(15) << "XJS = "     << (MATLAB)XJS << std::endl;
-	  HouseholderQR<MatrixXd> qr(XJS);
-
-	  MatrixXd XJSp = qr.solve( MatrixXd::Identity(nf,nf) );
-	  MatrixXd XJSptSBV = -XJSp.transpose()
-	    * sBi.transpose().topLeftCorner(6,6).triangularView<Lower>() * V.ROWS_FF;
-	  VectorXd ref = XJSp.transpose()
-	    * (b.ROWS_FF
-	       + sBi.transpose().topLeftCorner(6,6).triangularView<Lower>()*drift.ROWS_FF);
-
-	  sotDEBUG(15) << "XJSp = "     << (MATLAB)XJSp << std::endl;
-	  sotDEBUG(15) << "XJSptSBV = "     << (MATLAB)XJSptSBV << std::endl;
-	  sotDEBUG(15) << "ref = "     << (MATLAB)ref << std::endl;
-
-	  assert( XJSptSBV.rows()==nbForce*3 && K.rows()==nbForce*3 && ref.size()==nbForce*3 );
+	  MatrixXd XJSptSBV2( nf,nu );
+	  XJSptSBV2.ROWS_FF
+	    = - (sBi.transpose().topLeftCorner(6,6).triangularView<Lower>() * V.ROWS_FF);
+	  XJSptSBV2.bottomRows( nf-6 ).setZero();
+	  sotDEBUG(15) << "SBitV = " << (MATLAB)XJSptSBV2 << std::endl;
+	  X_qr.solveTransposeInPlace( XJSptSBV2 );
+	  sotDEBUG(15) << "XJSptSBitV = " << (MATLAB)XJSptSBV2 << std::endl;
+
+	  VectorXd XJSptdelta( nf );
+	  XJSptdelta.ROWS_FF
+	    = b.ROWS_FF
+	    + sBi.transpose().topLeftCorner(6,6).triangularView<Lower>()*drift.ROWS_FF;
+	  XJSptdelta.bottomRows( nf-6 ).setZero();
+	  sotDEBUG(15) << "SBitdelta = " << (MATLAB)XJSptdelta << std::endl;
+	  X_qr.solveTransposeInPlace( XJSptdelta );
+	  sotDEBUG(15) << "XJSptSBitdelta = " << (MATLAB)XJSptdelta << std::endl;
+
+	  assert( XJSptSBV2.rows()==nbForce*3 && K.rows()==nbForce*3
+		  && XJSptdelta.size()==nbForce*3 );
 	  for( int i=0;i<nbForce;++i )
 	    {
-	      Cforce.COLS_U.row(i) = XJSptSBV.row(3*i+2);
+	      Cforce.COLS_U.row(i) = XJSptSBV2.row(3*i+2);
 	      Cforce.COLS_F.row(i) = K.row(3*i+2);
-	      bforce[i] = Bound( ref[3*i+2], Bound::BOUND_SUP );
+	      bforce[i] = Bound( XJSptdelta[3*i+2], Bound::BOUND_SUP );
 	    }
 	}
 	sotDEBUG(15) << "Cforce = "     << (MATLAB)Cforce << std::endl;
@@ -1093,6 +1100,16 @@ namespace dynamicgraph
 	sotDEBUG(40) << "B = " << (MATLAB)sB << std::endl;
 	sotDEBUG(40) << "u = " << (MATLAB)u << std::endl;
 	ddq = BV*u + B*drift;
+
+	/* --- verif --- */
+	{
+	  EIGEN_CONST_MATRIX_FROM_SIGNAL(Jc,JcSOUT(t));
+	  sotDEBUG(40) << "fdrift = " << (MATLAB)forceDrift << std::endl;
+	  sotDEBUG(40) << "Jqdd = " << (MATLAB)(MatrixXd)(Jc*ddq)  << std::endl;
+	  sotDEBUG(40) << "diff = " << (MATLAB)(MatrixXd)(Jc*ddq-forceDrift)  << std::endl;
+	  sotDEBUG(40) << "ndiff = " << (Jc*ddq-forceDrift).norm() << std::endl;
+	}
+
 	return mlddq;
       }
       ml::Vector& SolverDynReduced::
diff --git a/src/solver-dyn-reduced.h b/src/solver-dyn-reduced.h
index 7112f0f..a4a9969 100644
--- a/src/solver-dyn-reduced.h
+++ b/src/solver-dyn-reduced.h
@@ -162,14 +162,13 @@ namespace dynamicgraph {
 	  void refreshTaskTime( int time );
 	  void resizeSolver( void );
 	  void computeSizesForce( int t );
- 
+
 	private:
 	  typedef boost::shared_ptr<soth::HCOD> hcod_ptr_t;
 	  hcod_ptr_t hsolver;
 
 	  int G_rank;
-	  Eigen::FullPivHouseholderQR<Eigen::MatrixXd> X_qr;
-	  Eigen::ColPivQRSolveInPlace Gt_qr;
+	  Eigen::ColPivQRSolveInPlace X_qr,Gt_qr;
 
 
 	  Eigen::MatrixXd Cforce,Czero;
-- 
GitLab