Project: engagement_generation License: BSD Dependencies:
Used by:
None |
engagement_generation/src/edu/wpi/hri/gen/policy/TurnPositionPolicy.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 ros.NodeHandle; 00037 import ros.Publisher; 00038 import ros.RosException; 00039 import ros.ServiceClient; 00040 import ros.pkg.engagement_msgs.msg.APAction; 00041 import ros.pkg.engagement_msgs.msg.ActorID; 00042 import ros.pkg.bml_msgs.msg.Entity; 00043 import ros.pkg.bml_msgs.msg.Flag; 00044 import ros.pkg.engagement_msgs.msg.Speech; 00045 import ros.pkg.engagement_srvs.srv.RobotAdjacencyPair; 00046 import edu.wpi.hri.bml.behavior.ConstraintBehavior; 00047 import edu.wpi.hri.bml.behavior.ConstraintBehavior.SyncBlock; 00048 import edu.wpi.hri.bml.behavior.EmitBehavior; 00049 import edu.wpi.hri.bml.behavior.GazeBehavior; 00050 import edu.wpi.hri.bml.behavior.SyncRef; 00051 import edu.wpi.hri.bml.behavior.SyncRef.SyncPoint; 00052 import edu.wpi.hri.gen.GenerationParams; 00053 import edu.wpi.hri.gen.comm.BMLEmitListener; 00054 import edu.wpi.hri.gen.ebml.EBMLList; 00055 import edu.wpi.hri.log.Logger; 00056 import edu.wpi.hri.log.Logger.Colors; 00057 import edu.wpi.hri.log.Logger.LoggerLevel; 00058 00090 public class TurnPositionPolicy { 00091 00092 private final Logger logger; 00093 private final BMLEmitListener emit; 00094 private APWaiter waiter; 00095 private final ServiceClient<RobotAdjacencyPair.Request, RobotAdjacencyPair.Response, RobotAdjacencyPair> apsrv; 00096 private final Publisher<Speech> bcpub; 00097 private final boolean full; 00098 00113 public TurnPositionPolicy(NodeHandle handle, Logger logger, 00114 BMLEmitListener emit, boolean full) throws RosException { 00115 this.logger = logger.sub(Colors.POLICY, "TrnPos"); 00116 this.emit = emit; 00117 this.apsrv = handle.serviceClient( 00118 GenerationParams.ROBOT_AP_PATH.getString(), 00119 new RobotAdjacencyPair()); 00120 if (full) { 00121 this.bcpub = handle.advertise("performing/utterance", new Speech(), 00122 10); 00123 } else { 00124 this.bcpub = null; 00125 } 00126 this.full = full; 00127 this.logger.debug(LoggerLevel.INIT, "Created ..."); 00128 } 00129 00133 public void shutdown() { 00134 if (this.waiter != null) 00135 this.waiter.getResponse(); 00136 this.apsrv.shutdown(); 00137 } 00138 00160 public APWaiter apply(EBMLList list, String position, String actor, 00161 boolean firstTurn, boolean delay, String delayTarget) 00162 throws Exception { 00163 logger.debug(LoggerLevel.POLICY_EXECUTION, "Applying ..."); 00164 // run which ever position, see class documentation 00165 if (position.equalsIgnoreCase("BEGINNING")) { 00166 this.execBeginning(firstTurn, actor); 00167 if (delay) 00168 this.execDelay(list, delayTarget); 00169 return null; 00170 } else if (position.equalsIgnoreCase("MIDDLE")) { 00171 if (delay) 00172 this.execDelay(list, delayTarget); 00173 return null; 00174 } else if (position.equalsIgnoreCase("END")) { 00175 if (delay) 00176 throw new Exception("Can not end and delay turn"); 00177 this.execEnd(list, actor); 00178 return this.waiter; 00179 } else if (position.equalsIgnoreCase("FULL")) { 00180 if (delay) 00181 throw new Exception("Can not full and delay turn"); 00182 this.execBeginning(firstTurn, actor); 00183 this.execEnd(list, actor); 00184 return this.waiter; 00185 } else if (position.equalsIgnoreCase("BACKCHANNEL")) { 00186 if (delay) 00187 throw new Exception("Can not backchannel and delay turn"); 00188 this.execBackchannel(list); 00189 return null; 00190 } else { 00191 throw new Exception("In valid turn position given"); 00192 } 00193 } 00194 00201 private void execBeginning(boolean firstTurn, String actor) { 00202 if (firstTurn) 00203 this.waiter = new APWaiter(actor); 00204 } 00205 00214 private void execEnd(EBMLList list, String actor) { 00215 if (full) { 00216 this.logger.debug(LoggerLevel.POLICY_EXECUTION, "executing end"); 00217 // create the behaviors first since they are independant 00218 GazeBehavior gazeBehav = new GazeBehavior(logger, "mfg-gaze", 00219 actor, false); 00220 EmitBehavior emitBehav = emit.createMFGEmit(actor, gazeBehav); 00221 00222 // the robot must look at the participant at the end of a turn 00223 ConstraintBehavior constraint = list.getRequiredConstraints(); 00224 SyncBlock block = new SyncBlock(new SyncRef(list.getID(), 00225 SyncPoint.END, 0)); 00226 block.addRef(new SyncRef(gazeBehav, SyncPoint.START, 0)); 00227 block.addRef(new SyncRef(emitBehav, SyncPoint.START, 0)); 00228 constraint.addSynchronized(block); 00229 00230 // then add the behaviors to the list to be executed 00231 list.getGazes().add(gazeBehav); 00232 list.getEmits().add(emitBehav); 00233 } 00234 } 00235 00236 private void execBackchannel(EBMLList list) { 00237 if (full) { 00238 this.logger.debug(LoggerLevel.POLICY_EXECUTION, "executing BC"); 00239 Speech speech = new Speech(); 00240 speech.actor.id = ActorID.ROBOT; 00241 speech.begin.value = Flag.BACKCHANNEL; 00242 speech.response.value = Flag.FALSE; 00243 bcpub.publish(speech); 00244 } 00245 } 00246 00247 private void execDelay(EBMLList list, String delayTarget) { 00248 if (full) { 00249 if (delayTarget == null || delayTarget.isEmpty()) 00250 delayTarget = Entity.UP_RIGHT; 00251 this.logger.debug(LoggerLevel.POLICY_EXECUTION, "executing delay"); 00252 GazeBehavior gaze = new GazeBehavior(logger, "delay-gaze", 00253 delayTarget, false); 00254 list.getGazes().add(gaze); 00255 } 00256 } 00257 00266 public class APWaiter { 00267 private final Thread thread; 00268 private byte response; 00269 00277 private APWaiter(final String actor) { 00278 this.response = APAction.NO_ACTION; 00279 this.thread = new Thread() { 00291 public void run() { 00292 // create the request 00293 RobotAdjacencyPair.Request req = new RobotAdjacencyPair.Request(); 00294 req.actor.id = actor; 00295 00296 // then find the response 00297 try { 00298 RobotAdjacencyPair.Response res = apsrv.call(req); 00299 00300 // determine what to return 00301 if (res.result.value == Flag.SUCCESS) { 00302 response = res.action.value; 00303 } else 00304 response = APAction.NO_ACTION; 00305 } catch (Exception e) { 00306 response = APAction.NO_ACTION; 00307 } 00308 }; 00309 }; 00310 this.thread.start(); 00311 } 00312 00318 public byte getResponse() { 00319 logger.debug(LoggerLevel.POLICY_EXECUTION, 00320 "waiting for AP response"); 00321 try { 00322 if (this.thread.isAlive()) 00323 this.thread.join(); 00324 } catch (InterruptedException e) { 00325 } 00326 return this.response; 00327 } 00328 } 00329 } |