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) {