/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 * Copyright Projet JRL-Japan, 2007
 *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 * File:      ForceCompensation.h
 * Project:   SOT
 * Author:    Nicolas Mansard
 *
 * Version control
 * ===============
 *
 *  $Id$
 *
 * Description
 * ============
 *
 *
 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

#include <sot-dynamic/force-compensation.h>
#include <sot-core/debug.h>
#include <dynamic-graph/factory.h>
#include <sot-core/macros-signal.h>

using namespace sot;
using namespace dynamicgraph;
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(ForceCompensationPlugin,"ForceCompensation");

/* --- PLUGIN --------------------------------------------------------------- */
/* --- PLUGIN --------------------------------------------------------------- */
/* --- PLUGIN --------------------------------------------------------------- */
ForceCompensation::
ForceCompensation(void)
  :usingPrecompensation(false)
{}


ForceCompensationPlugin::
ForceCompensationPlugin( const std::string & name ) 
  :Entity(name)
  ,calibrationStarted(false)
  
  ,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,ml::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,ml::Vector ),
		   "sotForceCompensation("+name+")::output(MatrixForce)::sensorXhand" )
//   ,inertiaSensorSOUT( SOT_INIT_SIGNAL_2( ForceCompensation::computeInertiaSensor,
// 					  inertiaJointSIN,ml::Matrix,
// 					  sensorXhandSOUT,MatrixForce ),
// 		       "ForceCompensation("+name+")::output(MatrixForce)::inertiaSensor" )
   ,momentumSOUT( SOT_INIT_SIGNAL_4(ForceCompensation::computeMomentum,
				    velocitySIN,ml::Vector,
				    accelerationSIN,ml::Vector,
				    sensorXhandSOUT,MatrixForce,
				    inertiaJointSIN,ml::Matrix),
		  "sotForceCompensation("+name+")::output(Vector6)::momentum" ) 
  ,momentumSIN(NULL,"sotForceCompensation("+name+")::input(vector6)::momentumIN")  
 
  ,torsorCompensatedSOUT( SOT_INIT_SIGNAL_7(ForceCompensation::computeTorsorCompensated,
					    torsorSIN,ml::Vector,
					    precompensationSIN,ml::Vector,
					    gravitySIN,ml::Vector,
					    handXworldSOUT,MatrixForce,
					    handVsensorSOUT,MatrixForce,
					    gainSensorSIN,ml::Matrix,
					    momentumSIN,ml::Vector),
			  "sotForceCompensation("+name+")::output(Vector6)::torsor" ) 
  ,torsorDeadZoneSOUT( SOT_INIT_SIGNAL_2(ForceCompensation::computeDeadZone,
					 torsorDeadZoneSIN,ml::Vector,
					 deadZoneLimitSIN,ml::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<< worldRhandSIN 
		      << handRsensorSIN << translationSensorComSIN
		      << gravitySIN << precompensationSIN << gainSensorSIN
		      << deadZoneLimitSIN 
		      << transSensorJointSIN << inertiaJointSIN 
		      << velocitySIN << accelerationSIN
 
		      << handXworldSOUT << handVsensorSOUT << torsorDeadZoneSIN
		      << sensorXhandSOUT //<< inertiaSensorSOUT 
		      << momentumSOUT << momentumSIN
		      << torsorCompensatedSOUT << torsorDeadZoneSOUT
		      << calibrationTrigerSOUT );
  torsorDeadZoneSIN.plug(&torsorCompensatedSOUT);
  
  // By default, I choose: momentum is not compensated.
  //  momentumSIN.plug( &momentumSOUT );
  ml::Vector v(6); v.fill(0); momentumSIN = v;

  sotDEBUGOUT(5);
}


ForceCompensationPlugin::
~ForceCompensationPlugin( void )
{
  return;
}

/* --- CALIB --------------------------------------------------------------- */
/* --- CALIB --------------------------------------------------------------- */
/* --- CALIB --------------------------------------------------------------- */

MatrixRotation ForceCompensation::I3;

void ForceCompensation::
clearCalibration( void )
{
  torsorList.clear();
  rotationList.clear();
}


