Skip to content
Snippets Groups Projects
controller-pd.cpp 9.26 KiB
Newer Older
Nicolas Mansard's avatar
Nicolas Mansard committed
/*
 * Copyright 2011, Nicolas Mansard, LAAS-CNRS
 *
 * This file is part of sot-dyninv.
 * sot-dyninv is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 * sot-dyninv is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.  You should
 * have received a copy of the GNU Lesser General Public License along
 * with sot-dyninv.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <sot-dyninv/controller-pd.h>
#include <sot-core/debug.h>
#include <dynamic-graph/factory.h>

Nicolas Mansard's avatar
Nicolas Mansard committed
#include <sot-dyninv/commands-helper.h>
Nicolas Mansard's avatar
Nicolas Mansard committed

namespace sot
{
  namespace dyninv
  {

Nicolas Mansard's avatar
Nicolas Mansard committed

    namespace dg = ::dynamicgraph;
Nicolas Mansard's avatar
Nicolas Mansard committed
    using namespace dg;

Nicolas Mansard's avatar
Nicolas Mansard committed
    /* --- DG FACTORY ------------------------------------------------------- */
Nicolas Mansard's avatar
Nicolas Mansard committed
    DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(ControllerPD,"ControllerPD");

Nicolas Mansard's avatar
Nicolas Mansard committed
    /* --- CONSTRUCTION ----------------------------------------------------- */
    /* --- CONSTRUCTION ----------------------------------------------------- */
    /* --- CONSTRUCTION ----------------------------------------------------- */
Nicolas Mansard's avatar
Nicolas Mansard committed
    ControllerPD::
    ControllerPD( const std::string & name )
Nicolas Mansard's avatar
Nicolas Mansard committed
      : Entity(name)

      ,CONSTRUCT_SIGNAL_IN(Kp,ml::Vector)
      ,CONSTRUCT_SIGNAL_IN(Kd,ml::Vector)
      ,CONSTRUCT_SIGNAL_IN(position,ml::Vector)
      ,CONSTRUCT_SIGNAL_IN(positionRef,ml::Vector)
      ,CONSTRUCT_SIGNAL_IN(velocity,ml::Vector)
      ,CONSTRUCT_SIGNAL_IN(velocityRef,ml::Vector)

      ,CONSTRUCT_SIGNAL_OUT(control,ml::Vector,
       			    KpSIN << KdSIN << positionSIN << positionRefSIN
       			    << velocitySIN << velocityRefSIN )
Nicolas Mansard's avatar
Nicolas Mansard committed
    {
Nicolas Mansard's avatar
Nicolas Mansard committed
      Entity::signalRegistration( KpSIN << KdSIN << positionSIN << positionRefSIN
				  << velocitySIN << velocityRefSIN
				  << controlSOUT );
Nicolas Mansard's avatar
Nicolas Mansard committed

Nicolas Mansard's avatar
Nicolas Mansard committed
      /* Commands. */
      addCommand("getSize",
		 makeDirectGetter(*this,&_dimension,
				  docDirectGetter("dimension","int")));

      addCommand("setSize",
		 makeDirectSetter(*this, &_dimension,
Nicolas Mansard's avatar
Nicolas Mansard committed
				  docDirectSetter("dimension","int")));

      addCommand("velocityOnly",
		 makeCommandVoid0(*this,&ControllerPD::setGainVelocityOnly,
				  docCommandVoid0("Set a friction-style controller.")));

      addCommand("stdGain",
		 makeCommandVoid1(*this,&ControllerPD::setStandardGains,
				  docCommandVoid1("Set spefic gains.",
						  "string (in low|medium|high)")));

Nicolas Mansard's avatar
Nicolas Mansard committed
    }

Nicolas Mansard's avatar
Nicolas Mansard committed

    /* --- SIGNALS ---------------------------------------------------------- */
    /* --- SIGNALS ---------------------------------------------------------- */
    /* --- SIGNALS ---------------------------------------------------------- */

