GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/control-manager.cpp Lines: 94 349 26.9 %
Date: 2023-06-05 17:45:50 Branches: 228 1006 22.7 %

Line Branch Exec Source
1
/*
2
 * Copyright 2014, Andrea Del Prete, LAAS-CNRS
3
 *
4
 */
5
6
#include <dynamic-graph/factory.h>
7
8
#include <sot/core/debug.hh>
9
#include <sot/torque_control/commands-helper.hh>
10
#include <sot/torque_control/control-manager.hh>
11
#include <tsid/robots/robot-wrapper.hpp>
12
#include <tsid/utils/statistics.hpp>
13
#include <tsid/utils/stop-watch.hpp>
14
15
using namespace tsid;
16
17
namespace dynamicgraph {
18
namespace sot {
19
namespace torque_control {
20
namespace dynamicgraph = ::dynamicgraph;
21
using namespace dynamicgraph;
22
using namespace dynamicgraph::command;
23
using namespace std;
24
using namespace dg::sot::torque_control;
25
26
// Size to be aligned "-------------------------------------------------------"
27
#define PROFILE_PWM_DESIRED_COMPUTATION \
28
  "Control manager                                        "
29
#define PROFILE_DYNAMIC_GRAPH_PERIOD \
30
  "Control period                                         "
31
32
#define INPUT_SIGNALS                                                        \
33
  m_i_maxSIN << m_u_maxSIN << m_tau_maxSIN << m_tauSIN << m_tau_predictedSIN \
34
             << m_i_measuredSIN
35
#define OUTPUT_SIGNALS m_uSOUT << m_u_safeSOUT
36
37
/// Define EntityClassName here rather than in the header file
38
/// so that it can be used by the macros DEFINE_SIGNAL_**_FUNCTION.
39
typedef ControlManager EntityClassName;
40
41
/* --- DG FACTORY ---------------------------------------------------- */
42
1
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(ControlManager, "ControlManager");
43
44
/* ------------------------------------------------------------------- */
45
/* --- CONSTRUCTION -------------------------------------------------- */
46
/* ------------------------------------------------------------------- */
47
1
ControlManager::ControlManager(const std::string& name)
48
    : Entity(name),
49



2
      CONSTRUCT_SIGNAL_IN(i_measured, dynamicgraph::Vector),
50



2
      CONSTRUCT_SIGNAL_IN(tau, dynamicgraph::Vector),
51



2
      CONSTRUCT_SIGNAL_IN(tau_predicted, dynamicgraph::Vector),
52



2
      CONSTRUCT_SIGNAL_IN(i_max, dynamicgraph::Vector),
53



2
      CONSTRUCT_SIGNAL_IN(u_max, dynamicgraph::Vector),
54



2
      CONSTRUCT_SIGNAL_IN(tau_max, dynamicgraph::Vector),
55



2
      CONSTRUCT_SIGNAL_OUT(u, dynamicgraph::Vector, m_i_measuredSIN),
56






2
      CONSTRUCT_SIGNAL_OUT(u_safe, dynamicgraph::Vector,
57
                           INPUT_SIGNALS << m_uSOUT),
58
      m_robot_util(RefVoidRobotUtil()),
59
      m_initSucceeded(false),
60
      m_emergency_stop_triggered(false),
61
      m_is_first_iter(true),
62
      m_iter(0),
63







17
      m_sleep_time(0.0) {
64




1
  Entity::signalRegistration(INPUT_SIGNALS << OUTPUT_SIGNALS);
65
66
  /* Commands. */
67

1
  addCommand("init",
68
1
             makeCommandVoid3(*this, &ControlManager::init,
69


2
                              docCommandVoid3("Initialize the entity.",
70
                                              "Time period in seconds (double)",
71
                                              "URDF file path (string)",
72
                                              "Robot reference (string)")));
73

1
  addCommand("addCtrlMode",
74
1
             makeCommandVoid1(
75
                 *this, &ControlManager::addCtrlMode,
76

2
                 docCommandVoid1("Create an input signal with name 'ctrl_x' "
77
                                 "where x is the specified name.",
78
                                 "Name (string)")));
79
80

1
  addCommand(
81
      "ctrlModes",
82
1
      makeCommandVoid0(
83
          *this, &ControlManager::ctrlModes,
84

2
          docCommandVoid0("Get a list of all the available control modes.")));
85
86

1
  addCommand(
87
      "setCtrlMode",
88
1
      makeCommandVoid2(
89
          *this, &ControlManager::setCtrlMode,
90


2
          docCommandVoid2("Set the control mode for a joint.",
91
                          "(string) joint name", "(string) control mode")));
92
93

1
  addCommand(
94
      "getCtrlMode",
95
1
      makeCommandVoid1(*this, &ControlManager::getCtrlMode,
96

2
                       docCommandVoid1("Get the control mode of a joint.",
97
                                       "(string) joint name")));
98
99

1
  addCommand("resetProfiler",
100
1
             makeCommandVoid0(
101
                 *this, &ControlManager::resetProfiler,
102

2
                 docCommandVoid0("Reset the statistics computed by the "
103
                                 "profiler (print this entity to see them).")));
104
105

1
  addCommand("setNameToId",
106
1
             makeCommandVoid2(
107
                 *this, &ControlManager::setNameToId,
108


2
                 docCommandVoid2("Set map for a name to an Id",
109
                                 "(string) joint name", "(double) joint id")));
110
111

1
  addCommand(
112
      "setForceNameToForceId",
113
1
      makeCommandVoid2(
114
          *this, &ControlManager::setForceNameToForceId,
115


2
          docCommandVoid2(
116
              "Set map from a force sensor name to a force sensor Id",
117
              "(string) force sensor name", "(double) force sensor id")));
118
119

1
  addCommand("setJointLimitsFromId",
120
1
             makeCommandVoid3(
121
                 *this, &ControlManager::setJointLimitsFromId,
122


2
                 docCommandVoid3("Set the joint limits for a given joint ID",
123
                                 "(double) joint id", "(double) lower limit",
124
                                 "(double) uppper limit")));
125
126

1
  addCommand(
127
      "setForceLimitsFromId",
128
1
      makeCommandVoid3(
129
          *this, &ControlManager::setForceLimitsFromId,
130


2
          docCommandVoid3("Set the force limits for a given force sensor ID",
131
                          "(double) force sensor id", "(double) lower limit",
132
                          "(double) uppper limit")));
133
134

1
  addCommand(
135
      "setJointsUrdfToSot",
136
1
      makeCommandVoid1(*this, &ControlManager::setJoints,
137

2
                       docCommandVoid1("Map Joints From URDF to SoT.",
138
                                       "Vector of integer for mapping")));
139
140

1
  addCommand(
141
      "setRightFootSoleXYZ",
142
1
      makeCommandVoid1(*this, &ControlManager::setRightFootSoleXYZ,
143

2
                       docCommandVoid1("Set the right foot sole 3d position.",
144
                                       "Vector of 3 doubles")));
145

1
  addCommand(
146
      "setRightFootForceSensorXYZ",
147
1
      makeCommandVoid1(*this, &ControlManager::setRightFootForceSensorXYZ,
148

2
                       docCommandVoid1("Set the right foot sensor 3d position.",
149
                                       "Vector of 3 doubles")));
150
151

1
  addCommand("setFootFrameName",
152
1
             makeCommandVoid2(
153
                 *this, &ControlManager::setFootFrameName,
154


2
                 docCommandVoid2("Set the Frame Name for the Foot Name.",
155
                                 "(string) Foot name", "(string) Frame name")));
156

1
  addCommand("setHandFrameName",
157
1
             makeCommandVoid2(
158
                 *this, &ControlManager::setHandFrameName,
159


2
                 docCommandVoid2("Set the Frame Name for the Hand Name.",
160
                                 "(string) Hand name", "(string) Frame name")));
161

1
  addCommand("setImuJointName",
162
1
             makeCommandVoid1(
163
                 *this, &ControlManager::setImuJointName,
164

2
                 docCommandVoid1("Set the Joint Name wich IMU is attached to.",
165
                                 "(string) Joint name")));
166

1
  addCommand("displayRobotUtil",
167
1
             makeCommandVoid0(
168
                 *this, &ControlManager::displayRobotUtil,
169

2
                 docCommandVoid0("Display the current robot util data set.")));
170
171

1
  addCommand(
172
      "setStreamPrintPeriod",
173
1
      makeCommandVoid1(
174
          *this, &ControlManager::setStreamPrintPeriod,
175

2
          docCommandVoid1("Set the period used for printing in streaming.",
176
                          "Print period in seconds (double)")));
177
178

1
  addCommand(
179
      "setSleepTime",
180
1
      makeCommandVoid1(*this, &ControlManager::setSleepTime,
181

2
                       docCommandVoid1("Set the time to sleep at every "
182
                                       "iteration (to slow down simulation).",
183
                                       "Sleep time in seconds (double)")));
184
185

1
  addCommand(
186
      "addEmergencyStopSIN",
187
1
      makeCommandVoid1(
188
          *this, &ControlManager::addEmergencyStopSIN,
189

2
          docCommandVoid1("Add emergency signal input from another entity that "
190
                          "can stop the control if necessary.",
191
                          "(string) signal name : 'emergencyStop_' + name")));
192
1
}
193
194
1
void ControlManager::init(const double& dt, const std::string& urdfFile,
195
                          const std::string& robotRef) {
196

1
  if (dt <= 0.0) return SEND_MSG("Timestep must be positive", MSG_TYPE_ERROR);
197
1
  m_dt = dt;
198
1
  m_emergency_stop_triggered = false;
199
1
  m_initSucceeded = true;
200
2
  vector<string> package_dirs;
201
2
  m_robot = new robots::RobotWrapper(urdfFile, package_dirs,
202

2
                                     pinocchio::JointModelFreeFlyer());
203
1
  std::string localName(robotRef);
204

1
  if (!isNameInRobotUtil(localName)) {
205
1
    m_robot_util = createRobotUtil(localName);
206

1
    SEND_MSG("createRobotUtil success\n", MSG_TYPE_INFO);
207
  } else {
208
    m_robot_util = getRobotUtil(localName);
209
    SEND_MSG("getRobotUtil success\n", MSG_TYPE_INFO);
210
  }
211
1
  SEND_MSG(m_robot_util->m_urdf_filename, MSG_TYPE_INFO);
212
1
  m_robot_util->m_urdf_filename = urdfFile;
213

1
  addCommand(
214
      "getJointsUrdfToSot",
215
1
      makeDirectGetter(*this, &m_robot_util->m_dgv_urdf_to_sot,
216

2
                       docDirectSetter("Display map Joints From URDF to SoT.",
217
                                       "Vector of integer for mapping")));
218
219
1
  m_robot_util->m_nbJoints = m_robot->nv() - 6;
220
1
  m_jointCtrlModes_current.resize(m_robot_util->m_nbJoints);
221
1
  m_jointCtrlModes_previous.resize(m_robot_util->m_nbJoints);
222
1
  m_jointCtrlModesCountDown.resize(m_robot_util->m_nbJoints, 0);
223
}
224
225
/* ------------------------------------------------------------------- */
226
/* --- SIGNALS ------------------------------------------------------- */
227
/* ------------------------------------------------------------------- */
228
229
DEFINE_SIGNAL_OUT_FUNCTION(u, dynamicgraph::Vector) {
230
  if (!m_initSucceeded) {
231
    SEND_WARNING_STREAM_MSG("Cannot compute signal u before initialization!");
232
    return s;
233
  }
234
235
  if (m_is_first_iter)
236
    m_is_first_iter = false;
237
  else
238
    getProfiler().stop(PROFILE_DYNAMIC_GRAPH_PERIOD);
239
  getProfiler().start(PROFILE_DYNAMIC_GRAPH_PERIOD);
240
241
  if (s.size() != (Eigen::VectorXd::Index)m_robot_util->m_nbJoints)
242
    s.resize(m_robot_util->m_nbJoints);
243
244
  getProfiler().start(PROFILE_PWM_DESIRED_COMPUTATION);
245
  {
246
    // trigger computation of all ctrl inputs
247
    for (unsigned int i = 0; i < m_ctrlInputsSIN.size(); i++)
248
      (*m_ctrlInputsSIN[i])(iter);
249
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;
253
      if (cm_id < 0) {
254
        SEND_MSG("You forgot to set the control mode of joint " + toString(i),
255
                 MSG_TYPE_ERROR_STREAM);
256
        continue;
257
      }
258
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));
262
263
      if (m_jointCtrlModesCountDown[i] == 0)
264
        s(i) = ctrl(i);
265
      else {
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));
271
272
        double alpha =
273
            m_jointCtrlModesCountDown[i] / CTRL_MODE_TRANSITION_TIME_STEP;
274
        //              SEND_MSG("Joint "+toString(i)+" changing ctrl mode from
275
        //              "+toString(cm_id_prev)+
276
        //                       " to "+toString(cm_id)+"
277
        //                       alpha="+toString(alpha),MSG_TYPE_DEBUG);
278
        s(i) = alpha * ctrl_prev(i) + (1 - alpha) * ctrl(i);
279
        m_jointCtrlModesCountDown[i]--;
280
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),
284
                   MSG_TYPE_INFO);
