$search
00001 /* 00002 * Copyright (C) 2010 by Moritz Tenorth 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 package edu.tum.cs.ias.knowrob; 00019 00020 import ros.*; 00021 import ros.pkg.vision_msgs.msg.aposteriori_position; 00022 import ros.pkg.vision_msgs.msg.cop_answer; 00023 import ros.pkg.vision_msgs.msg.cop_descriptor; 00024 import ros.pkg.vision_srvs.srv.cop_call; 00025 import ros.pkg.vision_srvs.srv.srvjlo; 00026 import ros.pkg.vision_srvs.srv.srvjlo.Response; 00027 import ros.pkg.vision_srvs.srv.srvjlo.Request; 00028 import ros.pkg.vision_msgs.msg.partial_lo; 00029 00030 import java.util.concurrent.ExecutionException; 00031 import java.util.HashMap; 00032 import java.util.Hashtable; 00033 import java.util.Queue; 00034 import java.util.Vector; 00035 import java.lang.Exception; 00036 import java.util.concurrent.ConcurrentLinkedQueue; 00037 import java.lang.Runnable; 00038 00039 import jpl.Query; 00040 00041 00042 00043 public class CopROSClient { 00044 00045 static Boolean rosInitialized = false; 00046 static Ros ros; 00047 static NodeHandle n; 00048 00049 00050 static Subscriber.QueueingCallback<cop_answer> copObjectDetectionsCallback; 00051 static Subscriber.QueueingCallback<cop_answer> copModelDBCallback; 00052 00053 Thread listenToCopDB; 00054 Thread updateKnowRobModelDB; 00055 Thread listenToCopObjDetections; 00056 Thread updateKnowRobObjDetections; 00057 00065 public CopROSClient(String node_name) throws InterruptedException, RosException, ExecutionException { 00066 00067 initRos(node_name); 00068 00069 copObjectDetectionsCallback = new Subscriber.QueueingCallback<cop_answer>(); 00070 copModelDBCallback = new Subscriber.QueueingCallback<cop_answer>(); 00071 00072 } 00073 00074 00075 public void startCopModelDBListener(String cop_topic, String cop_service) { 00076 00077 // create threads listening to /knowrob/cop_db to update the CoP database content 00078 listenToCopDB = new Thread( new CopModelDBListenerThread(cop_topic, cop_service) ); 00079 listenToCopDB.start(); 00080 updateKnowRobModelDB = new Thread( new UpdateKnowRobModelDBThread() ); 00081 updateKnowRobModelDB.start(); 00082 00083 } 00084 00085 public void startCopObjDetectionsListener(String cop_topic) { 00086 00087 // create threads listening to /kipla/cop_reply to receive object detections 00088 listenToCopObjDetections = new Thread( new CopObjListenerThread(cop_topic) ); 00089 listenToCopObjDetections.start(); 00090 updateKnowRobObjDetections = new Thread( new UpdateKnowRobObjectsThread() ); 00091 updateKnowRobObjDetections.start(); 00092 } 00093 00094 00095 00096 00100 protected static void initRos(String node_name) { 00101 00102 ros = Ros.getInstance(); 00103 00104 if(!Ros.getInstance().isInitialized()) { 00105 ros.init(node_name); 00106 } 00107 n = ros.createNodeHandle(); 00108 00109 } 00110 00120 public static class CopObjListenerThread implements Runnable { 00121 00122 String topic; 00123 00124 public CopObjListenerThread() { 00125 this("/kipla/cop_reply"); 00126 } 00127 00128 public CopObjListenerThread(String t) { 00129 topic=t; 00130 } 00131 00132 @Override public void run() { 00133 00134 try { 00135 00136 Subscriber<cop_answer> sub = n.subscribe(topic, new cop_answer(), copObjectDetectionsCallback, 10); 00137 00138 n.spin(); 00139 sub.shutdown(); 00140 00141 } catch(RosException e) { 00142 e.printStackTrace(); 00143 } 00144 } 00145 } 00146 00154 public static class UpdateKnowRobObjectsThread implements Runnable { 00155 00156 @Override public void run() { 00157 00158 try { 00159 00160 cop_answer res; 00161 HashMap<String, Vector<Object>> solutions; 00162 while(true) { 00163 00164 res = copObjectDetectionsCallback.pop(); 00165 00166 System.err.println("UpdateKnowRobObjectsThread: received data"); 00167 00168 // iterate over detected poses 00169 for(aposteriori_position pose : res.found_poses) { 00170 00171 long p_id = pose.objectId; 00172 //double p_prob = pose.probability; 00173 long p_lo_id = pose.position; 00174 HashMap<String, String> m_types_classes = new HashMap<String, String>(); 00175 00176 00177 // iterate over models used for detecting these poses 00178 for(cop_descriptor model : pose.models) { 00179 00180 //long m_id = model.object_id; 00181 //double m_qual = model.quality; 00182 m_types_classes.put(model.type, copToKnowrob(model.sem_class)); 00183 00184 } 00185 00186 // create VisualPerception instance 00187 System.err.println("comp_cop:cop_create_perception_instance("+objectArrayToPlList(m_types_classes.keySet().toArray())+", Perception)"); 00188 solutions = executeQuery("comp_cop:cop_create_perception_instance("+objectArrayToPlList(m_types_classes.keySet().toArray())+", Perception)"); 00189 if(solutions.get("Perception").size()>1) {throw new Exception("ERROR: More than one Perception instance created.");} 00190 String perception = solutions.get("Perception").get(0).toString(); 00191 00192 00193 // create object information 00194 System.err.println("comp_cop:cop_create_object_instance("+objectArrayToPlList(m_types_classes.values().toArray())+", "+p_id+", Obj)"); 00195 solutions = executeQuery("comp_cop:cop_create_object_instance("+objectArrayToPlList(m_types_classes.values().toArray())+", "+p_id+", Obj)"); 00196 if(solutions.get("Obj").size()>1) {throw new Exception("ERROR: More than one Object instance created:"+objectArrayToPlList(solutions.get("Obj").toArray()));} 00197 String obj = solutions.get("Obj").get(0).toString(); 00198 00199 00200 // read pose from loID, assert it (remember lo-ID) 00201 // System.out.println(); 00202 if(p_lo_id!=0) { 00203 synchronized(jpl.Query.class) { 00204 new Query("comp_cop:cop_set_loid("+perception+", "+p_lo_id+")").allSolutions(); 00205 partial_lo lo_pose = loQuery("framequery", "", (int)p_lo_id, 1); 00206 new Query("comp_cop:cop_set_perception_pose("+perception+","+doubleArrayToPlList(lo_pose.pose)+")").allSolutions(); 00207 new Query("comp_cop:cop_set_perception_cov("+ perception+","+doubleArrayToPlList(lo_pose.cov) +")").allSolutions(); 00208 } 00209 } 00210 00211 synchronized(jpl.Query.class) { 00212 // link VisualPerception instance to the object instance 00213 new Query("comp_cop:cop_set_object_perception("+obj+", "+perception+")").allSolutions(); 00214 } 00215 } 00216 n.spinOnce(); 00217 00218 } 00219 00220 } catch(Exception e) { 00221 e.printStackTrace(); 00222 } 00223 } 00224 } 00225 00226 00227 00237 public static class CopModelDBListenerThread implements Runnable { 00238 00239 String topic; 00240 String service; 00241 00242 public CopModelDBListenerThread() { 00243 this("/knowrob/cop_db", "/cop/in"); 00244 } 00245 00246 public CopModelDBListenerThread(String t, String s) { 00247 topic=t; 00248 service=s; 00249 } 00250 @Override public void run() { 00251 00252 try { 00253 00254 Subscriber<cop_answer> sub = n.subscribe(topic, new cop_answer(), copModelDBCallback, 10); 00255 00256 // call cop to get the cop_descriptor model 00257 cop_call copcall = new cop_call(); 00258 cop_call.Request cop_req = copcall.createRequest(); 00259 00260 cop_req.outputtopic="/knowrob/cop_db"; 00261 cop_req.action_type=25601; 00262 cop_req.number_of_objects=1; 00263 00264 // not required any more with new rosjava: auto-initialized 00265 // cop_req.list_of_poses=new apriori_position[1]; 00266 // cop_req.list_of_poses[0] = new apriori_position(); 00267 // cop_req.list_of_poses[0].positionId=1; 00268 // cop_req.list_of_poses[0].probability=1.0; 00269 00270 cop_req.object_ids = new long[1]; 00271 cop_req.object_ids[0] = 1; 00272 00273 ServiceClient<cop_call.Request, cop_call.Response, cop_call> cl = n.serviceClient(service, new cop_call()); 00274 cl.call(cop_req); 00275 00276 n.spin(); 00277 sub.shutdown(); 00278 00279 } catch(RosException e) { 00280 e.printStackTrace(); 00281 } 00282 } 00283 } 00284 00291 public static class UpdateKnowRobModelDBThread implements Runnable { 00292 00293 @Override public void run() { 00294 00295 try { 00296 00297 cop_answer res; 00298 while(true) { 00299 00300 res = copModelDBCallback.pop(); 00301 00302 System.err.println("GOT RESULT IN KNOWROB UPDATE"); 00303 00304 // iterate over objects 00305 for(aposteriori_position pose : res.found_poses) { 00306 00307 // iterate over model associated to these objects 00308 for(cop_descriptor model : pose.models) { 00309 00310 // create VisualPerception instance 00311 System.out.println("comp_cop:cop_create_model_instance('"+model.type+"', "+copToKnowrob(model.sem_class)+")"); 00312 executeQuery("comp_cop:cop_create_model_instance('"+model.type+"', "+copToKnowrob(model.sem_class)+")"); 00313 00314 } 00315 00316 00317 } 00318 n.spinOnce(); 00319 00320 } 00321 00322 } catch(Exception e) { 00323 e.printStackTrace(); 00324 } 00325 } 00326 } 00327 00328 00335 protected static String objectArrayToPlList(Object[] a) { 00336 String res="["; 00337 for(int i=0;i<a.length;i++) { 00338 00339 if(a[i].toString().startsWith("'")) 00340 res+=a[i].toString(); 00341 else 00342 res+="'"+a[i].toString()+"'"; 00343 00344 if(i<a.length-1) 00345 res+=","; 00346 } 00347 return res+="]"; 00348 } 00349 00350 protected static String doubleArrayToPlList(double[] a) { 00351 String res="["; 00352 for(int i=0;i<a.length;i++) { 00353 res+="'"+a[i]+"'"; 00354 if(i<a.length-1) 00355 res+=","; 00356 } 00357 return res+="]"; 00358 } 00359 00360 00369 private static String copToKnowrob(String copIdentifier) { 00370 00371 HashMap<String, Vector<Object>> solutions = 00372 executeQuery("downcase_atom('"+copIdentifier+"', CopID),cop_to_knowrob(CopID, KnowRobID)"); 00373 00374 if(solutions !=null) { 00375 Vector<Object> mappings = solutions.get("KnowRobID"); 00376 00377 if(mappings!=null && mappings.size()>0) { 00378 return mappings.get(0).toString(); 00379 } 00380 } 00381 return ""; 00382 } 00383 00384 00397 public static partial_lo loQuery(String command, String objName, int objID, int refFrame) throws RosException { 00398 00399 ServiceClient<Request, Response, srvjlo> client = n.serviceClient("/located_object", new ros.pkg.vision_srvs.srv.srvjlo()); 00400 00401 srvjlo srv = new srvjlo(); 00402 Request rq = srv.createRequest(); 00403 00404 rq.command=command; 00405 00406 if(command.equals("namequery")) { 00407 rq.query.name=objName; 00408 } 00409 else if(command.equals("framequery")) { 00410 rq.query.id=objID; 00411 00412 if(refFrame>0) 00413 rq.query.parent_id=refFrame; 00414 } 00415 00416 return client.call(rq).answer; 00417 } 00418 00425 public static HashMap<String, Vector<Object>> executeQuery(String query) { 00426 00427 HashMap<String, Vector<Object>> result = new HashMap< String, Vector<Object> >(); 00428 Hashtable[] solutions; 00429 00430 synchronized(jpl.Query.class) { 00431 00432 Query q = new Query( "expand_goal(("+query+"),_9), call(_9)" ); 00433 00434 if(!q.hasSolution()) 00435 return new HashMap<String, Vector<Object>>(); 00436 00437 00438 solutions = q.allSolutions(); 00439 for (Object key: solutions[0].keySet()) { 00440 result.put(key.toString(), new Vector<Object>()); 00441 } 00442 00443 // Build the result 00444 for (int i=0; i<solutions.length; i++) { 00445 Hashtable solution = solutions[i]; 00446 for (Object key: solution.keySet()) { 00447 String keyStr = key.toString(); 00448 if (!result.containsKey( keyStr )) { 00449 00450 // previously unknown column, add result vector 00451 Vector<Object> resultVector = new Vector<Object>(); 00452 resultVector.add( i, solution.get( key ).toString() ); 00453 result.put(keyStr, resultVector); 00454 00455 } 00456 // Put the solution into the correct vector 00457 Vector<Object> resultVector = result.get( keyStr ); 00458 resultVector.add( i, solution.get( key ).toString() ); 00459 } 00460 } 00461 } 00462 // Generate the final QueryResult and return 00463 return result; 00464 } 00465 00466 00467 00475 public static String[] copModelTypeSemClassForID(long id) { 00476 00477 // call cop to get the cop_descriptor model 00478 cop_call copcall = new cop_call(); 00479 cop_call.Request cop_req = copcall.createRequest(); 00480 00481 cop_req.outputtopic="/knowrob/cop_client"; 00482 cop_req.action_type=25600; 00483 cop_req.number_of_objects=1; 00484 00485 // not required any more with new rosjava: auto-initialized 00486 // cop_req.list_of_poses=new apriori_position[1]; 00487 // cop_req.list_of_poses[0] = new apriori_position(); 00488 // cop_req.list_of_poses[0].positionId=1; 00489 // cop_req.list_of_poses[0].probability=1.0; 00490 00491 cop_req.object_ids = new long[1]; 00492 cop_req.object_ids[0] = id; 00493 00494 cop_answer r = copOneResult(cop_req, "/knowrob/cop_client"); 00495 00496 String[] res = null; 00497 if(r!=null) { 00498 String modelType=""; String objClass=""; 00499 for(aposteriori_position pose : r.found_poses) { 00500 00501 // use first entry as model class 00502 if(pose.models.size() > 0) { 00503 modelType=pose.models.get(0).type; 00504 objClass=pose.models.get(0).sem_class; 00505 } 00506 } 00507 res = new String[2]; 00508 res[0]=modelType; 00509 res[1]=objClass; 00510 } 00511 return res; 00512 } 00513 00514 00515 00522 public static cop_answer copOneResult(cop_call.Request cop_req, String output_topic) { 00523 00524 initRos("knowrob_cop_one_result"); 00525 00526 // call the cop service and subscribe to the answer topic 00527 ServiceClient<cop_call.Request, cop_call.Response, cop_call> cl = n.serviceClient("/cop/in", new cop_call()); 00528 cop_answer r=null; 00529 00530 try { 00531 00532 // create a queuing callback that is used for listening on the answer topic 00533 Subscriber.QueueingCallback<cop_answer> cop_callback = new Subscriber.QueueingCallback<cop_answer>(); 00534 Subscriber<cop_answer> sub = n.subscribe(output_topic, new cop_answer(), cop_callback, 10); 00535 00536 00537 // make sure the queue is empty and wait one iteration to have everything setup up 00538 cop_callback.clear(); 00539 ros.spinOnce(); 00540 00541 // call CoP and wait until a result is received 00542 cl.call(cop_req); 00543 while (cop_callback.isEmpty()) { 00544 ros.spinOnce(); 00545 } 00546 00547 // just read the first result returned on the output_topic 00548 r = cop_callback.pop(); 00549 sub.shutdown(); 00550 00551 } catch (RosException e) { 00552 ros.logError("CopROSClient: Call to service /cop/in failed"); 00553 } catch (InterruptedException e) { 00554 e.printStackTrace(); 00555 } 00556 00557 cl.shutdown(); 00558 return r; 00559 } 00560 00561 00562 }