Project: engagement_test License: BSD Dependencies:
Used by:
None |
engagement_test/src/edu/wpi/hri/ros/testing/looper/Looper.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.ros.testing.looper; 00035 00036 import java.util.Date; 00037 import java.util.Random; 00038 import java.util.ArrayList; 00039 00040 import ros.NodeHandle; 00041 import ros.Ros; 00042 import ros.ServiceClient; 00043 import ros.Subscriber; 00044 import ros.pkg.engagement_msgs.msg.APAction; 00045 import ros.pkg.bml_msgs.msg.Behavior; 00046 import ros.pkg.bml_msgs.msg.Entity; 00047 import ros.pkg.bml_msgs.msg.Flag; 00048 import ros.pkg.engagement_msgs.msg.HumanBackchannel; 00049 import ros.pkg.engagement_msgs.msg.Performance; 00050 import ros.pkg.bml_srvs.srv.BMLGaze; 00051 import ros.pkg.bml_srvs.srv.BMLGesture; 00052 import ros.pkg.bml_srvs.srv.BMLHead; 00053 import ros.pkg.bml_srvs.srv.BMLSpeech; 00054 import ros.pkg.engagement_srvs.srv.RobotAdjacencyPair; 00055 import ros.pkg.engagement_srvs.srv.RobotDirectedGaze; 00056 import ros.pkg.engagement_srvs.srv.RobotMutualFacialGaze; 00057 import edu.wpi.hri.ros.testing.lib.Logger; 00058 import edu.wpi.hri.ros.testing.lib.LooperParams; 00059 import edu.wpi.hri.ros.testing.lib.TestingParams; 00060 00069 public class Looper { 00071 Random rand_ = new Random(new Date().getTime()); 00072 00074 public static Logger logger_; 00075 00077 private Thread cycle_thread_; 00078 00080 private NodeHandle handle_; 00081 00083 private static int DIRECTED_GAZE = 0; 00085 private static int MUTUAL_FACIAL_GAZE = 1; 00087 private static int ADJACENCY_PAIR = 2; 00089 private static int BACKCHANNEL = 3; 00091 private static int INVALID_SELECTION = -1; 00092 00094 private String recognize_; 00096 private String point_to_; 00097 00099 private String actor_; 00100 00102 private boolean wait_for_backchannel_ = false; 00103 00105 private static final String speeches_[] = { 00106 "Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.", 00107 "I have a dream that one day this nation will rise up and live out the true meaning of its creed: We hold these truths to be self-evident, that all men are created equal.", 00108 "We choose to go to the moon. We choose to go to the moon in this decade and do the other things, not because they are easy, but because they are hard, because that goal will serve to organize and measure the best of our energies and skills, because that challenge is one that we are willing to accept, one we are unwilling to postpone, and one which we intend to win, and the others, too. ", 00109 "So, first of all, let me assert my firm belief that the only thing we have to fear is fear itself -- nameless, unreasoning, unjustified terror which paralyzes needed efforts to convert retreat into advance. In every dark hour of our national life, a leadership of frankness and of vigor has met with that understanding and support of the people themselves which is essential to victory.", 00110 "One, a robot may not injure a human being, or through inaction, allow a human being to come to harm; Two, a robot must obey the orders given it by human beings except where such orders would conflict with the First Law; Three, a robot must protect its own existence as long as such protection does not conflict with the First or Second Laws.", 00111 "Kipple is useless objects, like junk mail or match folders after you use the last match or gum wrappers of yesterday's homeopape. When nobody's around, kipple reproduces itself. For instance, if you go to bed leaving any kipplpe around your apartment, when you wake up next morning there's twice as much of it. It always gets more and more.", 00112 "The first ten million years were the worst, and the second ten million, they were the worst too. The third ten million I didn't enjoy at all. After that I went into a bit of a decline.", 00113 "It is indeed true that at times like this R2 and I wish we were more than mechanical beings and we were really alive so we could share your feelings with you." }; 00114 00116 private int last_selected_speech_ = -1; 00117 00119 ServiceClient<BMLGesture.Request, BMLGesture.Response, BMLGesture> ctl_point_srv_; 00121 ServiceClient<BMLGaze.Request, BMLGaze.Response, BMLGaze> ctl_track_srv_; 00123 ServiceClient<BMLHead.Request, BMLHead.Response, BMLHead> ctl_head_srv_; 00125 ServiceClient<BMLSpeech.Request, BMLSpeech.Response, BMLSpeech> ctl_say_srv_; 00126 00128 ServiceClient<RobotDirectedGaze.Request, RobotDirectedGaze.Response, RobotDirectedGaze> rec_dg_srv_; 00130 ServiceClient<RobotMutualFacialGaze.Request, RobotMutualFacialGaze.Response, RobotMutualFacialGaze> rec_mfg_srv_; 00132 ServiceClient<RobotAdjacencyPair.Request, RobotAdjacencyPair.Response, RobotAdjacencyPair> rec_ap_srv_; 00133 00135 private Subscriber.QueueingCallback<HumanBackchannel> human_bc_q_; 00137 private Subscriber.QueueingCallback<Performance> pernod_q; 00139 @SuppressWarnings("unused") 00140 private Subscriber<HumanBackchannel> human_bc_s_; 00142 @SuppressWarnings("unused") 00143 private Subscriber<Performance> pernod_s; 00144 00148 public void loadParameters() { 00149 // Create a private configuration node handle 00150 NodeHandle priv_ = Ros.getInstance().createNodeHandle( 00151 "~" + TestingParams.CONF_NAMESPACE.toString()); 00152 00153 try { 00154 // Create the actor param in the configuration namespace 00155 String actor_param = LooperParams.ACTOR_PARAM.toString(); 00156 00157 // Grab the parameter from the configuration namespace 00158 this.actor_ = priv_.getStringParam(actor_param, false); 00159 } catch (Exception e) { 00160 logger_.fatal(Logger.NO_AREA, "Unable to determine which " 00161 + "actor to use."); 00162 } 00163 00164 try { 00165 // Create the recognize param in the configuration namespace 00166 String recognize_param = LooperParams.RECOGNIZE_PARAM.toString(); 00167 00168 // Grab the parameters from the configuration namespace 00169 this.recognize_ = priv_.getStringParam(recognize_param, false); 00170 } catch (Exception e) { 00171 logger_.fatal(Logger.NO_AREA, "Unable to determine which " 00172 + "behavior to recognize."); 00173 } 00174 00175 // Determine if the selection was valid 00176 int selection = this.whichBehavior(this.recognize_); 00177 00178 // If we're recognizing directed gaze determine 00179 // which object to point to 00180 if (selection == 0) { 00181 // Create the point to param in the configuration namespace 00182 String point_to_param = LooperParams.POINT_TO_PARAM.toString(); 00183 00184 try { 00185 // Grab the object to point to from the configuration namespace 00186 this.point_to_ = priv_.getStringParam(point_to_param, false); 00187 } catch (Exception e) { 00188 logger_.fatal(Logger.NO_AREA, "Unable to load object to" 00189 + "point to"); 00190 } 00191 } else if (selection == -1) { 00192 logger_.fatal(Logger.NO_AREA, "Attempting to recognize invalid " 00193 + "behavior [" + this.recognize_ + "]"); 00194 } 00195 } 00196 00204 public Looper(NodeHandle handle) { 00205 this.handle_ = handle; 00206 00207 // Create the logger using the conf node handle 00208 Looper.logger_ = new Logger("LOOPER", Ros.getInstance() 00209 .createNodeHandle("~" + TestingParams.CONF_NAMESPACE)); 00210 00211 // Load the parameters from the param server 00212 this.loadParameters(); 00213 00214 try { 00215 // Create strings for each of the namespaces 00216 String control_ns = TestingParams.CONTROL_NAMESPACE.toString(); 00217 String recog_ns = TestingParams.RECOGNITION_NAMESPACE.toString(); 00218 String robot_ns = recog_ns + "/" 00219 + TestingParams.ROBOT_NAMESPACE.toString(); 00220 String human_ns = recog_ns + "/" 00221 + TestingParams.HUMAN_NAMESPACE.toString(); 00222 String performing_ns = TestingParams.PERFORMING_NAMESPACE 00223 .toString(); 00224 00225 // Create service clients for all the control topics 00226 this.ctl_point_srv_ = handle.serviceClient(control_ns + "/" 00227 + TestingParams.CTL_POINT_TOPIC.toString(), 00228 new BMLGesture(), false); 00229 this.ctl_track_srv_ = handle.serviceClient(control_ns + "/" 00230 + TestingParams.CTL_TRACK_TOPIC.toString(), new BMLGaze(), 00231 false); 00232 this.ctl_head_srv_ = handle.serviceClient(control_ns + "/" 00233 + TestingParams.CTL_HEAD_TOPIC.toString(), new BMLHead(), 00234 false); 00235 this.ctl_say_srv_ = handle.serviceClient(control_ns + "/" 00236 + TestingParams.CTL_SAY_TOPIC.toString(), new BMLSpeech(), 00237 false); 00238 00239 // Create service clients for all the recognition topics 00240 this.rec_dg_srv_ = handle.serviceClient(robot_ns + "/" 00241 + TestingParams.REC_DIRECTED_GAZE_TOPIC.toString(), 00242 new RobotDirectedGaze(), false); 00243 this.rec_mfg_srv_ = handle.serviceClient(robot_ns + "/" 00244 + TestingParams.REC_MUTUAL_FACIAL_GAZE_TOPIC.toString(), 00245 new RobotMutualFacialGaze(), false); 00246 this.rec_ap_srv_ = handle.serviceClient(robot_ns + "/" 00247 + TestingParams.REC_ADJACENCY_PAIR_TOPIC.toString(), 00248 new RobotAdjacencyPair(), false); 00249 00250 this.human_bc_q_ = new Subscriber.QueueingCallback<HumanBackchannel>(); 00251 this.human_bc_s_ = handle.subscribe(human_ns + "/" 00252 + TestingParams.REC_BACKCHANNEL_TOPIC.toString(), 00253 new HumanBackchannel(), this.human_bc_q_, 100); 00254 this.pernod_q = new Subscriber.QueueingCallback<Performance>(); 00255 this.pernod_s = handle.subscribe(performing_ns + "/" 00256 + TestingParams.PER_NOD_TOPIC.toString(), 00257 new Performance(), this.pernod_q, 100); 00258 } catch (Exception e) { 00259 e.printStackTrace(); 00260 } 00261 00262 // create a Thread for handling the ROS stuff 00263 cycle_thread_ = new Thread() { 00264 00265 public void run() { 00266 try { 00267 // Sleep for five seconds at startup. 00268 Thread.sleep(5000); 00269 } catch (Exception e) { 00270 e.printStackTrace(); 00271 } 00272 00273 while (isValid()) { 00274 try { 00275 // Determine which behavior to perform 00276 int selection = whichBehavior(recognize_); 00277 00278 if (selection == DIRECTED_GAZE) 00279 performDirectedGaze(); 00280 else if (selection == MUTUAL_FACIAL_GAZE) 00281 performMutualFacialGaze(); 00282 else if (selection == ADJACENCY_PAIR) 00283 performAdjacencyPair(); 00284 else if (selection == BACKCHANNEL) 00285 { 00286 performBackchannel(); 00287 } 00288 else 00289 logger_.error(Logger.NO_AREA, 00290 "Unrecognized recognition " 00291 + "selection being used."); 00292 00293 // Sleep for 2.5 seconds 00294 Thread.sleep(2500); 00295 00296 // Create a new track message 00297 BMLGaze.Request track_msg = new BMLGaze.Request(); 00298 track_msg.target.type = Entity.QUADRANT; 00299 00300 // Grab the value of the upper right quadrant from 00301 // the vision position message 00302 track_msg.target.id = "UP_RIGHT"; 00303 00304 // Instruct the robot to look off in a 00305 // different direction (up and to the right) 00306 ctl_track_srv_.call(track_msg); 00307 00308 // Sleep for another 2.5 seconds 00309 Thread.sleep(2500); 00310 } catch (Exception e) { 00311 e.printStackTrace(); 00312 } 00313 } 00314 } 00315 }; 00316 cycle_thread_.start(); 00317 } 00318 00324 public synchronized boolean isValid() { 00325 return this.handle_.isValid(); 00326 } 00327 00331 public void run() { 00332 // Loop until the program is terminated 00333 while (this.handle_.isValid()) { 00334 try { 00335 // Spin to handle input 00336 this.handle_.spinOnce(); 00337 00338 // Handle incoming backchannel events 00339 this.checkBackchannel(); 00340 00341 Thread.sleep(10); 00342 } catch (Exception e) { 00343 e.printStackTrace(); 00344 } 00345 } 00346 } 00347 00355 private ArrayList<Entity> getEntitiesFromObjects(String objects[]) { 00356 // Create an array of entities of the same size 00357 ArrayList<Entity> entities = new ArrayList<Entity>(); 00358 00359 // Traverse through all the objects 00360 for (String obj : objects) { 00361 // Create the new entity object in the array 00362 Entity ent = new Entity(); 00363 ent.id = obj; 00364 ent.type = Entity.OBJECT; 00365 entities.add(ent); 00366 } 00367 00368 return entities; 00369 } 00370 00374 public void performAdjacencyPair() { 00375 // ADJACENCY PAIR CASE. 00376 logger_.debug(Logger.NO_AREA, "Performing an adjacency pair with " 00377 + "actor [" + this.actor_ + "]."); 00378 00379 // Create the speech text without any markup 00380 String please = "<mark name=\"track FACE " + this.actor_ 00381 + "\" />Please respond"; 00382 00383 // Speak the text 00384 this.speak(please); 00385 00386 // Create the message for adjacency pair 00387 RobotAdjacencyPair.Request ap_msg = new RobotAdjacencyPair.Request(); 00388 ap_msg.actor.id = this.actor_; 00389 00390 try { 00391 // Call the recognize adjacency pair service 00392 RobotAdjacencyPair.Response ap_response = this.rec_ap_srv_ 00393 .call(ap_msg); 00394 00395 // Determine if the service succeeded or failed 00396 if (ap_response.result.value == Flag.SUCCESS) { 00397 // Determine which action was used to complete the AP 00398 switch (ap_response.action.value) { 00399 case APAction.NOD: 00400 this.speak("You successfully nodded your head."); 00401 break; 00402 case APAction.SHAKE: 00403 this.speak("You successfully shook your head."); 00404 break; 00405 case APAction.POINT: 00406 this.speak("You successfully pointed."); 00407 break; 00408 case APAction.LOOK: 00409 this.speak("You successfully looked."); 00410 break; 00411 case APAction.SPEECH: 00412 this.speak("You successfully spoke."); 00413 break; 00414 case APAction.EXTENDED_ACTION: 00415 this.speak("You successfully performed an action."); 00416 break; 00417 default: 00418 this.speak("Success."); 00419 break; 00420 } 00421 } else if (ap_response.result.value == Flag.FAILURE) 00422 this.speak("You failed to respond."); 00423 else 00424 logger_.error(Logger.NO_AREA, "Invalid arguments to " 00425 + "adjacency pair service."); 00426 } catch (Exception e) { 00427 logger_.warn(Logger.NO_AREA, "Unable to successfully call " 00428 + "the adjacency pair service."); 00429 e.printStackTrace(); 00430 } 00431 } 00432 00436 public void performBackchannel() { 00437 // BACKCHANNEL CASE 00438 logger_.debug(Logger.NO_AREA, "Performing a long speech to " 00439 + "ellicit backchannels from actor [" + this.actor_ + "]."); 00440 00441 // Create the random speech to use 00442 String speech = this.selectRandomSpeech(); 00443 00444 // Wait for backchannels to occur 00445 this.wait_for_backchannel_ = true; 00446 00447 // Speak the text, have the robot track the human's face throughout 00448 this.speak("<mark name=\"track FACE " + this.actor_ + "\" />" + speech); 00449 00450 // Stop waiting for backchannel to occur 00451 this.wait_for_backchannel_ = false; 00452 } 00453 00457 public void performDirectedGaze() { 00458 // THE DIRECTED GAZE CASE 00459 logger_.debug(Logger.NO_AREA, "Performing a directed gaze to [" 00460 + this.point_to_ + "] with actor [" + this.actor_ + "]."); 00461 00462 // Create the speech text with markup to point and 00463 // look at the blue plate 00464 // also put a markup at the end to look back at the human 00465 String look_here = "<mark name=\"track OBJECT " + this.point_to_ 00466 + "\" />Please look <mark name=\"point EITHER " 00467 + this.point_to_ + "\" />here"; 00468 00469 // Create the array to hold the object to point to 00470 String objects[] = new String[1]; 00471 objects[0] = this.point_to_; 00472 00473 // Speak the text 00474 this.speak(look_here); 00475 00476 // Create the message for directed gaze 00477 RobotDirectedGaze.Request dg_msg = new RobotDirectedGaze.Request(); 00478 dg_msg.actor.id = "face0"; 00479 dg_msg.done.value = Flag.NOT_DONE; 00480 dg_msg.objects = this.getEntitiesFromObjects(objects); 00481 00482 try { 00483 // Call the recognize directed gaze service 00484 RobotDirectedGaze.Response dg_response = this.rec_dg_srv_ 00485 .call(dg_msg); 00486 00487 // Determine if the service succeeded or failed 00488 if (dg_response.result.value == Flag.SUCCESS) 00489 this.speak("You successfully looked."); 00490 else if (dg_response.result.value == Flag.FAILURE) 00491 this.speak("You failed to look."); 00492 else 00493 logger_.error(Logger.NO_AREA, "Invalid arguments to " 00494 + "directed gaze service."); 00495 } catch (Exception e) { 00496 logger_.warn(Logger.NO_AREA, "Unable to successfully call " 00497 + "the directed gaze service."); 00498 e.printStackTrace(); 00499 } 00500 00501 try { 00502 // Create the point message to end the pointing 00503 BMLGesture.Request pt_msg = new BMLGesture.Request(); 00504 pt_msg.side.value = Flag.EITHER; 00505 pt_msg.behav.synchPoint = Behavior.END; 00506 00507 // Call the point service to end 00508 ctl_point_srv_.call(pt_msg); 00509 } catch (Exception e) { 00510 logger_.warn(Logger.NO_AREA, "Unable to successfully call " 00511 + "the end control point service."); 00512 e.printStackTrace(); 00513 } 00514 } 00515 00519 public void performMutualFacialGaze() { 00520 // MUTUAL FACIAL GAZE CASE. 00521 logger_.debug(Logger.NO_AREA, "Performing a mutual facial gaze " 00522 + "with actor [" + this.actor_ + "]."); 00523 00524 // Create the speech text with markup to look at the actor's face 00525 String look_at_me = "<mark name=\"track FACE " + this.actor_ 00526 + "\" />Please look at me"; 00527 00528 // Speak the text 00529 this.speak(look_at_me); 00530 00531 // Create the message for mutual facial gaze using the actor 00532 RobotMutualFacialGaze.Request mfg_msg = new RobotMutualFacialGaze.Request(); 00533 mfg_msg.actor.id = this.actor_; 00534 00535 try { 00536 // Call the recognize mutual facial gaze service 00537 RobotMutualFacialGaze.Response mfg_response = this.rec_mfg_srv_ 00538 .call(mfg_msg); 00539 00540 if (mfg_response.result.value == Flag.SUCCESS) 00541 this.speak("You successfully looked."); 00542 else if (mfg_response.result.value == Flag.FAILURE) 00543 this.speak("You failed to look at me."); 00544 else 00545 logger_.error(Logger.NO_AREA, "Invalid arguments to " 00546 + "mutual facial gaze service."); 00547 } catch (Exception e) { 00548 logger_.error(Logger.NO_AREA, "Unable to successfully call " 00549 + "the mutual facial gaze service."); 00550 e.printStackTrace(); 00551 } 00552 } 00553 00557 public void checkBackchannel() { 00558 // check for shakes 00559 while (!this.human_bc_q_.isEmpty()) { 00560 try { 00561 HumanBackchannel msg = this.human_bc_q_.pop(); 00562 00563 // Make sure this was the actor's backchannel, and that 00564 // the robot is waiting for a backchannel to occur 00565 if (this.wait_for_backchannel_ 00566 && msg.actor.id.equals(this.actor_)) { 00567 logger_.info(Logger.NO_AREA, "Received a human " 00568 + "backchannel message"); 00569 00570 // The actor performed a backchannel event, respond 00571 // by having the robot nod 00572 BMLHead.Request nod_msg = new BMLHead.Request(); 00573 nod_msg.motion = BMLHead.Request.NOD; 00574 nod_msg.amount = BMLHead.Request.SMALL; 00575 nod_msg.behav.id = "nod"; 00576 nod_msg.behav.synchPoint = Behavior.START; 00577 00578 // Call the nod message 00579 this.ctl_head_srv_.call(nod_msg); 00580 00581 } 00582 } catch (Exception e) { 00583 e.printStackTrace(); 00584 } 00585 } 00586 } 00587 00594 public void speak(String text) { 00595 // Make sure we have a valid service to call, and text to speak 00596 if (this.ctl_say_srv_ != null && text.length() > 0) { 00597 // Create the control say request message 00598 BMLSpeech.Request msg = new BMLSpeech.Request(); 00599 00600 // Configure the message to say the given text 00601 msg.behav.synchPoint = Behavior.START; 00602 msg.behav.id = "looper-say"; 00603 msg.text = text; 00604 00605 // Call the service with the given message 00606 try { 00607 logger_.debug(Logger.NO_AREA, "Calling Say service."); 00608 00609 // Call the say service and keep track of the response 00610 BMLSpeech.Response response = this.ctl_say_srv_.call(msg); 00611 00612 // Determine if the say service was called successfully 00613 if (response.status.value == Flag.TRUE) 00614 logger_.debug(Logger.NO_AREA, "Called Say service [" + text 00615 + "]"); 00616 else 00617 logger_.error(Logger.NO_AREA, 00618 "Failed to call Say service [" + text + "]"); 00619 00620 msg.behav.synchPoint = Behavior.END; 00621 this.ctl_say_srv_.call(msg); 00622 00623 } catch (Exception e) { 00624 e.printStackTrace(); 00625 } 00626 } 00627 } 00628 00636 public int whichBehavior(String selection) { 00637 // Transform the selection to all lowercase 00638 selection = selection.toLowerCase(); 00639 00640 // Determine which goal was selected 00641 if (selection.equals("directed_gaze") 00642 || selection.equals("directedgaze") 00643 || selection.equals("directed gaze") || selection.equals("dg") 00644 || selection.equals("dirgaze") || selection.equals("dir gaze") 00645 || selection.equals("dir_gaze") || selection.equals("directed")) { 00646 return DIRECTED_GAZE; 00647 } else if (selection.equals("mutual_facial_gaze") 00648 || selection.equals("mutual") || selection.equals("mf gaze") 00649 || selection.equals("mutualfacialgaze") 00650 || selection.equals("mfg") 00651 || selection.equals("mutual facial gaze") 00652 || selection.equals("mfgaze") || selection.equals("mf gaze") 00653 || selection.equals("mf_gaze")) { 00654 return MUTUAL_FACIAL_GAZE; 00655 } else if (selection.equals("adjacency_pair") || selection.equals("ap") 00656 || selection.equals("adjacencypair") 00657 || selection.equals("adj_pair") 00658 || selection.equals("adjacency pair") 00659 || selection.equals("adj pair") 00660 || selection.equals("adjacency")) { 00661 return ADJACENCY_PAIR; 00662 } else if (selection.equals("backchannel") || selection.equals("bc") 00663 || selection.equals("back_channel") 00664 || selection.equals("bchannel") 00665 || selection.equals("b_channel") 00666 || selection.equals("back_chan") 00667 || selection.equals("backchan")) { 00668 return BACKCHANNEL; 00669 } else 00670 return INVALID_SELECTION; 00671 } 00672 00678 public String selectRandomSpeech() { 00679 int index = -1; 00680 00681 do { 00682 // Get a random speech, 00683 // different from the one previously selected 00684 index = this.rand_.nextInt(Looper.speeches_.length); 00685 } while (index == this.last_selected_speech_); 00686 00687 // Store the selected speech for next time 00688 this.last_selected_speech_ = index; 00689 00690 // Return the randomly selected speech 00691 return Looper.speeches_[index]; 00692 } 00693 00700 public static void main(String[] args) { 00701 // Initialize ROS 00702 Ros.getInstance().init("looper"); 00703 00704 // Create a default node handle 00705 NodeHandle handle = Ros.getInstance().createNodeHandle(); 00706 00707 // Create an instance of the Looper object 00708 Looper looper = new Looper(handle); 00709 00710 // Run the Echo node 00711 looper.run(); 00712 } 00713 } |