6 #include <dynamic-graph/factory.h> 
    8 #include <sot/core/debug.hh> 
   11 #include <tsid/robots/robot-wrapper.hpp> 
   12 #include <tsid/utils/statistics.hpp> 
   13 #include <tsid/utils/stop-watch.hpp> 
   22 using namespace dynamicgraph::command;
 
   24 using namespace dg::sot::torque_control;
 
   27 #define PROFILE_PWM_DESIRED_COMPUTATION \ 
   29 #define PROFILE_DYNAMIC_GRAPH_PERIOD \ 
   32 #define INPUT_SIGNALS                                                        \ 
   33   m_i_maxSIN << m_u_maxSIN << m_tau_maxSIN << m_tauSIN << m_tau_predictedSIN \ 
   35 #define OUTPUT_SIGNALS m_uSOUT << m_u_safeSOUT 
   47 ControlManager::ControlManager(
const std::string& name)
 
   51       CONSTRUCT_SIGNAL_IN(tau_predicted, 
dynamicgraph::Vector),
 
   55       CONSTRUCT_SIGNAL_OUT(u, 
dynamicgraph::Vector, m_i_measuredSIN),
 
   58       m_robot_util(RefVoidRobotUtil()),
 
   59       m_initSucceeded(false),
 
   60       m_emergency_stop_triggered(false),
 
   61       m_is_first_iter(true),
 
   69                               docCommandVoid3(
"Initialize the entity.",
 
   70                                               "Time period in seconds (double)",
 
   71                                               "URDF file path (string)",
 
   72                                               "Robot reference (string)")));
 
   73   addCommand(
"addCtrlMode",
 
   76                  docCommandVoid1(
"Create an input signal with name 'ctrl_x' " 
   77                                  "where x is the specified name.",
 
   84           docCommandVoid0(
"Get a list of all the available control modes.")));
 
   90           docCommandVoid2(
"Set the control mode for a joint.",
 
   91                           "(string) joint name", 
"(string) control mode")));
 
   96                        docCommandVoid1(
"Get the control mode of a joint.",
 
   97                                        "(string) joint name")));
 
   99   addCommand(
"resetProfiler",
 
  102                  docCommandVoid0(
"Reset the statistics computed by the " 
  103                                  "profiler (print this entity to see them).")));
 
  105   addCommand(
"setNameToId",
 
  108                  docCommandVoid2(
"Set map for a name to an Id",
 
  109                                  "(string) joint name", 
"(double) joint id")));
 
  112       "setForceNameToForceId",
 
  116               "Set map from a force sensor name to a force sensor Id",
 
  117               "(string) force sensor name", 