void ForceCompensation::
addCalibrationValue( const ml::Vector& torsor,
		     const MatrixRotation & worldRhand )
{
  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);
}
  
ml::Vector ForceCompensation::
calibrateTransSensorCom( const ml::Vector& gravity,
			 const MatrixRotation& handRsensor )
{
  //   sotDEBUGIN(25);

  //   ml::Vector grav3(3);
  //   ml::Vector Rgrav3(3),tau(3),Rtau(3);
  //   for( unsigned int j=0;j<3;++j ) { grav3(j)=gravity(j); }

  //   std::list< ml::Vector >::iterator iterTorsor = torsorList.begin();
  //   std::list< MatrixRotation >::const_iterator iterRotation 
  //     = rotationList.begin();


  //   const unsigned int NVAL = torsorList.size();
  //   if( 0==NVAL ) 
  //     {
  //       ml::Vector zero(3); zero.fill(0);
  //       return zero;
  //     }

  //   if(NVAL!=rotationList.size() ) 
  //     {
  // 	  // TODO: ERROR THROW
  //     }
  //   ml::Matrix torsors( 3,NVAL );
  //   ml::Matrix gravitys( 3,NVAL );

  //   for( unsigned int i=0;i<NVAL;++i )
  //     {
  //       if( (torsorList.end()==iterTorsor)||(rotationList.end()==iterRotation) )
  // 	{
  // 	  // TODO: ERROR THROW
  // 	  break;
  // 	}
  //       const ml::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;

  //   ml::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;

  //   ml::Matrix Skew(3,3);
  //   torsors.multiply( gravsInv,Skew );
  //   sotDEBUG(25) << "Skew = " << Skew << std::endl;
  
  //   ml::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 ;
  //   sotDEBUG(15) << "SC = " << sc << std::endl; 
  //   /* TAKE the antisym constraint into account inside the minimization pbm. */

  //   sotDEBUGOUT(25);
  //   return sc;
  return gravity;
}

ml::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< ml::Vector >::const_iterator iterTorsor = torsorList.begin();
  //   std::list< MatrixRotation >::const_iterator iterRotation 
  //     = rotationList.begin();

  //   const unsigned int NVAL = torsorList.size();
  //   if(NVAL!=rotationList.size() ) 
  //     {
  // 	  // TODO: ERROR THROW
  //     }
  //   if( 0==NVAL ) 
  //     {
  //       ml::Vector zero(6); zero.fill(0);
  //       return zero;
  //     }
  
  //   ml::Vector force(3),forceHand(3),forceWorld(3);
  //   ml::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 ml::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 )
  // 	{
  // 	  ml::Matrix R_I(3,3); R_I = R.transpose();
  // 	  R_I -= hand0Rsensor;
  // 	  R_I.pseudoInverse(.01).multiply( forceHand,forceWorld );
  // 	}
  //       else 
  // 	{ R.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);
  ml::Vector sumForce(3); sumForce.fill(0);
  return sumForce;
}


/* --- SIGNALS -------------------------------------------------------------- */
/* --- SIGNALS -------------------------------------------------------------- */
/* --- SIGNALS -------------------------------------------------------------- */
MatrixForce& ForceCompensation::
computeHandXworld( const MatrixRotation & worldRhand,
		   const ml::Vector & transSensorCom,
		   MatrixForce& res )
{
  sotDEBUGIN(35);

  sotDEBUG(25) << "wRrh = " << worldRhand <<std::endl;
  sotDEBUG(25) << "SC = " << transSensorCom <<std::endl;

  MatrixRotation R; worldRhand.transpose(R);
  MatrixHomogeneous scRw; scRw.buildFrom( R,transSensorCom);
  sotDEBUG(25) << "scMw = " << scRw <<std::endl;
  
  res.buildFrom( scRw );
  sotDEBUG(15) << "scXw = " << res <<std::endl;
  
  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 ml::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). */

  MatrixRotation sensorRhand;  sensorRhand.setIdentity();
  //handRsensor.transpose(sensorRhand);
  MatrixHomogeneous sensorMhand;
  sensorMhand.buildFrom( sensorRhand,transJointSensor );

  res.buildFrom( sensorMhand );
  sotDEBUG(25) << "shXJ" << res << std::endl;

  sotDEBUGOUT(35);
  return res;
}

