Project: engagement_recognition License: BSD Dependencies:
Used by:
None |
engagement_recognition/src/recognition/rnode/callbacks/recognition.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 _RECOGNITION_H 00036 #define _RECOGNITION_H 00037 00038 #include <ros/callback_queue.h> 00039 #include "engagement_msgs/APAction.h" 00040 00041 bool RNode::recogStatisticsService(engagement_srvs::ActorStatistics::Request &req, 00042 engagement_srvs::ActorStatistics::Response &res) 00043 { 00044 this->debug(24, "Entered %s %s callback", 00045 engagement::RECOGNITION_NAMESPACE.c_str(), 00046 engagement::RECOG_STATISTICS_TOPIC.c_str()); 00047 00048 // Extract the request object from the message 00049 const engagement_msgs::ActorID temp_msg = req.actor; 00050 00051 // Attempt to find the actor 00052 Actor *actor = this->findActor(temp_msg.id); 00053 00054 // Ensure that the actor exists 00055 if (!actor) 00056 { 00057 this->warn("Actor [%s] does not exist.", temp_msg.id.c_str()); 00058 this->error("Rejected '%s' message.", 00059 engagement::RECOG_STATISTICS_TOPIC.c_str()); 00060 return false; 00061 } 00062 00063 // Grab the statistics for this actor 00064 std::vector<unsigned long> stats = actor->getStatistics(); 00065 00066 // Make sure we have the correct number of elements 00067 // in the vector 00068 if (stats.size() != 14) 00069 return false; 00070 00071 this->debug(6, "Received a %s %s message.", 00072 engagement::RECOGNITION_NAMESPACE.c_str(), 00073 engagement::RECOG_STATISTICS_TOPIC.c_str()); 00074 00075 // Store all the overall statistics 00076 res.mean_tbce = stats.at(0); 00077 res.max_tbce = stats.at(1); 00078 res.mean_delay = stats.at(2); 00079 res.max_delay = stats.at(3); 00080 00081 // TODO: ADD MEAN AND MAX DURATION TO THE STATISTICS 00082 // res.mean_duration = stats.at(4); 00083 // res.max_duration = stats.at(5); 00084 00085 res.failure_rate = stats.at(6); 00086 00087 // Store all of the recent statistics 00088 res.recent_mean_tbce = stats.at(7); 00089 res.recent_max_tbce = stats.at(8); 00090 res.recent_mean_delay = stats.at(9); 00091 res.recent_max_delay = stats.at(10); 00092 00093 // TODO: ADD RECENT MEAN AND MAX DURATION TO THE STATISTICS 00094 // res.recent_mean_duration = stats.at(11); 00095 // res.recent_max_duration = stats.at(12); 00096 00097 res.recent_failure_rate = stats.at(13); 00098 00099 this->debug(24, "Exiting %s %s callback", 00100 engagement::RECOGNITION_NAMESPACE.c_str(), 00101 engagement::RECOG_STATISTICS_TOPIC.c_str()); 00102 00103 return true; 00104 } 00105 00106 bool RNode::recogDirGazeService(engagement_srvs::RobotDirectedGaze::Request &req, 00107 engagement_srvs::RobotDirectedGaze::Response &res) 00108 { 00109 this->debug(24, "Entered %s %s callback", 00110 engagement::RECOGNITION_NAMESPACE.c_str(), 00111 engagement::RECOG_DIRECTED_GAZE_TOPIC.c_str()); 00112 00113 // Extract the request object from the message 00114 const engagement_srvs::RobotDirectedGaze::Request temp_msg = req; 00115 00116 // Grab the vector of objects from the vector of entities 00117 std::vector<std::string> msg_objects = 00118 objects::getObjectsFromEntities(temp_msg.objects); 00119 00120 Actor *actor = this->findActor(temp_msg.actor.id); 00121 00122 // Ensure that the actor exists 00123 if (!actor) 00124 { 00125 this->warn("Actor [%s] does not exist.", temp_msg.actor.id.c_str()); 00126 this->error("Rejected '%s' message.", 00127 engagement::RECOG_DIRECTED_GAZE_TOPIC.c_str()); 00128 00129 res.result.value= bml_msgs::Flag::INVALID; 00130 return false; 00131 } 00132 00133 // If the directed gaze is starting, add the objects, otherwise remove them 00134 if (temp_msg.done.value == bml_msgs::Flag::NOT_DONE) 00135 { 00136 // Keep track of where the robot is looking 00137 Robot::setLookAt(true, msg_objects); 00138 00139 // If the robot is pointing as well, keep track of where the 00140 // robot is pointing 00141 Robot::setPointAt(true, msg_objects); 00142 00143 // If the shared gaze was already started, it just ended 00144 if (this->shared_gaze_start_ != UNDEFINED_TIME) 00145 this->endSharedGaze(); 00146 } 00147 00148 this->debug(6, "Received a %s %s message.", 00149 engagement::RECOGNITION_NAMESPACE.c_str(), 00150 engagement::RECOG_DIRECTED_GAZE_TOPIC.c_str()); 00151 00152 // First spawn a thread 00153 this->spawnThread(); 00154 00155 // Publish the message to the corresponding actor, which will block 00156 // until the recognizer succeeds or fails 00157 ServiceResponse status = actor->dirGazeService(&req, 00158 msg_objects); 00159 00160 // Set the response flag accordingly 00161 if (status.isSucceeded()) 00162 res.result.value = bml_msgs::Flag::TRUE; 00163 else 00164 res.result.value= bml_msgs::Flag::FALSE; 00165 00166 // Always send success in the event that we're degraded 00167 if (EngagementParams::isDegraded()) 00168 { 00169 this->purple("Sending success for directed gaze."); 00170 res.result.value = bml_msgs::Flag::TRUE; 00171 } 00172 00173 this->debug(24, "Exited %s %s callback", 00174 engagement::RECOGNITION_NAMESPACE.c_str(), 00175 engagement::RECOG_DIRECTED_GAZE_TOPIC.c_str()); 00176 00177 return true; 00178 } 00179 00180 bool RNode::recogMFGazeService(engagement_srvs::RobotMutualFacialGaze::Request &req, 00181 engagement_srvs::RobotMutualFacialGaze::Response &res) 00182 { 00183 this->debug(24, "Entered %s %s callback", 00184 engagement::RECOGNITION_NAMESPACE.c_str(), 00185 engagement::RECOG_MUTUAL_FACIAL_GAZE_TOPIC.c_str()); 00186 00187 // Extract the request object from the message 00188 engagement_msgs::ActorID temp_msg = req.actor; 00189 00190 Actor *actor = this->findActor(temp_msg.id); 00191 00192 // Ensure that the actor exists 00193 if (!actor) 00194 { 00195 this->warn("Actor [%s] does not exist.", temp_msg.id.c_str()); 00196 00197 this->error("Rejected '%s' message.", 00198 engagement::RECOG_MUTUAL_FACIAL_GAZE_TOPIC.c_str()); 00199 00200 res.result.value= bml_msgs::Flag::INVALID; 00201 00202 return false; 00203 } 00204 00205 // Keep track of where the robot is looking 00206 Robot::setFacialGaze(true, temp_msg.id); 00207 00208 // Since the facial gaze is starting, if the actor is already in facial 00209 // gaze then the shared gaze starts 00210 if (actor->isFacialGaze()) 00211 this->startSharedGaze(); 00212 00213 this->debug(6, "Received a %s %s message.", 00214 engagement::RECOGNITION_NAMESPACE.c_str(), 00215 engagement::RECOG_MUTUAL_FACIAL_GAZE_TOPIC.c_str()); 00216 00217 // First spawn a thread 00218 this->spawnThread(); 00219 00220 // Publish the message to the corresponding actor, which will block 00221 // until the recognizer succeeds or fails 00222 ServiceResponse status = actor->mfGazeService(&req); 00223 00224 // Set the response flag accordingly 00225 if (status.isSucceeded()) 00226 res.result.value = bml_msgs::Flag::TRUE; 00227 else 00228 res.result.value = bml_msgs::Flag::FALSE; 00229 00230 // Always send success in the event that we're degraded 00231 if (EngagementParams::isDegraded()) 00232 { 00233 this->purple("Sending success for mutual facial gaze."); 00234 res.result.value = bml_msgs::Flag::TRUE; 00235 } 00236 00237 this->debug(24, "Exited %s %s callback", 00238 engagement::RECOGNITION_NAMESPACE.c_str(), 00239 engagement::RECOG_MUTUAL_FACIAL_GAZE_TOPIC.c_str()); 00240 00241 return true; 00242 } 00243 00244 bool RNode::recogAdjacencyPairService(engagement_srvs::RobotAdjacencyPair::Request &req, 00245 engagement_srvs::RobotAdjacencyPair::Response &res) 00246 { 00247 this->debug(24, "Entered %s %s callback", 00248 engagement::RECOGNITION_NAMESPACE.c_str(), 00249 engagement::RECOG_ADJACENCY_PAIR_TOPIC.c_str()); 00250 00251 // Extract the request object from the message 00252 engagement_msgs::ActorID temp_msg = req.actor; 00253 00254 Actor *actor = this->findActor(temp_msg.id); 00255 00256 // Ensure that the actor exists 00257 if (!actor) 00258 { 00259 this->warn("Actor [%s] does not exist.", temp_msg.id.c_str()); 00260 this->error("Rejected '%s' message.", 00261 engagement::RECOG_ADJACENCY_PAIR_TOPIC.c_str()); 00262 00263 res.result.value= bml_msgs::Flag::INVALID; 00264 return false; 00265 } 00266 00267 this->debug(6, "Received a %s %s message.", 00268 engagement::RECOGNITION_NAMESPACE.c_str(), 00269 engagement::RECOG_ADJACENCY_PAIR_TOPIC.c_str()); 00270 00271 // Set the robot's waiting state to true 00272 Robot::setWaiting(true); 00273 00274 // First spawn a thread 00275 this->spawnThread(); 00276 00277 // Publish the message to the corresponding actor, which will block 00278 // until the recognizer succeeds or fails 00279 APServiceResponse status = actor->adjPairService(&req); 00280 00281 // Set the robot's waiting state to false 00282 Robot::setWaiting(false); 00283 00284 // Determine which action was used to complete the AP, 00285 // only if the event succeeded 00286 if (status.isSucceeded()) 00287 { 00288 // Select which action was used 00289 if (status.isNod()) 00290 res.action.value = engagement_msgs::APAction::NOD; 00291 else if (status.isShake()) 00292 res.action.value = engagement_msgs::APAction::SHAKE; 00293 else if (status.isSpeech()) 00294 res.action.value = engagement_msgs::APAction::SPEECH; 00295 else if (status.isPoint()) 00296 res.action.value = engagement_msgs::APAction::POINT; 00297 else if (status.isLook()) 00298 res.action.value = engagement_msgs::APAction::LOOK; 00299 else if (status.isExtendedAction()) 00300 res.action.value = engagement_msgs::APAction::EXTENDED_ACTION; 00301 else 00302 res.action.value = engagement_msgs::APAction::NO_ACTION; 00303 00304 // No matter what the event succeeded 00305 res.result.value = bml_msgs::Flag::TRUE; 00306 res.action.data = status.getData(); 00307 } 00308 else 00309 { 00310 // The event failed, with no action 00311 res.action.value = engagement_msgs::APAction::NO_ACTION; 00312 res.result.value = bml_msgs::Flag::FALSE; 00313 } 00314 00315 // Always send success in the event that we're degraded 00316 if (EngagementParams::isDegraded()) 00317 { 00318 this->purple("Sending success for adjacency pair."); 00319 res.result.value = bml_msgs::Flag::TRUE; 00320 } 00321 00322 this->debug(24, "Exited %s %s callback [action: %d] [result: %d]", 00323 engagement::RECOGNITION_NAMESPACE.c_str(), 00324 engagement::RECOG_ADJACENCY_PAIR_TOPIC.c_str(), 00325 res.action.value, res.result.value); 00326 00327 return true; 00328 } 00329 00330 #endif // _RECOGNITION_H |