00001 package edu.tum.cs.ias.knowrob.mod_dialog;
00002
00003 import instruction.gui.EHowInstructionPanel;
00004
00005 import java.awt.BorderLayout;
00006 import java.awt.Color;
00007 import java.awt.event.KeyEvent;
00008 import java.awt.event.MouseListener;
00009 import java.awt.event.MouseMotionListener;
00010 import java.awt.event.WindowAdapter;
00011 import java.awt.event.WindowEvent;
00012 import java.io.BufferedReader;
00013 import java.io.File;
00014 import java.io.IOException;
00015 import java.io.InputStreamReader;
00016 import java.lang.reflect.Constructor;
00017 import java.lang.reflect.InvocationTargetException;
00018 import java.lang.reflect.Modifier;
00019 import java.net.URL;
00020 import java.util.ArrayList;
00021 import java.util.Arrays;
00022 import java.util.Enumeration;
00023 import java.util.HashMap;
00024 import java.util.HashSet;
00025 import java.util.Hashtable;
00026 import java.util.List;
00027 import java.util.Vector;
00028
00029 import javax.swing.JFrame;
00030
00031 import processing.core.PApplet;
00032 import processing.core.PFont;
00033 import ros.NodeHandle;
00034 import ros.Publisher;
00035 import ros.Ros;
00036 import ros.RosException;
00037 import ros.ServiceClient;
00038 import ros.Subscriber;
00039 import ros.pkg.mary_tts.srv.SetMaryVoice;
00040 import controlP5.CheckBox;
00041 import controlP5.ControlEvent;
00042 import controlP5.ControlFont;
00043 import controlP5.ControlP5;
00044 import controlP5.Textarea;
00045 import controlP5.Textfield;
00046 import edu.tum.cs.ias.knowrob.json_prolog.Prolog;
00047 import edu.tum.cs.ias.knowrob.json_prolog.PrologBindings;
00048 import edu.tum.cs.ias.knowrob.json_prolog.PrologQueryProxy;
00049 import edu.tum.cs.ias.knowrob.json_prolog.PrologValue;
00050 import edu.tum.cs.ias.knowrob.mod_dialog.queries.DialogQuery;
00051
00052
00053
00054 public class DialogModule extends PApplet implements MouseListener, MouseMotionListener {
00055
00056 private static final long serialVersionUID = 4575739930038583994L;
00057
00058 public static String TOP_LEVEL_STATE = "init";
00059 protected String state = TOP_LEVEL_STATE;
00060 protected HashSet<String> registeredStates = new HashSet<String>();
00061
00062 private static HashMap<String, String> prologToEnglish;
00063 private static HashMap<String, String> englishToProlog;
00064
00065 protected String currentObject="";
00066
00067 public JFrame img_window;
00068 public ImageViewerApplet iviewer;
00069 public JFrame ehow_window;
00070 public EHowInstructionPanel ehow_panel;
00071
00072 protected boolean useSpeechInput = true;
00073 protected static boolean localProlog = false;
00074
00075
00076 static {
00077
00078 setMappings();
00079 }
00080
00081 ArrayList<DialogQuery> queries;
00082
00083
00084 public static ControlP5 controlP5;
00085 ControlFont font;
00086 CheckBox checkbox;
00087
00091 static Ros ros;
00092 public static NodeHandle n;
00093
00094 static Subscriber.QueueingCallback<ros.pkg.std_msgs.msg.String> callback;
00095
00096
00097 Publisher<ros.pkg.std_msgs.msg.String> mary_pub;
00098
00099 protected static void initRos() {
00100
00101 ros = Ros.getInstance();
00102
00103 if(!Ros.getInstance().isInitialized()) {
00104 ros.init("knowrob_dialog_applet");
00105 }
00106 n = ros.createNodeHandle();
00107
00108 callback = new Subscriber.QueueingCallback<ros.pkg.std_msgs.msg.String>();
00109 }
00110
00111
00112 @SuppressWarnings("unchecked")
00113 public void setup() {
00114
00115 size(550, 400, P2D);
00116
00117 background(20, 20, 20);
00118
00119
00120 frameRate(10);
00121 initControlP5();
00122 draw();
00123
00124
00125 try {
00126
00127 queries = new ArrayList<DialogQuery>();
00128 for(Class cl : getClasses("edu.tum.cs.ias.knowrob.mod_dialog.queries")) {
00129
00130 if(Modifier.isAbstract(cl.getModifiers()))
00131 continue;
00132
00133
00134 try {
00135 Constructor<DialogQuery> constructor = cl.getConstructor(DialogModule.class);
00136 DialogQuery q;
00137 q = constructor.newInstance(this);
00138 queries.add(q);
00139 } catch (SecurityException e) {
00140 e.printStackTrace();
00141 } catch (NoSuchMethodException e) {
00142 e.printStackTrace();
00143 } catch (IllegalArgumentException e) {
00144 e.printStackTrace();
00145 } catch (InstantiationException e) {
00146 e.printStackTrace();
00147 } catch (IllegalAccessException e) {
00148 e.printStackTrace();
00149 } catch (InvocationTargetException e) {
00150 e.printStackTrace();
00151 }
00152 }
00153
00154 } catch (ClassNotFoundException e) {
00155 e.printStackTrace();
00156 } catch (IOException e) {
00157 e.printStackTrace();
00158 }
00159
00160
00161
00162 initRos();
00163
00164 Thread speechIn = new Thread( new SpeechInListenerThread() );
00165 speechIn.start();
00166
00167 Thread answerQueries = new Thread( new AnswerQueriesThread(this) );
00168 answerQueries.start();
00169
00170 try {
00171 mary_pub = n.advertise("/mary/tts", new ros.pkg.std_msgs.msg.String(), 100);
00172
00173 } catch (RosException e) {
00174 e.printStackTrace();
00175 }
00176
00177
00178
00179 ehow_window = new JFrame();
00180 ehow_window.setVisible( false );
00181 ehow_window.setSize( 1100, 800 );
00182 ehow_window.setTitle( "Plan Importer GUI" );
00183 ehow_window.setLocation( 400, 300 );
00184 ehow_window.setBackground(new Color(20, 20, 20));
00185
00186 ehow_window.addWindowListener( new WindowAdapter() {
00187 public void windowClosing( WindowEvent we ) {
00188
00189 ehow_window.setVisible(false);
00190 } } );
00191
00192 ehow_panel = new EHowInstructionPanel();
00193 ehow_window.add( ehow_panel );
00194 ehow_panel.init();
00195 ehow_panel.revalidate();
00196
00197 if(localProlog) {
00198 initProlog();
00199 }
00200
00201
00202
00203
00204
00205
00206
00207 }
00208
00209 public void draw() {
00210
00211
00212 background(20, 20, 20);
00213 controlP5.draw();
00214 }
00215
00216
00220
00221
00222
00223
00224 public String getCurrentState() {
00225 return state;
00226 }
00227
00228 public boolean stateExists(String state) {
00229 return state.equals(TOP_LEVEL_STATE) || registeredStates.contains(state);
00230 }
00231
00232 public void registerState(String state) {
00233 if(stateExists(state))
00234 throw new IllegalArgumentException("State already registered");
00235 registeredStates.add(state);
00236 }
00237
00238 public void setState(String state) {
00239 if(!stateExists(state))
00240 throw new IllegalArgumentException("Tried to set invalid state");
00241 this.state = state;
00242 }
00243
00244 public void setTopLevelState() {
00245 setState(TOP_LEVEL_STATE);
00246 }
00247
00251
00252
00253
00254
00255
00256 String answer_query(String q) {
00257
00258 String res = null;
00259 try{
00260
00261
00262 for(DialogQuery query : queries) {
00263 res = query.process(q);
00264 if(res != null) {
00265 System.out.println(query.getClass().getSimpleName() + " returned '" + res + "'");
00266 return res;
00267 }
00268 }
00269
00270
00271 return "I don't know.\n";
00272
00273 } catch(Exception e) {
00274 e.printStackTrace();
00275 return "I don't know.\n";
00276 }
00277 }
00278
00279
00285 public static HashMap<String, Vector<PrologValue>> executeJSONPrologQuery(String query) {
00286
00287 if(localProlog) {
00288 return executeLocalPrologQuery(query);
00289 }
00290
00291 System.out.println(query);
00292
00293 HashMap<String, Vector<PrologValue>> result = new HashMap< String, Vector<PrologValue> >();
00294
00295 Prolog pl = new Prolog("/json_prolog");
00296 PrologQueryProxy bdgs = pl.query("expand_goal(("+query+"),_9), call(_9)");
00297
00298
00299 if(!bdgs.iterator().hasNext()) {
00300 return null;
00301 }
00302
00303 for(PrologBindings bdg : bdgs) {
00304
00305 for(String key : bdg.getBdgs_().keySet()) {
00306
00307 if(!result.containsKey(key)) {
00308 result.put(key, new Vector<PrologValue>());
00309 }
00310 result.get(key).add(bdg.getBdgs_().get(key));
00311 }
00312 }
00313 bdgs.finish();
00314
00315 return result;
00316 }
00317
00318 public static HashMap<String, Vector<PrologValue>> executeLispPrologQuery(String query) {
00319
00320 System.out.println(query);
00321
00322 HashMap<String, Vector<PrologValue>> result = new HashMap< String, Vector<PrologValue> >();
00323
00324 Prolog pl = new Prolog("/execution_trace_server");
00325 PrologQueryProxy bdgs = pl.query(query);
00326
00327
00328 if(!bdgs.iterator().hasNext()) {
00329 return null;
00330 }
00331
00332 for(PrologBindings bdg : bdgs) {
00333
00334 for(String key : bdg.getBdgs_().keySet()) {
00335
00336 if(!result.containsKey(key)) {
00337 result.put(key, new Vector<PrologValue>());
00338 }
00339 result.get(key).add(bdg.getBdgs_().get(key));
00340 }
00341 }
00342 bdgs.finish();
00343
00344 return result;
00345 }
00346
00347
00351
00352
00353
00354
00355
00356 public static class SpeechInListenerThread implements Runnable {
00357
00358 @Override public void run() {
00359
00360 try {
00361
00362 n.advertise("/knowrob/speech_in", new ros.pkg.std_msgs.msg.String(), 100);
00363 Subscriber<ros.pkg.std_msgs.msg.String> sub = n.subscribe("/knowrob/speech_in", new ros.pkg.std_msgs.msg.String(), callback, 10);
00364
00365 n.spin();
00366 sub.shutdown();
00367
00368 } catch(RosException e) {
00369 e.printStackTrace();
00370 }
00371 }
00372 }
00373
00374
00375 public static class AnswerQueriesThread implements Runnable {
00376
00377 DialogModule dialog_module;
00378
00379 public AnswerQueriesThread(DialogModule parent) {
00380 this.dialog_module=parent;
00381 }
00382
00383 @Override public void run() {
00384
00385 try {
00386
00387 ros.pkg.std_msgs.msg.String res;
00388 while (n.isValid()) {
00389
00390 res = callback.pop();
00391
00392 if(((CheckBox) controlP5.getGroup("speech_in")).getState(0))
00393 dialog_module.handleTextQuery(res.data);
00394
00395 }
00396
00397 } catch (InterruptedException e) {
00398 e.printStackTrace();
00399 }
00400 }
00401 }
00402
00403
00404
00405
00409
00410
00411
00412
00413 public void setVoice(String voice) {
00414
00415 try {
00416 ServiceClient<SetMaryVoice.Request, SetMaryVoice.Response, SetMaryVoice> cl =
00417 n.serviceClient("/mary_tts/set_voice", new SetMaryVoice());
00418 SetMaryVoice.Request req = new SetMaryVoice.Request();
00419 req.voice_name=voice;
00420 cl.call(req);
00421 } catch (RosException e) {
00422 }
00423 }
00424
00425
00426 public String getCurrentObject() {
00427 return currentObject;
00428 }
00429
00430
00431 public void setCurrentObject(String currentObject) {
00432 this.currentObject = currentObject;
00433 }
00434
00435 public static String removeSingleQuotes(String str) {
00436 if(str.startsWith("'"))
00437 str = str.substring(1);
00438
00439 if(str.endsWith("'"))
00440 str = str.substring(0, str.length()-1);
00441 return str;
00442 }
00443
00444 protected static String startToUpperCase(String q) {
00445 return q.substring(0,1).toUpperCase() + q.substring(1, q.length());
00446 }
00447
00448 public static String toProlog(String enString) {
00449
00450 if(englishToProlog.containsKey(enString)) {
00451 return "knowrob:'"+englishToProlog.get(enString)+"'";
00452
00453 } else if( enString.startsWith("cupboard") ||
00454 enString.startsWith("oven") ||
00455 enString.startsWith("refrigerator") ||
00456 enString.startsWith("diswasher") ||
00457 enString.startsWith("table") ||
00458 enString.startsWith("kitchentable") ) {
00459 return "ias_map:'"+enString+"'";
00460
00461 } else {
00462 return "knowrob:'"+startToUpperCase(enString)+"'";
00463 }
00464 }
00465
00466 public static String toEnglish(String plString) {
00467
00468 if(prologToEnglish.containsKey(plString)) {
00469 return prologToEnglish.get(plString);
00470
00471 } else if(plString.contains("#")) {
00472 return removeSingleQuotes(plString.split("#")[1]);
00473
00474 } else if(plString.contains(":")) {
00475 return removeSingleQuotes(plString.split(":")[1]);
00476 } else {
00477 return plString;
00478 }
00479 }
00480
00481 private static void setMappings() {
00482
00483 prologToEnglish = new HashMap<String, String>();
00484 englishToProlog = new HashMap<String, String>();
00485
00486 addMapping("type", "has the type");
00487 addMapping("depthOfObject", "has the depth");
00488 addMapping("widthOfObject", "has the width");
00489 addMapping("heightOfObject", "has the height");
00490 addMapping("properPhysicalPartTypes", "has a part");
00491 addMapping("describedInMap", "is part of the map");
00492 addMapping("subClassOf", "is a sub-class of");
00493
00494 }
00495
00496 private static void addMapping(String pl, String en) {
00497 prologToEnglish.put(pl, en);
00498 englishToProlog.put(en, pl);
00499 }
00500
00501
00502
00503
00507
00508
00509
00510
00511 private void initControlP5() {
00512
00513 controlP5 = new ControlP5(this);
00514
00515 PFont pfont = createFont("Helvetica",10,true);
00516 font = new ControlFont(pfont);
00517
00518 Textarea log = controlP5.addTextarea("Log","", 80,20,400,260);
00519 log.setColorBackground(0xFF000000);
00520 log.setColorForeground(0xFFCCCCCC);
00521 log.valueLabel().setFont(ControlP5.grixel);
00522 log.setLineHeight(16);
00523 log.showScrollbar();
00524
00525 Textfield input = controlP5.addTextfield("Query", 80,300,400,25);
00526 input.setColorBackground(0xFF000000);
00527 input.valueLabel().setFont(ControlP5.grixel);
00528
00529
00530
00531 input.setAutoClear(true);
00532 input.setFocus(true);
00533 input.keepFocus(true);
00534
00535
00536 checkbox = controlP5.addCheckBox("speech_in",68,360);
00537 checkbox.setColorForeground(color(120));
00538 checkbox.setColorActive(color(200));
00539 checkbox.setColorLabel(color(128));
00540
00541
00542 checkbox.addItem("Activate Speech Input",23);
00543 checkbox.activate("Activate Speech Input");
00544
00545
00546 }
00547
00548 void controlEvent(ControlEvent theEvent) {
00549
00550 if( (theEvent.isController()) &&
00551 (theEvent.controller() != null) &&
00552 (theEvent.controller() instanceof Textfield)) {
00553 handleTextQuery(theEvent.controller().stringValue());
00554 return;
00555 }
00556
00557 }
00558
00559
00560 public void keyPressed(){
00561
00562 switch(keyCode) {
00563 case ESC:
00564 this.state = TOP_LEVEL_STATE;
00565 ((Textarea)controlP5.getGroup("Log")).setText("");
00566 key=0;
00567 break;
00568 }
00569 }
00570
00571
00572 void handleTextQuery(String textquery) {
00573
00574
00575
00576 String log = ((Textarea)controlP5.getGroup("Log")).stringValue();
00577 log += "Op: "+textquery+"\n";
00578
00579 String response = answer_query(textquery);
00580
00581 log += "Robot: "+response+"\n";
00582
00583
00584 ((Textarea)controlP5.getGroup("Log")).setText(log);
00585 ((Textarea)controlP5.getGroup("Log")).scroll(1);
00586
00587
00588
00589 ros.pkg.std_msgs.msg.String m = new ros.pkg.std_msgs.msg.String();
00590 m.data = response;
00591 mary_pub.publish(m);
00592
00593 System.out.println("out: "+ response);
00594
00595 }
00596
00597 public void showImageInNewWindow(String img) {
00598
00599 int frameWidth = 0;
00600 int frameHeight = 30;
00601
00602 iviewer = new ImageViewerApplet();
00603 img_window = new JFrame();
00604 img_window.getContentPane().add(iviewer, BorderLayout.CENTER);
00605
00606
00607 iviewer.init();
00608 iviewer.setImage(img);
00609 img_window.setSize(iviewer.width + frameWidth, iviewer.height + frameHeight);
00610
00611 img_window.setVisible(true);
00612 img_window.setResizable(false);
00613
00614 }
00615
00616
00620
00621
00622
00623
00624
00633 private static Class[] getClasses(String packageName) throws ClassNotFoundException, IOException {
00634 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
00635 assert classLoader != null;
00636 String path = packageName.replace('.', '/');
00637 Enumeration<URL> resources = classLoader.getResources(path);
00638 List<File> dirs = new ArrayList<File>();
00639 while (resources.hasMoreElements()) {
00640 URL resource = resources.nextElement();
00641 dirs.add(new File(resource.getFile()));
00642 }
00643 ArrayList<Class> classes = new ArrayList<Class>();
00644 for (File directory : dirs) {
00645 classes.addAll(findClasses(directory, packageName));
00646 }
00647 return classes.toArray(new Class[classes.size()]);
00648 }
00649
00658 private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException {
00659 List<Class> classes = new ArrayList<Class>();
00660 if (!directory.exists()) {
00661 return classes;
00662 }
00663 File[] files = directory.listFiles();
00664 for (File file : files) {
00665 if (file.isDirectory()) {
00666 assert !file.getName().contains(".");
00667 classes.addAll(findClasses(file, packageName + "." + file.getName()));
00668 } else if (file.getName().endsWith(".class")) {
00669 classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
00670 }
00671 }
00672 return classes;
00673 }
00674
00680 public static String findRosPackage(String pkgname) {
00681
00682 try {
00683 String line;
00684 Process p = Runtime.getRuntime().exec( "rospack find " + pkgname +"");
00685 BufferedReader pathreader = new BufferedReader(new InputStreamReader(p.getInputStream(), "UTF-8"));
00686 if( (line = pathreader.readLine()) != null) {
00687 return line;
00688 }
00689 } catch (IOException e) {
00690 e.printStackTrace(System.err);
00691 }
00692 return null;
00693 }
00694
00695
00696
00697
00701
00702
00703
00704
00705 private static void initProlog() {
00706 try {
00707 Vector<String> args= new Vector<String>(Arrays.asList(jpl.fli.Prolog.get_default_init_args()));
00708 args.add( "-G256M" );
00709
00710 args.add( "-nosignals" );
00711
00712 String rosprolog = findRosPackage("rosprolog");
00713 System.err.println(rosprolog+"/prolog/init.pl");
00714 jpl.fli.Prolog.set_default_init_args( args.toArray( new String[0] ) );
00715
00716
00717 new jpl.Query("ensure_loaded('"+rosprolog+"/prolog/init.pl"+"')").oneSolution();
00718 new jpl.Query("register_ros_package('demo_cotesys_fall2010')").oneSolution();
00719 new jpl.Query("comp_cop:odufinder_listener(_)").oneSolution();
00720
00721 } catch(Exception e) {
00722 e.printStackTrace();
00723 }
00724 }
00725
00731 public static HashMap<String, Vector<PrologValue>> executeLocalPrologQuery(String query) {
00732
00733 jpl.Query q = new jpl.Query( "expand_goal(("+query+"),_9), call(_9)" );
00734
00735
00736 if(!q.hasSolution()) {
00737 return null;
00738 }
00739
00740 HashMap<String, Vector<PrologValue>> result = new HashMap<String, Vector<PrologValue>>();
00741
00742 Hashtable[] solutions = q.allSolutions();
00743
00744 for(Hashtable solution : q.allSolutions()) {
00745
00746 for(Object key : solution.keySet()) {
00747
00748 jpl.Term t = (jpl.Term) solution.get(key);
00749
00750 if(!result.containsKey(key)) {
00751 result.put(key.toString(), new Vector<PrologValue>());
00752 }
00753 result.get(key).add(new PrologValue(t.toString()));
00754 }
00755 }
00756 return result;
00757 }
00758
00759 public boolean isLocalProlog() {
00760 return localProlog;
00761 }
00762
00763
00764 public void setLocalProlog(boolean localProlog) {
00765 this.localProlog = localProlog;
00766 }
00767
00768 public static void main(String args[]) {
00769
00770 DialogModule dialog = new DialogModule();
00771 JFrame window = new JFrame();
00772 window.add(dialog);
00773 dialog.init();
00774
00775 window.setSize(550, 440);
00776 window.setVisible(true);
00777
00778 if(args.length>0 && args[0].equals("local")) {
00779 System.err.println("LOCAL PROLOG");
00780 dialog.setLocalProlog(true);
00781 }
00782 }
00783 }
00784
00785