icub-client
helpers.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 WYSIWYD Consortium, European Commission FP7 Project ICT-612139
3  * Authors: GrĂ©goire Pointeau, Tobias Fischer, Maxime Petit
4  * email: greg.pointeau@gmail.com, t.fischer@imperial.ac.uk, m.petit@imperial.ac.uk
5  * Permission is granted to copy, distribute, and/or modify this program
6  * under the terms of the GNU General Public License, version 2 or any
7  * later version published by the Free Software Foundation.
8  *
9  * A copy of the license can be found at
10  * icub-client/license/gpl.txt
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15  * Public License for more details
16 */
17 
18 #include "proactiveTagging.h"
19 
24 
25 using namespace std;
26 using namespace yarp::os;
27 using namespace icubclient;
28 
29 void proactiveTagging::subPopulateObjects(Bottle* objectList, bool addOrRetrieve) {
30  if (objectList) {
31  for (unsigned int d = 0; d < objectList->size(); d++) {
32  std::string name = objectList->get(d).asString().c_str();
34  if(addOrRetrieve) {
35  o = iCub->opc->addOrRetrieveEntity<Object>(name);
36  } else {
37  o = iCub->opc->addEntity<Object>(name);
38  }
39  yInfo() << " [configureOPC] object " << o->name() << "added" ;
40  o->m_present = 0.0;
41  iCub->opc->commit(o);
42  }
43  }
44 }
45 
47  Bottle bToPasar, bFromPasar;
48  bToPasar.addString("pointing");
49  if(on) {
50  bToPasar.addString("on");
51  } else {
52  bToPasar.addString("off");
53  }
54  if (!Network::connect(portToPasar.getName().c_str(), "/pasar/rpc")) {
55  yError() << "Could not connect to pasar";
56  iCub->say("Could not connect to pasar");
57  return false;
58  } else {
59  portToPasar.write(bToPasar, bFromPasar);
60  if(bFromPasar.get(0).asString()!="ack") {
61  yError() << "Pasar did not change pointing to on";
62  iCub->say("Pasar did not change pointing to on");
63  return false;
64  } else {
65  return true;
66  }
67  }
68 }
69 
70 std::string proactiveTagging::getBestEntity(std::string sTypeTarget) {
71  bool bFound = false;
72  std::string sNameBestEntity = "none", sNameSecondBest = "none";
73 
74  double start = yarp::os::Time::now();
75  // start detecting unknown objects
76  while (!bFound && start + 8.0 > yarp::os::Time::now()) {
77  iCub->opc->checkout();
78  std::list<std::shared_ptr<Entity>> lEntities = iCub->opc->EntitiesCacheCopy();
79 
80  double highestSaliency = 0.0;
81  double secondSaliency = 0.0;
82 
83  for (auto& entity : lEntities) {
84  if (entity->name().find("unknown")==0) {
85  if (sTypeTarget == ICUBCLIENT_OPC_ENTITY_OBJECT && (entity->entity_type() == ICUBCLIENT_OPC_ENTITY_OBJECT)) {
86  Object* temp = dynamic_cast<Object*>(entity.get());
87  if(!temp) {
88  yError() << "Could not cast " << entity->name() << " to an object";
89  iCub->say("Could not cast " + entity->name() + " to an object");
90  } else {
91  if (temp->m_saliency > highestSaliency) {
92  if (secondSaliency != 0.0) {
93  secondSaliency = highestSaliency;
94  }
95  highestSaliency = temp->m_saliency;
96  sNameBestEntity = temp->name();
97  } else {
98  if (temp->m_saliency > secondSaliency) {
99  secondSaliency = temp->m_saliency;
100  sNameSecondBest = temp->name();
101  }
102  }
103  }
104  }
105  }
106  }
107 
108  yDebug() << sNameBestEntity << " has highest saliency: " << highestSaliency;
109  yDebug() << sNameSecondBest << " has second highest saliency: " << secondSaliency;
110 
111  bFound = false;
112  if (highestSaliency > thresholdSalienceDetection) {
113  //the object with highest salience is salient enough
114  if (secondSaliency != 0.0) {
115  // there are other salient objects
116  if ((highestSaliency / secondSaliency) > thresholdDistinguishObjectsRatio) {
117  yDebug() << "Two objects are salient, but one is much more";
118  //but it is enough difference
119  bFound = true;
120  } else {
121  yDebug() << "Two objects are similarly salient";
122  }
123  } else {
124  yDebug() << "Only one object is salient, take this one";
125  //other object are not salient
126  bFound = true;
127  }
128  }
129  if (sNameBestEntity == "none") {
130  yDebug() << "No object is salient";
131  bFound = false;
132  }
133  }
134 
135  return sNameBestEntity;
136 }
137 
138 Bottle proactiveTagging::recogName(std::string entityType) {
139  Bottle bOutput;
140 
141  Bottle bRecognized, //received from speech recog with transfer information (1/0 (bAnswer))
142  bAnswer; //response from speech recog without transfer information, including raw sentence
143 
144  yDebug() << "Going to load grammar.";
145  string grammar, expectedresponse="error", semanticfield="error";
146  if (entityType == ICUBCLIENT_OPC_ENTITY_AGENT) {
147  grammar = GrammarAskNameAgent;
148  expectedresponse = "SENTENCEAGENT";
149  semanticfield = "agent";
150  } else if (entityType == ICUBCLIENT_OPC_ENTITY_OBJECT) {
151  grammar = GrammarAskNameObject;
152  expectedresponse = "SENTENCEOBJECT";
153  semanticfield = "object";
154  } else if (entityType == ICUBCLIENT_OPC_ENTITY_BODYPART) {
155  grammar = GrammarAskNameBodypart;
156  expectedresponse = "SENTENCEBODYPART";
157  semanticfield = "fingerName";
158  } else {
159  yError() << " error in proactiveTagging::recogName | for " << entityType << " | Entity Type not managed";
160  bOutput.addString("error");
161  bOutput.addString("Entity Type not managed");
162  iCub->say("I do not know what you want from me. Can you please ask me something else?");
163  return bOutput;
164  }
165 
166  // Load the Speech Recognition with grammar according to entityType
167  // bAnswer is the result of the recognition system (first element is the raw sentence, second is the list of semantic element)
168  bool recognizedCorrectGrammar=false;
169  while(!recognizedCorrectGrammar) {
170  bRecognized = iCub->getRecogClient()->recogFromGrammarLoop(grammarToString(grammar), 20);
171  bAnswer = *bRecognized.get(1).asList();
172  if(bAnswer.get(1).asList()->get(0).toString() != expectedresponse) {
173  iCub->say("I did not understand you. Can you please repeat?");
174  yError() << "Wrong sentence type returned (not " << expectedresponse << ")";
175  } else {
176  recognizedCorrectGrammar = true;
177  }
178  }
179 
180  yDebug() << "Response from recogClient: " << bRecognized.toString();
181 
182  if (bRecognized.get(0).asInt() == 0)
183  {
184  yError() << " error in proactiveTagging::askName | for " << entityType << " | Error in speechRecog";
185  bOutput.addString("error");
186  bOutput.addString("error in speechRecog");
187  return bOutput;
188  }
189 
190  iCub->say("I've understood " + bAnswer.get(0).asString());
191 
192  Bottle bSemantic = *bAnswer.get(1).asList(); // semantic information of the content of the recognition
193  string sName = bSemantic.check(semanticfield, Value("error")).asString();
194  bOutput.addString(sName);
195  return bOutput;
196 }
197 
198 void proactiveTagging::subPopulateBodyparts(Bottle* bodyPartList, Bottle* bodyPartJointList, bool addOrRetrieve) {
199  std::list<std::shared_ptr<Entity>> currentEntitiesList = iCub->opc->EntitiesCacheCopy();
200 
201  if (bodyPartList) {
202  for (unsigned int d = 0; d < bodyPartList->size(); d++) {
203  bool foundSame = false;
204  for(auto& e : currentEntitiesList) {
205  if(Bodypart* bp = dynamic_cast<Bodypart*>(e.get())) {
206  if(bp->m_joint_number == bodyPartJointList->get(d).asInt()) {
207  yWarning() << "Joint" << bp->m_joint_number << "already existing";
208  foundSame = true;
209  break;
210  }
211  }
212  }
213  if(foundSame) {
214  continue;
215  }
216  std::string name = bodyPartList->get(d).asString().c_str();
218  if(addOrRetrieve) {
219  o = iCub->opc->addOrRetrieveEntity<Bodypart>(name);
220  } else {
221  o = iCub->opc->addEntity<Bodypart>(name);
222  }
223  yInfo() << " [configureOPC] Bodypart " << o->name() << "added";
224  o->m_present = 0.0;
225  //apply the joint number if available. protect for the loop because using d from bodyPartList. should be same number of element between bodyPartList and bodyPartJointList
226  if(d < bodyPartJointList->size()) {
227  o->m_joint_number = bodyPartJointList->get(d).asInt();
228  yInfo() << " [configureOPC] Bodypart " << o->name() << " has now a joint " << o->m_joint_number ;
229  }
230  iCub->opc->commit(o);
231  }
232  }
233 }
234 
235 void proactiveTagging::configureOPC(yarp::os::ResourceFinder &rf) {
236  //Populate the OPC if required
237  yDebug() << "Populating OPC...";
238 
239  //1. Populate AddOrRetrieve part
240  Bottle grpOPC_AOR = rf.findGroup("OPC_AddOrRetrieve");
241  bool shouldPopulate_AOR = grpOPC_AOR.find("populateOPC").asInt() == 1;
242  if (shouldPopulate_AOR) {
243  Bottle *objectList = grpOPC_AOR.find("objectName").asList();
244  subPopulateObjects(objectList, true);
245 
246  Bottle *bodyPartList = grpOPC_AOR.find("bodypartName").asList();
247  Bottle *bodyPartJointList = grpOPC_AOR.find("bodypartJoint").asList();
248  subPopulateBodyparts(bodyPartList, bodyPartJointList, true);
249  }
250 
251  //2. Populate Add part (allows several object with same base name, e.g. object, object_1, object_2, ..., object_n)
252  Bottle grpOPC_Add = rf.findGroup("OPC_Add");
253  bool shouldPopulate_Add = grpOPC_Add.find("populateOPC").asInt() == 1;
254  if (shouldPopulate_Add) {
255  Bottle *objectList = grpOPC_Add.find("objectName").asList();
256  subPopulateObjects(objectList, false);
257 
258  Bottle *bodyPartList = grpOPC_Add.find("bodypartName").asList();
259  Bottle *bodyPartJointList = grpOPC_Add.find("bodypartJoint").asList();
260  subPopulateBodyparts(bodyPartList, bodyPartJointList, false);
261  }
262 
263  yDebug() << "configureOPC done";
264 }
265 
266 std::string proactiveTagging::getBodyPartNameForSpeech(const std::string bodypart) {
267  std::string out = bodypart;
268  if(bodypart == "index" || bodypart == "middle" || bodypart == "ring" || bodypart == "little") {
269  out = out + " finger";
270  }
271  return out;
272 }
bool setPasarPointing(bool on)
Ask pasar to increase saliency when a human is pointing to an object.
Definition: helpers.cpp:46
std::string getBestEntity(std::string sTypeTarget)
Loop through all objects in the OPC, and check their saliency.
Definition: helpers.cpp:70
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
STL namespace.
std::string grammarToString(const std::string &sPath)
Get the context path of a .grxml grammar, and return it as a string.
Definition: functions.cpp:58
Represent any physical entity (including objects and agents) that can be stored within the OPC...
Definition: object.h:35
#define ICUBCLIENT_OPC_ENTITY_BODYPART
Definition: tags.h:39
int m_joint_number
Joint number of the represented body part.
Definition: bodypart.h:38
void subPopulateObjects(yarp::os::Bottle *objectList, bool addOrRetrieve)
Definition: helpers.cpp:29
std::string getBodyPartNameForSpeech(const std::string bodypart)
Return a "nice" version of a body part name, eg given "index" as input, it returns "index finger"...
Definition: helpers.cpp:266
Represents a body part of the robot.
Definition: bodypart.h:29
void subPopulateBodyparts(yarp::os::Bottle *bodyPartList, yarp::os::Bottle *bodyPartJointList, bool addOrRetrieve)
Definition: helpers.cpp:198
void configureOPC(yarp::os::ResourceFinder &rf)
Read config file and fill OPC accordingly.
Definition: helpers.cpp:235
std::string name() const
Return the name of an entity (which has to be unique within the OPC)
Definition: entity.h:93
#define ICUBCLIENT_OPC_ENTITY_OBJECT
Definition: tags.h:38
double m_saliency
A measurement of the object saliency [0,1].
Definition: object.h:74
#define ICUBCLIENT_OPC_ENTITY_AGENT
Definition: tags.h:40
yarp::os::Bottle recogName(std::string entityType)
Recognize the name of an unknown entity (communicate with speech recognizer)
Definition: helpers.cpp:138