285
          updateJointCtrlModesOutputSignal();
286
        }
287
      }
288
    }
289
  }
290
  getProfiler().stop(PROFILE_PWM_DESIRED_COMPUTATION);
291
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, " ") +
297
                   m_ctrlModes[i],
298
               MSG_TYPE_ERROR);
299
    }
300
  }
301
302
  return s;
303
}
304
305
DEFINE_SIGNAL_OUT_FUNCTION(u_safe, dynamicgraph::Vector) {
306
  if (!m_initSucceeded) {
307
    SEND_WARNING_STREAM_MSG(
308
        "Cannot compute signal u_safe before initialization!");
309
    return s;
310
  }
311
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);
319
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",
325
               MSG_TYPE_ERROR);
326
    }
327
  }
328
329
  s = u;
330
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),
338
                 MSG_TYPE_ERROR);
339
      }
340
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),
346
                 MSG_TYPE_ERROR);
347
      }
348
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",
354
                 MSG_TYPE_ERROR);
355
        break;
356
      }
357
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",
363
                 MSG_TYPE_ERROR);
364
        break;
365
      }
366
    }
367
  }
368
369
  if (m_emergency_stop_triggered) s.setZero();
370
371
  return s;
372
}
373
374
/* --- COMMANDS ---------------------------------------------------------- */
375
376
void ControlManager::addCtrlMode(const string& name) {
377
  // check there is no other control mode with the same name
378
  for (unsigned int i = 0; i < m_ctrlModes.size(); i++)
379
    if (name == m_ctrlModes[i])
380
      return SEND_MSG("It already exists a control mode with name " + name,
381
                      MSG_TYPE_ERROR);
382
383
  // create a new input signal to read the new control
384
  m_ctrlInputsSIN.push_back(new SignalPtr<dynamicgraph::Vector, int>(
385
      NULL, getClassName() + "(" + getName() +
386
                ")::input(dynamicgraph::Vector)::ctrl_" + name));
387
388
  // create a new output signal to specify which joints are controlled with the
389
  // new control mode
390
  m_jointsCtrlModesSOUT.push_back(new Signal<dynamicgraph::Vector, int>(
391
      getClassName() + "(" + getName() +
392
      ")::output(dynamicgraph::Vector)::joints_ctrl_mode_" + name));
393
394
  // add the new control mode to the list of available control modes
395
  m_ctrlModes.push_back(name);
396
397
  // register the new signals and add the new signal dependecy
398
  Eigen::VectorXd::Index i = m_ctrlModes.size() - 1;
399
  m_uSOUT.addDependency(*m_ctrlInputsSIN[i]);
400
  Entity::signalRegistration(*m_ctrlInputsSIN[i]);
401
  Entity::signalRegistration(*m_jointsCtrlModesSOUT[i]);
402
  updateJointCtrlModesOutputSignal();
403
}
404
405
void ControlManager::ctrlModes() {
406
  SEND_MSG(toString(m_ctrlModes), MSG_TYPE_INFO);
407
}
408
409
void ControlManager::setCtrlMode(const string& jointName,
410
                                 const string& ctrlMode) {
411
  CtrlMode cm;
412
  if (convertStringToCtrlMode(ctrlMode, cm) == false) return;
413
414
  if (jointName == "all") {
415
    for (unsigned int i = 0; i < m_robot_util->m_nbJoints; i++)
416
      setCtrlMode(i, cm);
417
  } else {
418
    // decompose strings like "rk-rhp-lhp-..."
419
    std::stringstream ss(jointName);
420
    std::string item;
421
    std::list<int> jIdList;
422
    unsigned int i;
423
    while (std::getline(ss, item, '-')) {
424
      SEND_MSG("parsed joint : " + item, MSG_TYPE_INFO);
425
      if (convertJointNameToJointId(item, i)) jIdList.push_back(i);
426
    }
427
    for (std::list<int>::iterator it = jIdList.begin(); it != jIdList.end();
428
         ++it)
429
      setCtrlMode(*it, cm);
430
  }
431
  updateJointCtrlModesOutputSignal();
432
}
433
434
void ControlManager::setCtrlMode(const int jid, const CtrlMode& cm) {
435
  if (m_jointCtrlModesCountDown[jid] != 0)
436
    return SEND_MSG("Cannot change control mode of joint " +
437
                        m_robot_util->get_name_from_id(jid) +
438
                        " because its previous ctrl mode transition has not "
439
                        "terminated yet: " +
440
                        toString(m_jointCtrlModesCountDown[jid]),
441
                    MSG_TYPE_ERROR);
442
443
  if (cm.id == m_jointCtrlModes_current[jid].id)
444
    return SEND_MSG("Cannot change control mode of joint " +
445
                        m_robot_util->get_name_from_id(jid) +
446
                        " because it has already the specified ctrl mode",
447
                    MSG_TYPE_ERROR);
448
449
  if (m_jointCtrlModes_current[jid].id < 0) {
450
    // first setting of the control mode
451
    m_jointCtrlModes_previous[jid] = cm;
452
    m_jointCtrlModes_current[jid] = cm;
453
  } else {
454
    m_jointCtrlModesCountDown[jid] = CTRL_MODE_TRANSITION_TIME_STEP;
455
    m_jointCtrlModes_previous[jid] = m_jointCtrlModes_current[jid];
456
    m_jointCtrlModes_current[jid] = cm;
457
  }
458
}
459
460
void ControlManager::getCtrlMode(const std::string& jointName) {
461
  if (jointName == "all") {
462
    stringstream ss;
463
    for (unsigned int i = 0; i < m_robot_util->m_nbJoints; i++)
464
      ss << m_robot_util->get_name_from_id(i) << " "
465
         << m_jointCtrlModes_current[i] << "; ";
466
    SEND_MSG(ss.str(), MSG_TYPE_INFO);
467
    return;
468
  }
469
470
  unsigned int i;
471
  if (convertJointNameToJointId(jointName, i) == false) return;
472
  SEND_MSG("The control mode of joint " + jointName + " is " +
473
               m_jointCtrlModes_current[i].name,
474
           MSG_TYPE_INFO);
475
}
476
477
void ControlManager::resetProfiler() {
478
  getProfiler().reset_all();
479
  getStatistics().reset_all();
480
}
481
482
void ControlManager::setStreamPrintPeriod(const double& s) {
483
  setStreamPrintPeriod(s);
484
}
485
486
void ControlManager::setSleepTime(const double& seconds) {
487
  if (seconds < 0.0)
488
    return SEND_MSG("Sleep time cannot be negative!", MSG_TYPE_ERROR);
489
  m_sleep_time = seconds;
490
}
491
492
void ControlManager::addEmergencyStopSIN(const string& name) {
493
  SEND_MSG("New emergency signal input emergencyStop_" + name + " created",
494
           MSG_TYPE_INFO);
495
  // create a new input signal
496
  m_emergencyStopSIN.push_back(new SignalPtr<bool, int>(
497
      NULL, getClassName() + "(" + getName() +
498
                ")::input(bool)::emergencyStop_" + name));
499
500
  // register the new signals and add the new signal dependecy
501
  Eigen::VectorXd::Index i = m_emergencyStopSIN.size() - 1;
502
  m_u_safeSOUT.addDependency(*m_emergencyStopSIN[i]);
503
  Entity::signalRegistration(*m_emergencyStopSIN[i]);
504
}
505
506
void ControlManager::setNameToId(const std::string& jointName,
507
                                 const double& jointId) {
508
  if (!m_initSucceeded) {
509
    SEND_WARNING_STREAM_MSG(
510
        "Cannot set joint name from joint id  before initialization!");
511
    return;
512
  }
513
  m_robot_util->set_name_to_id(jointName,
514
                               static_cast<Eigen::VectorXd::Index>(jointId));
515
}
516
517
void ControlManager::setJointLimitsFromId(const double& jointId,
518
                                          const double& lq, const double& uq) {
519
  if (!m_initSucceeded) {
520
    SEND_WARNING_STREAM_MSG(
521
        "Cannot set joints limits from joint id  before initialization!");
522
    return;
523
  }
524
525
  m_robot_util->set_joint_limits_for_id((Index)jointId, lq, uq);
526
}
527
528
void ControlManager::setForceLimitsFromId(const double& jointId,
529
                                          const dynamicgraph::Vector& lq,
530
                                          const dynamicgraph::Vector& uq) {
531
  if (!m_initSucceeded) {
532
    SEND_WARNING_STREAM_MSG(
533
        "Cannot set force limits from force id  before initialization!");
534
    return;
535
  }
536
537
  m_robot_util->m_force_util.set_force_id_to_limits((Index)jointId, lq, uq);
538
}
539
540
void ControlManager::setForceNameToForceId(const std::string& forceName,
541
                                           const double& forceId) {
542
  if (!m_initSucceeded) {
543
    SEND_WARNING_STREAM_MSG(
544
        "Cannot set force sensor name from force sensor id  before "
545
        "initialization!");
546
    return;
547
  }
548
549
  m_robot_util->m_force_util.set_name_to_force_id(
550
      forceName, static_cast<Eigen::VectorXd::Index>(forceId));
551
}
552
553
void ControlManager::setJoints(const dg::Vector& urdf_to_sot) {
554
  if (!m_initSucceeded) {
555
    SEND_WARNING_STREAM_MSG("Cannot set mapping to sot before initialization!");
556
    return;
557
  }
558
  m_robot_util->set_urdf_to_sot(urdf_to_sot);
559
}
560
561
void ControlManager::setRightFootSoleXYZ(const dynamicgraph::Vector& xyz) {
562
  if (!m_initSucceeded) {
563
    SEND_WARNING_STREAM_MSG(
564
        "Cannot set right foot sole XYZ before initialization!");
565
    return;
566
  }
567
568
  m_robot_util->m_foot_util.m_Right_Foot_Sole_XYZ = xyz;
569
}
570
571
void ControlManager::setRightFootForceSensorXYZ(
572
    const dynamicgraph::Vector& xyz) {
573
  if (!m_initSucceeded) {
574
    SEND_WARNING_STREAM_MSG(
575
        "Cannot set right foot force sensor XYZ before initialization!");
576
    return;
577
  }
578
579
  m_robot_util->m_foot_util.m_Right_Foot_Force_Sensor_XYZ = xyz;
580
}
581
582
void ControlManager::setFootFrameName(const std::string& FootName,
583
                                      const std::string& FrameName) {
584
  if (!m_initSucceeded) {
585
    SEND_WARNING_STREAM_MSG("Cannot set foot frame name!");
586
    return;
587
  }
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;
592
  else
593
    SEND_WARNING_STREAM_MSG("Did not understand the foot name !" + FootName);
594
}
595
596
void ControlManager::setHandFrameName(const std::string& HandName,
597
                                      const std::string& FrameName) {
598
  if (!m_initSucceeded) {
599
    SEND_WARNING_STREAM_MSG("Cannot set hand frame name!");
600
    return;
601
  }
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;
606
  else
607
    SEND_WARNING_STREAM_MSG("Did not understand the hand name !" + HandName);
608
}
609
610
void ControlManager::setImuJointName(const std::string& JointName) {
611
  if (!m_initSucceeded) {
612
    SEND_WARNING_STREAM_MSG("Cannot set IMU joint name!");
613
    return;
614
  }
615
  m_robot_util->m_imu_joint_name = JointName;
616
}
617
618
void ControlManager::displayRobotUtil() { m_robot_util->display(std::cout); }
619
620
/* --- PROTECTED MEMBER METHODS
621
 * ---------------------------------------------------------- */
