Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 package edu.tum.cs.ias.knowrob.json_prolog;
00031
00032 import java.util.*;
00033 import java.io.*;
00034
00035 import ros.NodeHandle;
00036 import ros.Ros;
00037 import ros.RosException;
00038 import ros.ServiceServer;
00039 import ros.pkg.json_prolog_msgs.srv.PrologFinish;
00040 import ros.pkg.json_prolog_msgs.srv.PrologNextSolution;
00041 import ros.pkg.json_prolog_msgs.srv.PrologQuery;
00042
00043
00050 public final class JSONPrologNode {
00051 private Hashtable<String, PrologSolutions> queries;
00052 private boolean hasIncrementalQuery = false;
00053 private String initPackage="";
00054
00055 public JSONPrologNode() {
00056 this("");
00057 }
00058
00059 public JSONPrologNode(String initpkg) {
00060 this.initPackage=initpkg;
00061 queries = new Hashtable<String, PrologSolutions>();
00062 }
00063
00064
00065 static private class RospackError extends Exception {
00066 private static final long serialVersionUID = 1L;
00067 }
00068
00075 private class QueryCallback implements ServiceServer.Callback<PrologQuery.Request, PrologQuery.Response> {
00076
00077
00078 @Override
00079 public PrologQuery.Response call(PrologQuery.Request request) {
00080
00081 PrologQuery.Response response = new PrologQuery.Response();
00082
00083 if (hasIncrementalQuery ) {
00084 response.ok = false;
00085 response.message = "Already processing an incremental query.";
00086
00087 } else if ( queries.get(request.id) != null ) {
00088 response.ok = false;
00089 response.message = "Already processing a query with id " + request.id;
00090
00091 } else {
00092 try {
00093 Ros.getInstance().logDebug("Received query with id " + request.id);
00094
00095 synchronized(jpl.Query.class) {
00096
00097 jpl.Query currentQuery = JSONQuery.makeQuery(request.query);
00098 String currentQueryId = request.id;
00099
00100 if(request.mode == PrologQuery.Request.INCREMENTAL) {
00101 queries.put(currentQueryId, new PrologIncrementalSolutions(currentQuery));
00102 hasIncrementalQuery = true;
00103 }
00104
00105 else {
00106 queries.put(currentQueryId, new PrologAllSolutions(currentQuery));
00107 }
00108 }
00109 response.ok = true;
00110
00111 } catch (JSONQuery.InvalidJSONQuery e) {
00112 response.ok = false;
00113 response.message = e.toString();
00114
00115 } catch (jpl.JPLException e) {
00116 response.ok = false;
00117 response.message = e.getMessage();
00118 }
00119 }
00120 return response;
00121 }
00122 }
00123
00130 private class SimpleQueryCallback implements
00131 ServiceServer.Callback<PrologQuery.Request, PrologQuery.Response> {
00132
00133 @Override
00134 public PrologQuery.Response call(PrologQuery.Request request) {
00135
00136
00137 PrologQuery.Response response = new PrologQuery.Response();
00138
00139 try {
00140
00141 synchronized(jpl.Query.class) {
00142
00143 if (hasIncrementalQuery ) {
00144 response.ok = false;
00145 response.message = "Already processing an incremental query.";
00146
00147 } else if (queries!=null && queries.get(request.id) != null ) {
00148 response.ok = false;
00149 response.message = "Already processing a query with id " + request.id;
00150
00151 } else {
00152 try {
00153 Ros.getInstance().logDebug("Received query with id " + request.id);
00154
00155 jpl.Query currentQuery = new jpl.Query("expand_goal(("+request.query+"),_Q), call(_Q)");
00156 String currentQueryId = request.id;
00157
00158 if(request.mode == PrologQuery.Request.INCREMENTAL) {
00159 queries.put(currentQueryId, new PrologIncrementalSolutions(currentQuery));
00160 hasIncrementalQuery = true;
00161
00162 } else {
00163 queries.put(currentQueryId, new PrologAllSolutions(currentQuery));
00164 }
00165 response.ok = true;
00166
00167 } catch (jpl.JPLException e) {
00168 response.ok = false;
00169 response.message = e.getMessage();
00170 }
00171 }
00172 }
00173 } catch (Exception e) {
00174 e.printStackTrace();
00175 }
00176
00177 return response;
00178 }
00179 }
00180
00181
00191 private class NextSolutionCallback implements
00192 ServiceServer.Callback<PrologNextSolution.Request, PrologNextSolution.Response> {
00193
00194
00195 @Override
00196 public PrologNextSolution.Response call(PrologNextSolution.Request request) {
00197
00198 PrologNextSolution.Response response = new PrologNextSolution.Response();
00199 try {
00200 synchronized(jpl.Query.class) {
00201
00202 PrologSolutions currentQuery = queries.get(request.id);
00203 if (currentQuery == null)
00204 response.status = PrologNextSolution.Response.WRONG_ID;
00205
00206 else if (!currentQuery.hasMoreSolutions()){
00207 response.status = PrologNextSolution.Response.NO_SOLUTION;
00208 removeQuery(request.id);
00209
00210 } else {
00211 Hashtable<String, jpl.Term> solution = (Hashtable<String, jpl.Term>) currentQuery.nextSolution();
00212 response.solution = JSONQuery.encodeResult(solution).toString();
00213 response.status = PrologNextSolution.Response.OK;
00214 }
00215 }
00216
00217 } catch (jpl.JPLException e) {
00218 response.solution = e.getMessage();
00219 response.status = PrologNextSolution.Response.QUERY_FAILED;
00220 removeQuery(request.id);
00221
00222 } catch (Exception e) {
00223 e.printStackTrace();
00224 }
00225
00226 return response;
00227 }
00228 }
00229
00230
00237 private class FinishCallback implements
00238 ServiceServer.Callback<PrologFinish.Request, PrologFinish.Response> {
00239
00240 @Override
00241 public PrologFinish.Response call(PrologFinish.Request request) {
00242
00243 PrologFinish.Response response = new PrologFinish.Response();
00244
00245
00246 if (request.id.equals("*")){
00247 Enumeration<String> e = queries.keys();
00248 while(e.hasMoreElements())
00249 removeQuery(e.nextElement());
00250 } else {
00251 removeQuery(request.id);
00252 }
00253 return response;
00254 }
00255 }
00256
00261 public void execute(String args[]) throws InterruptedException, RosException, IOException, RospackError {
00262
00263
00264 final Ros ros = Ros.getInstance();
00265 if(!Ros.getInstance().isInitialized()) {
00266 ros.init("json_prolog", false, false, false, args);
00267 }
00268 NodeHandle n = ros.createNodeHandle("~");
00269
00270
00271 synchronized(jpl.Query.class) {
00272
00273 initProlog();
00274
00275 if(n.hasParam("initial_package"))
00276 {
00277 if(!initPackage.equals(""))
00278 ros.logWarn("Initial package has been specivied via command line parameter but the ROS parameter ~initial_package has been set. Using ROS parameter.");
00279 initPackage = n.getStringParam("initial_package");
00280 }
00281 if(!this.initPackage.equals("")) {
00282 new jpl.Query("ensure_loaded('" + findRosPackage(initPackage)
00283 + "/prolog/init.pl')").oneSolution();
00284 }
00285 if(n.hasParam("goal"))
00286 {
00287 String goal = n.getStringParam("goal");
00288 new jpl.Query(goal).oneSolution();
00289 }
00290 }
00291
00292
00293 @SuppressWarnings("unused")
00294 ServiceServer<PrologQuery.Request, PrologQuery.Response, PrologQuery> query_srv = n
00295 .advertiseService("query", new PrologQuery(), new QueryCallback());
00296 @SuppressWarnings("unused")
00297 ServiceServer<PrologQuery.Request, PrologQuery.Response, PrologQuery> simple_query_srv = n
00298 .advertiseService("simple_query", new PrologQuery(), new SimpleQueryCallback());
00299 @SuppressWarnings("unused")
00300 ServiceServer<PrologNextSolution.Request, PrologNextSolution.Response, PrologNextSolution> next_solution_srv = n
00301 .advertiseService("next_solution", new PrologNextSolution(),
00302 new NextSolutionCallback());
00303 @SuppressWarnings("unused")
00304 ServiceServer<PrologFinish.Request, PrologFinish.Response, PrologFinish> finish_srv = n
00305 .advertiseService("finish", new PrologFinish(), new FinishCallback());
00306
00307
00308 ros.logInfo("json_prolog initialized and waiting for queries.");
00309 ros.spin();
00310 }
00311
00312
00317 public void removeQuery(String id) {
00318
00319 PrologSolutions query = queries.get(id);
00320
00321 if(query != null) {
00322 query.close();
00323 queries.remove(id);
00324 if(query instanceof PrologIncrementalSolutions)
00325 hasIncrementalQuery = false;
00326 }
00327 }
00328
00329
00337 private static void initProlog() throws IOException, InterruptedException,
00338 RospackError {
00339 Vector<String> pl_args = new Vector<String>(Arrays.asList(jpl.JPL.getDefaultInitArgs()));
00340 pl_args.set(0, "/usr/bin/swipl");
00341 pl_args.add("-G256M");
00342 pl_args.add("-nosignals");
00343 jpl.JPL.setDefaultInitArgs(pl_args.toArray(new String[0]));
00344 jpl.JPL.init();
00345 new jpl.Query("ensure_loaded('" + findRosPackage("rosprolog") + "/prolog/init.pl')").oneSolution();
00346 }
00347
00357 private static String findRosPackage(String name) throws IOException, InterruptedException, RospackError {
00358
00359 Process rospack = Runtime.getRuntime().exec("rospack find " + name);
00360 if (rospack.waitFor() != 0)
00361 throw new RospackError();
00362 return new BufferedReader(new InputStreamReader(rospack.getInputStream())).readLine();
00363 }
00364
00365
00366
00367 public static void main(String args[]) {
00368
00369 try {
00370
00371
00372 if(args.length>0 && !args[0].contains(":="))
00373 {
00374 Ros.getInstance().logWarn("Using deprecated specification of package to load. Please use the corresponding ROS parameter ~initial_package instead");
00375 new JSONPrologNode(args[0]).execute(args);
00376 }
00377 else
00378 new JSONPrologNode().execute(args);
00379
00380 } catch (Exception e) {
00381 e.printStackTrace();
00382 }
00383 }
00384 }