6 #include <dynamic-graph/factory.h> 
    8 #include <sot/core/debug.hh> 
   11 #include <tsid/utils/statistics.hpp> 
   12 #include <tsid/utils/stop-watch.hpp> 
   19 using namespace dynamicgraph::command;
 
   21 using namespace dg::sot::torque_control;
 
   23 #define SAFETY_SIGNALS m_i_maxSIN << m_u_maxSIN << m_u_saturationSIN 
   24 #define INPUT_SIGNALS                                                    \ 
   25   m_i_desSIN << m_percentage_dead_zone_compensationSIN << SAFETY_SIGNALS \ 
   26              << m_i_max_dead_zone_compensationSIN << m_dqSIN             \ 
   27              << m_bemf_factorSIN << m_in_out_gainSIN << m_i_measuredSIN  \ 
   28              << m_dead_zone_offsetsSIN << m_i_sens_gainsSIN              \ 
   29              << m_i_sensor_offsets_low_levelSIN                          \ 
   30              << m_i_sensor_offsets_real_inSIN << m_kp_currentSIN         \ 
   31              << m_ki_currentSIN << m_percentage_bemf_compensationSIN 
   32 #define OUTPUT_SIGNALS                                         \ 
   33   m_uSOUT << m_u_safeSOUT << m_i_realSOUT << m_i_low_levelSOUT \ 
   34           << m_dead_zone_compensationSOUT << m_i_errorsSOUT    \ 
   35           << m_i_errors_ll_wo_bemfSOUT << m_i_sensor_offsets_real_outSOUT 
   61       CONSTRUCT_SIGNAL_IN(percentage_bemf_compensation, 
dynamicgraph::Vector),
 
   62       CONSTRUCT_SIGNAL_IN(dead_zone_offsets, 
dynamicgraph::Vector),
 
   63       CONSTRUCT_SIGNAL_IN(percentage_dead_zone_compensation,
 
   65       CONSTRUCT_SIGNAL_IN(i_max_dead_zone_compensation, 
dynamicgraph::Vector),
 
   66       CONSTRUCT_SIGNAL_IN(i_sensor_offsets_low_level, 
dynamicgraph::Vector),
 
   67       CONSTRUCT_SIGNAL_IN(i_sensor_offsets_real_in, 
dynamicgraph::Vector),
 
   68       CONSTRUCT_SIGNAL_OUT(u, 
dynamicgraph::Vector, m_i_desSIN),
 
   72                                          << m_i_sensor_offsets_real_outSOUT),
 
   74                            m_i_measuredSIN << m_i_sens_gainsSIN
 
   75                                            << m_i_sensor_offsets_real_outSOUT),
 
   77                            m_i_measuredSIN << m_i_sens_gainsSIN
 
   78                                            << m_i_sensor_offsets_low_levelSIN),
 
   79       CONSTRUCT_SIGNAL_OUT(i_sensor_offsets_real_out, 
dynamicgraph::Vector,
 
   80                            m_i_measuredSIN << m_i_sensor_offsets_real_inSIN),
 
   81       CONSTRUCT_SIGNAL_OUT(dead_zone_compensation, 
dynamicgraph::Vector,
 
   82                            m_u_safeSOUT << m_dead_zone_offsetsSIN),
 
   84                            m_i_realSOUT << m_uSOUT),
 
   85       CONSTRUCT_SIGNAL_OUT(i_errors_ll_wo_bemf, 
dynamicgraph::Vector,
 
   86                            m_i_realSOUT << m_uSOUT
 
   87                                         << m_percentage_bemf_compensationSIN
 
   88                                         << m_dqSIN << m_bemf_factorSIN),
 
   89       m_robot_util(RefVoidRobotUtil()),
 
   90       m_initSucceeded(false),
 
   91       m_emergency_stop_triggered(false),
 
   92       m_is_first_iter(true),
 
   97   addCommand(
"init", makeCommandVoid3(
 
  100                              "Initialize the entity.",
 
  101                              "Time period in seconds (double)",
 
  102                              "Robot reference (string)",
 
  103                              "Number of iterations while control is disabled " 
  104                              "to calibrate current sensors (int)")));
 
  106   addCommand(
"reset_integral",
 
  108                               docCommandVoid0(
"Reset the integral error.")));
 
  112                              const unsigned int& currentOffsetIters) {
 
  113   if (dt <= 0.0) 
return SEND_MSG(
"Timestep must be positive", MSG_TYPE_ERROR);
 
  118   std::string localName(robotRef);
 
  119   if (!isNameInRobotUtil(localName)) {
 
  137   if (!m_initSucceeded) {
 
  138     SEND_WARNING_STREAM_MSG(
"Cannot compute signal u before initialization!");
 
  142   if (m_is_first_iter) m_is_first_iter = 
false;
 
  144   if (s.size() != (Eigen::VectorXd::Index)m_robot_util->m_nbJoints)
 
  145     s.resize(m_robot_util->m_nbJoints);
 
  147   const dynamicgraph::Vector& i_des = m_i_desSIN(iter);
 
  148   const dynamicgraph::Vector& i_real = m_i_realSOUT(iter);
 
  149   const dynamicgraph::Vector& i_ll = m_i_low_levelSOUT(iter);
 
  150   const dynamicgraph::Vector& cur_sens_gains = m_i_sens_gainsSIN(iter);
 
  151   const dynamicgraph::Vector& i_offset_real =
 
  152       m_i_sensor_offsets_real_outSOUT(iter);
 
  153   const dynamicgraph::Vector& dq = m_dqSIN(iter);
 
  156   const dynamicgraph::Vector& dead_zone_offsets = m_dead_zone_offsetsSIN(iter);
 
  157   const dynamicgraph::Vector& dead_zone_comp_perc =
 
  158       m_percentage_dead_zone_compensationSIN(iter);
 
  159   const dynamicgraph::Vector& bemf_factor = m_bemf_factorSIN(iter);
 
  160   const dynamicgraph::Vector& bemf_comp_perc =
 
  161       m_percentage_bemf_compensationSIN(iter);
 
  162   const dynamicgraph::Vector& i_max_dz_comp =
 
  163       m_i_max_dead_zone_compensationSIN(iter);
 
  164   const dynamicgraph::Vector& kp = m_kp_currentSIN(iter);
 
  165   const dynamicgraph::Vector& ki = m_ki_currentSIN(iter);
 
  167   m_i_err_integr += ki.cwiseProduct(i_des - i_real);
 
  169   s = i_des + m_i_err_integr;            
 
  170   s += kp.cwiseProduct(i_des - i_real);  
 
  172       cur_sens_gains.cwiseProduct(i_offset_real);  
 
  173   s += bemf_comp_perc.cwiseProduct(
 
  174       bemf_factor.cwiseProduct(dq));  
 
  176   for (
unsigned int i = 0; i < m_robot_util->m_nbJoints; i++) {
 
  177     double err = s(i) - i_ll(i);
 
  178     if (err > i_max_dz_comp(i))
 
  180     else if (err < -i_max_dz_comp(i))
 
  181       m_dz_coeff(i) = -1.0;
 
  183       m_dz_coeff(i) = err / i_max_dz_comp(i);
 
  187   s += m_dz_coeff.cwiseProduct(
 
  188       dead_zone_comp_perc.cwiseProduct(dead_zone_offsets));
 
  192   if (m_emergency_stop_triggered ||
 
  193       m_iter < 
static_cast<int>(m_currentOffsetIters))
 
  200   if (!m_initSucceeded) {
 
  201     SEND_WARNING_STREAM_MSG(
 
  202         "Cannot compute signal u_safe before initialization!");
 
  206   const dynamicgraph::Vector& u = m_uSOUT(iter);
 
  207   const dynamicgraph::Vector& u_max = m_u_maxSIN(iter);
 
  208   const dynamicgraph::Vector& u_saturation = m_u_saturationSIN(iter);
 
  209   const dynamicgraph::Vector& i_real = m_i_realSOUT(iter);
 
  210   const dynamicgraph::Vector& in_out_gain = m_in_out_gainSIN(iter);
 
  212   if (s.size() != 
static_cast<Eigen::VectorXd::Index
>(m_robot_util->m_nbJoints))
 
  213     s.resize(m_robot_util->m_nbJoints);
 
  215   for (
unsigned int i = 0; i < m_robot_util->m_nbJoints; i++) {
 
  216     double i_max = m_i_maxSIN(iter)(i);
 
  217     if ((fabs(i_real(i)) > i_max)) {
 
  218       m_emergency_stop_triggered = 
true;
 
  219       SEND_MSG(
"Joint " + m_robot_util->get_name_from_id(i) +
 
  220                    " measured current is too large: " + toString(i_real(i)) +
 
  221                    "A > " + toString(i_max) + 
"A",
 
  225     if (fabs(u(i)) > u_max(i)) {
 
  226       m_emergency_stop_triggered = 
true;
 
  227       SEND_MSG(
"Joint " + m_robot_util->get_name_from_id(i) +
 
  228                    " control is too large: " + toString(u(i)) + 
"A > " +
 
  229                    toString(u_max(i)) + 
"A",
 
  233     s(i) = u(i) * in_out_gain(i);
 
  236     if (s(i) > u_saturation(i))
 
  237       s(i) = u_saturation(i);
 
  238     else if (s(i) < -u_saturation(i))
 
  239       s(i) = -u_saturation(i);
 
  243   if (m_emergency_stop_triggered ||
 
  244       m_iter < 
static_cast<int>(m_currentOffsetIters))
 
  251   if (!m_initSucceeded) {
 
  252     SEND_WARNING_STREAM_MSG(
 
  253         "Cannot compute signal i_real before initialization!");
 
  256   s = m_i_measuredSIN(iter);
 
  259   const dynamicgraph::Vector& offset = m_i_sensor_offsets_real_outSOUT(iter);
 
  263   const dynamicgraph::Vector& K = m_i_sens_gainsSIN(iter);
 
  264   s = s.cwiseProduct(K);
 
  270   if (!m_initSucceeded) {
 
  271     SEND_WARNING_STREAM_MSG(
 
  272         "Cannot compute signal currents_low_level before initialization!");
 
  275   s = m_i_measuredSIN(iter);
 
  277   const dynamicgraph::Vector& i_offsets_low_level =
 
  278       m_i_sensor_offsets_low_levelSIN(iter);
 
  279   s -= i_offsets_low_level;
 
  281   const dynamicgraph::Vector& K = m_i_sens_gainsSIN(iter);
 
  282   s = s.cwiseProduct(K);
 
  287   if (!m_initSucceeded) {
 
  288     SEND_WARNING_STREAM_MSG(
 
  289         "Cannot compute signal i_sensor_offsets_real_out before " 
  293   const dynamicgraph::Vector& currents = m_i_measuredSIN(iter);
 
  296   if (m_currentOffsetIters > 0) {
 
  297     if (m_iter < 
static_cast<int>(m_currentOffsetIters))
 
  298       m_i_offsets_real += (currents - m_i_offsets_real) / (m_iter + 1);
 
  299     else if (m_iter == 
static_cast<int>(m_currentOffsetIters)) {
 
  300       SEND_MSG(
"Current sensor offsets computed in " + toString(m_iter) +
 
  301                    " iterations: " + toString(m_i_offsets_real),
 
  303       for (
int i = 0; i < s.size(); i++)
 
  304         if (fabs(m_i_offsets_real(i)) > 0.6) {
 
  306               "Current offset for joint " + m_robot_util->get_name_from_id(i) +
 
  307                   " is too large, suggesting that the sensor may be broken: " +
 
  308                   toString(m_i_offsets_real(i)),
 
  310           m_i_offsets_real(i) = 0.0;
 
  316   if (m_i_sensor_offsets_real_inSIN.isPlugged())
 
  317     s = m_i_sensor_offsets_real_inSIN(iter);
 
  319     s = m_i_offsets_real;
 
  325   if (!m_initSucceeded) {
 
  326     SEND_WARNING_STREAM_MSG(
 
  327         "Cannot compute signal dead_zone_compensation before initialization!");
 
  330   const dynamicgraph::Vector& dead_zone_offsets = m_dead_zone_offsetsSIN(iter);
 
  332   s = m_dz_coeff.cwiseProduct(dead_zone_offsets);
 
  337   if (!m_initSucceeded) {
 
  338     SEND_WARNING_STREAM_MSG(
 
  339         "Cannot compute signal i_errors before initialization!");
 
  342   const dynamicgraph::Vector& u = m_uSOUT(iter);
 
  343   const dynamicgraph::Vector& currents = m_i_realSOUT(iter);
 
  349   if (!m_initSucceeded) {
 
  350     SEND_WARNING_STREAM_MSG(
 
  351         "Cannot compute signal i_errors_ll_wo_bemf before initialization!");
 
  354   const dynamicgraph::Vector& u = m_uSOUT(iter);
 
  355   const dynamicgraph::Vector& currents = m_i_realSOUT(iter);
 
  356   const dynamicgraph::Vector& bemfFactor = m_bemf_factorSIN(iter);
 
  357   const dynamicgraph::Vector& bemf_comp_perc =
 
  358       m_percentage_bemf_compensationSIN(iter);
 
  359   const dynamicgraph::Vector& dq = m_dqSIN(iter);
 
  362       (dynamicgraph::Vector::Ones(m_robot_util->m_nbJoints) - bemf_comp_perc)
 
  363           .cwiseProduct(bemfFactor.cwiseProduct(dq));
 
  365   for (
int i = 0; i < s.size(); i++)
 
  367       m_avg_i_err_pos(i) += (s(i) - m_avg_i_err_pos(i)) * 1e-3;
 
  369       m_avg_i_err_neg(i) += (s(i) - m_avg_i_err_neg(i)) * 1e-3;
 
  383   os << 
"CurrentController " << getName();
 
  385     getProfiler().report_all(3, os);
 
  386   } 
catch (ExceptionSignal e) {
 
dynamicgraph::Vector m_dz_coeff
 
dynamicgraph::Vector m_i_offsets_real
 
RobotUtilShrPtr m_robot_util
 
void init(const double &dt, const std::string &robotRef, const unsigned int ¤tOffsetIters)
 
dynamicgraph::Vector m_i_err_integr
 
dynamicgraph::Vector m_avg_i_err_neg
 
dynamicgraph::Vector m_avg_i_err_pos
 
CurrentController(const std::string &name)
 
virtual void display(std::ostream &os) const
 
void reset_integral()
current tracking error without BEMF effect
 
unsigned int m_currentOffsetIters
 
DEFINE_SIGNAL_OUT_FUNCTION(u, dynamicgraph::Vector)
 
AdmittanceController EntityClassName
 
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(AdmittanceController, "AdmittanceController")