Project: engagement_generation License: BSD Dependencies:
Used by:
None |
engagement_generation/src/edu/wpi/hri/gen/policy/ref/ReferenceOptions.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.ref; 00035 00036 import java.util.ArrayList; 00037 import java.util.List; 00038 00039 import edu.wpi.hri.bml.behavior.Behavior; 00040 import edu.wpi.hri.bml.behavior.EmitBehavior; 00041 import edu.wpi.hri.bml.behavior.GazeBehavior; 00042 import edu.wpi.hri.bml.behavior.GestureBehavior; 00043 import edu.wpi.hri.bml.behavior.SpeechBehavior; 00044 import edu.wpi.hri.gen.comm.BMLEmitListener; 00045 import edu.wpi.hri.gen.comm.SituationKnowledge; 00046 import edu.wpi.hri.gen.ebml.ReferenceBehavior; 00047 import edu.wpi.hri.gen.ebml.SpeechOption; 00048 import edu.wpi.hri.log.Logger; 00049 import edu.wpi.hri.log.Logger.Colors; 00050 import edu.wpi.hri.log.Logger.LoggerLevel; 00051 00061 class ReferenceOptions { 00062 00063 protected final Logger logger; 00064 private List<GestureSpeechPair> pairs; 00065 private List<GestureSpeechPair> unreliable; 00066 private final ReferenceBehavior ref; 00067 private GestureSpeechPair best; 00068 private ReferenceOptions next; 00069 protected final SituationKnowledge situation; 00070 00082 ReferenceOptions(Logger logger, ReferenceBehavior behavior, 00083 SituationKnowledge situation) { 00084 this.logger = logger.sub(Colors.REFERENCE, "RO-" + behavior.getID()); 00085 this.situation = situation; 00086 00087 this.ref = behavior; 00088 this.pairs = filterReliable(generateOptions(behavior), behavior, 00089 situation); 00090 this.best = null; 00091 this.next = null; 00092 this.logger.debug(LoggerLevel.INIT, "Created ..."); 00093 } 00094 00095 protected List<GestureSpeechPair> generateOptions(ReferenceBehavior behavior) { 00096 String target = behavior.getTarget(); 00097 List<GestureSpeechPair> pairs = new ArrayList<GestureSpeechPair>(); 00098 // Create all of the possible gesture-speech pairs from the reference 00099 for (SpeechOption so : behavior.getSpeechOptions()) { 00100 if (!so.isDeictic()) { 00101 pairs.add(new GestureSpeechPair(logger, GestureOption.LAMBDA, 00102 so, target, situation)); 00103 pairs.add(new GestureSpeechPair(logger, GestureOption.GAZE, so, 00104 target, situation)); 00105 pairs.add(new GestureSpeechPair(logger, 00106 GestureOption.DIRECTED_GAZE, so, target, situation)); 00107 } 00108 pairs.add(new GestureSpeechPair(logger, 00109 GestureOption.DIRECTED_GAZE_POINTING, so, target, situation)); 00110 } 00111 return pairs; 00112 } 00113 00114 protected List<GestureSpeechPair> filterReliable( 00115 List<GestureSpeechPair> pairs, ReferenceBehavior behavior, 00116 SituationKnowledge situation) { 00117 // then there is no sense in keeping those that don't have the minimum 00118 // reliability requested, so remove them 00119 List<GestureSpeechPair> toKeep = new ArrayList<GestureSpeechPair>(); 00120 unreliable = new ArrayList<GestureSpeechPair>(); 00121 this.logger.debug(LoggerLevel.MATH, "filtering for reliability"); 00122 00123 for (GestureSpeechPair gsp : pairs) { 00124 double reliability = reliabilityOf(gsp); 00125 00126 if (reliability > behavior.getMinReliability()) 00127 toKeep.add(gsp); 00128 else 00129 unreliable.add(gsp); 00130 } 00131 return toKeep; 00132 } 00133 00134 private double reliabilityOf(GestureSpeechPair gsp) { 00135 DistractorSet dist = gsp.getDistractors(situation); 00136 if (dist == null) 00137 return 0.0; 00138 double inherent = gsp.getInherentReliability(); 00139 return (1.0 / (dist.size() + (1.0 / inherent))); 00140 } 00141 00147 public ReferenceBehavior getBehavior() { 00148 return ref; 00149 } 00150 00157 void setNextOption(ReferenceOptions next) { 00158 this.next = next; 00159 } 00160 00164 boolean isLast() { 00165 return next == null; 00166 } 00167 00173 SpeechBehavior createSpeech() { 00174 return new SpeechBehavior(logger, ref.getID() + "-speech", best 00175 .getSpeech().getText(), null, ref.isRequired()); 00176 } 00177 00183 GazeBehavior createGaze() { 00184 if (this.best != null) 00185 return this.best.getGesture().createGaze(logger, ref.getID(), 00186 ref.getTarget(), ref.isRequired()); 00187 else 00188 return null; 00189 } 00190 00198 GestureBehavior createPoint(SituationKnowledge situation) { 00199 if (this.best != null) { 00200 boolean sameHand = false; 00201 00202 // if the next is null, we obviously should home the hand. 00203 if (this.next != null) { 00204 boolean nextRight = situation.isObjectOnRight(next.ref 00205 .getTarget()); 00206 boolean thisRight = situation.isObjectOnRight(this.ref 00207 .getTarget()); 00208 boolean nextPointing = this.next.createPoint(situation) != null; 00209 sameHand = (nextRight == thisRight) && nextPointing; 00210 00211 this.logger.debug(LoggerLevel.ALL, "this object is [" 00212 + thisRight + "] next object is [" + nextRight 00213 + "] next is pointing [" + nextPointing 00214 + "]and same is [" + sameHand + "]"); 00215 } else { 00216 // if it is null, just log that is true. 00217 this.logger.debug(LoggerLevel.ALL, 00218 "this next object is null and same is [" + sameHand 00219 + "]"); 00220 } 00221 return this.best.getGesture().createGesture(logger, ref.getID(), 00222 ref.getTarget(), ref.isRequired(), !sameHand); 00223 } else 00224 return null; 00225 } 00226 00239 EmitBehavior createDG(String actor, BMLEmitListener emit, Behavior source) { 00240 if (this.best != null) { 00241 return this.best.getGesture().createDG(source, actor, 00242 ref.getTarget(), emit); 00243 } else 00244 return null; 00245 } 00246 00261 double findBest(SituationKnowledge situation, GestureState state, 00262 NoPointZone noZone) throws UnreferencableException { 00263 if (this.pairs.size() > 0) { 00264 logger.debug(LoggerLevel.MATH, "Finding costs for options ..."); 00265 // first find the cost of each pair in context 00266 List<GSCost> costs = new ArrayList<GSCost>(); 00267 for (GestureSpeechPair pair : pairs) { 00268 GSCost gsc = new GSCost(); 00269 gsc.pair = pair; 00270 gsc.cost = pair.getCost(state, noZone); 00271 if (this.next != null) 00272 gsc.cost += this.next.findBest(situation, 00273 pair.getNextState(state, situation), noZone); 00274 costs.add(gsc); 00275 } 00276 00277 logger.debug(LoggerLevel.MATH, "finding the lowest cost ..."); 00278 // then find the best option based on cost 00279 GSCost lowest = costs.get(0); 00280 for (int c = 0; c < costs.size(); c++) { 00281 if (costs.get(c).cost < lowest.cost) 00282 lowest = costs.get(c); 00283 } 00284 00285 // if the cost is infinite, then we can't do it, so find the next 00286 // best option from the unreliable bin. 00287 List<GestureSpeechPair> used = new ArrayList<GestureSpeechPair>(); 00288 while (Double.isInfinite(lowest.cost)) { 00289 00290 GestureSpeechPair nextBest = null; 00291 double nextReliability = 0; 00292 double temp; 00293 00294 // Find the next most reliable pair 00295 for (GestureSpeechPair gsp : unreliable) { 00296 if (used.contains(gsp)) 00297 continue; 00298 00299 else if (nextBest == null) { 00300 nextBest = gsp; 00301 nextReliability = reliabilityOf(gsp); 00302 } 00303 00304 else if (nextReliability < (temp = reliabilityOf(gsp))) { 00305 nextBest = gsp; 00306 nextReliability = temp; 00307 } 00308 } 00309 00310 // if it's null, then we just can't do anything, although this 00311 // shouldn't happen since LAMBDA is ok 00312 if (nextBest == null) 00313 throw new UnreferencableException("0 available options"); 00314 00315 // then calculate the cost to see if it is still INF 00316 lowest.pair = nextBest; 00317 lowest.cost = nextBest.getCost(state, noZone); 00318 if (this.next != null) 00319 lowest.cost += this.next.findBest(situation, 00320 nextBest.getNextState(state, situation), noZone); 00321 used.add(nextBest); 00322 } 00323 00324 logger.debug(LoggerLevel.MATH, "returning the lowest ..."); 00325 // then remember this and inform the future references, then return 00326 // the cost 00327 this.best = lowest.pair; 00328 if (this.next != null) 00329 this.next.findBest(situation, 00330 lowest.pair.getNextState(state, situation), noZone); 00331 return lowest.cost; 00332 } else 00333 throw new UnreferencableException("0 available options"); 00334 } 00335 00336 private class GSCost { 00337 GestureSpeechPair pair; 00338 double cost; 00339 } 00340 00346 @SuppressWarnings("serial") 00347 static class UnreferencableException extends Exception { 00348 00355 public UnreferencableException(String string) { 00356 super(string); 00357 } 00358 } 00359 } |