"(double) force sensor id")));
 
  119   addCommand(
"setJointLimitsFromId",
 
  122                  docCommandVoid3(
"Set the joint limits for a given joint ID",
 
  123                                  "(double) joint id", 
"(double) lower limit",
 
  124                                  "(double) uppper limit")));
 
  127       "setForceLimitsFromId",
 
  130           docCommandVoid3(
"Set the force limits for a given force sensor ID",
 
  131                           "(double) force sensor id", 
"(double) lower limit",
 
  132                           "(double) uppper limit")));
 
  135       "setJointsUrdfToSot",
 
  137                        docCommandVoid1(
"Map Joints From URDF to SoT.",
 
  138                                        "Vector of integer for mapping")));
 
  141       "setRightFootSoleXYZ",
 
  143                        docCommandVoid1(
"Set the right foot sole 3d position.",
 
  144                                        "Vector of 3 doubles")));
 
  146       "setRightFootForceSensorXYZ",
 
  148                        docCommandVoid1(
"Set the right foot sensor 3d position.",
 
  149                                        "Vector of 3 doubles")));
 
  151   addCommand(
"setFootFrameName",
 
  154                  docCommandVoid2(
"Set the Frame Name for the Foot Name.",
 
  155                                  "(string) Foot name", 
"(string) Frame name")));
 
  156   addCommand(
"setHandFrameName",
 
  159                  docCommandVoid2(
"Set the Frame Name for the Hand Name.",
 
  160                                  "(string) Hand name", 
"(string) Frame name")));
 
  161   addCommand(
"setImuJointName",
 
  164                  docCommandVoid1(
"Set the Joint Name wich IMU is attached to.",
 
  165                                  "(string) Joint name")));
 
  166   addCommand(
"displayRobotUtil",
 
  169                  docCommandVoid0(
"Display the current robot util data set.")));
 
  172       "setStreamPrintPeriod",
 
  175           docCommandVoid1(
"Set the period used for printing in streaming.",
 
  176                           "Print period in seconds (double)")));
 
  181                        docCommandVoid1(
"Set the time to sleep at every " 
  182                                        "iteration (to slow down simulation).",
 
  183                                        "Sleep time in seconds (double)")));
 
  186       "addEmergencyStopSIN",
 
  189           docCommandVoid1(
"Add emergency signal input from another entity that " 
  190                           "can stop the control if necessary.",
 
  191                           "(string) signal name : 'emergencyStop_' + name")));
 
  195                           const std::string& robotRef) {
 
  196   if (dt <= 0.0) 
return SEND_MSG(
"Timestep must be positive", MSG_TYPE_ERROR);
 
  200   vector<string> package_dirs;
 
  201   m_robot = 
new robots::RobotWrapper(urdfFile, package_dirs,
 
  202                                      pinocchio::JointModelFreeFlyer());
 
  203   std::string localName(robotRef);
 
  204   if (!isNameInRobotUtil(localName)) {
 
  206     SEND_MSG(
"createRobotUtil success\n", MSG_TYPE_INFO);
 
  209     SEND_MSG(
"getRobotUtil success\n", MSG_TYPE_INFO);
 
  214       "getJointsUrdfToSot",
 
  215       makeDirectGetter(*
this, &
m_robot_util->m_dgv_urdf_to_sot,
 
  216                        docDirectSetter(
"Display map Joints From URDF to SoT.",
 
  217                                        "Vector of integer for mapping")));
 
  230   if (!m_initSucceeded) {
 
  231     SEND_WARNING_STREAM_MSG(
"Cannot compute signal u before initialization!");
 
  236     m_is_first_iter = 
false;
 
  241   if (s.size() != (Eigen::VectorXd::Index)m_robot_util->m_nbJoints)
 
  242     s.resize(m_robot_util->m_nbJoints);
 
  247     for (
unsigned int i = 0; i < m_ctrlInputsSIN.size(); i++)
 
  248       (*m_ctrlInputsSIN[i])(iter);
 
  250     int cm_id, cm_id_prev;
 
  251     for (
unsigned int i = 0; i < m_robot_util->m_nbJoints; i++) {
 
  252       cm_id = m_jointCtrlModes_current[i].id;
 
  254         SEND_MSG(
"You forgot to set the control mode of joint " + toString(i),
 
  255                  MSG_TYPE_ERROR_STREAM);
 
  259       const dynamicgraph::Vector& ctrl = (*m_ctrlInputsSIN[cm_id])(iter);
 
  260       assert(ctrl.size() ==
 
  261              static_cast<Eigen::VectorXd::Index
>(m_robot_util->m_nbJoints));
 
  263       if (m_jointCtrlModesCountDown[i] == 0)
 
  266         cm_id_prev = m_jointCtrlModes_previous[i].id;
 
  267         const dynamicgraph::Vector& ctrl_prev =
 
  268             (*m_ctrlInputsSIN[cm_id_prev])(iter);
 
  269         assert(ctrl_prev.size() ==
 
  270                static_cast<Eigen::VectorXd::Index
>(m_robot_util->m_nbJoints));
 
  278         s(i) = alpha * ctrl_prev(i) + (1 - alpha) * ctrl(i);
 
  279         m_jointCtrlModesCountDown[i]--;
 
  281         if (m_jointCtrlModesCountDown[i] == 0) {
 
  282           SEND_MSG(
"Joint " + toString(i) + 
" changed ctrl mode from " +
 
  283                        toString(cm_id_prev) + 
" to " + toString(cm_id),
 
  285           updateJointCtrlModesOutputSignal();
 
  292   usleep(
static_cast<unsigned int>(1e6 * m_sleep_time));
 
  293   if (m_sleep_time >= 0.1) {
 
  294     for (
unsigned int i = 0; i < m_ctrlInputsSIN.size(); i++) {
 
  295       const dynamicgraph::Vector& ctrl = (*m_ctrlInputsSIN[i])(iter);
 
  296       SEND_MSG(toString(iter) + 
") tau =" + toString(ctrl, 1, 4, 
" ") +
 
  306   if (!m_initSucceeded) {
 
  307     SEND_WARNING_STREAM_MSG(
 
  308         "Cannot compute signal u_safe before initialization!");
 
  312   const dynamicgraph::Vector& u = m_uSOUT(iter);
 
  313   const dynamicgraph::Vector& tau_max = m_tau_maxSIN(iter);
 
  314   const dynamicgraph::Vector& ctrl_max = m_u_maxSIN(iter);
 
  315   const dynamicgraph::Vector& i_max = m_i_maxSIN(iter);
 
  316   const dynamicgraph::Vector& tau = m_tauSIN(iter);
 
  317   const dynamicgraph::Vector& i_real = m_i_measuredSIN(iter);
 
  318   const dynamicgraph::Vector& tau_predicted = m_tau_predictedSIN(iter);
 
  320   for (std::size_t i = 0; i < m_emergencyStopSIN.size(); i++) {
 
  321     if ((*m_emergencyStopSIN[i]).isPlugged() &&
 
  322         (*m_emergencyStopSIN[i])(iter)) {
 
  323       m_emergency_stop_triggered = 
true;
 
  324       SEND_MSG(
"Emergency Stop has been triggered by an external entity",
 
  331   if (!m_emergency_stop_triggered) {
 
  332     for (
unsigned int i = 0; i < m_robot_util->m_nbJoints; i++) {
 
  333       if (fabs(tau(i)) > tau_max(i)) {
 
  334         m_emergency_stop_triggered = 
true;
 
  335         SEND_MSG(
"Estimated torque " + toString(tau(i)) + 
" > max torque " +
 
  336                      toString(tau_max(i)) + 
" for joint " +
 
  337                      m_robot_util->get_name_from_id(i),
 
  341       if (fabs(tau_predicted(i)) > tau_max(i)) {
 
  342         m_emergency_stop_triggered = 
true;
 
  343         SEND_MSG(
"Predicted torque " + toString(tau_predicted(i)) +
 
  344                      " > max torque " + toString(tau_max(i)) + 
" for joint " +
 
  345                      m_robot_util->get_name_from_id(i),
 
  349       if (fabs(i_real(i)) > i_max(i)) {
 
  350         m_emergency_stop_triggered = 
true;
 
  351         SEND_MSG(
"Joint " + m_robot_util->get_name_from_id(i) +
 
  352                      " measured current is too large: " + toString(i_real(i)) +
 
  353                      "A > " + toString(i_max(i)) + 
"A",
 
  358       if (fabs(u(i)) > ctrl_max(i)) {
 
  359         m_emergency_stop_triggered = 
true;
 
  360         SEND_MSG(
"Joint " + m_robot_util->get_name_from_id(i) +
 
  361                      " desired current is too large: " + toString(u(i)) +
 
  362                      "A > " + toString(ctrl_max(i)) + 
"A",
 
  369   if (m_emergency_stop_triggered) s.setZero();
 
  378   for (
unsigned int i = 0; i < 
m_ctrlModes.size(); i++)
 
  380       return SEND_MSG(
"It already exists a control mode with name " + name,
 
  385       NULL, getClassName() + 
"(" + getName() +
 
  386                 ")::input(dynamicgraph::Vector)::ctrl_" + name));
 
  391       getClassName() + 
"(" + getName() +
 
  392       ")::output(dynamicgraph::Vector)::joints_ctrl_mode_" + name));
 
  410                                  const string& ctrlMode) {
 
  414   if (jointName == 
"all") {
 
  415     for (
unsigned int i = 0; i < 
m_robot_util->m_nbJoints; i++)
 
  419     std::stringstream ss(jointName);
 
  421     std::list<int> jIdList;
 
  423     while (std::getline(ss, item, 
'-')) {
 
  424       SEND_MSG(
"parsed joint : " + item, MSG_TYPE_INFO);
 
  427     for (std::list<int>::iterator it = jIdList.begin(); it != jIdList.end();
 
  436     return SEND_MSG(
"Cannot change control mode of joint " +
 
  438                         " because its previous ctrl mode transition has not " 
  444     return SEND_MSG(
"Cannot change control mode of joint " +
 
  446                         " because it has already the specified ctrl mode",
 
  461   if (jointName == 
"all") {
 
  463     for (
unsigned int i = 0; i < 
m_robot_util->m_nbJoints; i++)
 
  466     SEND_MSG(ss.str(), MSG_TYPE_INFO);
 
  472   SEND_MSG(
"The control mode of joint " + jointName + 
" is " +
 
  478   getProfiler().reset_all();
 
  479   getStatistics().reset_all();
 
  488     return SEND_MSG(
"Sleep time cannot be negative!", MSG_TYPE_ERROR);
 
  493   SEND_MSG(
"New emergency signal input emergencyStop_" + name + 
" created",
 
  497       NULL, getClassName() + 
"(" + getName() +
 
  498                 ")::input(bool)::emergencyStop_" + name));
 
  507                                  const double& jointId) {
 
  509     SEND_WARNING_STREAM_MSG(
 
  510         "Cannot set joint name from joint id  before initialization!");
 
  514                                static_cast<Eigen::VectorXd::Index
>(jointId));
 
  518                                           const double& lq, 
const double& uq) {
 
  520     SEND_WARNING_STREAM_MSG(
 
  521         "Cannot set joints limits from joint id  before initialization!");
 
  525   m_robot_util->set_joint_limits_for_id((Index)jointId, lq, uq);
 
  529                                           const dynamicgraph::Vector& lq,
 
  530                                           const dynamicgraph::Vector& uq) {
 
  532     SEND_WARNING_STREAM_MSG(
 
  533         "Cannot set force limits from force id  before initialization!");
 
  537   m_robot_util->m_force_util.set_force_id_to_limits((Index)jointId, lq, uq);
 
  541                                            const double& forceId) {
 
  543     SEND_WARNING_STREAM_MSG(
 
  544         "Cannot set force sensor name from force sensor id  before " 
  550       forceName, 
static_cast<Eigen::VectorXd::Index
>(forceId));
 
  555     SEND_WARNING_STREAM_MSG(
"Cannot set mapping to sot before initialization!");
 
  563     SEND_WARNING_STREAM_MSG(
 
  564         "Cannot set right foot sole XYZ before initialization!");
 
  572     const dynamicgraph::Vector& xyz) {
 
  574     SEND_WARNING_STREAM_MSG(
 
  575         "Cannot set right foot force sensor XYZ before initialization!");
 
  579   m_robot_util->m_foot_util.m_Right_Foot_Force_Sensor_XYZ = xyz;
 
  583                                       const std::string& FrameName) {
 
  585     SEND_WARNING_STREAM_MSG(
"Cannot set foot frame name!");
 
  588   if (FootName == 
"Left")
 
  589     m_robot_util->m_foot_util.m_Left_Foot_Frame_Name = FrameName;
 
  590   else if (FootName == 
"Right")
 
  591     m_robot_util->m_foot_util.m_Right_Foot_Frame_Name = FrameName;
 
  593     SEND_WARNING_STREAM_MSG(
"Did not understand the foot name !" + FootName);
 
  597                                       const std::string& FrameName) {
 
  599     SEND_WARNING_STREAM_MSG(
"Cannot set hand frame name!");
 
  602   if (HandName == 
"Left")
 
  603     m_robot_util->m_hand_util.m_Left_Hand_Frame_Name = FrameName;
 
  604   else if (HandName == 
"Right")
 
  605     m_robot_util->m_hand_util.m_Right_Hand_Frame_Name = FrameName;
 
  607     SEND_WARNING_STREAM_MSG(
"Did not understand the hand name !" + HandName);
 
  612     SEND_WARNING_STREAM_MSG(
"Cannot set IMU joint name!");
 
  625     SEND_MSG(
"You should call init first. The size of the vector is unknown.",
 
  632     for (
unsigned int j = 0; j < 
m_robot_util->m_nbJoints; j++) {
 
  648   for (
unsigned int i = 0; i < 
m_ctrlModes.size(); i++)
 
  653   SEND_MSG(
"The specified control mode does not exist", MSG_TYPE_ERROR);
 
  654   SEND_MSG(
"Possible control modes are: " + toString(
m_ctrlModes),
 
  664     SEND_MSG(
"The specified joint name does not exist: " + name,
 
  666     std::stringstream ss;
 
  667     for (pinocchio::Model::JointIndex it = 0; it < 
m_robot_util->m_nbJoints;
 
  670     SEND_MSG(
"Possible joint names are: " + ss.str(), MSG_TYPE_INFO);
 
  673   id = (
unsigned int)jid;
 
  678   const JointLimits& JL = 
m_robot_util->get_joint_limits_from_id((Index)
id);
 
  680   double jl = JL.lower;
 
  682     SEND_MSG(
"Desired joint angle " + toString(q) +
 
  683                  " is smaller than lower limit: " + toString(jl),
 
  687   double ju = JL.upper;
 
  689     SEND_MSG(
"Desired joint angle " + toString(q) +
 
  690                  " is larger than upper limit: " + toString(ju),
 
  702   os << 
"ControlManager " << getName();
 
  704     getProfiler().report_all(3, os);
 
  705   } 
catch (ExceptionSignal e) {
 
std::vector< dynamicgraph::SignalPtr< dynamicgraph::Vector, int > * > m_ctrlInputsSIN
 
RobotUtilShrPtr m_robot_util
 
bool convertStringToCtrlMode(const std::string &name, CtrlMode &cm)
 
std::vector< CtrlMode > m_jointCtrlModes_previous
control mode of the joints
 
bool isJointInRange(unsigned int id, double q)
 
void setRightFootForceSensorXYZ(const dynamicgraph::Vector &)
 
void setSleepTime(const double &seconds)
 
double m_dt
true if the entity has been successfully initialized
 
tsid::robots::RobotWrapper * m_robot
 
void setCtrlMode(const std::string &jointName, const std::string &ctrlMode)
 
virtual void display(std::ostream &os) const
 
std::vector< int > m_jointCtrlModesCountDown
previous control mode of the joints
 
void setForceLimitsFromId(const double &jointId, const dynamicgraph::Vector &lq, const dynamicgraph::Vector &uq)
Command related to ForceUtil.
 
std::vector< std::string > m_ctrlModes
 
std::vector< dynamicgraph::SignalPtr< bool, int > * > m_emergencyStopSIN
 
std::vector< CtrlMode > m_jointCtrlModes_current
existing control modes
 
void addEmergencyStopSIN(const std::string &name)
 
void setImuJointName(const std::string &)
 
void updateJointCtrlModesOutputSignal()
 
void init(const double &dt, const std::string &urdfFile, const std::string &robotRef)
 
void setJointLimitsFromId(const double &jointId, const double &lq, const double &uq)
 
void setForceNameToForceId(const std::string &forceName, const double &forceId)
 
bool convertJointNameToJointId(const std::string &name, unsigned int &id)
 
std::vector< dynamicgraph::Signal< dynamicgraph::Vector, int > * > m_jointsCtrlModesSOUT
 
bool m_emergency_stop_triggered
control loop time period
 
void addCtrlMode(const std::string &name)
same as u when everything is fine, 0 otherwise
 
void setRightFootSoleXYZ(const dynamicgraph::Vector &)
Commands related to FootUtil.
 
void setNameToId(const std::string &jointName, const double &jointId)
Commands related to joint name and joint id.
 
void setJoints(const dynamicgraph::Vector &)
Set the mapping between urdf and sot.
 
void getCtrlMode(const std::string &jointName)
 
void setHandFrameName(const std::string &, const std::string &)
Commands related to HandUtil.
 
void setStreamPrintPeriod(const double &s)
 
void setFootFrameName(const std::string &, const std::string &)
 
#define PROFILE_PWM_DESIRED_COMPUTATION
 
#define PROFILE_DYNAMIC_GRAPH_PERIOD
 
#define CTRL_MODE_TRANSITION_TIME_STEP
Number of time step to transition from one ctrl mode to another.
 
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(DeviceTorqueCtrl, "DeviceTorqueCtrl")
 
DEFINE_SIGNAL_OUT_FUNCTION(u, dynamicgraph::Vector)
 
AdmittanceController EntityClassName