622
623
void ControlManager::updateJointCtrlModesOutputSignal() {
624
  if (m_robot_util->m_nbJoints == 0) {
625
    SEND_MSG("You should call init first. The size of the vector is unknown.",
626
             MSG_TYPE_ERROR);
627
    return;
628
  }
629
630
  dynamicgraph::Vector cm(m_robot_util->m_nbJoints);
631
  for (unsigned int i = 0; i < m_jointsCtrlModesSOUT.size(); i++) {
632
    for (unsigned int j = 0; j < m_robot_util->m_nbJoints; j++) {
633
      cm(j) = 0;
634
      if ((unsigned int)m_jointCtrlModes_current[j].id == i) cm(j) = 1;
635
636
      // during the transition between two ctrl modes they both result active
637
      if (m_jointCtrlModesCountDown[j] > 0 &&
638
          (unsigned int)m_jointCtrlModes_previous[j].id == i)
639
        cm(j) = 1;
640
    }
641
    m_jointsCtrlModesSOUT[i]->setConstant(cm);
642
  }
643
}
644
645
bool ControlManager::convertStringToCtrlMode(const std::string& name,
646
                                             CtrlMode& cm) {
647
  // Check if the ctrl mode name exists
648
  for (unsigned int i = 0; i < m_ctrlModes.size(); i++)
649
    if (name == m_ctrlModes[i]) {
650
      cm = CtrlMode(i, name);
651
      return true;
652
    }
653
  SEND_MSG("The specified control mode does not exist", MSG_TYPE_ERROR);
654
  SEND_MSG("Possible control modes are: " + toString(m_ctrlModes),
655
           MSG_TYPE_INFO);
656
  return false;
657
}
658
659
bool ControlManager::convertJointNameToJointId(const std::string& name,
660
                                               unsigned int& id) {
661
  // Check if the joint name exists
662
  sot::Index jid = m_robot_util->get_id_from_name(name);
663
  if (jid < 0) {
664
    SEND_MSG("The specified joint name does not exist: " + name,
665
             MSG_TYPE_ERROR);
666
    std::stringstream ss;
667
    for (pinocchio::Model::JointIndex it = 0; it < m_robot_util->m_nbJoints;
668
         it++)
669
      ss << m_robot_util->get_name_from_id(it) << ", ";
670
    SEND_MSG("Possible joint names are: " + ss.str(), MSG_TYPE_INFO);
671
    return false;
672
  }
673
  id = (unsigned int)jid;
674
  return true;
675
}
676
677
bool ControlManager::isJointInRange(unsigned int id, double q) {
678
  const JointLimits& JL = m_robot_util->get_joint_limits_from_id((Index)id);
679
680
  double jl = JL.lower;
681
  if (q < jl) {
682
    SEND_MSG("Desired joint angle " + toString(q) +
683
                 " is smaller than lower limit: " + toString(jl),
684
             MSG_TYPE_ERROR);
685
    return false;
686
  }
687
  double ju = JL.upper;
688
  if (q > ju) {
689
    SEND_MSG("Desired joint angle " + toString(q) +
690
                 " is larger than upper limit: " + toString(ju),
691
             MSG_TYPE_ERROR);
692
    return false;
693
  }
694
  return true;
695
}
696
697
/* ------------------------------------------------------------------- */
698
/* --- ENTITY -------------------------------------------------------- */
699
/* ------------------------------------------------------------------- */
700
701
void ControlManager::display(std::ostream& os) const {
702
  os << "ControlManager " << getName();
703
  try {
704
    getProfiler().report_all(3, os);
705
  } catch (ExceptionSignal e) {
706
  }
707
}
708
709
}  // namespace torque_control
710
}  // namespace sot
711
}  // namespace dynamicgraph