icub-client
icubClient.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 WYSIWYD Consortium, European Commission FP7 Project ICT-612139
3  * Authors: Stéphane Lallée
4  * email: stephane.lallee@gmail.com
5  * website: https://github.com/robotology/icub-client/
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 <yarp/os/LogStream.h>
30 
31 using namespace std;
32 using namespace yarp::os;
33 using namespace yarp::sig;
34 using namespace yarp::dev;
35 using namespace icubclient;
36 
37 ICubClient::ICubClient(const std::string &moduleName, const std::string &context, const std::string &clientConfigFile, bool isRFVerbose)
38 {
39  yarp::os::ResourceFinder rfClient;
40  rfClient.setVerbose(isRFVerbose);
41  rfClient.setDefaultContext(context.c_str());
42  rfClient.setDefaultConfigFile(clientConfigFile.c_str());
43  rfClient.configure(0, nullptr);
44 
45  if (rfClient.check("robot"))
46  {
47  robot = rfClient.find("robot").asString();
48  yInfo("Robot name set to %s", robot.c_str());
49  }
50  else
51  {
52  robot = "icub";
53  yInfo("Robot name set to default, i.e. %s", robot.c_str());
54  }
55 
56  //Reaching range
57  Bottle defaultRangeMin; defaultRangeMin.fromString("-0.5 -0.3 -0.15");
58  Bottle defaultRangeMax; defaultRangeMax.fromString("-0.1 0.3 0.5");
59  Bottle *rangeMin = rfClient.find("reachingRangeMin").asList();
60  Bottle *rangeMax = rfClient.find("reachingRangeMax").asList();
61  if (rangeMin == nullptr) rangeMin = new Bottle(defaultRangeMin);
62  if (rangeMax == nullptr) rangeMax = new Bottle(defaultRangeMax);
63  xRangeMin = defaultRangeMin.get(0).asDouble(); xRangeMax = defaultRangeMax.get(0).asDouble();
64  yRangeMin = defaultRangeMin.get(1).asDouble(); yRangeMax = defaultRangeMax.get(1).asDouble();
65  zRangeMin = defaultRangeMin.get(2).asDouble(); zRangeMax = defaultRangeMax.get(2).asDouble();
66 
67  icubAgent = nullptr;
68 
69  //OPC
70  string fullName = moduleName + "/icubClient";
71  opc = new OPCClient(fullName);
72  opc->isVerbose = false;
73 
74  //Susbsystems
75  if (Bottle* bSubsystems = rfClient.find("subsystems").asList())
76  {
77  for (unsigned int s = 0; s < bSubsystems->size(); s++)
78  {
79  std::string currentSS = bSubsystems->get(s).asString();
80  yInfo() << "Trying to open subsystem : " << currentSS;
81  if (currentSS == SUBSYSTEM_SPEECH)
82  subSystems[SUBSYSTEM_SPEECH] = new SubSystem_Speech(fullName);
83  else if (currentSS == SUBSYSTEM_ARE)
84  subSystems[SUBSYSTEM_ARE] = new SubSystem_ARE(fullName);
85  else if (currentSS == SUBSYSTEM_RECOG)
86  subSystems[SUBSYSTEM_RECOG] = new SubSystem_Recog(fullName);
87  else if (currentSS == SUBSYSTEM_IOL2OPC)
88  subSystems[SUBSYSTEM_IOL2OPC] = new SubSystem_IOL2OPC(fullName);
89  else if (currentSS == SUBSYSTEM_AGENTDETECTOR)
90  subSystems[SUBSYSTEM_AGENTDETECTOR] = new SubSystem_agentDetector(fullName);
91  else if (currentSS == SUBSYSTEM_BABBLING)
92  subSystems[SUBSYSTEM_BABBLING] = new SubSystem_babbling(fullName);
93  else if (currentSS == SUBSYSTEM_KARMA)
94  subSystems[SUBSYSTEM_KARMA] = new SubSystem_KARMA(fullName, robot);
95  else if (currentSS == SUBSYSTEM_SAM)
96  subSystems[SUBSYSTEM_SAM] = new SubSystem_SAM(fullName);
97  else if (currentSS == SUBSYSTEM_EMOTION)
98  subSystems[SUBSYSTEM_EMOTION] = new SubSystem_emotion(fullName);
99  else
100  yError() << "Unknown subsystem!";
101  }
102  }
103 
104  closed = false;
105 }
106 
107 bool ICubClient::connectOPC(const string &opcName)
108 {
109  bool isConnected = opc->connect(opcName);
110  if (isConnected)
111  updateAgent();
112  yInfo() << "Connection to OPC: " << (isConnected ? "successful" : "failed");
113  return isConnected;
114 }
115 
116 
117 bool ICubClient::connectSubSystems()
118 {
119  bool isConnected = true;
120  for (map<string, SubSystem*>::iterator sIt = subSystems.begin(); sIt != subSystems.end(); sIt++)
121  {
122  yInfo() << "Connection to " << sIt->first << ": ";
123  bool result = sIt->second->Connect();
124  yInfo() << (result ? "successful" : "failed");
125  isConnected &= result;
126  }
127 
128  return isConnected;
129 }
130 
131 
132 bool ICubClient::connect(const string &opcName)
133 {
134  bool isConnected = connectOPC(opcName);
135  isConnected &= connectSubSystems();
136  return isConnected;
137 }
138 
139 
140 void ICubClient::close()
141 {
142  if (closed)
143  return;
144 
145  yInfo() << "Terminating subsystems:";
146  for (map<string, SubSystem*>::iterator sIt = subSystems.begin(); sIt != subSystems.end(); sIt++)
147  {
148  yInfo() << "\t" << sIt->first;
149  sIt->second->Close();
150  if(sIt->second) {
151  delete sIt->second;
152  }
153  }
154 
155  opc->interrupt();
156  opc->close();
157 
158  closed = true;
159 }
160 
161 ICubClient::~ICubClient() {
162  close();
163  if(opc) {
164  delete opc;
165  }
166 }
167 
168 
169 void ICubClient::updateAgent()
170 {
171  if (opc->isConnected())
172  {
173  if (this->icubAgent == nullptr)
174  {
175  icubAgent = opc->addOrRetrieveEntity<Agent>("icub");
176  }
177  else
178  opc->update(this->icubAgent);
179  }
181 }
182 
183 bool ICubClient::changeName(Entity *e, const std::string &newName) {
184  bool allOkay = true;
186  if (subSystems.find("agentDetector") == subSystems.end()) {
187  say("Could not change name of default partner of agentDetector");
188  yWarning() << "Could not change name of default partner of agentDetector";
189  opc->changeName(e, newName);
190  opc->commit(e);
191 
192  allOkay = false;
193  }
194  else {
195  SubSystem_agentDetector* sub_agent = dynamic_cast<SubSystem_agentDetector*>(subSystems["agentDetector"]);
196  if(!sub_agent) {
197  yError() << "Could not cast to SubSystem_agentDetector!";
198  return false;
199  }
200 
201  sub_agent->pause();
202 
203  opc->changeName(e, newName);
204  opc->commit(e);
205 
206  if (!sub_agent->changeDefaultName(newName)) {
207  say("could not change default name of partner");
208  yError() << "[SubSystem_agentDetector] Could not change default name of partner";
209  allOkay = false;
210  }
211 
212  sub_agent->resume();
213  }
214  }
215  else if (e->entity_type() == ICUBCLIENT_OPC_ENTITY_OBJECT) {
216  if (subSystems.find("iol2opc") == subSystems.end()) {
217  say("iol2opc not reachable, did not change object name");
218  yWarning() << "iol2opc not reachable, did not change object name";
219  opc->changeName(e, newName);
220  opc->commit(e);
221 
222  allOkay = false;
223  }
224  else {
225  SubSystem_IOL2OPC* sub_iol2opc = dynamic_cast<SubSystem_IOL2OPC*>(subSystems["iol2opc"]);
226  string oldName = e->name();
227  if (!sub_iol2opc || !sub_iol2opc->changeName(oldName, newName)) {
228  yError() << "iol2opc did not change name successfuly";
229  say("iol2opc did not change name successfuly");
230  allOkay = false;
231  }
232  }
233  }
234  else {
235  if (!opc->changeName(e, newName)) {
236  yError() << "Could not change name of entity";
237  say("Could not change name of entity");
238  allOkay = false;
239  }
240  opc->commit(e);
241  }
242  return allOkay;
243 }
244 
245 void ICubClient::commitAgent()
246 {
247  if (opc->isConnected())
248  opc->commit(this->icubAgent);
249 }
250 
251 std::string ICubClient::getPartnerName(bool verbose)
252 {
253  string partnerName = "";
254  list<shared_ptr<Entity>> lEntities = opc->EntitiesCacheCopy();
255  for (auto& entity : lEntities) {
256  if (entity->entity_type() == ICUBCLIENT_OPC_ENTITY_AGENT) {
257  Agent* a = dynamic_cast<Agent*>(entity.get());
258  //We assume kinect can only recognize one skeleton at a time
259  if (a && a->m_present == 1.0 && a->name() != "icub") {
260  partnerName = a->name();
261  if (verbose) {
262  yInfo() << "Partner found: name =" << partnerName;
263  }
264  return partnerName;
265  }
266  }
267  }
268  if (verbose) {
269  yWarning() << "No partner present was found!";
270  }
271  return partnerName;
272 }
273 
274 yarp::sig::VectorOf<double> ICubClient::getPartnerBodypartLoc(std::string sBodypartName){
275 
276  Vector vLoc;
277 
278  //we extract the coordinates of a specific bodypart of the partner and we look with ARE
279  string partnerName = getPartnerName();
280  if (partnerName == ""){
281  yWarning() << "[iCubclient] Called getPartnerBodypartLoc :No partner present was found: cannot look at his/her ";
282  return vLoc;
283  }
284 
285 
286  if (Agent *oPartner = dynamic_cast<Agent*>(opc->getEntity(partnerName, true))){
287  if (oPartner->m_present == 1.0){
288  if (oPartner->m_body.m_parts.find(sBodypartName) != oPartner->m_body.m_parts.end()){
289  vLoc = oPartner->m_body.m_parts[sBodypartName];
290  yDebug() << "The bodypart " << sBodypartName << "of the agemt " << partnerName << " is at position " << vLoc.toString();
291  return vLoc;
292  }
293  else {
294  yError() << "[iCubClient] Called getPartnerBodypartLoc() on an unavalid bodypart (" << sBodypartName << ")";
295  return vLoc;
296  }
297  }
298  else {
299  yError() << "[iCubClient] Called getPartnerBodypartLoc() on a non-present agent (" << partnerName << ")";
300  return vLoc;
301  }
302  }
303 
304  return vLoc;
305 }
306 
307 bool ICubClient::lookAtPartner()
308 {
309  return look(getPartnerName());
310 }
311 
312 bool ICubClient::babbling(const string &bpName, const string &babblingLimb, double train_dur)
313 {
314  //check the subsystem is running
315  if (subSystems.find("babbling") != subSystems.end()){
316 
317  //extract the bodypart with the name
318  Entity *target = opc->getEntity(bpName, true);
320  {
321  yError() << "[iCubClient] Called babbling() on a unallowed entity: \"" << bpName << "\"";
322  return false;
323  }
324 
325  Bodypart *bp = dynamic_cast<Bodypart*>(target);
326  if(bp) {
327  int jointNumber = bp->m_joint_number;
328  if (jointNumber == -1){
329  yError() << "[iCubClient] Called babbling() on " << bpName << " which have no joint number linked to it\"";
330  return false;
331  }
332 
333  return ((SubSystem_babbling*)subSystems["babbling"])->babbling(jointNumber, babblingLimb, train_dur);
334  } else {
335  yError() << "Could not cast" << target << "to Bodypart";
336  return false;
337  }
338  }
339 
340  yError() << "Error, babbling is not running...";
341  return false;
342 }
343 
344 bool ICubClient::babbling(int jointNumber, const string &babblingLimb, double train_dur)
345 {
346  if (subSystems.find("babbling") != subSystems.end())
347  return ((SubSystem_babbling*)subSystems["babbling"])->babbling(jointNumber, babblingLimb, train_dur);
348 
349  yError() << "Error, babbling is not running...";
350  return false;
351 }
352 
353 
354 std::tuple<std::string, double> ICubClient::getHighestEmotion()
355 {
356  double intensity = 0.0;
357  string emotionName = "joy";
358 
359  //cout<<"EMOTIONS : "<<endl;
360  for (map<string, double>::iterator d = this->icubAgent->m_emotions_intrinsic.begin(); d != this->icubAgent->m_emotions_intrinsic.end(); d++)
361  {
362  //cout<<'\t'<<d->first<<'\t'<<d->second<<endl;
363  if (d->second > intensity)
364  {
365  emotionName = d->first;
366  intensity = d->second;
367  }
368  }
369 
370  return std::make_tuple(emotionName, intensity);
371 }
372 
373 
374 bool ICubClient::say(const string &text, bool shouldWait)
375 {
376  if (subSystems.find("speech") == subSystems.end())
377  {
378  yError() << "Impossible, speech is not running...";
379  return false;
380  }
381 
382  yDebug() << "iCub says" << text;
383  ((SubSystem_Speech*)subSystems["speech"])->TTS(text, shouldWait);
384  return true;
385 }
386 
387 list<Action*> ICubClient::getKnownActions()
388 {
389  this->actionsKnown.clear();
390  list<Entity*> entities = opc->Entities(ICUBCLIENT_OPC_ENTITY_TAG, "==", ICUBCLIENT_OPC_ENTITY_ACTION);
391  for (list<Entity*>::iterator it = entities.begin(); it != entities.end(); it++)
392  {
393  actionsKnown.push_back(dynamic_cast<Action*>(*it));
394  }
395  return actionsKnown;
396 }
397 
398 
399 list<Object*> ICubClient::getObjectsInSight()
400 {
401  list<Object*> inSight;
402  opc->checkout();
403  list<Entity*> allEntities = opc->EntitiesCache();
404  for (list<Entity*>::iterator it = allEntities.begin(); it != allEntities.end(); it++)
405  {
406  if ((*it)->isType(ICUBCLIENT_OPC_ENTITY_OBJECT))
407  {
408  Object* o = dynamic_cast<Object*>(*it);
409  if(o) {
410  Vector itemPosition = this->icubAgent->getSelfRelativePosition(o->m_ego_position);
411 
412  //For now we just test if the object is in front of the robot
413  if (itemPosition[0] < 0)
414  inSight.push_back(dynamic_cast<Object*>(*it));
415  }
416  }
417  }
418  return inSight;
419 }
420 
421 
422 list<Object*> ICubClient::getObjectsInRange()
423 {
424  list<Object*> inRange;
425  opc->checkout();
426  list<Entity*> allEntities = opc->EntitiesCache();
427  for (list<Entity*>::iterator it = allEntities.begin(); it != allEntities.end(); it++)
428  {
429  if ((*it)->isType(ICUBCLIENT_OPC_ENTITY_OBJECT))
430  {
431  Object* o = dynamic_cast<Object*>(*it);
432  if(o && o->m_present == 1.0) {
433  Vector itemPosition = this->icubAgent->getSelfRelativePosition(o->m_ego_position);
434 
435  if (isTargetInRange(itemPosition))
436  inRange.push_back(o);
437  }
438  }
439  }
440  return inRange;
441 }
442 
443 
444 bool ICubClient::isTargetInRange(const Vector &target) const
445 {
446  bool isIn = ((target[0] > xRangeMin) && (target[0] < xRangeMax) &&
447  (target[1] > yRangeMin) && (target[1]<yRangeMax) &&
448  (target[2]>zRangeMin) && (target[2] < zRangeMax));
449 
450  return isIn;
451 }
452 
453 
454 SubSystem_agentDetector* ICubClient::getAgentDetectorClient()
455 {
456  return getSubSystem<SubSystem_agentDetector>(SUBSYSTEM_AGENTDETECTOR);
457 }
458 
459 SubSystem_babbling* ICubClient::getBabblingClient()
460 {
461  return getSubSystem<SubSystem_babbling>(SUBSYSTEM_BABBLING);
462 }
463 
464 SubSystem_IOL2OPC* ICubClient::getIOL2OPCClient()
465 {
466  return getSubSystem<SubSystem_IOL2OPC>(SUBSYSTEM_IOL2OPC);
467 }
468 
469 SubSystem_Recog* ICubClient::getRecogClient()
470 {
471  return getSubSystem<SubSystem_Recog>(SUBSYSTEM_RECOG);
472 }
473 
474 SubSystem_ARE* ICubClient::getARE()
475 {
476  return getSubSystem<SubSystem_ARE>(SUBSYSTEM_ARE);
477 }
478 
479 SubSystem_KARMA* ICubClient::getKARMA()
480 {
481  return getSubSystem<SubSystem_KARMA>(SUBSYSTEM_KARMA);
482 }
483 
484 SubSystem_Speech* ICubClient::getSpeechClient()
485 {
486  // first, try to get SUBSYSTEM_SPEECH
487  // if it's not available, fall back to SUBSYSTEM_SPEECH_ESPEAK
488  SubSystem_Speech* s = getSubSystem<SubSystem_Speech>(SUBSYSTEM_SPEECH);
489  if(s==nullptr) {
490  return getSubSystem<SubSystem_Speech>(SUBSYSTEM_SPEECH_ESPEAK);
491  } else {
492  return s;
493  }
494 }
495 
496 SubSystem_SAM* ICubClient::getSAMClient()
497 {
498  return getSubSystem<SubSystem_SAM>(SUBSYSTEM_SAM);
499 }
500 
501 SubSystem_emotion* ICubClient::getEmotionClient()
502 {
503  return getSubSystem<SubSystem_emotion>(SUBSYSTEM_EMOTION);
504 }
bool changeDefaultName(const std::string &new_name)
Changes the name of the partner within agentDetector Internally used by ICubClient::changeName.
#define SUBSYSTEM_EMOTION
Abstract subSystem for speech management (Text to Speech)
Represent any entity that can be stored within the OPC.
Definition: entity.h:40
SubSystem to deal with the actionsRenderingEngine module (a.k.a.
Definition: subSystem_ARE.h:41
SubSystem for SAM.
Definition: subSystem_SAM.h:33
virtual bool isType(std::string _entityType) const
Test if an entity is inheriting a given type.
Definition: entity.h:67
#define SUBSYSTEM_KARMA
double m_present
Is the object present in the scene A value of 1.0 means that the object currently is in the scene A v...
Definition: object.h:69
yarp::sig::VectorOf< double > getSelfRelativePosition(const yarp::sig::VectorOf< double > &vInitialRoot) const
Express a point given in the initial ego-centered reference frame in respect to the object reference ...
Definition: object.cpp:236
void resume()
The skeleton detection of agentDetector will be resumed.
SubSystem to deal with the experimental affordance learning module (a.k.a.
STL namespace.
#define SUBSYSTEM_ARE
Definition: subSystem_ARE.h:30
#define SUBSYSTEM_SAM
Definition: subSystem_SAM.h:22
Represent any physical entity (including objects and agents) that can be stored within the OPC...
Definition: object.h:35
yarp::sig::VectorOf< double > m_ego_position
Position of the Object, in the initial ego-centered reference frame of the agent mainting the OPC (in...
Definition: object.h:46
#define SUBSYSTEM_SPEECH
Represent an agent.
Definition: agent.h:93
#define ICUBCLIENT_OPC_ENTITY_BODYPART
Definition: tags.h:39
int m_joint_number
Joint number of the represented body part.
Definition: bodypart.h:38
#define SUBSYSTEM_AGENTDETECTOR
SubSystem for iol2opc.
Represents a body part of the robot.
Definition: bodypart.h:29
bool changeName(const std::string &old_name, const std::string &new_name)
Change the name of an object Internally used by ICubClient::changeName.
void pause()
Pause the agentDetector.
#define ICUBCLIENT_OPC_ENTITY_TAG
Definition: tags.h:37
An OPC client using the datastructures defined within the icub-client library.
Definition: opcClient.h:35
std::string name() const
Return the name of an entity (which has to be unique within the OPC)
Definition: entity.h:93
Abstract subSystem for speech recognizer.
#define ICUBCLIENT_OPC_ENTITY_OBJECT
Definition: tags.h:38
SubSystem for emotion.
#define ICUBCLIENT_OPC_ENTITY_ACTION
Definition: tags.h:41
#define SUBSYSTEM_BABBLING
#define ICUBCLIENT_OPC_ENTITY_AGENT
Definition: tags.h:40
SubSystem for babbling.
#define SUBSYSTEM_IOL2OPC
#define SUBSYSTEM_SPEECH_ESPEAK
std::string entity_type() const
Return the specific type of an entity.
Definition: entity.h:121
#define SUBSYSTEM_RECOG