Forked from
loco-3d / sot-talos-balance
685 commits behind the upstream repository.
-
Gabriele Buondonno authoredGabriele Buondonno authored
dcm-com-controller.cpp 9.17 KiB
/*
* Copyright 2018, Gepetto team, LAAS-CNRS
*
* This file is part of sot-talos-balance.
* sot-talos-balance 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-talos-balance 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-talos-balance. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sot/talos_balance/dcm-com-controller.hh"
#include <sot/core/debug.hh>
#include <dynamic-graph/factory.h>
#include <dynamic-graph/command-bind.h>
#include "sot/talos_balance/utils/commands-helper.hh"
#include "sot/talos_balance/utils/stop-watch.hh"
namespace dynamicgraph
{
namespace sot
{
namespace talos_balance
{
namespace dg = ::dynamicgraph;
using namespace dg;
using namespace dg::command;
//Size to be aligned "-------------------------------------------------------"
#define PROFILE_DCMCOMCONTROLLER_DDCOMREF_COMPUTATION "DcmComController: ddcomRef computation "
#define PROFILE_DCMCOMCONTROLLER_ZMPREF_COMPUTATION "DcmComController: zmpRef computation "
#define PROFILE_DCMCOMCONTROLLER_WRENCHREF_COMPUTATION "DcmComController: wrenchRef computation "
#define INPUT_SIGNALS m_KpSIN << m_KiSIN << m_decayFactorSIN << m_omegaSIN << m_massSIN << m_dcmSIN << m_dcmDesSIN << m_comDesSIN << m_ddcomDesSIN
#define OUTPUT_SIGNALS m_ddcomRefSOUT << m_zmpRefSOUT << m_wrenchRefSOUT
/// Define EntityClassName here rather than in the header file
/// so that it can be used by the macros DEFINE_SIGNAL_**_FUNCTION.
typedef DcmComController EntityClassName;
/* --- DG FACTORY ---------------------------------------------------- */
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(DcmComController,
"DcmComController");
/* ------------------------------------------------------------------- */
/* --- CONSTRUCTION -------------------------------------------------- */
/* ------------------------------------------------------------------- */
DcmComController::DcmComController(const std::string& name)
: Entity(name)
, CONSTRUCT_SIGNAL_IN(Kp, dynamicgraph::Vector)
, CONSTRUCT_SIGNAL_IN(Ki, dynamicgraph::Vector)
, CONSTRUCT_SIGNAL_IN(decayFactor, double)
, CONSTRUCT_SIGNAL_IN(omega, double)
, CONSTRUCT_SIGNAL_IN(mass, double)
, CONSTRUCT_SIGNAL_IN(dcm, dynamicgraph::Vector)
, CONSTRUCT_SIGNAL_IN(dcmDes, dynamicgraph::Vector)
, CONSTRUCT_SIGNAL_IN(comDes, dynamicgraph::Vector)
, CONSTRUCT_SIGNAL_IN(ddcomDes, dynamicgraph::Vector)
, CONSTRUCT_SIGNAL_OUT(ddcomRef, dynamicgraph::Vector, INPUT_SIGNALS)
, CONSTRUCT_SIGNAL_OUT(zmpRef, dynamicgraph::Vector, m_ddcomRefSOUT << m_comDesSIN << m_omegaSIN )
, CONSTRUCT_SIGNAL_OUT(wrenchRef, dynamicgraph::Vector, m_ddcomRefSOUT << m_comDesSIN << m_massSIN )
, m_initSucceeded(false)
{
Entity::signalRegistration( INPUT_SIGNALS << OUTPUT_SIGNALS );
/* Commands. */
addCommand("init", makeCommandVoid1(*this, &DcmComController::init, docCommandVoid1("Initialize the entity.","time step")));
addCommand("resetDcmIntegralError", makeCommandVoid0(*this, &DcmComController::resetDcmIntegralError, docCommandVoid0("Set dcm integral error to zero.")));
}
void DcmComController::init(const double & dt)
{
if(!m_KpSIN.isPlugged())
return SEND_MSG("Init failed: signal Kp is not plugged", MSG_TYPE_ERROR);
if(!m_KiSIN.isPlugged())
return SEND_MSG("Init failed: signal Ki is not plugged", MSG_TYPE_ERROR);
if(!m_decayFactorSIN.isPlugged())
return SEND_MSG("Init failed: signal decayFactor is not plugged", MSG_TYPE_ERROR);
if(!m_omegaSIN.isPlugged())
return SEND_MSG("Init failed: signal omega is not plugged", MSG_TYPE_ERROR);
if(!m_massSIN.isPlugged())
return SEND_MSG("Init failed: signal mass is not plugged", MSG_TYPE_ERROR);
if(!m_dcmSIN.isPlugged())
return SEND_MSG("Init failed: signal dcm is not plugged", MSG_TYPE_ERROR);
if(!m_dcmDesSIN.isPlugged())
return SEND_MSG("Init failed: signal dcmDes is not plugged", MSG_TYPE_ERROR);
if(!m_comDesSIN.isPlugged())
return SEND_MSG("Init failed: signal comDes is not plugged", MSG_TYPE_ERROR);
if(!m_ddcomDesSIN.isPlugged())
return SEND_MSG("Init failed: signal ddcomDes is not plugged", MSG_TYPE_ERROR);
m_dt = dt;
resetDcmIntegralError();
m_initSucceeded = true;
}
void DcmComController::resetDcmIntegralError()
{
m_dcmIntegralError.setZero(3);
}
/* ------------------------------------------------------------------- */
/* --- SIGNALS ------------------------------------------------------- */
/* ------------------------------------------------------------------- */
DEFINE_SIGNAL_OUT_FUNCTION(ddcomRef, dynamicgraph::Vector)
{
if(!m_initSucceeded)
{
SEND_WARNING_STREAM_MSG("Cannot compute signal ddcomRef before initialization!");
return s;
}
getProfiler().start(PROFILE_DCMCOMCONTROLLER_DDCOMREF_COMPUTATION);
const Vector & Kp = m_KpSIN(iter);
const Vector & Ki = m_KiSIN(iter);
const double & decayFactor = m_decayFactorSIN(iter);
const double & omega = m_omegaSIN(iter);
const Vector & dcm = m_dcmSIN(iter);
const Vector & dcmDes = m_dcmDesSIN(iter);
const Vector & ddcomDes = m_ddcomDesSIN(iter);
assert(Kp.size()==3 && "Unexpected size of signal Kp");
assert(Ki.size()==3 && "Unexpected size of signal Ki");
assert(dcm.size()==3 && "Unexpected size of signal dcm");
assert(dcmDes.size()==3 && "Unexpected size of signal dcmDes");
assert(ddcomDes.size()==3 && "Unexpected size of signal ddcomDes");
Vector dcmError = dcmDes - dcm;
m_dcmIntegralError += ( dcmError - decayFactor*m_dcmIntegralError ) * m_dt;
Vector ddcomRef = ddcomDes + omega * Kp.cwiseProduct(dcmError) + omega * Ki.cwiseProduct(m_dcmIntegralError);
s = ddcomRef;
getProfiler().stop(PROFILE_DCMCOMCONTROLLER_DDCOMREF_COMPUTATION);
return s;
}
DEFINE_SIGNAL_OUT_FUNCTION(zmpRef, dynamicgraph::Vector)
{
if(!m_initSucceeded)
{
SEND_WARNING_STREAM_MSG("Cannot compute signal zmpRef before initialization!");
return s;
}
getProfiler().start(PROFILE_DCMCOMCONTROLLER_ZMPREF_COMPUTATION);
const double & omega = m_omegaSIN(iter);
const Vector & comDes = m_comDesSIN(iter);
const Vector & ddcomRef = m_ddcomRefSOUT(iter);
assert(comDes.size()==3 && "Unexpected size of signal comDes");
Vector zmpRef = comDes - ddcomRef/(omega*omega);
s = zmpRef;
getProfiler().stop(PROFILE_DCMCOMCONTROLLER_ZMPREF_COMPUTATION);
return s;
}
DEFINE_SIGNAL_OUT_FUNCTION(wrenchRef, dynamicgraph::Vector)
{
if(!m_initSucceeded)
{
SEND_WARNING_STREAM_MSG("Cannot compute signal wrenchRef before initialization!");
return s;
}
getProfiler().start(PROFILE_DCMCOMCONTROLLER_WRENCHREF_COMPUTATION);
const double & mass = m_massSIN(iter);
const Vector & comDes = m_comDesSIN(iter);
const Vector & ddcomRef = m_ddcomRefSOUT(iter);
assert(comDes.size()==3 && "Unexpected size of signal comDes");
Vector gravity(3);
gravity << 0.0, 0.0, -9.81;
Vector forceRef = mass * ( ddcomRef - gravity );
Vector wrenchRef(6);
wrenchRef.head<3>() = forceRef;
Eigen::Vector3d comDes3 = comDes;
wrenchRef.tail<3>() = comDes3.cross(wrenchRef.head<3>());
s = wrenchRef;
getProfiler().stop(PROFILE_DCMCOMCONTROLLER_WRENCHREF_COMPUTATION);
return s;
}
/* --- COMMANDS ---------------------------------------------------------- */
/* ------------------------------------------------------------------- */
/* --- ENTITY -------------------------------------------------------- */
/* ------------------------------------------------------------------- */
void DcmComController::display(std::ostream& os) const
{
os << "DcmComController " << getName();
try
{
getProfiler().report_all(3, os);
}
catch (ExceptionSignal e) {}
}
} // namespace talos_balance
} // namespace sot
} // namespace dynamicgraph