Newer
Older
/*
* Copyright 2010,
* François Bleibel,
* Olivier Stasse,
#include <sot-dynamic-pinocchio/force-compensation.h>
Florent Lamiraux
committed
#include <sot/core/debug.hh>
Florent Lamiraux
committed
#include <sot/core/macros-signal.hh>
using namespace dynamicgraph::sot;
using namespace dynamicgraph;
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(ForceCompensationPlugin,"ForceCompensation");
/* --- PLUGIN --------------------------------------------------------------- */
/* --- PLUGIN --------------------------------------------------------------- */
/* --- PLUGIN --------------------------------------------------------------- */
ForceCompensation::
ForceCompensation(void)
:usingPrecompensation(false)
{}
ForceCompensationPlugin::
,torsorSIN(NULL,"sotForceCompensation("+name+")::input(vector6)::torsorIN")
,worldRhandSIN(NULL,"sotForceCompensation("+name+")::input(MatrixRotation)::worldRhand")
,handRsensorSIN(NULL,"sotForceCompensation("+name+")::input(MatrixRotation)::handRsensor")
,translationSensorComSIN(NULL,"sotForceCompensation("+name+")::input(vector3)::sensorCom")
,gravitySIN(NULL,"sotForceCompensation("+name+")::input(vector6)::gravity")
,precompensationSIN(NULL,"sotForceCompensation("+name+")::input(vector6)::precompensation")
,gainSensorSIN(NULL,"sotForceCompensation("+name+")::input(matrix6)::gain")
,deadZoneLimitSIN(NULL,"sotForceCompensation("+name+")::input(vector6)::deadZoneLimit")
,transSensorJointSIN(NULL,"sotForceCompensation("+name+")::input(vector6)::sensorJoint") ,inertiaJointSIN(NULL,"sotForceCompensation("+name+")::input(matrix6)::inertiaJoint")
,velocitySIN(NULL,"sotForceCompensation("+name+")::input(vector6)::velocity")
,accelerationSIN(NULL,"sotForceCompensation("+name+")::input(vector6)::acceleration")
,handXworldSOUT( SOT_INIT_SIGNAL_2( ForceCompensation::computeHandXworld,
worldRhandSIN,MatrixRotation,
translationSensorComSIN,dynamicgraph::Vector ),
"sotForceCompensation("+name+")::output(MatrixForce)::handXworld" )
,handVsensorSOUT( SOT_INIT_SIGNAL_1( ForceCompensation::computeHandVsensor,
handRsensorSIN,MatrixRotation),
"sotForceCompensation("+name+")::output(MatrixForce)::handVsensor" )
,torsorDeadZoneSIN(NULL,"sotForceCompensation("+name+")::input(vector6)::torsorNullifiedIN")
,sensorXhandSOUT( SOT_INIT_SIGNAL_2( ForceCompensation::computeSensorXhand,
handRsensorSIN,MatrixRotation,
transSensorJointSIN,dynamicgraph::Vector ),
"sotForceCompensation("+name+")::output(MatrixForce)::sensorXhand" )
// ,inertiaSensorSOUT( SOT_INIT_SIGNAL_2( ForceCompensation::computeInertiaSensor,
// inertiaJointSIN,dynamicgraph::Matrix,
// sensorXhandSOUT,MatrixForce ),
// "ForceCompensation("+name+")::output(MatrixForce)::inertiaSensor" )
,momentumSOUT( SOT_INIT_SIGNAL_4(ForceCompensation::computeMomentum,
velocitySIN,dynamicgraph::Vector,
accelerationSIN,dynamicgraph::Vector,
inertiaJointSIN,dynamicgraph::Matrix),
"sotForceCompensation("+name+")::output(Vector6)::momentum" )
,momentumSIN(NULL,"sotForceCompensation("+name+")::input(vector6)::momentumIN")
,torsorCompensatedSOUT( SOT_INIT_SIGNAL_7(ForceCompensation::computeTorsorCompensated,
torsorSIN,dynamicgraph::Vector,
precompensationSIN,dynamicgraph::Vector,
gravitySIN,dynamicgraph::Vector,
handXworldSOUT,MatrixForce,
handVsensorSOUT,MatrixForce,
gainSensorSIN,dynamicgraph::Matrix,
momentumSIN,dynamicgraph::Vector),
"sotForceCompensation("+name+")::output(Vector6)::torsor" )
,torsorDeadZoneSOUT( SOT_INIT_SIGNAL_2(ForceCompensation::computeDeadZone,
torsorDeadZoneSIN,dynamicgraph::Vector,
deadZoneLimitSIN,dynamicgraph::Vector),
"sotForceCompensation("+name+")::output(Vector6)::torsorNullified" )
,calibrationTrigerSOUT( boost::bind(&ForceCompensationPlugin::calibrationTriger,
this,_1,_2),
torsorSIN << worldRhandSIN,
"sotForceCompensation("+name+")::output(Dummy)::calibrationTriger")
{
sotDEBUGIN(5);
signalRegistration(torsorSIN);
signalRegistration(worldRhandSIN);
signalRegistration(handRsensorSIN);
signalRegistration(translationSensorComSIN);
signalRegistration(gravitySIN);
signalRegistration(precompensationSIN);
signalRegistration(gainSensorSIN);
signalRegistration(deadZoneLimitSIN);
signalRegistration(transSensorJointSIN);
signalRegistration(inertiaJointSIN);
signalRegistration(velocitySIN );
signalRegistration(accelerationSIN);
signalRegistration(handXworldSOUT);
signalRegistration(handVsensorSOUT);
signalRegistration(torsorDeadZoneSIN);
signalRegistration(sensorXhandSOUT);
signalRegistration(momentumSOUT);
signalRegistration(momentumSIN);
signalRegistration(torsorCompensatedSOUT);
signalRegistration(torsorDeadZoneSOUT);
signalRegistration(calibrationTrigerSOUT);
torsorDeadZoneSIN.plug(&torsorCompensatedSOUT);
// By default, I choose: momentum is not compensated.
// momentumSIN.plug( &momentumSOUT );
dynamicgraph::Vector v(6); v.fill(0); momentumSIN = v;
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
sotDEBUGOUT(5);
}
ForceCompensationPlugin::
~ForceCompensationPlugin( void )
{
return;
}
/* --- CALIB --------------------------------------------------------------- */
/* --- CALIB --------------------------------------------------------------- */
/* --- CALIB --------------------------------------------------------------- */
MatrixRotation ForceCompensation::I3;
void ForceCompensation::
clearCalibration( void )
{
torsorList.clear();
rotationList.clear();
}
void ForceCompensation::
addCalibrationValue( const dynamicgraph::Vector& /*torsor*/,
{
sotDEBUGIN(45);
// sotDEBUG(25) << "Add torsor: t"<<torsorList.size() <<" = " << torsor;
// sotDEBUG(25) << "Add Rotation: wRh"<<torsorList.size() <<" = " << worldRhand;
// torsorList.push_back(torsor);
// rotationList.push_back(worldRhand);
sotDEBUGOUT(45);
}
dynamicgraph::Vector ForceCompensation::
calibrateTransSensorCom( const dynamicgraph::Vector& gravity,
// dynamicgraph::Vector grav3(3);
// dynamicgraph::Vector Rgrav3(3),tau(3),Rtau(3);
// for( unsigned int j=0;j<3;++j ) { grav3(j)=gravity(j); }
// std::list< dynamicgraph::Vector >::iterator iterTorsor = torsorList.begin();
// std::list< MatrixRotation >::const_iterator iterRotation
// = rotationList.begin();
// const unsigned int NVAL = torsorList.size();
// dynamicgraph::Vector zero(3); zero.fill(0);
// dynamicgraph::Matrix torsors( 3,NVAL );
// dynamicgraph::Matrix gravitys( 3,NVAL );
// for( unsigned int i=0;i<NVAL;++i )
// {
// if( (torsorList.end()==iterTorsor)||(rotationList.end()==iterRotation) )
// {
// // TODO: ERROR THROW
// break;
// }
// const dynamicgraph::Vector & torsor = *iterTorsor;
// const MatrixRotation & worldRhand = *iterRotation;
// for( unsigned int j=0;j<3;++j ) { tau(j)=torsor(j+3); }
// handRsensor.multiply(tau,Rtau);
// worldRhand.transpose().multiply( grav3,Rgrav3 );
// for( unsigned int j=0;j<3;++j )
// {
// torsors( j,i ) = -Rtau(j);
// gravitys( j,i ) = Rgrav3(j);
// }
// sotDEBUG(35) << "R" << i << " = " << worldRhand;
// sotDEBUG(35) << "Rtau" << i << " = " << Rtau;
// sotDEBUG(35) << "Rg" << i << " = " << Rgrav3;
// iterTorsor++; iterRotation++;
// }
// sotDEBUG(35) << "Rgs = " << gravitys;
// sotDEBUG(35) << "Rtaus = " << torsors;
// dynamicgraph::Matrix gravsInv( gravitys.nbCols(),gravitys.nbRows() );
// sotDEBUG(25) << "Compute the pinv..." << std::endl;
// gravitys.pseudoInverse(gravsInv);
// sotDEBUG(25) << "Compute the pinv... [DONE]" << std::endl;
// sotDEBUG(25) << "gravsInv = " << gravsInv << std::endl;
// dynamicgraph::Matrix Skew(3,3);
// torsors.multiply( gravsInv,Skew );
// sotDEBUG(25) << "Skew = " << Skew << std::endl;
// dynamicgraph::Vector sc(3);
// sc(0)=(Skew(2,1)-Skew(1,2))*.5 ;
// sc(1)=(Skew(0,2)-Skew(2,0))*.5 ;
// sc(2)=(Skew(1,0)-Skew(0,1))*.5 ;
// /* TAKE the antisym constraint into account inside the minimization pbm. */
// sotDEBUGOUT(25);
// return sc;
return gravity;
}
dynamicgraph::Vector ForceCompensation::
calibrateGravity( const MatrixRotation& /*handRsensor*/,
bool /*precompensationCalibration*/,
const MatrixRotation& /*hand0RsensorArg*/ )
{
sotDEBUGIN(25);
// MatrixRotation hand0Rsensor;
// if( &hand0Rsensor==&I3 ) hand0Rsensor.setIdentity();
// else hand0Rsensor=hand0RsensorArg;
// std::list< dynamicgraph::Vector >::const_iterator iterTorsor = torsorList.begin();
// std::list< MatrixRotation >::const_iterator iterRotation
// = rotationList.begin();
// const unsigned int NVAL = torsorList.size();
// dynamicgraph::Vector zero(6); zero.fill(0);
// dynamicgraph::Vector force(3),forceHand(3),forceWorld(3);
// dynamicgraph::Vector sumForce(3); sumForce.fill(0);
// for( unsigned int i=0;i<NVAL;++i )
// {
// if( (torsorList.end()==iterTorsor)||(rotationList.end()==iterRotation) )
// {
// // TODO: ERROR THROW
// break;
// }
// const dynamicgraph::Vector & torsor = *iterTorsor;
// const MatrixRotation & R = *iterRotation;
// /* The sensor read [-] the value, and the grav is [-] the sensor force.
// * [-]*[-] = [+] -> force = + torsor(1:3). */
// for( unsigned int j=0;j<3;++j ) { force(j)=-torsor(j); }
// handRsensor.multiply(force,forceHand);
// if( usingPrecompensation )
// {
// dynamicgraph::Matrix R_I(3,3); R_I = R.transpose();
// R_I -= hand0Rsensor;
// R_I.pseudoInverse(.01).multiply( forceHand,forceWorld );
// }
// sotDEBUG(35) << "R(" << i << "*3+1:" << i << "*3+3,:) = " << R << "';";
// sotDEBUG(35) << "rhFs(" << i << "*3+1:" << i << "*3+3) = " << forceHand;
// sotDEBUG(45) << "fworld(" << i << "*3+1:" << i << "*3+3) = " << forceWorld;
// sumForce+= forceWorld;
// iterTorsor++; iterRotation++;
// }
// sumForce*= (1./NVAL);
// sotDEBUG(35) << "Fmean = " << sumForce;
// sumForce.resize(6,false);
// sumForce(3)=sumForce(4)=sumForce(5)=0.;
// sotDEBUG(25)<<"mg = " << sumForce<<std::endl;
sotDEBUGOUT(25);
dynamicgraph::Vector sumForce(3); sumForce.fill(0);
return sumForce;
}
/* --- SIGNALS -------------------------------------------------------------- */
/* --- SIGNALS -------------------------------------------------------------- */
/* --- SIGNALS -------------------------------------------------------------- */
MatrixForce& ForceCompensation::
computeHandXworld( const MatrixRotation & worldRhand,
const dynamicgraph::Vector & transSensorCom,
MatrixForce& res )
{
sotDEBUGIN(35);
sotDEBUG(25) << "wRrh = " << worldRhand <<std::endl;
sotDEBUG(25) << "SC = " << transSensorCom <<std::endl;
scRw.linear()=worldRhand.transpose(); scRw.translation()=transSensorCom;
sotDEBUG(25) << "scMw = " << scRw <<std::endl;
/////////////////////////////
// res.buildFrom( scRw );
Eigen::Vector3d _t = scRw.translation();
MatrixRotation R(scRw.linear());
Eigen::Matrix3d Tx;
Tx << 0, -_t(2), _t(1),
_t(2), 0, -_t(0),
-_t(1), _t(0), 0;
Eigen::Matrix3d sk; sk = Tx*R;
res.block<3,3>(0,0) = R;
res.block<3,3>(0,3).setZero();
res.block<3,3>(3,0) = sk;
res.block<3,3>(3,3) = R;
////////////////////////////
sotDEBUG(15) << "scXw = " << res <<std::endl;
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
sotDEBUGOUT(35);
return res;
}
MatrixForce& ForceCompensation::
computeHandVsensor( const MatrixRotation & handRsensor,
MatrixForce& res )
{
sotDEBUGIN(35);
for( unsigned int i=0;i<3;++i )
for( unsigned int j=0;j<3;++j )
{
res(i,j)=handRsensor(i,j);
res(i+3,j+3)=handRsensor(i,j);
res(i+3,j)=0.;
res(i,j+3)=0.;
}
sotDEBUG(25) << "hVs" << res << std::endl;
sotDEBUGOUT(35);
return res;
}
MatrixForce& ForceCompensation::
computeSensorXhand( const MatrixRotation & /*handRsensor*/,
const dynamicgraph::Vector & transJointSensor,
MatrixForce& res )
{
sotDEBUGIN(35);
/* Force Matrix to pass from the joint frame (ie frame located
* at the position of the motor, in which the acc is computed by Spong)
* to the frame SensorHand where all the forces are expressed (ie
* frame located at the sensor position bu oriented like the hand). */
Eigen::Matrix3d Tx;
Tx << 0, -transJointSensor(2), transJointSensor(1),
transJointSensor(2), 0, -transJointSensor(0),
-transJointSensor(1), transJointSensor(0), 0;
res.block<3,3>(0,0).setIdentity();
res.block<3,3>(0,3).setZero();
res.block<3,3>(3,0) = Tx;
res.block<3,3>(3,3).setIdentity();
sotDEBUG(25) << "shXJ" << res << std::endl;
sotDEBUGOUT(35);
return res;
}
// dynamicgraph::Matrix& ForceCompensation::
// computeInertiaSensor( const dynamicgraph::Matrix& inertiaJoint,
// dynamicgraph::Matrix& res )
// /* Inertia felt at the sensor position, expressed in the orientation
// * of the hand. */
// res.resize(6,6);
// sensorXhand.multiply( inertiaJoint,res );
// sotDEBUGOUT(35);
// return res;
// }
dynamicgraph::Vector& ForceCompensation::
computeTorsorCompensated( const dynamicgraph::Vector& torqueInput,
const dynamicgraph::Vector& torquePrecompensation,
const dynamicgraph::Vector& gravity,
const MatrixForce& handXworld,
const MatrixForce& handVsensor,
const dynamicgraph::Matrix& gainSensor,
const dynamicgraph::Vector& momentum,
dynamicgraph::Vector& res )
{
sotDEBUGIN(35);
/* Torsor in the sensor frame: K*(-torsred-gamma)+sVh*hXw*mg */
/* Torsor in the hand frame: hVs*K*(-torsred-gamma)+hXw*mg */
/* With gamma expressed in the sensor frame (gamma_s = sVh*gamma_h) */
sotDEBUG(25) << "t_nc = " << torqueInput;
dynamicgraph::Vector torquePrecompensated(6);
//else { torquePrecompensated = torqueInput; }
sotDEBUG(25) << "t_pre = " << torquePrecompensated;
dynamicgraph::Vector torqueS(6), torqueRH(6);
torqueS = gainSensor*torquePrecompensated;
res = handVsensor*torqueS;
dynamicgraph::Vector grh(6);
grh = handXworld*gravity;
grh *= -1;
sotDEBUG(25) << "g_rh = " << grh;
res+=grh;
sotDEBUG(25) << "fcomp = " << res;
res+=momentum;
sotDEBUG(25) << "facc = " << res;
/* TODO res += m xddot */
sotDEBUGOUT(35);
return res;
}
dynamicgraph::Vector& ForceCompensation::
crossProduct_V_F( const dynamicgraph::Vector& velocity,
const dynamicgraph::Vector& force,
dynamicgraph::Vector& res )
{
/* [ v;w] x [ f;tau ] = [ w x f; v x f + w x tau ] */
Eigen::Vector3d v,w,f,tau;
for( unsigned int i=0;i<3;++i )
{
v(i)=velocity(i); w(i) = velocity(i+3);
f(i) = force(i); tau(i) = force(i+3);
}
Eigen::Vector3d res1(3),res2a(3),res2b(3);
res1 = w.cross(f);
res2a = v.cross(f);
res2b = w.cross(tau);
res2a += res2b;
res.resize(6);
for( unsigned int i=0;i<3;++i )
{
res(i)=res1(i); res(i+3)=res2a(i);
}
return res;
}
dynamicgraph::Vector& ForceCompensation::
computeMomentum( const dynamicgraph::Vector& velocity,
const dynamicgraph::Vector& acceleration,
const dynamicgraph::Matrix& inertiaJoint,
dynamicgraph::Vector& res )
{
sotDEBUGIN(35);
/* Fs + Fext = I acc + V x Iv */
dynamicgraph::Vector Iacc(6); Iacc = inertiaJoint* acceleration;
res.resize(6); res = sensorXhand*Iacc;
dynamicgraph::Vector Iv(6); Iv = inertiaJoint*velocity;
dynamicgraph::Vector vIv(6); crossProduct_V_F( velocity,Iv,vIv );
dynamicgraph::Vector XvIv(6); XvIv = sensorXhand*vIv;
res+= XvIv;
sotDEBUGOUT(35);
return res;
}
dynamicgraph::Vector& ForceCompensation::
computeDeadZone( const dynamicgraph::Vector& torqueInput,
const dynamicgraph::Vector& deadZone,
dynamicgraph::Vector& res )
if( torqueInput.size()>deadZone.size() ) return res;
res.resize(torqueInput.size());
for( int i=0;i<torqueInput.size();++i )
if( (torqueInput(i)<th)&&(torqueInput(i)>-th) )
{ res(i)=0; }
else if(torqueInput(i)<0) res(i)=torqueInput(i)+th;
else res(i)=torqueInput(i)-th;
}
sotDEBUGOUT(35);
return res;
}
ForceCompensationPlugin::sotDummyType& ForceCompensationPlugin::
calibrationTriger( ForceCompensationPlugin::sotDummyType& dummy,int /*time*/ )
{
// if(! calibrationStarted ) { sotDEBUGOUT(45); return dummy=0; }
// addCalibrationValue( torsorSIN(time),worldRhandSIN(time) );
// sotDEBUGOUT(45);
return dummy=1;
}