Nicolas Mansard's avatar
Nicolas Mansard committed
    ml::Vector& ControllerPD::
Nicolas Mansard's avatar
Nicolas Mansard committed
    controlSOUT_function( ml::Vector &tau, int iter )
Nicolas Mansard's avatar
Nicolas Mansard committed
    {
      sotDEBUGIN(15);
Nicolas Mansard's avatar
Nicolas Mansard committed
      const ml::Vector& Kp = KpSIN(iter);
      const ml::Vector& Kd = KdSIN(iter);
      const ml::Vector& position = positionSIN(iter);
      const ml::Vector& desiredposition = positionRefSIN(iter);
      const unsigned int size = Kp.size();

      assert( _dimension == (int)size );
      assert( size==Kp.size() );        assert( size==Kd.size() );
      assert( size==position.size() );  assert( size==desiredposition.size() );

      bool useVelocity = velocitySIN;
      ml::Vector velocity;
      bool useVelocityDesired = false;
      ml::Vector desiredvelocity;
      if( useVelocity ) // TODO: there is a useless copy here. Use a pointer?
Nicolas Mansard's avatar
Nicolas Mansard committed
	{
Nicolas Mansard's avatar
Nicolas Mansard committed
	  velocity = velocitySIN(iter);
	  assert( size==velocity.size() );
	  useVelocityDesired = velocityRefSIN;
	  if( useVelocityDesired )
	    {
	      desiredvelocity = velocityRefSIN(iter);
	      assert( size==desiredvelocity.size() );
	    }
Nicolas Mansard's avatar
Nicolas Mansard committed
	}
Nicolas Mansard's avatar
Nicolas Mansard committed

      tau.resize(size); double dv; // TODO: use dv from start to avoid the copy.
      for(unsigned i = 0u; i < size; ++i)
Nicolas Mansard's avatar
Nicolas Mansard committed
	{
Nicolas Mansard's avatar
Nicolas Mansard committed
	  tau(i) = Kp(i)*(desiredposition(i)-position(i));
	  if( useVelocity )
	    {
	      dv= velocity(i);
	      if( useVelocityDesired )
		dv-=desiredvelocity(i);
	      tau(i) -= Kd(i)*dv;
	    }
Nicolas Mansard's avatar
Nicolas Mansard committed
	}

Nicolas Mansard's avatar
Nicolas Mansard committed
      sotDEBUG(15) << "p = " << position << std::endl;
      sotDEBUG(15) << "pd = " << desiredposition << std::endl;
      if( useVelocity ) {sotDEBUG(15) << "v= " << velocity << std::endl;}
      if( useVelocityDesired ) { sotDEBUG(15) << "vd= " << velocity << std::endl; }
      sotDEBUG(15) << "kp = " << Kp << std::endl;
      sotDEBUG(15) << "kd = " << Kd << std::endl;
      sotDEBUG(15) << "PD torque= " << tau << std::endl;
Nicolas Mansard's avatar
Nicolas Mansard committed

      sotDEBUGOUT(15);
Nicolas Mansard's avatar
Nicolas Mansard committed
      return tau;
Nicolas Mansard's avatar
Nicolas Mansard committed
    }


Nicolas Mansard's avatar
Nicolas Mansard committed
    /* --- COMMANDS ---------------------------------------------------------- */
    /* --- MEMBERS ---------------------------------------------------------- */
    void ControllerPD::
    size(const int & dimension)
Nicolas Mansard's avatar
Nicolas Mansard committed
    {
Nicolas Mansard's avatar
Nicolas Mansard committed
      _dimension = dimension;
Nicolas Mansard's avatar
Nicolas Mansard committed
    }

Nicolas Mansard's avatar
Nicolas Mansard committed
    int ControllerPD::
    size(void) const
