Project: engagement_generation License: BSD Dependencies:
Used by:
None |
engagement_generation/src/edu/wpi/hri/gen/policy/ref/GestureOption.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.BehaviorEnums.Amplitude; 00044 import edu.wpi.hri.bml.behavior.BehaviorEnums.Direction; 00045 import edu.wpi.hri.bml.behavior.BehaviorEnums.Distance; 00046 import edu.wpi.hri.bml.behavior.BehaviorEnums.GestureType; 00047 import edu.wpi.hri.bml.behavior.BehaviorEnums.HandShape; 00048 import edu.wpi.hri.bml.behavior.BehaviorEnums.HorizontalLocation; 00049 import edu.wpi.hri.bml.behavior.BehaviorEnums.Power; 00050 import edu.wpi.hri.bml.behavior.BehaviorEnums.Side; 00051 import edu.wpi.hri.bml.behavior.BehaviorEnums.Trajectory; 00052 import edu.wpi.hri.bml.behavior.BehaviorEnums.TwoHanded; 00053 import edu.wpi.hri.bml.behavior.BehaviorEnums.VerticalLocation; 00054 import edu.wpi.hri.gen.GenerationParams; 00055 import edu.wpi.hri.gen.comm.BMLEmitListener; 00056 import edu.wpi.hri.gen.comm.SituationKnowledge; 00057 import edu.wpi.hri.log.Logger; 00058 00067 abstract class GestureOption { 00068 00084 abstract double getCost(GestureState state, String object, 00085 SituationKnowledge situation, NoPointZone noZone); 00086 00098 abstract DistractorSet getDistractors(String object, 00099 SituationKnowledge situation); 00100 00107 abstract double getReliability(); 00108 00120 abstract GestureState getNextState(GestureState state, String object, 00121 SituationKnowledge situation); 00122 00139 abstract GestureBehavior createGesture(Logger logger, String id, 00140 String target, boolean required, boolean last); 00141 00156 abstract GazeBehavior createGaze(Logger logger, String id, String target, 00157 boolean required); 00158 00173 abstract EmitBehavior createDG(Behavior source, String actor, 00174 String target, BMLEmitListener emit); 00175 00189 protected double findGazeCost(GestureState state, String object, 00190 SituationKnowledge situation) { 00191 Point start = state.getGazePoint(); 00192 Point end = situation.get(object); 00193 Point head = situation.getRobotHead(); 00194 00195 // first find the yaw angle 00196 double numerator = start.xyDistanceSquared(end) 00197 - head.xyDistanceSquared(start) - end.xyDistanceSquared(head); 00198 double denominator = -2 * head.xyDistance(start) * end.xyDistance(head); 00199 double yaw = Math.acos(numerator / denominator); 00200 00201 // then find the pitch angle 00202 numerator = start.xzDistanceSquared(end) 00203 - head.xzDistanceSquared(start) - end.xzDistanceSquared(head); 00204 denominator = -2 * head.xzDistance(start) * end.xzDistance(head); 00205 double pitch = Math.acos(numerator / denominator); 00206 00207 // then find the degree maximum (which means max and convert) 00208 double max = Math.PI * Math.max(Math.abs(yaw), Math.abs(pitch)) / 180.0; 00209 00210 // then multiply by the gaze cost constant 00211 return GenerationParams.CONSTANT_GAZE_COST_FACTOR.getDouble() * max; 00212 } 00213 00225 protected Point findHandPoint(String object, SituationKnowledge situation) { 00226 // first find the point and the correct arm to use 00227 boolean right = situation.isObjectOnRight(object); 00228 Point point = situation.get(object); 00229 Point shoulder = right ? situation.getRobotRightShoulder() : situation 00230 .getRobotLeftShoulder(); 00231 00232 // then check if the arm length is shorter that the object distance 00233 double spDist = shoulder.fullDistance(point); 00234 double armLength = GenerationParams.ROBOT_ARM_LENGTH.getDouble(); 00235 if (spDist > armLength) { 00236 // if so, set the point to the maximum extension along that line. 00237 double x = shoulder.getX() 00238 + ((shoulder.getX() - point.getX()) * (armLength / spDist)); 00239 double y = shoulder.getY() 00240 + ((shoulder.getY() - point.getY()) * (armLength / spDist)); 00241 double z = shoulder.getZ() 00242 + ((shoulder.getZ() - point.getZ()) * (armLength / spDist)); 00243 point = new Point(x, y, z); 00244 } 00245 return point; 00246 } 00247 00263 protected double findPointCost(GestureState state, String object, 00264 SituationKnowledge situation, NoPointZone noZone) { 00265 Point start = situation.isObjectOnRight(object) ? state 00266 .getRobotRightHand() : state.getRobotLeftHand(); 00267 Point end = findHandPoint(object, situation); 00268 00269 if (noZone.canPointTo(situation.get(object))) 00270 return GenerationParams.CONSTANT_POINT_COST_FACTOR.getDouble() 00271 * start.fullDistance(end); 00272 else 00273 return Double.POSITIVE_INFINITY; 00274 } 00275 00285 protected DistractorSet findGazeDistractors(String object, 00286 SituationKnowledge situation) { 00287 List<String> distractors = new ArrayList<String>(); 00288 Point realPoint = situation.get(object); 00289 double sphereSize = GenerationParams.CONSTANT_GAZE_DISTRACTOR_DISTANCE 00290 .getDouble(); 00291 00292 // for each distractor, ensure it is not the object and find if it is 00293 // within the sphere 00294 for (String distractor : situation.getAllObjects()) { 00295 if ((!distractor.equals(object)) 00296 && (realPoint.fullDistance(situation.get(distractor)) < sphereSize)) 00297 distractors.add(distractor); 00298 } 00299 return new DistractorSet(distractors); 00300 } 00301 00312 protected DistractorSet findPointDistractors(String object, 00313 SituationKnowledge situation) { 00314 // find all of the data required 00315 List<String> distractors = new ArrayList<String>(); 00316 Point realPoint = situation.get(object); 00317 double rectSize = GenerationParams.CONSTANT_POINT_DISTRACTOR_DISTANCE 00318 .getDouble(); 00319 // Point handPoint = findHandPoint(object, situation); 00320 Point handPoint = situation.isObjectOnRight(object) ? situation 00321 .getRobotRightShoulder() : situation.getRobotLeftShoulder(); 00322 00323 // now start doing the line intersection algorithm 00324 double realHandM = (handPoint.getY() - realPoint.getY()) 00325 / (handPoint.getX() - realPoint.getX()); 00326 double realHandB = handPoint.getY() - (realHandM * handPoint.getX()); 00327 double crossM = -1 / realHandM; 00328 00329 // then for each object that exists, check if it is within range of the 00330 // line and not the real object 00331 for (String distractor : situation.getAllObjects()) { 00332 if (!distractor.equals(object)) { 00333 Point fakePoint = situation.get(distractor); 00334 double crossB = fakePoint.getY() - (crossM * fakePoint.getX()); 00335 double x = (crossB - realHandB) / (realHandM - crossM); 00336 double y = realHandB + (realHandM * x); 00337 Point crossPoint = new Point(x, y, 0); 00338 if (fakePoint.xyDistance(crossPoint) < rectSize) 00339 distractors.add(distractor); 00340 } 00341 } 00342 return new DistractorSet(distractors); 00343 } 00344 00348 static final GestureOption LAMBDA = new GestureOption() { 00349 00350 @Override 00351 double getReliability() { 00352 return 0; 00353 } 00354 00355 @Override 00356 DistractorSet getDistractors(String object, SituationKnowledge situation) { 00357 return null; 00358 } 00359 00360 @Override 00361 double getCost(GestureState state, String object, 00362 SituationKnowledge situation, NoPointZone noZone) { 00363 return 0; 00364 } 00365 00366 @Override 00367 GestureState getNextState(GestureState state, String object, 00368 SituationKnowledge situation) { 00369 return state; 00370 }; 00371 00372 @Override 00373 public String toString() { 00374 return "LAMBDA"; 00375 } 00376 00377 @Override 00378 public GazeBehavior createGaze(Logger logger, String id, String target, 00379 boolean required) { 00380 return null; 00381 } 00382 00383 @Override 00384 public GestureBehavior createGesture(Logger logger, String id, 00385 String target, boolean required, boolean last) { 00386 return null; 00387 } 00388 00389 @Override 00390 public EmitBehavior createDG(Behavior source, String actor, 00391 String target, BMLEmitListener emit) { 00392 return null; 00393 }; 00394 }; 00398 static final GestureOption GAZE = new GestureOption() { 00399 00400 @Override 00401 double getReliability() { 00402 return GenerationParams.RELIABILITY_GAZE.getDouble(); 00403 } 00404 00405 @Override 00406 DistractorSet getDistractors(String object, SituationKnowledge situation) { 00407 return findGazeDistractors(object, situation); 00408 } 00409 00410 @Override 00411 double getCost(GestureState state, String object, 00412 SituationKnowledge situation, NoPointZone noZone) { 00413 return findGazeCost(state, object, situation); 00414 } 00415 00416 @Override 00417 GestureState getNextState(GestureState state, String object, 00418 SituationKnowledge situation) { 00419 return state.nextState(situation.get(object), null, null); 00420 }; 00421 00422 @Override 00423 public String toString() { 00424 return "GAZE"; 00425 } 00426 00427 @Override 00428 public GazeBehavior createGaze(Logger logger, String id, String target, 00429 boolean required) { 00430 return new GazeBehavior(logger, id + "-gaze", target, required); 00431 } 00432 00433 @Override 00434 public GestureBehavior createGesture(Logger logger, String id, 00435 String target, boolean required, boolean last) { 00436 return null; 00437 } 00438 00439 @Override 00440 public EmitBehavior createDG(Behavior source, String actor, 00441 String target, BMLEmitListener emit) { 00442 return emit.createDGEmit(actor, new String[] { target }, source, 00443 false); 00444 }; 00445 }; 00450 static final GestureOption DIRECTED_GAZE = new GestureOption() { 00451 00452 @Override 00453 double getReliability() { 00454 return GenerationParams.RELIABILITY_DIRECTED_GAZE.getDouble(); 00455 } 00456 00457 @Override 00458 DistractorSet getDistractors(String object, SituationKnowledge situation) { 00459 return findGazeDistractors(object, situation); 00460 } 00461 00462 @Override 00463 double getCost(GestureState state, String object, 00464 SituationKnowledge situation, NoPointZone noZone) { 00465 return findGazeCost(state, object, situation); 00466 } 00467 00468 @Override 00469 GestureState getNextState(GestureState state, String object, 00470 SituationKnowledge situation) { 00471 return state.nextState(situation.get(object), null, null); 00472 }; 00473 00474 @Override 00475 public String toString() { 00476 return "DIRECTED_GAZE"; 00477 } 00478 00479 @Override 00480 public GazeBehavior createGaze(Logger logger, String id, String target, 00481 boolean required) { 00482 return new GazeBehavior(logger, id + "-gaze", target, required); 00483 } 00484 00485 @Override 00486 public GestureBehavior createGesture(Logger logger, String id, 00487 String target, boolean required, boolean last) { 00488 return null; 00489 } 00490 00491 @Override 00492 public EmitBehavior createDG(Behavior source, String actor, 00493 String target, BMLEmitListener emit) { 00494 return emit.createDGEmit(actor, new String[] { target }, source, 00495 true); 00496 }; 00497 }; 00502 static final GestureOption DIRECTED_GAZE_POINTING = new GestureOption() { 00503 00504 @Override 00505 double getReliability() { 00506 return GenerationParams.RELIABILITY_DIRECTED_GAZE_POINTING 00507 .getDouble(); 00508 } 00509 00510 @Override 00511 DistractorSet getDistractors(String object, SituationKnowledge situation) { 00512 return findGazeDistractors(object, situation).intersection( 00513 findPointDistractors(object, situation)); 00514 } 00515 00516 @Override 00517 double getCost(GestureState state, String object, 00518 SituationKnowledge situation, NoPointZone noZone) { 00519 return findGazeCost(state, object, situation) 00520 + findPointCost(state, object, situation, noZone); 00521 } 00522 00523 @Override 00524 GestureState getNextState(GestureState state, String object, 00525 SituationKnowledge situation) { 00526 boolean right = situation.isObjectOnRight(object); 00527 Point point = findHandPoint(object, situation); 00528 return state.nextState(situation.get(object), right ? null : point, 00529 right ? point : null); 00530 }; 00531 00532 @Override 00533 public String toString() { 00534 return "DIRECTED_GAZE_POINTING"; 00535 }; 00536 00537 @Override 00538 public GazeBehavior createGaze(Logger logger, String id, String target, 00539 boolean required) { 00540 return new GazeBehavior(logger, id + "-gaze", target, required); 00541 } 00542 00543 @Override 00544 public GestureBehavior createGesture(Logger logger, String id, 00545 String target, boolean required, boolean last) { 00546 return new GestureBehavior(logger, id + "-point", 00547 GestureType.POINT, Side.BOTH, 1, target, 00548 HandShape.INDEXFINGER, Direction.POLAR, Direction.POLAR, 00549 Trajectory.STRAIGHT, TwoHanded.PARALLEL, 00550 VerticalLocation.CENTER, HorizontalLocation.CENTER, 00551 Distance.CONTACT, Direction.POLAR, "", Amplitude.MEDIUM, 00552 Power.NORMAL, last, required); 00553 } 00554 00555 @Override 00556 public EmitBehavior createDG(Behavior source, String actor, 00557 String target, BMLEmitListener emit) { 00558 return emit.createDGEmit(actor, new String[] { target }, source, 00559 true); 00560 }; 00561 }; 00562 } |