GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/sot-tiago-device.cpp Lines: 0 171 0.0 %
Date: 2022-09-12 09:50:59 Branches: 0 502 0.0 %

Line Branch Exec Source
1
/*
2
 * Copyright 2016,
3
 *
4
 * Olivier Stasse
5
 * Rohan Budhiraja
6
 *
7
 * LAAS, CNRS
8
 *
9
 * This file is part of TiagoController.
10
 * TIAGOController is a free software,
11
 *
12
 */
13
14
#include <stdlib.h>
15
16
#include <fstream>
17
#include <map>
18
19
#if DEBUG
20
#define ODEBUG(x) std::cout << x << std::endl
21
#else
22
#define ODEBUG(x)
23
#endif
24
#define ODEBUG3(x) std::cout << x << std::endl
25
26
#define DBGFILE "/tmp/sot-tiago-device.txt"
27
28
#if 1
29
#define RESETDEBUG5()                            \
30
  {                                              \
31
    std::ofstream DebugFile;                     \
32
    DebugFile.open(DBGFILE, std::ofstream::out); \
33
    DebugFile.close();                           \
34
  }
35
#define ODEBUG5FULL(x)                                               \
36
  {                                                                  \
37
    std::ofstream DebugFile;                                         \
38
    DebugFile.open(DBGFILE, std::ofstream::app);                     \
39
    DebugFile << __FILE__ << ":" << __FUNCTION__ << "(#" << __LINE__ \
40
              << "):" << x << std::endl;                             \
41
    DebugFile.close();                                               \
42
  }
43
#define ODEBUG5(x)                               \
44
  {                                              \
45
    std::ofstream DebugFile;                     \
46
    DebugFile.open(DBGFILE, std::ofstream::app); \
47
    DebugFile << x << std::endl;                 \
48
    DebugFile.close();                           \
49
  }
50
51
#else
52
// Void the macro
53
#define RESETDEBUG5()
54
#define ODEBUG5FULL(x)
55
#define ODEBUG5(x)
56
#endif
57
58
#include <dynamic-graph/all-commands.h>
59
#include <dynamic-graph/factory.h>
60
61
#include <sot/core/debug.hh>
62
63
#include "sot-tiago-device.hh"
64
65
using namespace std;
66
67
Eigen::Matrix3d rpy(const double roll, double pitch, double yaw) {
68
  Eigen::Matrix3d R;
69
  // Build rotation matrix as a vector of colums
70
  R(0, 0) = cos(pitch) * cos(yaw);
71
  R(1, 0) = cos(pitch) * sin(yaw);
72
  R(2, 0) = -sin(pitch);
73
74
  R(0, 1) = sin(roll) * sin(pitch) * cos(yaw) - cos(roll) * sin(yaw);
75
  R(1, 1) = sin(roll) * sin(pitch) * sin(yaw) + cos(roll) * cos(yaw);
76
  R(2, 1) = sin(roll) * cos(pitch);
77
78
  R(0, 2) = cos(roll) * sin(pitch) * cos(yaw) + sin(roll) * sin(yaw);
79
  R(1, 2) = cos(roll) * sin(pitch) * sin(yaw) - sin(roll) * cos(yaw);
80
  R(2, 2) = cos(roll) * cos(pitch);
81
82
  return R;
83
}
84
85
const double SoTTiagoDevice::TIMESTEP_DEFAULT = 0.001;
86
87
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(SoTTiagoDevice, "DeviceTiago");
88
89
SoTTiagoDevice::SoTTiagoDevice(std::string RobotName)
90
    : dgsot::Device(RobotName),
91
      closedLoop_(false),
92
      previousState_(),
93
      baseff_(),
94
      accelerometerSOUT_("StackOfTasks(" + RobotName +
95
                         ")::output(vector)::accelerometer"),
96
      gyrometerSOUT_("StackOfTasks(" + RobotName +
97
                     ")::output(vector)::gyrometer"),