Nicolas Mansard's avatar
Nicolas Mansard committed
    {
Nicolas Mansard's avatar
Nicolas Mansard committed
      return _dimension;
Nicolas Mansard's avatar
Nicolas Mansard committed
    }

    void ControllerPD::
    setGainVelocityOnly( void )
    {
      ml::Vector zero(_dimension); zero.fill(0);
      positionSIN = zero;
      positionRefSIN = zero;
      KpSIN = zero;
    }

    /** Give some specific values for the Kp and Kd gains. Possible
     * configs are "low", "middle" and "high".
     * Warning: middle and high only works for dim 30.
     * TODO: properly throw errors when needed.
     */
    void ControllerPD::
    setStandardGains( const std::string & config )
    {

      if( config =="low" )
	{
	  // Low gains
	  ml::Vector Kp(_dimension); Kp.fill(100);
	  ml::Vector Kd(_dimension); Kd.fill(20);
	  KpSIN = Kp;
	  KdSIN = Kd;
	}
      else if( config =="medium" )
	{
	  // Medium gains
	  if( _dimension != 30 )
	    { std::cerr << "Only working for dim=30!" << std::endl; return; }

	  ml::Vector Kp(_dimension),Kd(_dimension);
	  unsigned int i=0;
	  Kp(i++)=400;   Kp(i++)=1000; Kp(i++)=2000;  Kp(i++)=1800;  Kp(i++)=2000;
	  Kp(i++)=1000;  Kp(i++)=400;  Kp(i++)=1000;  Kp(i++)=2000;  Kp(i++)=1800;
	  Kp(i++)=2000;  Kp(i++)=1000; Kp(i++)=500;  Kp(i++)=250;  Kp(i++)=200;
	  Kp(i++)=200;   Kp(i++)=300;  Kp(i++)=300;  Kp(i++)=200;  Kp(i++)=400;
	  Kp(i++)=400;   Kp(i++)=200;  Kp(i++)=200;  Kp(i++)=300;  Kp(i++)= 300;
	  Kp(i++)=200;   Kp(i++)=400;  Kp(i++)=400;  Kp(i++)=200;  Kp(i++)=200;

	  i=0;
	  Kd(i++)=40;  Kd(i++)=100;  Kd(i++)=200;  Kd(i++)=180;  Kd(i++)=200;
	  Kd(i++)=100; Kd(i++)=40;   Kd(i++)=100;  Kd(i++)=200;  Kd(i++)=180;
	  Kd(i++)=200; Kd(i++)=100;  Kd(i++)=50;   Kd(i++)=25;   Kd(i++)=20;
	  Kd(i++)=20;  Kd(i++)=30;   Kd(i++)=30;   Kd(i++)=20;   Kd(i++)=40;
	  Kd(i++)=40;  Kd(i++)=20;   Kd(i++)=20;   Kd(i++)=30;   Kd(i++)= 30;
	  Kd(i++)=20;  Kd(i++)=40;   Kd(i++)=40;   Kd(i++)=20;   Kd(i++)=20;

	  KpSIN = Kp;
	  KdSIN = Kd;
	}
      else // high
	{
	  // High gains
	  if( _dimension != 30 )
	    { std::cerr << "Only working for dim=30!" << std::endl; return; }

	  ml::Vector Kp(_dimension),Kd(_dimension);
	  unsigned int i=0;
	  Kp(i++)=4000;  Kp(i++)=10000; Kp(i++)=20000; Kp(i++)=18000;  Kp(i++)=20000;
	  Kp(i++)=10000; Kp(i++)=4000;  Kp(i++)=10000; Kp(i++)=20000;  Kp(i++)=18000;
	  Kp(i++)=20000; Kp(i++)=10000; Kp(i++)=5000;  Kp(i++)=2500;   Kp(i++)=2000;
	  Kp(i++)=2000;  Kp(i++)=3000;  Kp(i++)=3000;  Kp(i++)=2000;   Kp(i++)=4000;
	  Kp(i++)=4000;  Kp(i++)=2000;  Kp(i++)=2000;  Kp(i++)=3000;   Kp(i++)= 3000;
	  Kp(i++)=2000;  Kp(i++)=4000;  Kp(i++)=4000;  Kp(i++)=2000;   Kp(i++)=2000;

	  i=0;
	  Kd(i++)=120;   Kd(i++)=300;   Kd(i++)=600;   Kd(i++)=500;    Kd(i++)=600;
	  Kd(i++)=300;   Kd(i++)=120;   Kd(i++)=300;   Kd(i++)=600;    Kd(i++)=500;
	  Kd(i++)=600;   Kd(i++)=300;   Kd(i++)=150;   Kd(i++)=75;     Kd(i++)=60;
	  Kd(i++)=60;    Kd(i++)=90;    Kd(i++)=90;    Kd(i++)=60;     Kd(i++)=120;
	  Kd(i++)=120;   Kd(i++)=60;    Kd(i++)=60;    Kd(i++)=90;     Kd(i++)= 90;
	  Kd(i++)=60;    Kd(i++)=120;   Kd(i++)=120;   Kd(i++)=60;     Kd(i++)=60;

	  KpSIN = Kp;
	  KdSIN = Kd;
	}
    }