// ml::Matrix& ForceCompensation::
// computeInertiaSensor( const ml::Matrix& inertiaJoint,
// 		      const MatrixForce& sensorXhand,
// 		      ml::Matrix& res )
// {
//   sotDEBUGIN(35);
  
//   /* 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;
// }


ml::Vector& ForceCompensation::
computeTorsorCompensated( const ml::Vector& torqueInput,
			  const ml::Vector& torquePrecompensation,
			  const ml::Vector& gravity,
			  const MatrixForce& handXworld,
			  const MatrixForce& handVsensor,
			  const ml::Matrix& gainSensor,
			  const ml::Vector& momentum,
			  ml::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;
  ml::Vector torquePrecompensated(6);
  //if( usingPrecompensation )
  { torqueInput.addition( torquePrecompensation,torquePrecompensated ); }
  //else { torquePrecompensated = torqueInput; }
  sotDEBUG(25) << "t_pre = " << torquePrecompensated;

  ml::Vector torqueS(6), torqueRH(6);
  gainSensor.multiply( torquePrecompensated,torqueS );
  handVsensor.multiply( torqueS,res );
  sotDEBUG(25) << "t_rh = " << res;

  ml::Vector grh(6);
  handXworld.multiply(gravity,grh);
  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;
}

ml::Vector& ForceCompensation::
crossProduct_V_F( const ml::Vector& velocity,
		  const ml::Vector& force,
		  ml::Vector& res )
{
  /* [ v;w] x [ f;tau ] = [ w x f; v x f + w x tau ] */
  ml::Vector v(3),w(3),f(3),tau(3);
  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);
    }
  ml::Vector res1(3),res2a(3),res2b;
  w.crossProduct( f,res1 );
  v.crossProduct( f,res2a );
  w.crossProduct( tau,res2b );
  res2a+= res2b;
  
  res.resize(6);
  for( unsigned int i=0;i<3;++i )
    {
      res(i)=res1(i); res(i+3)=res2a(i);
    }
  return res;
}
				      

ml::Vector& ForceCompensation::
computeMomentum( const ml::Vector& velocity,
		 const ml::Vector& acceleration,
		 const MatrixForce& sensorXhand,
		 const ml::Matrix& inertiaJoint,
		 ml::Vector& res )
{
  sotDEBUGIN(35);

  /* Fs + Fext = I acc + V x Iv */
  ml::Vector Iacc(6); inertiaJoint.multiply( acceleration,Iacc );
  res.resize(6); sensorXhand.multiply( Iacc,res );
  
  ml::Vector Iv(6); inertiaJoint.multiply( velocity,Iv);
  ml::Vector vIv(6); crossProduct_V_F( velocity,Iv,vIv );
  ml::Vector XvIv(6); sensorXhand.multiply( vIv,XvIv);
  res+= XvIv;

  sotDEBUGOUT(35);
  return res;
}

ml::Vector& ForceCompensation::
computeDeadZone( const ml::Vector& torqueInput,
		 const ml::Vector& deadZone,
		 ml::Vector& res )

