/***************************************************************************
 *   Copyright (C) 2005 by Robot Group Leipzig                             *
 *    martius@informatik.uni-leipzig.de                                    *
 *    fhesse@informatik.uni-leipzig.de                                     *
 *    der@informatik.uni-leipzig.de                                        *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 *                                                                         *
 *   $Log: deprivation.h,v $
 *   Revision 1.1.2.3  2006/03/29 15:11:19  martius
 *   damping is now in invertmotornstep
 *
 *   Revision 1.1.2.2  2006/02/20 10:56:21  martius
 *   lowered damping
 *
 *   Revision 1.1.2.1  2006/02/14 10:27:11  martius
 *   investigation about deprivation of worldmodel
 *
 *   Revision 1.1.2.1  2006/02/08 15:14:49  martius
 *   new version of proactive which uses direct H feeding
 *
 *
 ***************************************************************************/
#ifndef __DEPRIVATION_H
#define __DEPRIVATION_H

#include "invertmotornstep.h"
#include "onelayerffnn.h"

#include <assert.h>
#include <math.h>

#include "matrix.h"

/**
 * robot controller for self-organized behaviour 
 * just like invertmotornstep, 
 *  just that is enables us to execute the same motor commands for a long time
 */
class Deprivation : public InvertMotorNStep {
public:
  /// is called with current motor values and returns new motor values
  typedef matrix::Matrix (*MotorCallback)(const matrix::Matrix& y);

  /// is called with current controller matrix C and bias H which can be alterned
  typedef void (*ControllerCallback)(matrix::Matrix& C, matrix::Matrix& H);

  /**
   */
  Deprivation(MotorCallback motorCallback, ControllerCallback controllerCallback =0, 
	      const InvertMotorNStepConf& conf = getDefaultConf())
    : InvertMotorNStep(conf), motorCallback(motorCallback), controllerCallback(controllerCallback) {
    assert(motorCallback);
    // prepare name;
    Configurable::insertCVSInfo(name, "$RCSfile: deprivation.h,v $", "$Revision: 1.1.2.3 $");
    useExternal=false;
  }

  virtual ~Deprivation(){
  }

  virtual void setExternalControlMode(bool useExternal){
    this->useExternal=useExternal;
    if(controllerCallback && initialised){
      controllerCallback(C, H);
    }    
  }
  virtual bool getExternalControlMode(){
    return useExternal;
  }
  
  
protected:
  /// overloaded 
  virtual void learnController(){
    if(!useExternal){      
      InvertMotorNStep::learnController();
    }
  }

  /// calculate controller outputs (only of nop external value is set)
  /// @param x_smooth smoothed sensors Matrix(number_channels,1) 
  virtual matrix::Matrix calculateControllerValues(const Matrix& x_smooth){
    Matrix y = InvertMotorNStep::calculateControllerValues(x_smooth);
    if(useExternal){
      return motorCallback(y);      
    }
    else
      return y;
  };
  
protected:
  bool useExternal;

  MotorCallback motorCallback;
  ControllerCallback controllerCallback;

};

#endif
