hri.cpp
Go to the documentation of this file.
1 // Copyright 2022 PAL Robotics S.L.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 //
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 //
13 // * Neither the name of the PAL Robotics S.L. nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 
29 #include "hri/hri.h"
30 #include <algorithm>
31 #include <functional>
32 #include <iterator>
33 #include <memory>
34 #include <tuple>
35 #include <utility>
36 #include "hri/body.h"
37 #include "hri/face.h"
38 #include "hri/person.h"
39 #include "hri_msgs/IdsList.h"
40 
41 using namespace std;
42 using namespace hri;
43 
44 HRIListener::HRIListener() : _reference_frame("base_link"), _tf_listener(_tf_buffer)
45 {
46  init();
47 }
48 
50 {
51  ROS_DEBUG("Closing the HRI Listener");
52 
53  faces.clear();
54 
55  for (auto& sub : feature_subscribers_)
56  {
57  sub.second.shutdown();
58  }
59 }
60 
61 
62 map<ID, FaceWeakConstPtr> HRIListener::getFaces() const
63 {
64  map<ID, FaceWeakConstPtr> result;
65 
66  // creates a map of *weak* pointers from the internally managed list of
67  // shared pointers
68  for (auto const& f : faces)
69  {
70  result[f.first] = f.second;
71  }
72 
73  return result;
74 }
75 
76 map<ID, BodyWeakConstPtr> HRIListener::getBodies() const
77 {
78  map<ID, BodyWeakConstPtr> result;
79 
80  // creates a map of *weak* pointers from the internally managed list of
81  // shared pointers
82  for (auto const& f : bodies)
83  {
84  result[f.first] = f.second;
85  }
86 
87  return result;
88 }
89 
90 map<ID, VoiceWeakConstPtr> HRIListener::getVoices() const
91 {
92  map<ID, VoiceWeakConstPtr> result;
93 
94  // creates a map of *weak* pointers from the internally managed list of
95  // shared pointers
96  for (auto const& f : voices)
97  {
98  result[f.first] = f.second;
99  }
100 
101  return result;
102 }
103 
104 map<ID, PersonWeakConstPtr> HRIListener::getPersons() const
105 {
106  map<ID, PersonWeakConstPtr> result;
107 
108  vector<PersonConstPtr> aliased;
109 
110  // creates a map of *weak* pointers from the internally managed list of
111  // shared pointers
112  for (auto const& f : persons)
113  {
114  if (f.second->alias().empty())
115  {
116  result[f.first] = f.second;
117  }
118  else
119  {
120  aliased.push_back(f.second);
121  }
122  }
123 
124  for (auto const& p : aliased)
125  {
126  if (result.count(p->alias()) != 0)
127  {
128  result[p->id()] = result[p->alias()];
129  }
130  else // ouch! the person points to an inexistant alias! this should not happen
131  {
132  assert(false);
133  }
134  }
135 
136  return result;
137 }
138 
139 map<ID, PersonWeakConstPtr> HRIListener::getTrackedPersons() const
140 {
141  map<ID, PersonWeakConstPtr> result;
142 
143  vector<PersonConstPtr> aliased;
144 
145  // creates a map of *weak* pointers from the internally managed list of
146  // shared pointers
147  for (auto const& f : tracked_persons)
148  {
149  if (f.second->alias().empty())
150  {
151  result[f.first] = f.second;
152  }
153  else
154  {
155  aliased.push_back(f.second);
156  }
157  }
158 
159  for (auto const& p : aliased)
160  {
161  if (result.count(p->alias()) != 0)
162  {
163  result[p->id()] = result[p->alias()];
164  }
165  else // ouch! the person points to an inexistant alias! this should not happen.
166  {
167  assert(false);
168  }
169  }
170 
171  return result;
172 }
173 
175 {
176  ROS_DEBUG("Initialising the HRI Listener");
177 
178 
180  "/humans/faces/tracked", 1,
182 
184  "/humans/bodies/tracked", 1,
186 
188  "/humans/voices/tracked", 1,
190 
192  "/humans/persons/tracked", 1,
194 
196  "/humans/persons/known", 1,
198 }
199 
200 void HRIListener::onTrackedFeature(FeatureType feature, hri_msgs::IdsListConstPtr tracked)
201 {
202  // update the current list of tracked feature (face, body...) with
203  // what has just been received on the respective /tracked topic.
204 
205  set<ID> new_ids;
206  for (auto const& id : tracked->ids)
207  {
208  new_ids.insert(ID(id));
209  }
210 
211  set<ID> to_remove;
212  set<ID> to_add;
213 
214  set<ID> current_ids;
215 
216  switch (feature)
217  {
218  case FeatureType::face:
219  for (auto const& kv : faces)
220  {
221  current_ids.insert(kv.first);
222  }
223  break;
224  case FeatureType::body:
225  for (auto const& kv : bodies)
226  {
227  current_ids.insert(kv.first);
228  }
229  break;
230  case FeatureType::voice:
231  for (auto const& kv : voices)
232  {
233  current_ids.insert(kv.first);
234  }
235  break;
236  case FeatureType::person:
237  for (auto const& kv : persons)
238  {
239  current_ids.insert(kv.first);
240  }
241  break;
243  for (auto const& kv : tracked_persons)
244  {
245  current_ids.insert(kv.first);
246  }
247  break;
248  }
249 
250 
251 
252  for (auto id : new_ids)
253  {
254  if (current_ids.find(id) == current_ids.end())
255  {
256  to_add.insert(id);
257  }
258  }
259 
260  for (auto id : current_ids)
261  {
262  if (new_ids.find(id) == new_ids.end())
263  {
264  to_remove.insert(id);
265  }
266  }
267 
268  switch (feature)
269  {
270  case FeatureType::face:
271  for (auto id : to_remove)
272  {
273  faces.erase(id);
274 
275  // invoke all the callbacks
276  for (auto& cb : face_lost_callbacks)
277  {
278  cb(id);
279  }
280  }
281  break;
282  case FeatureType::body:
283  for (auto id : to_remove)
284  {
285  bodies.erase(id);
286 
287  // invoke all the callbacks
288  for (auto& cb : body_lost_callbacks)
289  {
290  cb(id);
291  }
292  }
293  break;
294  case FeatureType::voice:
295  for (auto id : to_remove)
296  {
297  voices.erase(id);
298 
299  // invoke all the callbacks
300  for (auto& cb : voice_lost_callbacks)
301  {
302  cb(id);
303  }
304  }
305  break;
307  for (auto id : to_remove)
308  {
309  tracked_persons.erase(id);
310 
311  // also erase the *aliases* of this ID
312  vector<ID> aliases;
313  for (const auto& p : tracked_persons)
314  {
315  if (p.second->alias() == id)
316  {
317  aliases.push_back(p.first);
318  }
319  }
320  for (auto alias : aliases)
321  {
322  tracked_persons.erase(alias);
323  }
324 
325  // invoke all the callbacks
326  for (auto& cb : person_tracked_lost_callbacks)
327  {
328  cb(id);
329  }
330  }
331  break;
332  case FeatureType::person:
333  for (auto id : to_remove)
334  {
335  persons.erase(id);
336 
337  // also erase the *aliases* of this ID
338  vector<ID> aliases;
339  for (const auto& p : persons)
340  {
341  if (p.second->alias() == id)
342  {
343  aliases.push_back(p.first);
344  }
345  }
346  for (auto alias : aliases)
347  {
348  persons.erase(alias);
349  }
350 
351  // invoke all the callbacks
352  for (auto& cb : person_lost_callbacks)
353  {
354  cb(id);
355  }
356  }
357  break;
358  }
359 
360  switch (feature)
361  {
362  case FeatureType::face:
363  for (auto id : to_add)
364  {
365  auto face = make_shared<Face>(id, node_, &_tf_buffer, _reference_frame);
366  face->init();
367  faces.insert({ id, face });
368 
369  // invoke all the callbacks
370  for (auto& cb : face_callbacks)
371  {
372  cb(face);
373  }
374  }
375  break;
376  case FeatureType::body:
377  for (auto id : to_add)
378  {
379  auto body = make_shared<Body>(id, node_, &_tf_buffer, _reference_frame);
380  body->init();
381  bodies.insert({ id, body });
382 
383  // invoke all the callbacks
384  for (auto& cb : body_callbacks)
385  {
386  cb(body);
387  }
388  }
389  break;
390  case FeatureType::voice:
391  for (auto id : to_add)
392  {
393  auto voice = make_shared<Voice>(id, node_, &_tf_buffer, _reference_frame);
394  voice->init();
395  voices.insert({ id, voice });
396 
397  // invoke all the callbacks
398  for (auto& cb : voice_callbacks)
399  {
400  cb(voice);
401  }
402  }
403  break;
404  case FeatureType::person:
405  for (auto id : to_add)
406  {
407  auto person = make_shared<Person>(id, this, node_, &_tf_buffer, _reference_frame);
408  person->init();
409  persons.insert({ id, person });
410 
411  // invoke all the callbacks
412  for (auto& cb : person_callbacks)
413  {
414  cb(person);
415  }
416  }
417  break;
419  for (auto id : to_add)
420  {
421  auto person = make_shared<Person>(id, this, node_, &_tf_buffer, _reference_frame);
422  person->init();
423  tracked_persons.insert({ id, person });
424 
425  // invoke all the callbacks
426  for (auto& cb : person_tracked_callbacks)
427  {
428  cb(person);
429  }
430  }
431  break;
432  }
433 }
434 
hri::HRIListener::person_callbacks
std::vector< std::function< void(PersonConstPtr)> > person_callbacks
Definition: hri.h:235
hri
Definition: base.h:38
hri::HRIListener::faces
std::map< ID, FaceConstPtr > faces
Definition: hri.h:220
hri::HRIListener::body_callbacks
std::vector< std::function< void(BodyWeakConstPtr)> > body_callbacks
Definition: hri.h:225
face.h
hri::HRIListener::tracked_persons
std::map< ID, PersonConstPtr > tracked_persons
Definition: hri.h:237
hri::HRIListener::body_lost_callbacks
std::vector< std::function< void(ID)> > body_lost_callbacks
Definition: hri.h:226
hri::HRIListener::person_lost_callbacks
std::vector< std::function< void(ID)> > person_lost_callbacks
Definition: hri.h:236
hri::HRIListener::person_tracked_lost_callbacks
std::vector< std::function< void(ID)> > person_tracked_lost_callbacks
Definition: hri.h:239
hri::HRIListener::persons
std::map< ID, PersonConstPtr > persons
Definition: hri.h:234
hri::HRIListener::~HRIListener
~HRIListener()
Definition: hri.cpp:49
hri::body
@ body
Definition: base.h:48
hri::HRIListener::bodies
std::map< ID, BodyConstPtr > bodies
Definition: hri.h:224
hri::HRIListener::getBodies
std::map< ID, BodyWeakConstPtr > getBodies() const
Returns the list of currently detected bodies, mapped to their IDs.
Definition: hri.cpp:76
hri::HRIListener::getPersons
std::map< ID, PersonWeakConstPtr > getPersons() const
Returns the list of all known persons, whether or not they are currently actively detected (eg,...
Definition: hri.cpp:104
f
f
hri::tracked_person
@ tracked_person
Definition: base.h:46
hri::HRIListener::getTrackedPersons
std::map< ID, PersonWeakConstPtr > getTrackedPersons() const
Returns the list of currently detected persons, mapped to their IDs.
Definition: hri.cpp:139
ROS_DEBUG
#define ROS_DEBUG(...)
hri::HRIListener::node_
ros::NodeHandle node_
Definition: hri.h:212
hri::HRIListener::person_tracked_callbacks
std::vector< std::function< void(PersonConstPtr)> > person_tracked_callbacks
Definition: hri.h:238
hri::HRIListener::_reference_frame
std::string _reference_frame
Definition: hri.h:241
hri.h
hri::HRIListener::face_callbacks
std::vector< std::function< void(FaceWeakConstPtr)> > face_callbacks
Definition: hri.h:221
hri::HRIListener::voice_lost_callbacks
std::vector< std::function< void(ID)> > voice_lost_callbacks
Definition: hri.h:232
ros::NodeHandle::subscribe
Subscriber subscribe(const std::string &topic, uint32_t queue_size, const boost::function< void(C)> &callback, const VoidConstPtr &tracked_object=VoidConstPtr(), const TransportHints &transport_hints=TransportHints())
body.h
hri::HRIListener::getFaces
std::map< ID, FaceWeakConstPtr > getFaces() const
Returns the list of currently detected faces, mapped to their IDs.
Definition: hri.cpp:62
hri::face
@ face
Definition: base.h:47
hri::HRIListener::feature_subscribers_
std::map< FeatureType, ros::Subscriber > feature_subscribers_
Definition: hri.h:218
std
hri::HRIListener::init
void init()
Definition: hri.cpp:174
hri::voice
@ voice
Definition: base.h:49
hri::ID
std::string ID
Definition: base.h:40
hri::HRIListener::getVoices
std::map< ID, VoiceWeakConstPtr > getVoices() const
Returns the list of currently detected voices, mapped to their IDs.
Definition: hri.cpp:90
hri::HRIListener::_tf_buffer
tf2_ros::Buffer _tf_buffer
Definition: hri.h:242
hri::HRIListener::face_lost_callbacks
std::vector< std::function< void(ID)> > face_lost_callbacks
Definition: hri.h:222
hri::HRIListener::voice_callbacks
std::vector< std::function< void(VoiceWeakPtr)> > voice_callbacks
Definition: hri.h:231
hri::HRIListener::voices
std::map< ID, VoiceConstPtr > voices
Definition: hri.h:228
hri::HRIListener::onTrackedFeature
void onTrackedFeature(FeatureType feature, hri_msgs::IdsListConstPtr tracked)
Definition: hri.cpp:200
person.h
hri::person
@ person
Definition: base.h:45
hri::FeatureType
FeatureType
Definition: base.h:42


libhri
Author(s): Séverin Lemaignan
autogenerated on Thu Jul 6 2023 02:43:58