{
  sotDEBUGIN(35);
  
  if( torqueInput.size()>deadZone.size() ) return res;
  res.resize(torqueInput.size());
  for( unsigned int i=0;i<torqueInput.size();++i )
    {
      const double th = fabsf(deadZone(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 )
{ 
  //   sotDEBUGIN(45);
  //   if(! calibrationStarted ) { sotDEBUGOUT(45); return dummy=0; } 
  
  //   addCalibrationValue( torsorSIN(time),worldRhandSIN(time) );
  //   sotDEBUGOUT(45);
  return dummy=1;
}

/* --- COMMANDLINE ---------------------------------------------------------- */
/* --- COMMANDLINE ---------------------------------------------------------- */
/* --- COMMANDLINE ---------------------------------------------------------- */

void ForceCompensationPlugin::
commandLine( const std::string& cmdLine,
	     std::istringstream& cmdArgs,
	     std::ostream& os )
{
  if( "help"==cmdLine )
    {
      os << "ForceCompensation: "
	 << "  - clearCalibration" << std::endl
	 << "  - {start|stop}Calibration [wait <time_sec>]" << std::endl
	 << "  - calibrateGravity\t[only {x|y|z}]" << std::endl
	 << "  - calibratePosition" << std::endl
	 << "  - precomp [{true|false}]:  get/set the "
	 << "precompensation due to sensor calib." << std::endl;
    }
  //   else if( "clearCalibration" == cmdLine )
  //     {
  //       clearCalibration();
  //     }
  //   else if( "startCalibration" == cmdLine )
  //     {
  //       calibrationStarted = true;
  //       cmdArgs >> std::ws;
  //       if( cmdArgs.good() )
  // 	{
  // 	  std::string cmdWait; cmdArgs>>cmdWait>>std::ws;
  // 	  if( (cmdWait == "wait")&&(cmdArgs.good()) )
  // 	    {
  // 	      double timeSec; cmdArgs >> timeSec;
  // 	      unsigned int timeMSec= (unsigned int)(round(timeSec*1000*1000));
  // 	      sotDEBUG(15) << "Calibration: wait for " << timeMSec << "us."<<std::endl;
  // 	      usleep( timeMSec );
  // 	      calibrationStarted = false;
  // 	    }
  // 	}
  //     }
  //   else if( "stopCalibration" == cmdLine )
  //     {
  //       calibrationStarted = false;
  //     }
  //   else if( "calibrateGravity" == cmdLine )
  //     {
  //       if( calibrationStarted ) 
  // 	{
  // 	  os<< "Calibration phase is on, stop it first."<<std::endl;
  // 	  return;
  // 	}
  //       ml::Vector grav = calibrateGravity( handRsensorSIN.accessCopy(),
  // 					  usingPrecompensation );
 
  //       cmdArgs >> std::ws;
  //       if( cmdArgs.good() )
  // 	{
  // 	  std::string cmdOnly; cmdArgs>>cmdOnly>>std::ws;
  // 	  if( (cmdOnly == "only")&&(cmdArgs.good()) )
  // 	    {
  // 	      std::string xyz; cmdArgs >> xyz;
  // 	      if( "x"==xyz ) { grav(1)=grav(2)=0.; }
  // 	      else if( "y"==xyz ) { grav(0)=grav(2)=0.; }
  // 	      else if( "z"==xyz ) { grav(0)=grav(1)=0.; }
  // 	    }
  // 	}

  //       gravitySIN = grav;
  //     }
  //   else if( "calibratePosition" == cmdLine )
  //     {
  //       if( calibrationStarted )
  // 	{
  // 	  return;
  //       	  os<< "Calibration phase is on, stop it first."<<std::endl;
  // 	}
  //       ml::Vector position(3);
  //       position = calibrateTransSensorCom( gravitySIN.accessCopy(), 
  // 					  handRsensorSIN.accessCopy() );
  //       transSensorComSIN = position;
  //     }
  else if( "precomp" == cmdLine )
    {
      cmdArgs>>std::ws; 
      if( cmdArgs.good() )
	{  cmdArgs >>  usingPrecompensation; } 
      else { os << "precompensation = " << usingPrecompensation <<std::endl; }
    }
  else if( "compensateMomentum" == cmdLine )
    {
      cmdArgs>>std::ws; 
      if( cmdArgs.good() )
	{
	  bool use;  cmdArgs >> use;
	  if( use ) momentumSIN.plug( &momentumSOUT );
	  else
	    {
	      ml::Vector m(6); m.resize(0); momentumSIN = m; 
	    }
	} 
      else 
	{ 
	  os << "compensateMomentum = " << (momentumSIN.getPtr()!=&momentumSIN)
	     <<std::endl; 
	}
    }
  else{ Entity::commandLine( cmdLine,cmdArgs,os ); }


}