98
      currentSOUT_("StackOfTasks(" + RobotName + ")::output(vector)::currents"),
99
      p_gainsSOUT_("StackOfTasks(" + RobotName + ")::output(vector)::p_gains"),
100
      d_gainsSOUT_("StackOfTasks(" + RobotName + ")::output(vector)::d_gains"),
101
      dgforces_(6),
102
      pose(),
103
      accelerometer_(3),
104
      gyrometer_(3),
105
      torques_(),
106
      leftWheelIdx_(-1),
107
      rightWheelIdx_(-1) {
108
  RESETDEBUG5();
109
  timestep_ = TIMESTEP_DEFAULT;
110
  sotDEBUGIN(25);
111
  for (int i = 0; i < 4; ++i) {
112
    withForceSignals[i] = true;
113
  }
114
  signalRegistration(accelerometerSOUT_ << gyrometerSOUT_ << currentSOUT_
115
                                        << p_gainsSOUT_ << d_gainsSOUT_);
116
  dg::Vector data(3);
117
  data.setZero();
118
  accelerometerSOUT_.setConstant(data);
119
  gyrometerSOUT_.setConstant(data);
120
  baseff_.resize(7);
121
  using namespace dynamicgraph::command;
122
  std::string docstring;
123
  /* Command increment. */
124
  docstring =
125
      "\n"
126
      "    Integrate dynamics for time step provided as input\n"
127
      "\n"
128
      "      take one floating point number as input\n"
129
      "\n";
130
  addCommand("increment",
131
             makeCommandVoid1((Device&)*this, &Device::increment, docstring));
132
133
  docstring =
134
      "    Set the integration in closed loop (express mobile base velocity in "
135
      "odometry frame)\n"
136
      "\n"
137
      "      - Input: boolean\n"
138
      "\n";
139
  addCommand(
140
      "setClosedLoop",
141
      makeCommandVoid1(*this, &SoTTiagoDevice::setClosedLoop, docstring));
142
  sotDEBUGOUT(25);
143
}
144
145
void SoTTiagoDevice::setLeftWheelIndex(int idx) { leftWheelIdx_ = idx; }
146
147
void SoTTiagoDevice::setRightWheelIndex(int idx) { rightWheelIdx_ = idx; }
148
149
SoTTiagoDevice::~SoTTiagoDevice() {}
150
151
void SoTTiagoDevice::setSensors(map<string, dgsot::SensorValues>& SensorsIn) {
152
  sotDEBUGIN(25);
153
  map<string, dgsot::SensorValues>::iterator it;
154
  int t = stateSOUT.getTime() + 1;
155
  bool setRobotState = false;
156
157
  it = SensorsIn.find("forces");
158
  if (it != SensorsIn.end()) {
159
    // Implements force recollection.
160
    const vector<double>& forcesIn = it->second.getValues();
161
    assert(std::div(forcesIn.size(), 6).rem == 0);
162
    int K = (int)forcesIn.size() / 6;
163
    for (int i = 0; i < K; ++i) {
164
      for (int j = 0; j < 6; ++j) dgforces_(j) = forcesIn[i * 6 + j];
165
      forcesSOUT[i]->setConstant(dgforces_);
166
      forcesSOUT[i]->setTime(t);
167
    }
168
  }
169
170
  // TODO: Confirm if this can be made quaternion
171
  it = SensorsIn.find("attitude");
172
  if (it != SensorsIn.end()) {
173
    const vector<double>& attitude = it->second.getValues();
174
    for (unsigned int i = 0; i < 3; ++i)
175
      for (unsigned int j = 0; j < 3; ++j) pose(i, j) = attitude[i * 3 + j];
176
    attitudeSOUT.setConstant(pose);
177
    attitudeSOUT.setTime(t);
178
  }
179
180
  it = SensorsIn.find("motor-angles");
181
  if (it != SensorsIn.end()) {
182
    const vector<double>& anglesIn = it->second.getValues();
183
    dgRobotState_.resize(anglesIn.size() + 6);
184
    for (unsigned i = 0; i < 6; ++i) dgRobotState_(i) = 0.;
185
    for (unsigned i = 0; i < anglesIn.size(); ++i)
186
      dgRobotState_(i + 6) = anglesIn[i];
187
    setRobotState = true;
188
  }
189
190
  it = SensorsIn.find("odometry");
191
  if (it != SensorsIn.end()) {
192
    const vector<double>& odomIn = it->second.getValues();
193
    dgRobotState_(0) = odomIn[0];
194
    dgRobotState_(1) = odomIn[1];
195
    dgRobotState_(5) = odomIn[2];
196
    setRobotState = true;
197
  }
198
199
  it = SensorsIn.find("accelerometer_0");
200
  if (it != SensorsIn.end()) {
201
    const vector<double>& accelerometer =
202
        SensorsIn["accelerometer_0"].getValues();
203
    for (std::size_t i = 0; i < 3; ++i) accelerometer_(i) = accelerometer[i];
204
    accelerometerSOUT_.setConstant(accelerometer_);
205
    accelerometerSOUT_.setTime(t);
206
  }
207
208
  it = SensorsIn.find("gyrometer_0");
209
  if (it != SensorsIn.end()) {
210
    const vector<double>& gyrometer = SensorsIn["gyrometer_0"].getValues();
211
    for (std::size_t i = 0; i < 3; ++i) gyrometer_(i) = gyrometer[i];
212
    gyrometerSOUT_.setConstant(gyrometer_);
213
    gyrometerSOUT_.setTime(t);
214
  }
215
216
  it = SensorsIn.find("torques");
217
  if (it != SensorsIn.end()) {
218
    const std::vector<double>& torques = SensorsIn["torques"].getValues();
219
    torques_.resize(torques.size());
220
    for (std::size_t i = 0; i < torques.size(); ++i) torques_(i) = torques[i];
221
    pseudoTorqueSOUT.setConstant(torques_);
222
    pseudoTorqueSOUT.setTime(t);
223
  }
224
225
  it = SensorsIn.find("currents");
226
  if (it != SensorsIn.end()) {
227
    const std::vector<double>& currents = SensorsIn["currents"].getValues();
228
    currents_.resize(currents.size());
229
    for (std::size_t i = 0; i < currents.size(); ++i)
230
      currents_(i) = currents[i];
231
    currentSOUT_.setConstant(currents_);
232
    currentSOUT_.setTime(t);
233
  }
234
235
  it = SensorsIn.find("p_gains");
236
  if (it != SensorsIn.end()) {
237
    const std::vector<double>& p_gains = SensorsIn["p_gains"].getValues();
238
    p_gains_.resize(p_gains.size());
239
    for (std::size_t i = 0; i < p_gains.size(); ++i) p_gains_(i) = p_gains[i];
240
    p_gainsSOUT_.setConstant(p_gains_);
241
    p_gainsSOUT_.setTime(t);
242
  }
243
244
  it = SensorsIn.find("d_gains");
245
  if (it != SensorsIn.end()) {
246
    const std::vector<double>& d_gains = SensorsIn["d_gains"].getValues();
247
    d_gains_.resize(d_gains.size());
248
    for (std::size_t i = 0; i < d_gains.size(); ++i) d_gains_(i) = d_gains[i];
249
    d_gainsSOUT_.setConstant(d_gains_);
250
    d_gainsSOUT_.setTime(t);
251
  }
252
253
  if (setRobotState) {
254
    robotState_.setConstant(dgRobotState_);
255
    robotState_.setTime(t);
256
  }
257
258
  sotDEBUGOUT(25);
259
}
260
261
void SoTTiagoDevice::setupSetSensors(
262
    map<string, dgsot::SensorValues>& SensorsIn) {
263
  setSensors(SensorsIn);
264
265
  setState(robotState_);
266
}
267
268
void SoTTiagoDevice::nominalSetSensors(
269
    map<string, dgsot::SensorValues>& SensorsIn) {
270
  setSensors(SensorsIn);
271
}
272
273
void SoTTiagoDevice::cleanupSetSensors(
274
    map<string, dgsot::SensorValues>& SensorsIn) {
275
  setSensors(SensorsIn);
276
}
277
278
void SoTTiagoDevice::getControl(map<string, dgsot::ControlValues>& controlOut) {
279
  ODEBUG5FULL("start");
280
  sotDEBUGIN(25);
281
  vector<double> anglesOut;
282
283
  Eigen::Matrix3d R;
284
  if (closedLoop_)
285
    R = rpy(dgRobotState_[3], dgRobotState_[4], dgRobotState_[5]);
286
  else
287
    R = rpy(state_[3], state_[4], state_[5]);
288
289
  // Integrate control
290
  increment(timestep_);
291
  sotDEBUG(25) << "state = " << state_ << std::endl;
292
  sotDEBUG(25) << "diff  = "
293
               << ((previousState_.size() == state_.size())
294
                       ? (state_ - previousState_)
295
                       : state_)
296
               << std::endl;
297
  ODEBUG5FULL("state = " << state_);
298
  ODEBUG5FULL("diff  = " << ((previousState_.size() == state_.size())
299
                                 ? (state_ - previousState_)
300
                                 : state_));
301
  previousState_ = state_;
302
303
  // Specify the joint values for the controller.
304
  anglesOut.resize(state_.size() - 6);
305
306
  for (unsigned int i = 6; i < state_.size(); ++i) anglesOut[i - 6] = state_(i);
307
  bool hasWheels = (leftWheelIdx_ >= 0 && rightWheelIdx_ >= 0);
308
  if (hasWheels) {
309
    // Control wheels in velocity.
310
    // 6 and 7 correspond to left and right wheel joints.
311
    anglesOut[0] = vel_control_(leftWheelIdx_);
312
    anglesOut[1] = vel_control_(rightWheelIdx_);
313
  }
314
  controlOut["control"].setValues(anglesOut);
315
  // Read zmp reference from input signal if plugged
316
  if (zmpSIN.isPlugged()) {
317
    int time = controlSIN.getTime();
318
    zmpSIN.recompute(time + 1);
319
    // Express ZMP in free flyer reference frame
320
    dg::Vector zmpGlobal(4);
321
    for (unsigned int i = 0; i < 3; ++i) zmpGlobal(i) = zmpSIN(time + 1)(i);
322
    zmpGlobal(3) = 1.;
323
    dgsot::MatrixHomogeneous inversePose;
324
325
    inversePose = freeFlyerPose().inverse(Eigen::Affine);
326
    dg::Vector localZmp(4);
327
    localZmp = inversePose.matrix() * zmpGlobal;
328
    vector<double> ZMPRef(3);
329
    for (unsigned int i = 0; i < 3; ++i) ZMPRef[i] = localZmp(i);
330
331
    controlOut["zmp"].setName("zmp");
332
    controlOut["zmp"].setValues(ZMPRef);
333
  }
334
335
  // Update position of freeflyer in global frame
336
  Eigen::Vector3d transq_(freeFlyerPose().translation());
337
  dg::sot::VectorQuaternion qt_(freeFlyerPose().linear());
338
339
  // translation
340
  for (int i = 0; i < 3; i++) baseff_[i] = transq_(i);
341
342
  // rotation: quaternion
343
  baseff_[3] = qt_.w();
344
  baseff_[4] = qt_.x();
345
  baseff_[5] = qt_.y();
346
  baseff_[6] = qt_.z();
347
348
  controlOut["baseff"].setValues(baseff_);
349
  ODEBUG5FULL("end");
350
  sotDEBUGOUT(25);
351
}