Project: engagement_recognition License: BSD Dependencies:
Used by:
None |
engagement_recognition/src/recognition/rnode/callbacks/vision.hGo to the documentation of this file.00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2010, Worcester Polytechnic Institute 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of Worcester Polytechnic Institute. nor the names 00018 * of its contributors may be used to endorse or promote products 00019 * derived from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 */ 00034 // @author Brett Ponsler (bponsler (at) wpi (dot) edu) 00035 #ifndef _VISION_H 00036 #define _VISION_H 00037 00038 void RNode::visionFacialGazeCallback(const engagement_msgs::PerformanceConstPtr& msg) 00039 { 00040 this->debug(24, "Entered %s %s callback", 00041 engagement::VISION_NAMESPACE.c_str(), 00042 engagement::PERFORMING_FACIAL_GAZE_TOPIC.c_str()); 00043 00044 // Make sure we have a valid message 00045 if (msg) 00046 { 00047 // Determine if this message was rejected or not 00048 bool rejected = false; 00049 00050 // Grab the message type from the constant pointer 00051 engagement_msgs::Performance temp_msg = *msg; 00052 00053 // Attempt to locate the actor 00054 Actor *actor = this->findActor(temp_msg.actor.id); 00055 00056 // Make sure the actor exists 00057 if (!actor) 00058 { 00059 this->warn("Actor [%s] does not exist.", 00060 temp_msg.actor.id.c_str()); 00061 rejected = true; 00062 } 00063 00064 // Now make sure the actor is not currently in the 00065 // same state as the message 00066 if (!rejected && actor->isFacialGaze() 00067 == (temp_msg.begin.value == bml_msgs::Flag::BEGIN)) 00068 { 00069 this->warn("Actor [%s] is %s in facial gaze state.", 00070 temp_msg.actor.id.c_str(), 00071 (temp_msg.begin.value == 00072 bml_msgs::Flag::BEGIN ? "already" : "not")); 00073 rejected = true; 00074 } 00075 00076 // Determine if this message was rejected. 00077 if (rejected) 00078 { 00079 this->error("Rejected '%s' message.", 00080 engagement::PERFORMING_FACIAL_GAZE_TOPIC.c_str()); 00081 return; 00082 } 00083 00084 this->debug(6, "Received a %s %s message.", 00085 engagement::VISION_NAMESPACE.c_str(), 00086 engagement::PERFORMING_FACIAL_GAZE_TOPIC.c_str()); 00087 00088 // Update the facial gaze state based on the received message 00089 actor->setFacialGaze((temp_msg.begin.value == bml_msgs::Flag::BEGIN)); 00090 00091 // If the facial gaze is starting, and the robot is in 00092 // facial gaze, shared gaze starts 00093 // If the facial gaze is ending, and the robot is in 00094 // facial gaze, shared gaze ends 00095 if (temp_msg.begin.value == bml_msgs::Flag::BEGIN 00096 && Robot::isFacialGaze(temp_msg.actor.id)) 00097 this->startSharedGaze(); 00098 else if (Robot::isFacialGaze(temp_msg.actor.id) 00099 && this->shared_gaze_start_ != UNDEFINED_TIME) 00100 this->endSharedGaze(); 00101 00102 // Publish the message internally 00103 this->relayToActors(engagement::VISION_NAMESPACE + "/" + 00104 engagement::PERFORMING_FACIAL_GAZE_TOPIC, &temp_msg); 00105 } 00106 00107 this->debug(24, "Exited %s %s callback", 00108 engagement::VISION_NAMESPACE.c_str(), 00109 engagement::PERFORMING_FACIAL_GAZE_TOPIC.c_str()); 00110 } 00111 00112 void RNode::visionLookCallback(const engagement_msgs::PerformanceConstPtr& msg) 00113 { 00114 this->debug(24, "Entered %s %s callback", 00115 engagement::VISION_NAMESPACE.c_str(), 00116 engagement::PERFORMING_LOOK_TOPIC.c_str()); 00117 00118 // Make sure we have a valid message 00119 if (msg) 00120 { 00121 // Determine if the message was rejected or not 00122 bool rejected = false; 00123 00124 // Grab the message type from the constant pointer 00125 engagement_msgs::Performance temp_msg = *msg; 00126 00127 // Keep the objects with the highest probability 00128 objects::keepHighest(temp_msg); 00129 00130 // Grab the vector of objects from the vector of entities 00131 std::vector<std::string> msg_objects = 00132 objects::getObjectsFromEntities(temp_msg.objects); 00133 00134 // Attempt to locate the actor 00135 Actor *actor = this->findActor(temp_msg.actor.id); 00136 00137 // Make sure the actor exists 00138 if (!actor) 00139 { 00140 this->warn("Actor [%s] does not exist.", 00141 temp_msg.actor.id.c_str()); 00142 rejected = true; 00143 } 00144 00145 // Determine if the look is starting or ending 00146 if (!rejected && temp_msg.begin.value) 00147 { 00148 // Check to see if the actor is already looking at these objects 00149 if (objects::contains(actor->getLooking(), msg_objects)) 00150 { 00151 this->warn("Actor [%s] is already looking at objects.", 00152 temp_msg.actor.id.c_str()); 00153 rejected = true; 00154 } 00155 } 00156 else if (!rejected && !temp_msg.begin.value) 00157 { 00158 // Check to see if the actor is not already looking at these objects 00159 if (!objects::contains(actor->getLooking(), msg_objects)) 00160 { 00161 this->warn("Actor [%s] is not looking at objects.", 00162 temp_msg.actor.id.c_str()); 00163 rejected = true; 00164 } 00165 } 00166 00167 // Check if the message was rejected 00168 if (rejected) 00169 { 00170 this->error("Rejected '%s' message.", 00171 engagement::PERFORMING_LOOK_TOPIC.c_str()); 00172 return; 00173 } 00174 00175 // Ensure that the actor is still alive 00176 if (ActorManager::isAlive(temp_msg.actor.id)) 00177 { 00178 this->debug(6, "Received a %s %s message.", 00179 engagement::VISION_NAMESPACE.c_str(), 00180 engagement::PERFORMING_LOOK_TOPIC.c_str()); 00181 00182 // Update the actor's recognizers with all of the objects 00183 actor->updateDirGazeRecognizers(msg_objects); 00184 00185 // Update the looking with the object with the highest probability 00186 actor->setLooking(msg_objects, temp_msg.begin.value); 00187 00188 // If the actor and robot were in facial gaze then end the shared gaze 00189 if (this->shared_gaze_start_ != UNDEFINED_TIME) 00190 this->endSharedGaze(); 00191 00192 // Publish the message internally 00193 this->relayToActors(engagement::VISION_NAMESPACE + "/" + 00194 engagement::PERFORMING_LOOK_TOPIC, &temp_msg); 00195 } 00196 } 00197 00198 this->debug(24, "Exited %s %s callback", 00199 engagement::VISION_NAMESPACE.c_str(), 00200 engagement::PERFORMING_LOOK_TOPIC.c_str()); 00201 } 00202 00203 void RNode::visionPointCallback(const engagement_msgs::PerformanceConstPtr& msg) 00204 { 00205 this->debug(24, "Entered %s %s callback", 00206 engagement::VISION_NAMESPACE.c_str(), 00207 engagement::PERFORMING_POINT_TOPIC.c_str()); 00208 00209 // Make sure we have a valid message 00210 if (msg) 00211 { 00212 // Determine if the message was rejected or not 00213 bool rejected = false; 00214 00215 // Grab the message type from the constant pointer 00216 engagement_msgs::Performance temp_msg = *msg; 00217 00218 // Keep the objects with the highest probability 00219 objects::keepHighest(temp_msg); 00220 00221 // Grab the vector of objects from the vector of entities 00222 std::vector<std::string> msg_objects = 00223 objects::getObjectsFromEntities(temp_msg.objects); 00224 00225 // Attempt to locate the actor 00226 Actor *actor = this->findActor(temp_msg.actor.id); 00227 00228 // Make sure the actor exists 00229 if (!actor) 00230 { 00231 this->warn("Actor [%s] does not exist.", 00232 temp_msg.actor.id.c_str()); 00233 rejected = true; 00234 } 00235 00236 // Make sure we're not yet rejected 00237 if (!rejected) 00238 { 00239 // Determine if the actor is currently looking at the same objects 00240 bool contained = 00241 objects::contains(actor->getPointing(), msg_objects); 00242 00243 // If we're starting the look, the actor cannot be looking at the objects 00244 // If we're ending the look, the actor must be looking at the objects 00245 if (temp_msg.begin.value && contained) 00246 { 00247 this->warn("Actor [%s] is already pointing at objects.", 00248 temp_msg.actor.id.c_str()); 00249 rejected = true; 00250 } 00251 else if (!temp_msg.begin.value && !contained) 00252 { 00253 this->warn("Actor [%s] is not pointing at objects.", 00254 temp_msg.actor.id.c_str()); 00255 rejected = true; 00256 } 00257 } 00258 00259 // Check if the message was rejected 00260 if (rejected) 00261 { 00262 this->error("Rejected '%s' message.", 00263 engagement::PERFORMING_POINT_TOPIC.c_str()); 00264 return; 00265 } 00266 00267 this->debug(6, "Received a %s %s message.", 00268 engagement::VISION_NAMESPACE.c_str(), 00269 engagement::PERFORMING_POINT_TOPIC.c_str()); 00270 00271 // Make sure the actor is still alive 00272 if (ActorManager::isAlive(temp_msg.actor.id)) 00273 { 00274 // Update the actor's recognizers with all of the objects 00275 actor->updateDirGazeRecognizers(msg_objects); 00276 00277 // Update the pointing with the object with the highest probability 00278 actor->setPointing(msg_objects, temp_msg.begin.value); 00279 00280 // Publish the message internally 00281 this->relayToActors(engagement::VISION_NAMESPACE + "/" + 00282 engagement::PERFORMING_POINT_TOPIC, &temp_msg); 00283 } 00284 } 00285 00286 this->debug(24, "Exited %s %s callback", 00287 engagement::VISION_NAMESPACE.c_str(), 00288 engagement::PERFORMING_POINT_TOPIC.c_str()); 00289 } 00290 00291 void RNode::visionShakeCallback(const engagement_msgs::PerformanceConstPtr& msg) 00292 { 00293 this->debug(24, "Entered %s %s callback", 00294 engagement::VISION_NAMESPACE.c_str(), 00295 engagement::PERFORMING_SHAKE_TOPIC.c_str()); 00296 00297 // Make sure we have a valid message 00298 if (msg) 00299 { 00300 // Grab the message type from the constant pointer 00301 engagement_msgs::Performance temp_msg = *msg; 00302 00303 // Make sure the actor exists 00304 if (!this->findActor(temp_msg.actor.id)) 00305 { 00306 this->warn("Actor [%s] does not exist.", 00307 temp_msg.actor.id.c_str()); 00308 this->error("Rejected '%s' message.", 00309 engagement::PERFORMING_SHAKE_TOPIC.c_str()); 00310 return; 00311 } 00312 00313 this->debug(6, "Received a %s %s message.", 00314 engagement::VISION_NAMESPACE.c_str(), 00315 engagement::PERFORMING_SHAKE_TOPIC.c_str()); 00316 00317 // Publish the message internally 00318 this->relayToActors(engagement::VISION_NAMESPACE + "/" + 00319 engagement::PERFORMING_SHAKE_TOPIC, &temp_msg); 00320 } 00321 00322 this->debug(24, "Exited %s %s callback", 00323 engagement::VISION_NAMESPACE.c_str(), 00324 engagement::PERFORMING_SHAKE_TOPIC.c_str()); 00325 } 00326 00327 void RNode::visionNodCallback(const engagement_msgs::PerformanceConstPtr& msg) 00328 { 00329 this->debug(24, "Entered %s %s callback", 00330 engagement::VISION_NAMESPACE.c_str(), 00331 engagement::PERFORMING_NOD_TOPIC.c_str()); 00332 00333 // Make sure we have a valid message 00334 if (msg) 00335 { 00336 // Grab the message type from the constant pointer 00337 engagement_msgs::Performance temp_msg = *msg; 00338 00339 // Make sure the actor exists 00340 if (!this->findActor(temp_msg.actor.id)) 00341 { 00342 this->warn("Actor [%s] does not exist.", 00343 temp_msg.actor.id.c_str()); 00344 this->error("Rejected '%s' message.", 00345 engagement::PERFORMING_NOD_TOPIC.c_str()); 00346 return; 00347 } 00348 00349 this->debug(6, "Received a %s %s message.", 00350 engagement::VISION_NAMESPACE.c_str(), 00351 engagement::PERFORMING_NOD_TOPIC.c_str()); 00352 00353 // Publish the message internally 00354 this->relayToActors(engagement::VISION_NAMESPACE + "/" + 00355 engagement::PERFORMING_NOD_TOPIC, &temp_msg); 00356 } 00357 00358 this->debug(24, "Exited %s %s callback", 00359 engagement::VISION_NAMESPACE.c_str(), 00360 engagement::PERFORMING_NOD_TOPIC.c_str()); 00361 } 00362 00363 void RNode::visionExtendedActionCallback(const engagement_msgs::PerformanceConstPtr& msg) 00364 { 00365 this->debug(24, "Entered %s %s callback", 00366 engagement::VISION_NAMESPACE.c_str(), 00367 engagement::PERFORMING_EXTENDED_ACTION_TOPIC.c_str()); 00368 00369 // Make sure we have a valid message 00370 if (msg) 00371 { 00372 // Grab the message type from the constant pointer 00373 engagement_msgs::Performance temp_msg = *msg; 00374 00375 // Make sure the actor exists 00376 if (!this->findActor(temp_msg.actor.id)) 00377 { 00378 this->warn("Actor [%s] does not exist.", 00379 temp_msg.actor.id.c_str()); 00380 this->error("Rejected '%s' message.", 00381 engagement::PERFORMING_EXTENDED_ACTION_TOPIC.c_str()); 00382 return; 00383 } 00384 00385 this->debug(6, "Received a %s %s message.", 00386 engagement::VISION_NAMESPACE.c_str(), 00387 engagement::PERFORMING_EXTENDED_ACTION_TOPIC.c_str()); 00388 00389 // Publish the message internally 00390 this->relayToActors(engagement::VISION_NAMESPACE + "/" + 00391 engagement::PERFORMING_EXTENDED_ACTION_TOPIC, &temp_msg); 00392 } 00393 00394 this->debug(24, "Exited %s %s callback", 00395 engagement::VISION_NAMESPACE.c_str(), 00396 engagement::PERFORMING_EXTENDED_ACTION_TOPIC.c_str()); 00397 } 00398 00399 void RNode::visionFaceCallback(const engagement_msgs::ActorIDStatusConstPtr& msg) 00400 { 00401 this->debug(24, "Entered %s %s callback", 00402 engagement::VISION_NAMESPACE.c_str(), 00403 engagement::VISION_FACE_TOPIC.c_str()); 00404 00405 // Make sure we have a valid message 00406 if (msg) 00407 { 00408 // Determine if this message was rejected or not 00409 bool rejected = false; 00410 00411 // Grab the message type from the constant pointer 00412 engagement_msgs::ActorIDStatus temp_msg = *msg; 00413 00414 Actor *act = this->findActor(temp_msg.actor.id); 00415 00416 if (temp_msg.status.value == bml_msgs::Flag::TRUE && act) 00417 { 00418 this->warn("Actor [%s] already exists.", 00419 temp_msg.actor.id.c_str()); 00420 rejected = true; 00421 } 00422 else if (temp_msg.status.value != bml_msgs::Flag::TRUE && !act) 00423 { 00424 this->warn("Actor [%s] does not exist.", 00425 temp_msg.actor.id.c_str()); 00426 rejected = true; 00427 } 00428 00429 // Check if the message was rejected 00430 if (rejected) 00431 { 00432 this->error("Rejected '%s' message.", 00433 engagement::VISION_FACE_TOPIC.c_str()); 00434 return; 00435 } 00436 00437 // Update the face based on the message received 00438 if (temp_msg.status.value == bml_msgs::Flag::TRUE) 00439 { 00440 this->debug(6, "Received a found %s %s message.", 00441 engagement::VISION_NAMESPACE.c_str(), 00442 engagement::VISION_FACE_TOPIC.c_str()); 00443 00444 // We found the actor 00445 this->foundActor(temp_msg.actor.id); 00446 00447 // Publish an Unengaged status message, since the actor 00448 // is originally unengaged 00449 engagement_msgs::ActorIDStatus actor_msg; 00450 00451 // Set the actor's id, and flag to false (for unengaged) 00452 actor_msg.actor = temp_msg.actor; 00453 actor_msg.status.value = bml_msgs::Flag::FALSE; 00454 00455 // Publish the engaged message, externally 00456 this->status_pub_.publish(actor_msg); 00457 this->relayToActors(engagement::RECOGNITION_NAMESPACE + "/" + 00458 engagement::HUMAN_NAMESPACE + "/" + 00459 engagement::RECOG_STATUS_TOPIC, &actor_msg); 00460 00461 // Propagate the message internally 00462 ros::spinOnce(); 00463 } 00464 else 00465 { 00466 this->debug(6, "Received a lost %s %s message.", 00467 engagement::VISION_NAMESPACE.c_str(), 00468 engagement::VISION_FACE_TOPIC.c_str()); 00469 00470 this->lostActor(temp_msg.actor.id); 00471 00472 // If we lost the actor we need to send the unengaged message 00473 // Create the Actor message 00474 engagement_msgs::ActorIDStatus actor_msg;; 00475 00476 // Set the message to be for this actor, and for unengaged 00477 actor_msg.actor = temp_msg.actor; 00478 actor_msg.status.value = bml_msgs::Flag::FALSE; 00479 00480 // Publish the unengaged message externally 00481 this->status_pub_.publish(actor_msg); 00482 this->relayToActors(engagement::RECOGNITION_NAMESPACE + "/" + 00483 engagement::HUMAN_NAMESPACE + "/" + 00484 engagement::RECOG_STATUS_TOPIC, &actor_msg); 00485 } 00486 } 00487 00488 this->debug(24, "Exited %s %s callback", 00489 engagement::VISION_NAMESPACE.c_str(), 00490 engagement::VISION_FACE_TOPIC.c_str()); 00491 } 00492 00493 #endif // _VISION_H |