Nicolas Mansard's avatar
Nicolas Mansard committed
    /* --- ENTITY ----------------------------------------------------------- */
    /* --- ENTITY ----------------------------------------------------------- */
    /* --- ENTITY ----------------------------------------------------------- */
Nicolas Mansard's avatar
Nicolas Mansard committed

Nicolas Mansard's avatar
Nicolas Mansard committed
    void ControllerPD::
    display( std::ostream& os ) const
Nicolas Mansard's avatar
Nicolas Mansard committed
    {
Nicolas Mansard's avatar
Nicolas Mansard committed
      os << "ControllerPD "<<getName();
      try
	{
	  os <<"control = "<<controlSOUT;
Nicolas Mansard's avatar
Nicolas Mansard committed
	}
Nicolas Mansard's avatar
Nicolas Mansard committed
      catch (ExceptionSignal e) {}
Nicolas Mansard's avatar
Nicolas Mansard committed
    }

    void ControllerPD::
    commandLine( const std::string& cmdLine,
		 std::istringstream& cmdArgs,
		 std::ostream& os )
    {
      if( cmdLine == "help" )
	{
Nicolas Mansard's avatar
Nicolas Mansard committed
	  os << "sotControlPD:\n"
	     << " - size <arg>\t\tset the size of the vector.\n"
	     << " - stdGain \t\tset the input vector gains according to the size for HRP2.\n"
	     << " - velocityonly <arg>\t\tset Kp = 0.\n"
	     << std::endl;
Nicolas Mansard's avatar
Nicolas Mansard committed
	}
Nicolas Mansard's avatar
Nicolas Mansard committed
      else if( cmdLine == "size" )
Nicolas Mansard's avatar
Nicolas Mansard committed
	{
Nicolas Mansard's avatar
Nicolas Mansard committed
	  cmdArgs >> std::ws;
	  if( cmdArgs.good() )
	    {
	      unsigned int i; cmdArgs >> i ;
	      size(i);
	    }
	  else
Nicolas Mansard's avatar
Nicolas Mansard committed
	    {
Nicolas Mansard's avatar
Nicolas Mansard committed
	      os << "size = " << size() << std::endl;
	    }
	}
      else if( cmdLine == "velocityonly" )
	{ setGainVelocityOnly(); }
Nicolas Mansard's avatar
Nicolas Mansard committed
      else if( cmdLine == "stdGain" )
	{
	  std::string config = "high";
	  cmdArgs >> std::ws; if( cmdArgs.good() ) cmdArgs >> config;
	  setStandardGains( config );
Nicolas Mansard's avatar
Nicolas Mansard committed
	}
      else
	{
	  Entity::commandLine(cmdLine,cmdArgs,os);
Nicolas Mansard's avatar
Nicolas Mansard committed
	}
    }

Nicolas Mansard's avatar
Nicolas Mansard committed
  } // namespace dyninv
} // namespace sot