icub-client
babbling.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 WYSIWYD Consortium, European Commission FP7 Project
3  * ICT-612139
4  * Authors: Martina Zambelli
5  * email: m.zambelli13@imperial.ac.uk
6  * Permission is granted to copy, distribute, and/or modify this program
7  * under the terms of the GNU General Public License, version 2 or any
8  * later version published by the Free Software Foundation.
9  *
10  * A copy of the license can be found at
11  * icub-client/license/gpl.txt
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16  * Public License for more details
17 */
18 
19 #include "babbling.h"
20 
21 #include <iostream>
22 
23 using namespace std;
24 using namespace yarp::os;
25 using namespace yarp::sig;
26 
27 bool Babbling::configure(yarp::os::ResourceFinder &rf) {
28  bool bEveryThingisGood = true;
29 
30  string moduleName = rf.check("name", Value("babbling"), "module name (string)").asString();
31 
32  robot = rf.check("robot", Value("icub")).asString();
33  single_joint = rf.check("single_joint", Value(-1)).asInt();
34 
35  Bottle &start_pos = rf.findGroup("start_position");
36  Bottle *b_start_commandHead = start_pos.find("head").asList();
37  Bottle *b_start_command = start_pos.find("arm").asList();
38 
39  start_command_head.resize(3, 0.0);
40  if ((b_start_commandHead->isNull()) || (b_start_commandHead->size() < 3)) {
41  yWarning("Something is wrong in ini file. Default value is used");
42  start_command_head[0] = -20.0;
43  start_command_head[1] = -20.0;
44  start_command_head[2] = +10.0;
45  } else {
46  for (unsigned int i = 0; i < b_start_commandHead->size(); i++) {
47  start_command_head[i] = b_start_commandHead->get(i).asDouble();
48  yDebug() << start_command_head[i];
49  }
50  }
51 
52  if ((b_start_command->isNull()) || (b_start_command->size() < 16)) {
53  yWarning("Something is wrong in ini file. Default values are used");
54  start_command_arm[0] = -45.0; start_command_arm[1] = 35.0; start_command_arm[2] = 0.0;
55  start_command_arm[3] = 50.0; start_command_arm[4] = -45.0; start_command_arm[5] = 0.0;
56  start_command_arm[6] = 0.0; start_command_arm[7] = 0.0; start_command_arm[8] = 10.0;
57  start_command_arm[9] = 0.0; start_command_arm[10] = 0.0; start_command_arm[11] = 0.0;
58  start_command_arm[12] = 0.0; start_command_arm[13] = 0.0; start_command_arm[14] = 0.0;
59  start_command_arm[15] = 0.0;
60  } else {
61  for (unsigned int i = 0; i < b_start_command->size(); i++)
62  start_command_arm[i] = b_start_command->get(i).asDouble();
63  }
64 
65  Bottle &babbl_par = rf.findGroup("babbling_param");
66  freq = babbl_par.check("freq", Value(0.2)).asDouble();
67  amp = babbl_par.check("amp", Value(5.0)).asDouble();
68  duration = babbl_par.check("duration", Value(20.0)).asDouble();
69 
70  setName(moduleName.c_str());
71 
72  // Open handler port
73  if (!handlerPort.open("/" + getName() + "/rpc")) {
74  yError() << getName() << ": Unable to open port " << "/" << getName() << "/rpc";
75  bEveryThingisGood = false;
76  }
77 
78  // Initialize iCub
79  yInfo() << "Going to initialise iCub ...";
80  while (!init_iCub()) {
81  yDebug() << getName() << ": initialising iCub... please wait... ";
82  }
83 
84  yDebug() << "End configuration...";
85 
86  attach(handlerPort);
87 
88  return bEveryThingisGood;
89 }
90 
92  handlerPort.interrupt();
93 
94  yInfo() << "Bye!";
95 
96  return true;
97 }
98 
100  yInfo() << "Closing module, please wait ... ";
101 
102  leftArmDev.close();
103  rightArmDev.close();
104  headDev.close();
105 
106  handlerPort.interrupt();
107  handlerPort.close();
108 
109  yInfo() << "Bye!";
110 
111  return true;
112 }
113 
114 bool Babbling::respond(const Bottle &command, Bottle &reply) {
115  string helpMessage = string(getName().c_str()) + " commands are: \n " +
116  "babbling arm <left/right>: motor commands sent to all "
117  "the arm joints \n " +
118  "babbling hand <left/right>: motor commands sent to all "
119  "the hand joints \n " +
120  "babbling joint <int joint_number> <left/right>: motor "
121  "commands sent to joint_number only \n " +
122  "help \n " + "quit \n";
123 
124  reply.clear();
125 
126  if (command.get(0).asString() == "quit") {
127  reply.addString("Quitting");
128  return false;
129  } else if (command.get(0).asString() == "help") {
130  yInfo() << helpMessage;
131  reply.addString(helpMessage);
132  } else if (command.get(0).asString() == "babbling") {
133  if (command.get(1).asString() == "arm") {
134  single_joint = -1;
135  part_babbling = command.get(1).asString();
136 
137  if (command.get(2).asString() == "left" || command.get(2).asString() == "right") {
138  part = command.get(2).asString() + "_arm";
139  yInfo() << "Babbling " + command.get(2).asString() + " arm...";
140 
141  if (command.size() >= 4) {
142  yInfo() << "Custom duration = " << command.get(3).asDouble();
143  if (command.get(3).asDouble() >= 0.0) {
144  double newDuration = command.get(3).asDouble();
145  double oldDuration = duration;
146  duration = newDuration;
147  yInfo() << "duration is changed from " << oldDuration << " to " << duration;
148  doBabbling();
149  duration = oldDuration;
150  yInfo() << "Going back to duration from config file: " << duration;
151  reply.addString("ack");
152  return true;
153  } else {
154  yError("Invalid train duration: Must be a double >= 0.0");
155  yWarning("Doing the babbling anyway with default value");
156  }
157  }
158 
159  doBabbling();
160  reply.addString("ack");
161  return true;
162  } else {
163  yError("Invalid babbling part: specify LEFT or RIGHT after 'arm'.");
164  reply.addString("nack");
165  return false;
166  }
167  } else if (command.get(1).asString() == "joint") {
168  single_joint = command.get(2).asInt();
169  if (single_joint < 16 && single_joint >= 0) {
170  if (command.get(3).asString() == "left" || command.get(3).asString() == "right") {
171  part = command.get(3).asString() + "_arm";
172  yInfo() << "Babbling joint " << single_joint << " of " << part;
173 
174  // change duration if specified
175  if (command.size() >= 5) {
176  yInfo() << "Custom duration = " << command.get(4).asDouble();
177  if (command.get(4).asDouble() >= 0.0) {
178  double newDuration = command.get(4).asDouble();
179  double oldDuration = duration;
180  duration = newDuration;
181  yInfo() << "duration is changed from " << oldDuration
182  << " to " << duration;
183  doBabbling();
184  duration = oldDuration;
185  yInfo() << "Going back to duration from config file: "
186  << duration;
187  reply.addString("ack");
188  return true;
189  } else {
190  yError("Invalid train duration: Must be a double >= 0.0");
191  yWarning("Doing the babbling anyway with default value");
192  }
193  }
194 
195  doBabbling();
196  reply.addString("ack");
197  return true;
198  } else {
199  yError("Invalid babbling part: specify LEFT or RIGHT after joint number.");
200  reply.addString("nack");
201  return false;
202  }
203  } else {
204  yError("Invalid joint number.");
205  reply.addString("nack");
206  return false;
207  }
208  } else if (command.get(1).asString() == "hand") {
209  single_joint = -1;
210  part_babbling = command.get(1).asString();
211 
212  if (command.get(2).asString() == "left" ||
213  command.get(2).asString() == "right") {
214  part = command.get(2).asString() + "_arm";
215  yInfo() << "Babbling " + command.get(2).asString() + " hand...";
216  doBabbling();
217  reply.addString("ack");
218  return true;
219  } else {
220  yError("Invalid babbling part: specify LEFT or RIGHT after 'hand'.");
221  reply.addString("nack");
222  return false;
223  }
224  } else {
225  yInfo() << "Command not found\n" << helpMessage;
226  reply.addString("nack");
227  reply.addString("command not found");
228  reply.addString(helpMessage);
229  return false;
230  }
231  }
232 
233  return true;
234 }
235 
237  return true;
238 }
239 
241  return 0.1;
242 }
243 
245  bool homeStart = gotoStartPos(); // First go to home position
246  if (!homeStart) {
247  yError() << "I got lost going home!";
248  return false;
249  }
250 
251  // Change to velocity mode
252  for (int i = 0; i < 16; i++) {
253  if (part == "right_arm") {
254  ictrlRightArm->setControlMode(i, VOCAB_CM_VELOCITY);
255  } else if (part == "left_arm") {
256  ictrlLeftArm->setControlMode(i, VOCAB_CM_VELOCITY);
257  } else {
258  yError() << "Don't know which part to move to do babbling.";
259  return false;
260  }
261  }
262 
263  double startTime = yarp::os::Time::now();
264 
265  yDebug() << "============> babbling with COMMAND will START";
266  yInfo() << "AMP " << amp << "FREQ " << freq;
267 
268  // now loop and issue the actual babbling commands
269  while (Time::now() < startTime + duration) {
270  double t = Time::now() - startTime;
271  yInfo() << "t = " << t << "/ " << duration;
272 
273  babblingCommands(t, single_joint);
274  }
275 
276  yDebug() << "============> babbling with COMMAND is FINISHED";
277 
278  return true;
279 }
280 
281 void Babbling::babblingCommands(double &t, int j_idx) {
282  double ref_command[16]; // Reference command for the 16 arm joints
283  yarp::sig::VectorOf<double> command; // Command after correction
284  yarp::sig::VectorOf<double> encodersUsed;
285  command.resize(16);
286 
287  for (unsigned int l = 0; l < command.size(); l++) {
288  command[l] = 0;
289  }
290 
291  for (unsigned int l = 0; l < 16; l++) {
292  ref_command[l] = start_command_arm[l] + amp * sin(freq * t * 2 * M_PI);
293  }
294 
295  if (part == "right_arm" || part == "left_arm") {
296  bool okEncArm = false;
297 
298  if (part == "right_arm") {
299  encodersUsed = encodersRightArm;
300  okEncArm = encsRightArm->getEncoders(encodersUsed.data());
301  } else {
302  encodersUsed = encodersLeftArm;
303  okEncArm = encsLeftArm->getEncoders(encodersUsed.data());
304  }
305 
306  yDebug() << "j_idx: " << j_idx;
307 
308  if (j_idx != -1) { // single joint babbling
309  if (!okEncArm) {
310  yError() << "Error receiving encoders";
311  command[j_idx] = 0;
312  } else {
313  yDebug() << "command before correction = " << ref_command[j_idx];
314  yDebug() << "current encoders : " << encodersUsed[j_idx];
315  command[j_idx] = amp * sin(freq * t * 2 * M_PI);
316  yDebug() << "command after correction = " << command[j_idx];
317  if (command[j_idx] > 50) command[j_idx] = 50;
318  if (command[j_idx] < -50) command[j_idx] = -50;
319  yDebug() << "command after saturation = " << command[j_idx];
320  }
321  } else {
322  if (part_babbling == "arm") {
323  if (!okEncArm) {
324  yError() << "Error receiving encoders";
325  for (unsigned int l = 0; l < 7; l++) command[l] = 0;
326  } else {
327  for (unsigned int l = 0; l < 7; l++) {
328  command[l] = 10 * (ref_command[l] - encodersUsed[l]);
329  if (command[l] > 20) command[l] = 20;
330  if (command[l] < -20) command[l] = -20;
331  }
332  }
333  } else if (part_babbling == "hand") {
334  if (!okEncArm) {
335  yError() << "Error receiving encoders";
336  for (unsigned int l = 7; l < command.size(); l++) command[l] = 0;
337  } else {
338  for (unsigned int l = 7; l < command.size(); l++) {
339  command[l] = 10 * (ref_command[l] - encodersUsed[l]);
340  if (command[l] > 20) command[l] = 20;
341  if (command[l] < -20) command[l] = -20;
342  }
343  }
344  } else {
345  yError("Can't babble the required body part.");
346  }
347  }
348 
349  if (part == "right_arm") {
350  velRightArm->velocityMove(command.data());
351  } else if (part == "left_arm") {
352  velLeftArm->velocityMove(command.data());
353  } else {
354  yError() << "Don't know which part to move to do babbling.";
355  }
356 
357  yarp::os::Time::delay(0.05); // This delay is needed!!!
358 
359  } else {
360  yError() << "Which arm to babble with?";
361  }
362 }
363 
365  yarp::sig::VectorOf<double> ang = start_command_head;
366  if (part == "right_arm") {
367  ang[0] = -ang[0];
368  }
369  return igaze->lookAtAbsAngles(ang);
370 }
371 
373  igaze->stopControl();
374  velLeftArm->stop();
375  velRightArm->stop();
376 
377  yarp::os::Time::delay(2.0);
378 
379  moveHeadToStartPos();
380 
381  yarp::sig::VectorOf<double> command; // Command after correction
382  command.resize(16);
383 
384  /* Move arm to start position */
385  if (part == "left_arm" || part == "right_arm") {
386  if (part == "left_arm") {
387  command = encodersLeftArm;
388  for (int i = 0; i < 16; i++) {
389  ictrlLeftArm->setControlMode(i, VOCAB_CM_POSITION);
390  command[i] = start_command_arm[i];
391  }
392  posLeftArm->positionMove(command.data());
393  } else {
394  command = encodersRightArm;
395  for (int i = 0; i < 16; i++) {
396  ictrlRightArm->setControlMode(i, VOCAB_CM_POSITION);
397  command[i] = start_command_arm[i];
398  }
399  posRightArm->positionMove(command.data());
400  }
401 
402  bool done_head = false;
403  bool done_arm = false;
404  while (!done_head || !done_arm) {
405  yInfo() << "Wait for position moves to finish";
406  igaze->checkMotionDone(&done_head);
407  if (part == "left_arm") {
408  posLeftArm->checkMotionDone(&done_arm);
409  } else {
410  posRightArm->checkMotionDone(&done_arm);
411  }
412  Time::delay(0.04);
413  }
414  yInfo() << "Done.";
415 
416  Time::delay(1.0);
417  } else {
418  yError() << "Don't know which part to move to start position.";
419  return false;
420  }
421 
422  return true;
423 }
424 
426  Property option_left;
427 
428  string portnameLeftArm = "left_arm"; // part;
429  option_left.put("robot", robot.c_str());
430  option_left.put("device", "remote_controlboard");
431  Value &robotnameLeftArm = option_left.find("robot");
432 
433  option_left.put("local", "/babbling/" + robotnameLeftArm.asString() + "/" + portnameLeftArm + "/control");
434  option_left.put("remote", "/" + robotnameLeftArm.asString() + "/" + portnameLeftArm);
435 
436  yDebug() << "option left arm: " << option_left.toString().c_str();
437 
438  if (!leftArmDev.open(option_left)) {
439  yError() << "Device not available. Here are the known devices:";
440  yError() << yarp::dev::Drivers::factory().toString();
441  return false;
442  }
443 
444  leftArmDev.view(posLeftArm);
445  leftArmDev.view(velLeftArm);
446  leftArmDev.view(itrqLeftArm);
447  leftArmDev.view(encsLeftArm);
448  leftArmDev.view(ictrlLeftArm);
449  leftArmDev.view(ictrlLimLeftArm);
450 
451  double minLimArm[16];
452  double maxLimArm[16];
453  for (int l = 0; l < 16; l++) {
454  ictrlLimLeftArm->getLimits(l, &minLimArm[l], &maxLimArm[l]);
455  }
456 
457  for (int l = 0; l < 16; l++) {
458  yInfo() << "Joint " << l << ": limits = [" << minLimArm[l] << ","
459  << maxLimArm[l] << "]. start_commad = " << start_command_arm[l];
460  }
461 
462  if (posLeftArm == nullptr || encsLeftArm == nullptr || velLeftArm == nullptr ||
463  itrqLeftArm == nullptr || ictrlLeftArm == nullptr || encsLeftArm == nullptr) {
464  yError() << "Cannot get interface to robot device for left arm";
465  leftArmDev.close();
466  }
467 
468  int nj_left = 0;
469  posLeftArm->getAxes(&nj_left);
470  encodersLeftArm.resize(nj_left);
471 
472  yInfo() << "Wait for arm encoders";
473  while (!encsLeftArm->getEncoders(encodersLeftArm.data())) {
474  Time::delay(0.1);
475  yInfo() << "Wait for arm encoders";
476  }
477 
478  return true;
479 }
480 
482  /* Create PolyDriver for right arm */
483  Property option_right;
484 
485  string portnameRightArm = "right_arm";
486  option_right.put("robot", robot.c_str());
487  option_right.put("device", "remote_controlboard");
488  Value &robotnameRightArm = option_right.find("robot");
489 
490  option_right.put("local", "/babbling/" + robotnameRightArm.asString() + "/" + portnameRightArm + "/control");
491  option_right.put("remote", "/" + robotnameRightArm.asString() + "/" + portnameRightArm);
492 
493  yDebug() << "option right arm: " << option_right.toString().c_str();
494 
495  if (!rightArmDev.open(option_right)) {
496  yError() << "Device not available. Here are the known devices:";
497  yError() << yarp::dev::Drivers::factory().toString();
498  return false;
499  }
500 
501  rightArmDev.view(posRightArm);
502  rightArmDev.view(velRightArm);
503  rightArmDev.view(itrqRightArm);
504  rightArmDev.view(encsRightArm);
505  rightArmDev.view(ictrlRightArm);
506  rightArmDev.view(ictrlLimRightArm);
507 
508  double minLimArm[16];
509  double maxLimArm[16];
510  for (int l = 0; l < 16; l++) {
511  ictrlLimRightArm->getLimits(l, &minLimArm[l], &maxLimArm[l]);
512  }
513 
514  for (int l = 0; l < 16; l++) {
515  yInfo() << "Joint " << l << ": limits = [" << minLimArm[l] << ","
516  << maxLimArm[l] << "]. start_commad = " << start_command_arm[l];
517  }
518 
519  if (posRightArm == nullptr || encsRightArm == nullptr || velRightArm == nullptr ||
520  itrqRightArm == nullptr || ictrlRightArm == nullptr || encsRightArm == nullptr) {
521  yError() << "Cannot get interface to robot device for right arm";
522  rightArmDev.close();
523  }
524 
525  int nj_right = 0;
526  posRightArm->getAxes(&nj_right);
527  encodersRightArm.resize(nj_right);
528 
529  yInfo() << "Wait for arm encoders";
530  while (!encsRightArm->getEncoders(encodersRightArm.data())) {
531  Time::delay(0.1);
532  yInfo() << "Wait for arm encoders";
533  }
534 
535  return true;
536 }
537 
539  if(!init_left_arm()) {
540  return false;
541  }
542  if(!init_right_arm()) {
543  return false;
544  }
545 
546  yInfo() << "Arms initialized.";
547 
548  /* Init. head */
549  Property option_head;
550  option_head.clear();
551  option_head.put("device", "gazecontrollerclient");
552  option_head.put("remote", "/iKinGazeCtrl");
553  option_head.put("local", "/babbling/gaze");
554 
555  if (!headDev.open(option_head)) {
556  yError() << "Device not available. Here are the known devices:";
557  yError() << yarp::dev::Drivers::factory().toString();
558  return false;
559  }
560 
561  headDev.view(igaze);
562  yInfo() << "Head initialized.";
563 
564  yInfo() << "> Initialisation done.";
565 
566  return true;
567 }
bool init_left_arm()
Create PolyDriver for left arm.
Definition: babbling.cpp:425
bool interruptModule()
Definition: babbling.cpp:91
double getPeriod()
Definition: babbling.cpp:240
bool init_iCub()
Initializes all the device controllers.
Definition: babbling.cpp:538
bool gotoStartPos()
Move head + arm in start position.
Definition: babbling.cpp:372
bool init_right_arm()
Create PolyDriver for left arm.
Definition: babbling.cpp:481
STL namespace.
bool moveHeadToStartPos()
Use iGazeController to move head in start position.
Definition: babbling.cpp:364
bool doBabbling()
Sets the joints to be in velocity control, then goes in a loop to call babblingCommands for duration ...
Definition: babbling.cpp:244
bool close()
Definition: babbling.cpp:99
bool configure(yarp::os::ResourceFinder &rf)
Definition: babbling.cpp:27
bool updateModule()
Definition: babbling.cpp:236
void babblingCommands(double &t, int j_idx)
Issues the actual velocity commands for time t.
Definition: babbling.cpp:281
bool respond(const yarp::os::Bottle &command, yarp::os::Bottle &reply)
Definition: babbling.cpp:114