Project: engagement_generation License: BSD Dependencies:
Used by:
None |
engagement_generation/src/edu/wpi/hri/gen/policy/GlancePolicy.javaGo 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 package edu.wpi.hri.gen.policy; 00035 00036 import java.util.Timer; 00037 import java.util.TimerTask; 00038 00039 import ros.NodeHandle; 00040 import ros.RosException; 00041 import ros.ServiceClient; 00042 import ros.pkg.engagement_srvs.srv.ActorStatistics; 00043 import edu.wpi.hri.gen.GenerationParams; 00044 import edu.wpi.hri.gen.comm.GazeKnowledge; 00045 import edu.wpi.hri.gen.comm.GazeListener; 00046 import edu.wpi.hri.log.Logger; 00047 import edu.wpi.hri.log.Logger.Colors; 00048 import edu.wpi.hri.log.Logger.LoggerLevel; 00049 00059 public class GlancePolicy extends GazeListener { 00060 00061 private final Logger logger; 00062 private Timer timer; 00063 private String lastFace; 00064 private boolean lastGazeWasFace; 00065 private final ServiceClient<ActorStatistics.Request, ActorStatistics.Response, ActorStatistics> statsSrv; 00066 00080 public GlancePolicy(NodeHandle handle, Logger logger, GazeKnowledge gaze, 00081 GazeListener next) { 00082 super(next); 00083 this.logger = logger.sub(Colors.POLICY, "GLANCE"); 00084 this.lastFace = ""; 00085 this.lastGazeWasFace = false; 00086 this.statsSrv = handle.serviceClient("recognition/statistics", 00087 new ActorStatistics()); 00088 gaze.addListener(this); 00089 this.logger.debug(LoggerLevel.INIT, "Created ..."); 00090 } 00091 00092 private TimerTask createTask() { 00093 return new TimerTask() { 00094 @Override 00095 public void run() { 00096 applyGlance(); 00097 } 00098 }; 00099 } 00100 00104 public void shutdown() { 00105 if (this.timer != null) { 00106 this.timer.cancel(); 00107 this.timer = null; 00108 } 00109 this.statsSrv.shutdown(); 00110 } 00111 00112 private void applyGlance() { 00113 this.logger.debug(LoggerLevel.POLICY_EXECUTION, "executing glance"); 00114 if (setTarget(this.lastFace)) { 00115 try { 00116 Thread.sleep(GenerationParams.GLANCE_DURATION_MS.getInt()); 00117 } catch (InterruptedException e) { 00118 this.logger.debug(LoggerLevel.ALL, 00119 "sleep error: " + e.getMessage()); 00120 } 00121 setTarget(null); 00122 } 00123 } 00124 00125 @Override 00126 public void gazeChanged(String target, boolean face, boolean lock) { 00127 if (face) { 00128 // since we have a face, cancel the timer so that the glance doesn't 00129 // occur 00130 this.logger.debug(LoggerLevel.IO, "received gaze to face"); 00131 this.lastFace = target; 00132 if (this.timer != null) { 00133 this.timer.cancel(); 00134 this.timer = null; 00135 } 00136 } else if (lastGazeWasFace) { 00137 // OOOOO we started looking at something else, cancel the timer if 00138 // it exists and start a new one to look back at the face 00139 this.logger.debug(LoggerLevel.IO, "received gaze away from face"); 00140 this.timer = new Timer(); 00141 int mtbce = this.findMTBCE(); 00142 double factor = GenerationParams.GLANCE_DELAY_FACTOR.getDouble(); 00143 long glance = (long) (factor * mtbce); 00144 this.logger.debug(LoggerLevel.MATH, "MTBCE: [" + mtbce 00145 + "] and factor [" + factor + "] becomes glance [" + glance 00146 + "]"); 00147 if (glance < 0) { 00148 logger.error("Glance time should not be negative"); 00149 glance = -glance; 00150 } 00151 glance = Math.max(GenerationParams.GLANCE_DELAY_MIN.getInt(), Math 00152 .min(GenerationParams.GLANCE_DELAY_MAX.getInt(), glance)); 00153 this.logger.debug(LoggerLevel.MATH, "Limited glance to [" + glance 00154 + "]"); 00155 this.timer.schedule(this.createTask(), glance); 00156 } 00157 this.lastGazeWasFace = face; 00158 } 00159 00160 private int findMTBCE() { 00161 try { 00162 ActorStatistics.Request req = new ActorStatistics.Request(); 00163 req.actor.id = this.lastFace; 00164 ActorStatistics.Response res = this.statsSrv.call(req); 00165 return res.recent_mean_tbce; 00166 } catch (RosException e) { 00167 this.logger 00168 .warn("Failed to retrieve MTBCE, is recognition running?"); 00169 this.logger.printThrowable(LoggerLevel.ALL, e); 00170 return 0; 00171 } 00172 } 00173 } |