roseus.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2008, Willow Garage, Inc.
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 Willow Garage, Inc. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     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 
00035 // author: Kei Okada
00036 
00037 
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <unistd.h>
00041 #include <string.h>
00042 #include <signal.h>
00043 #include <math.h>
00044 #include <time.h>
00045 #include <pthread.h>
00046 #include <setjmp.h>
00047 #include <errno.h>
00048 
00049 #include <list>
00050 #include <vector>
00051 #include <set>
00052 #include <string>
00053 #include <map>
00054 #include <sstream>
00055 
00056 #include <cstdio>
00057 #include <boost/thread/mutex.hpp>
00058 #include <boost/thread/condition.hpp>
00059 #include <boost/shared_ptr.hpp>
00060 
00061 #include <ros/init.h>
00062 #include <ros/time.h>
00063 #include <ros/rate.h>
00064 #include <ros/master.h>
00065 #include <ros/this_node.h>
00066 #include <ros/node_handle.h>
00067 #include <ros/service.h>
00068 #include <rospack/rospack.h>
00069 #include <ros/param.h>
00070 #include <ros/callback_queue.h>
00071 
00072 // for eus.h
00073 #define class   eus_class
00074 #define throw   eus_throw
00075 #define export  eus_export
00076 #define vector  eus_vector
00077 #define string  eus_string
00078 
00079 #include "eus.h"
00080 extern "C" {
00081   pointer ___roseus(register context *ctx, int n, pointer *argv, pointer env);
00082   void register_roseus(){
00083     char modname[] = "___roseus";
00084     return add_module_initializer(modname, (pointer (*)())___roseus);}
00085 }
00086 
00087 #undef class
00088 #undef throw
00089 #undef export
00090 #undef vector
00091 #undef string
00092 
00093 namespace ros {
00094   namespace master {
00095     std::string g_uri;
00096     void init(const M_string& remappings);
00097   }
00098   namespace param {
00099     void init(const M_string& remappings);
00100   }
00101 }
00102 
00103 using namespace ros;
00104 using namespace std;
00105 
00106 #define isInstalledCheck \
00107   if( ! ros::ok() ) { error(E_USER,"You must call ros::init() before creating the first NodeHandle"); }
00108 
00109 class RoseusStaticData
00110 {
00111 public:
00112   RoseusStaticData() {}
00113   ~RoseusStaticData() {
00114   }
00115   boost::shared_ptr<ros::NodeHandle> node;
00116   ros::Rate *rate;
00117   map<string, boost::shared_ptr<Publisher> > mapAdvertised; 
00118   map<string, boost::shared_ptr<Subscriber> > mapSubscribed; 
00119   map<string, boost::shared_ptr<ServiceServer> > mapServiced; 
00120 
00121   map<string, boost::shared_ptr<NodeHandle> > mapHandle; 
00122 };
00123 
00124 static RoseusStaticData s_staticdata;
00125 static bool s_bInstalled = false;
00126 #define s_node s_staticdata.node
00127 #define s_rate s_staticdata.rate
00128 #define s_mapAdvertised s_staticdata.mapAdvertised
00129 #define s_mapSubscribed s_staticdata.mapSubscribed
00130 #define s_mapServiced s_staticdata.mapServiced
00131 #define s_mapHandle s_staticdata.mapHandle
00132 
00133 pointer K_ROSEUS_MD5SUM,K_ROSEUS_DATATYPE,K_ROSEUS_DEFINITION,K_ROSEUS_SERIALIZATION_LENGTH,K_ROSEUS_SERIALIZE,K_ROSEUS_DESERIALIZE,K_ROSEUS_INIT,K_ROSEUS_GET,K_ROSEUS_REQUEST,K_ROSEUS_RESPONSE,K_ROSEUS_GROUPNAME,QANON,QNOOUT,QREPOVERSION;
00134 extern pointer LAMCLOSURE;
00135 
00136 /***********************************************************
00137  *   Message wrapper
00138  ************************************************************/
00139 
00140 string getString(pointer message, pointer method) {
00141   context *ctx = current_ctx;
00142   pointer r, curclass;
00143   if ((pointer)findmethod(ctx,method,classof(message),&curclass)!=NIL) {
00144     r = csend(ctx,message,method,0);
00145   } else if ((pointer)findmethod(ctx,K_ROSEUS_GET,classof(message),&curclass) != NIL ) {
00146     r = csend(ctx,message,K_ROSEUS_GET,1,method);
00147   } else {
00148     r = NULL;
00149 #ifdef x86_64
00150     ROS_ERROR("could not find method %s for pointer %lx",
00151               get_string(method), (long unsigned int)message);
00152 #else
00153     ROS_ERROR("could not find method %s for pointer %x",
00154               get_string(method), (unsigned int)message);
00155 #endif
00156   }
00157   if ( !isstring(r) ) {
00158     pointer dest=(pointer)mkstream(ctx,K_OUT,makebuffer(64));
00159     prinx(ctx,message,dest);
00160     pointer str = makestring((char *)dest->c.stream.buffer->c.str.chars,
00161                              intval(dest->c.stream.count));
00162     ROS_ERROR("send %s to %s returns nil", get_string(method), get_string(str));
00163   }
00164   ROS_ASSERT(isstring(r));
00165   string ret = (char *)get_string(r);
00166   return ret;
00167 }
00168 
00169 int getInteger(pointer message, pointer method) {
00170   context *ctx = current_ctx;
00171   pointer a,curclass;
00172   vpush(message);
00173   a = (pointer)findmethod(ctx,method,classof(message),&curclass);
00174   if (a!=NIL) {
00175     pointer r = csend(ctx,message,method,0);
00176     vpop();                     // message
00177     return (ckintval(r));
00178   } else {
00179 #ifdef x86_64
00180     ROS_ERROR("could not find method %s for pointer %lx",
00181               get_string(method), (long unsigned int)message);
00182 #else
00183     ROS_ERROR("could not find method %s for pointer %x",
00184               get_string(method), (unsigned int)message);
00185 #endif
00186     vpop();                     // message
00187   }
00188   return 0;
00189 }
00190 
00191 class EuslispMessage
00192 {
00193 public:
00194   pointer _message;
00195 
00196   EuslispMessage(pointer message) : _message(message) {
00197   }
00198   EuslispMessage(const EuslispMessage &r) {
00199     context *ctx = current_ctx;
00200     if (ctx!=euscontexts[0])ROS_WARN("ctx is not correct %d\n",thr_self());
00201     if ( isclass(r._message) ) {
00202       //ROS_ASSERT(isclass(r._message));
00203       vpush(r._message);
00204       _message = makeobject(r._message);
00205       vpush(_message);
00206       csend(ctx,_message,K_ROSEUS_INIT,0);
00207       vpop();                   // _message
00208       vpop();                   // r._message
00209     } else {
00210       ROS_WARN("r._message must be class");prinx(ctx,r._message,ERROUT);flushstream(ERROUT);terpri(ERROUT);
00211       _message = r._message;
00212     }
00213   }
00214   virtual ~EuslispMessage() { }
00215 
00216   virtual void replaceContents (pointer newMessage) {
00217     _message = newMessage;
00218   }
00219 
00220   virtual const string __getDataType() const {
00221     return getString(_message, K_ROSEUS_DATATYPE);
00222   }
00223   virtual const string __getMD5Sum()   const {
00224     return getString(_message, K_ROSEUS_MD5SUM);
00225   }
00226   virtual const string __getMessageDefinition() const {
00227     return getString(_message, K_ROSEUS_DEFINITION);
00228   }
00229   virtual const string __getServiceDataType() const {
00230     return getString(_message, K_ROSEUS_DATATYPE);
00231   }
00232   virtual const string __getServerMD5Sum()    const {
00233     return getString(_message, K_ROSEUS_MD5SUM);
00234   }
00235 
00236   uint32_t serializationLength() const {
00237     context *ctx = current_ctx;
00238     if (ctx!=euscontexts[0])ROS_WARN("ctx is not correct %d\n",thr_self());
00239     pointer a,curclass;
00240     a = (pointer)findmethod(ctx,K_ROSEUS_SERIALIZATION_LENGTH,classof(_message),&curclass);
00241     ROS_ASSERT(a!=NIL);
00242     return getInteger(_message, K_ROSEUS_SERIALIZATION_LENGTH);
00243   }
00244 
00245   virtual uint8_t *serialize(uint8_t *writePtr, uint32_t seqid) const
00246   {
00247     context *ctx = current_ctx;
00248     if (ctx!=euscontexts[0])ROS_WARN("ctx is not correct %d\n",thr_self());
00249     pointer a,curclass;
00250     vpush(_message);            // to avoid GC
00251     uint32_t len = serializationLength();
00252     vpop();                     // pop _message
00253     a = (pointer)findmethod(ctx,K_ROSEUS_SERIALIZE,classof(_message),&curclass);
00254     ROS_ASSERT(a!=NIL);
00255     pointer r = csend(ctx,_message,K_ROSEUS_SERIALIZE,0);
00256     ROS_ASSERT(isstring(r));
00257     memcpy(writePtr, get_string(r), len);
00258     //ROS_INFO("serialize");
00259 
00260     return writePtr + len;
00261   }
00262 
00263   virtual uint8_t *deserialize(uint8_t *readPtr, uint32_t sz)
00264   {
00265     context *ctx = current_ctx;
00266     if (ctx!=euscontexts[0])ROS_WARN("ctx is not correct %d\n",thr_self());
00267     pointer a,curclass;
00268 
00269     if ( sz == 0 ) {
00270       ROS_DEBUG("empty message!");
00271       return readPtr;
00272     }
00273     vpush(_message);
00274     a = (pointer)findmethod(ctx,K_ROSEUS_DESERIALIZE,classof(_message),&curclass);
00275     ROS_ASSERT(a!=NIL);
00276     pointer p = makestring((char *)readPtr, sz);
00277     pointer r = csend(ctx,_message,K_ROSEUS_DESERIALIZE,1,p);
00278     ROS_ASSERT(r!=NIL);
00279     //ROS_INFO("deserialize %d", __serialized_length);
00280     vpop(); // pop _message
00281 
00282     return readPtr + sz;
00283   }
00284 };
00285 
00286 namespace ros{
00287   namespace serialization{
00288 template<> struct Serializer<EuslispMessage> {
00289   template<typename Stream>
00290   inline static void write(Stream& stream, boost::call_traits<EuslispMessage>::param_type t) {
00291     t.serialize(stream.getData(), 0);
00292   }
00293 
00294   template<typename Stream>
00295   inline static void read(Stream& stream, boost::call_traits<EuslispMessage>::reference t) {
00296     t.deserialize(stream.getData(), stream.getLength());
00297   }
00298   inline static uint32_t serializedLength(boost::call_traits<EuslispMessage>::param_type t) {
00299     return t.serializationLength();
00300   }
00301 };
00302   }
00303 }
00304 
00305 /************************************************************
00306  *   Subscriptions
00307  ************************************************************/
00308 class EuslispSubscriptionCallbackHelper : public ros::SubscriptionCallbackHelper {
00309 public:
00310   pointer _scb,_args;
00311   EuslispMessage _msg;
00312 
00313   EuslispSubscriptionCallbackHelper(pointer scb, pointer args,pointer tmpl) :  _args(args), _msg(tmpl) {
00314     context *ctx = current_ctx;
00315     mutex_trylock(&mark_lock);
00316     //ROS_WARN("func");prinx(ctx,scb,ERROUT);flushstream(ERROUT);terpri(ERROUT);
00317     //ROS_WARN("argc");prinx(ctx,args,ERROUT);flushstream(ERROUT);terpri(ERROUT);
00318     if (piscode(scb)) { // compiled code
00319       _scb=scb;
00320     } else if ((ccar(scb))==LAMCLOSURE) { // uncompiled code
00321       if ( ccar(ccdr(scb)) != NIL ) { // function
00322         _scb=ccar(ccdr(scb));
00323       } else { // lambda function
00324         _scb=scb;
00325       }
00326     } else {
00327       ROS_ERROR("subcriptoin callback function install error");
00328     }
00329     // avoid gc
00330     pointer p=gensym(ctx);
00331     setval(ctx,intern(ctx,(char*)(p->c.sym.pname->c.str.chars),strlen((char*)(p->c.sym.pname->c.str.chars)),lisppkg),cons(ctx,scb,args));
00332     mutex_unlock(&mark_lock);
00333   }
00334   ~EuslispSubscriptionCallbackHelper() {
00335       ROS_ERROR("subcriptoin gc");
00336   }
00337   virtual ros::VoidConstPtr deserialize(const ros::SubscriptionCallbackHelperDeserializeParams& param) {
00338 #if DEBUG
00339     cerr << __PRETTY_FUNCTION__ << endl;
00340     cerr << "param.length = " << param.length << endl;
00341     cerr << "param.buffer = " << (param.buffer + 4) << endl;
00342     cerr << "c_header == " << param.connection_header << endl;
00343 #endif
00344     ros::VoidConstPtr ptr(new EuslispMessage(_msg));
00345     EuslispMessage *eus_msg = (EuslispMessage *)(ptr.get());
00346     eus_msg->deserialize(param.buffer, param.length);
00347 
00348     return ptr;
00349   }
00350   virtual void call(ros::SubscriptionCallbackHelperCallParams& param) {
00351     EuslispMessage* eus_msg = (EuslispMessage *)((void *)param.event.getConstMessage().get());
00352     context *ctx = current_ctx;
00353     pointer argp=_args;
00354     int argc=0;
00355     //ROS_WARN("func");prinx(ctx,_scb,ERROUT);flushstream(ERROUT);terpri(ERROUT);
00356     //ROS_WARN("argc");prinx(ctx,argp,ERROUT);flushstream(ERROUT);terpri(ERROUT);
00357     vpush(eus_msg->_message);    // to avoid GC
00358     if ( ! ( issymbol(_scb) || piscode(_scb) || ccar(_scb)==LAMCLOSURE ) ) {
00359       ROS_ERROR("%s : can't find callback function", __PRETTY_FUNCTION__);
00360     }
00361     
00362     while(argp!=NIL){ ckpush(ccar(argp)); argp=ccdr(argp); argc++;}
00363     vpush((pointer)(eus_msg->_message));argc++;
00364     
00365     ufuncall(ctx,(ctx->callfp?ctx->callfp->form:NIL),_scb,(pointer)(ctx->vsp-argc),NULL,argc);
00366     while(argc-->0)vpop();
00367     vpop();    // remove eus_msg._message
00368   }
00369   virtual const std::type_info& getTypeInfo() {
00370     return typeid(EuslispMessage);
00371   }
00372   virtual bool isConst(){
00373     return true;
00374   }
00375   virtual bool hasHeader(){
00376     return true;
00377   }
00378 };
00379 
00380 /************************************************************
00381  *   ServiceCall
00382  ************************************************************/
00383 class EuslispServiceCallbackHelper : public ros::ServiceCallbackHelper {
00384 public:
00385   pointer _scb, _args;
00386   EuslispMessage _req, _res;
00387   string md5, datatype, requestDataType, responseDataType,
00388     requestMessageDefinition, responseMessageDefinition;
00389 
00390   EuslispServiceCallbackHelper(pointer scb, pointer args, string smd5, string sdatatype, pointer reqclass, pointer resclass) : _args(args), _req(reqclass), _res(resclass), md5(smd5), datatype(sdatatype) {
00391     context *ctx = current_ctx;
00392     mutex_trylock(&mark_lock);
00393     //ROS_WARN("func");prinx(ctx,scb,ERROUT);flushstream(ERROUT);terpri(ERROUT);
00394     //ROS_WARN("argc");prinx(ctx,args,ERROUT);flushstream(ERROUT);terpri(ERROUT);
00395 
00396     if (piscode(scb)) { // compiled code
00397       _scb=scb;
00398     } else if ((ccar(scb))==LAMCLOSURE) {
00399       if ( ccar(ccdr(scb)) != NIL ) { // function
00400         _scb=ccar(ccdr(scb));
00401       } else { // lambda function
00402         _scb=scb;
00403       }
00404     } else  {
00405       ROS_ERROR("service callback function install error");
00406     }
00407     // avoid gc
00408     pointer p=gensym(ctx);
00409     setval(ctx,intern(ctx,(char*)(p->c.sym.pname->c.str.chars),strlen((char*)(p->c.sym.pname->c.str.chars)),lisppkg),cons(ctx,scb,args));
00410 
00411     requestDataType = _req.__getDataType();
00412     responseDataType = _res.__getDataType();
00413     requestMessageDefinition = _req.__getMessageDefinition();
00414     responseMessageDefinition = _res.__getMessageDefinition();
00415     mutex_unlock(&mark_lock);
00416   }
00417   ~EuslispServiceCallbackHelper() { }
00418 
00419   virtual boost::shared_ptr<EuslispMessage> createRequest() { return boost::shared_ptr<EuslispMessage>(new EuslispMessage(_req)); }
00420   virtual boost::shared_ptr<EuslispMessage> createResponse() { return boost::shared_ptr<EuslispMessage>(new EuslispMessage(_res)); }
00421 
00422   virtual std::string getMD5Sum() { return md5; }
00423   virtual std::string getDataType() { return datatype; }
00424   virtual std::string getRequestDataType() { return requestDataType; }
00425   virtual std::string getResponseDataType() { return responseDataType; }
00426   virtual std::string getRequestMessageDefinition() { return requestMessageDefinition; }
00427   virtual std::string getResponseMessageDefinition() { return responseMessageDefinition; }
00428 
00429   virtual bool call(ros::ServiceCallbackHelperCallParams& params) {
00430     context *ctx = current_ctx;
00431     pointer r, argp=_args;
00432     int argc=0;
00433 
00434     vpush(_res._message);       // _res._message
00435     vpush(_req._message);       // _res._message, _req._message
00436 
00437     if ( ! ( issymbol(_scb) || piscode(_scb) || ccar(_scb)==LAMCLOSURE ) ) {
00438       ROS_ERROR("%s : can't find callback function", __PRETTY_FUNCTION__);
00439     }
00440     // Deserialization
00441     EuslispMessage eus_msg(_req);
00442     vpush(eus_msg._message);    // _res._message, _req._message, eus_msg._message
00443     eus_msg.deserialize(params.request.message_start, params.request.num_bytes);
00444 
00445     while(argp!=NIL){ ckpush(ccar(argp)); argp=ccdr(argp); argc++;}
00446     vpush((pointer) eus_msg._message);argc++;
00447 
00448     r = ufuncall(ctx, (ctx->callfp?ctx->callfp->form:NIL),
00449                  _scb, (pointer)(ctx->vsp-argc),
00450                  NULL, argc);
00451     while(argc-->0)vpop();// _res._message, _req._message, eus_msg._message
00452     vpush(r); // _res._message, _req._message, eus_msg._message, r, 
00453     
00454     // Serializaion
00455     EuslispMessage eus_res(_res);
00456     eus_res.replaceContents(r);
00457     vpush(eus_res._message);    // _res._message, _req._message, eus_msg._message, r, eus_res._message
00458     
00459     uint32_t serialized_length = eus_res.serializationLength();
00460     params.response.num_bytes = serialized_length + 5; // add 5 bytes of message header
00461     params.response.buf.reset (new uint8_t[params.response.num_bytes]);
00462     params.response.message_start = 0;
00463 
00464     // SerializedResponseMessage
00465     uint8_t *tmp = params.response.buf.get();
00466     *tmp++ = 1; // 1 byte of success services flag, now always set true
00467     *tmp++ = (uint8_t)((serialized_length >> 0) & 0xFF); // 4bytes of message length
00468     *tmp++ = (uint8_t)((serialized_length >> 8) & 0xFF);
00469     *tmp++ = (uint8_t)((serialized_length >> 16) & 0xFF);
00470     *tmp++ = (uint8_t)((serialized_length >> 24) & 0xFF);
00471     eus_res.serialize(tmp, 0);
00472 #if DEBUG
00473     cerr << "num bytes = " << params.response.num_bytes << endl;
00474     ROS_INFO("message_start =  %X",params.response.message_start);
00475     ROS_INFO("message_ptr =  %X",params.response.buf.get());
00476     tmp = params.response.buf.get();
00477     for(int i=0;i<params.response.num_bytes;i++){
00478       ROS_INFO("%X", tmp[i]);
00479     }
00480 #endif
00481     vpop(); // _res._message, _req._message, eus_msg._message, r, eus_res._message
00482     vpop(); // _res._message, _req._message, eus_msg._message, r
00483     vpop(); // _res._message, _req._message, eus_msg._message
00484     vpop(); // _res._message, _req._message,
00485     vpop(); // _res._message
00486     return(T);
00487   }
00488 };
00489 
00490 void roseusSignalHandler(int sig)
00491 {
00492     // memoize for euslisp handler...
00493     context *ctx=euscontexts[thr_self()];
00494     ctx->intsig = sig;
00495 }
00496 
00497 /************************************************************
00498  *   EUSLISP functions
00499  ************************************************************/
00500 pointer ROSEUS(register context *ctx,int n,pointer *argv)
00501 {
00502   char name[256] = "";
00503   uint32_t options = 0;
00504   int cargc = 0;
00505   char *cargv[32];
00506 
00507   if( s_bInstalled ) {
00508     ROS_WARN("ROSEUS is already installed as %s", ros::this_node::getName().c_str());
00509     return (T);
00510   }
00511 
00512   ckarg(3);
00513   if (isstring(argv[0]))
00514     strncpy(name,(char *)(argv[0]->c.str.chars),255);
00515   else error(E_NOSTRING);
00516   options = ckintval(argv[1]);
00517   pointer p = argv[2];
00518   if (islist(p)) {
00519     while (1) {
00520       if (!iscons(p)) break;
00521       cargv[cargc]=(char *)((ccar(p))->c.str.chars);
00522       cargc++;
00523       p=ccdr(p);
00524     }
00525   } else error(E_NOSEQ);
00526 
00527   for (unsigned int i=0; i < strlen(name); i++)
00528     if ( ! isalpha(name[i]) ) name[i] = '_';
00529 
00530   K_ROSEUS_MD5SUM   = defkeyword(ctx,"MD5SUM-");
00531   K_ROSEUS_DATATYPE = defkeyword(ctx,"DATATYPE-");
00532   K_ROSEUS_DEFINITION = defkeyword(ctx,"DEFINITION-");
00533   K_ROSEUS_SERIALIZATION_LENGTH = defkeyword(ctx,"SERIALIZATION-LENGTH");
00534   K_ROSEUS_SERIALIZE   = defkeyword(ctx,"SERIALIZE");
00535   K_ROSEUS_DESERIALIZE = defkeyword(ctx,"DESERIALIZE");
00536   K_ROSEUS_GET  = defkeyword(ctx,"GET");
00537   K_ROSEUS_INIT = defkeyword(ctx,"INIT");
00538   K_ROSEUS_REQUEST  = defkeyword(ctx,"REQUEST");
00539   K_ROSEUS_RESPONSE = defkeyword(ctx,"RESPONSE");
00540   K_ROSEUS_GROUPNAME = defkeyword(ctx,"GROUPNAME");
00541 
00542   s_mapAdvertised.clear();
00543   s_mapSubscribed.clear();
00544   s_mapServiced.clear();
00545   s_mapHandle.clear();
00546   
00547   /*
00548     force to flag ros::init_options::NoSigintHandler.
00549     In fact, this code make no sence, because we steals
00550     SIGINT handler by the following `signal'.
00551    */
00552   options |= ros::init_options::NoSigintHandler;
00553 
00554   /*
00555     clear ros::master::g_uri which is defined in ros::master::init in __roseus.
00556     this occurs if user set unix::setenv("ROS_MASTER_URI") between __roseus and
00557     ROSEUS.
00558    */
00559   if (!ros::master::g_uri.empty()) {
00560     if ( ros::master::g_uri != getenv("ROS_MASTER_URI") ) {
00561       ROS_WARN("ROS master uri will be changed!!, master uri %s, which is defineed previously is differ from current ROS_MASTE_URI(%s)", ros::master::g_uri.c_str(), getenv("ROS_MASTER_URI"));
00562       ros::master::g_uri.clear();
00563     }
00564   }
00565   try {
00566     ros::init(cargc, cargv, name, options);
00567   } catch (const ros::InvalidNameException &e) {
00568     ROS_ERROR("%s",e.what());
00569     error(E_MISMATCHARG);
00570     return(NIL);
00571   }
00572 
00573   s_node.reset(new ros::NodeHandle());
00574   s_rate = new ros::Rate(50);
00575 
00576   s_bInstalled = true;
00577 
00578   // install signal handler for sigint. DO NOT call unix:signal after
00579   // ros::roseus
00580   signal(SIGINT, roseusSignalHandler);
00581   return (T);
00582 }
00583 
00584 pointer ROSEUS_CREATE_NODEHANDLE(register context *ctx,int n,pointer *argv)
00585 {
00586   isInstalledCheck;
00587   string groupname;
00588   string ns;
00589 
00590   ckarg2(1, 2);
00591   // ;; arguments ;;
00592   // groupname [ namespace ]
00593 
00594   if (isstring(argv[0])) groupname.assign((char *)get_string(argv[0]));
00595   else error(E_NOSTRING);
00596   if ( n > 1 ) {
00597     if(isstring(argv[1])) ns.assign((char *)get_string(argv[1]));
00598     else error(E_NOSTRING);
00599   }
00600 
00601   if( s_mapHandle.find(groupname) != s_mapHandle.end() ) {
00602     ROS_DEBUG("groupname %s is already used", groupname.c_str());
00603     return (NIL);
00604   }
00605 
00606   boost::shared_ptr<NodeHandle> hd;
00607   if ( n > 1 ) {
00608     hd = boost::shared_ptr<NodeHandle> (new NodeHandle(ns));
00609     s_mapHandle[groupname] = hd;
00610   } else {
00611     hd = boost::shared_ptr<NodeHandle>(new NodeHandle());
00612     s_mapHandle[groupname] = hd;
00613   }
00614   //add callbackqueue to hd
00615   hd->setCallbackQueue( new CallbackQueue() );
00616 
00617   return (T);
00618 }
00619 
00620 pointer ROSEUS_SPIN(register context *ctx,int n,pointer *argv)
00621 {
00622   isInstalledCheck;
00623   while (ctx->intsig==0) {
00624     ros::spinOnce();
00625     s_rate->sleep();
00626   }
00627   return (NIL);
00628 }
00629 
00630 pointer ROSEUS_SPINONCE(register context *ctx,int n,pointer *argv)
00631 {
00632   isInstalledCheck;
00633   ckarg2(0, 1);
00634   // ;; arguments ;;
00635   // [ groupname ]
00636 
00637   if ( n > 0 ) {
00638     string groupname;
00639     if (isstring(argv[0])) groupname.assign((char *)get_string(argv[0]));
00640     else error(E_NOSTRING);
00641 
00642     map<string, boost::shared_ptr<NodeHandle > >::iterator it = s_mapHandle.find(groupname);
00643     if( it == s_mapHandle.end() ) {
00644       ROS_ERROR("Groupname %s is missing", groupname.c_str());
00645       return (T);
00646     }
00647     boost::shared_ptr<NodeHandle > hdl = (it->second);
00648     // spin this nodehandle
00649     ((CallbackQueue *)hdl->getCallbackQueue())->callAvailable();
00650 
00651     return (NIL);
00652   } else {
00653     ros::spinOnce();
00654     return (NIL);
00655   }
00656 }
00657 
00658 pointer ROSEUS_TIME_NOW(register context *ctx,int n,pointer *argv)
00659 {
00660   isInstalledCheck;
00661   pointer timevec;
00662   ros::Time t = ros::Time::now();
00663 
00664   timevec=makevector(C_INTVECTOR,2);
00665   vpush(timevec);
00666   timevec->c.ivec.iv[0]=t.sec;
00667   timevec->c.ivec.iv[1]=t.nsec;
00668   vpop();
00669   return (timevec);
00670 }
00671 
00672 pointer ROSEUS_RATE(register context *ctx,int n,pointer *argv)
00673 {
00674   isInstalledCheck;
00675   numunion nu;
00676   ckarg(1);
00677   float timeout=ckfltval(argv[0]);
00678   s_rate = new ros::Rate(timeout);
00679   return(T);
00680 }
00681 
00682 pointer ROSEUS_SLEEP(register context *ctx,int n,pointer *argv)
00683 {
00684   isInstalledCheck;
00685   s_rate->sleep();
00686   return (T);
00687 }
00688 
00689 pointer ROSEUS_OK(register context *ctx,int n,pointer *argv)
00690 {
00691   if (ros::ok()) {
00692     return (T);
00693   } else {
00694     return (NIL);
00695   }
00696 }
00697 
00698 
00699 #define def_rosconsole_formatter(funcname, rosfuncname)         \
00700   pointer funcname(register context *ctx,int n,pointer *argv)   \
00701   { pointer *argv2,msg;                                         \
00702     int argc2;                                                  \
00703     argc2 = n+1;                                                \
00704     argv2 = (pointer *)malloc(sizeof(pointer)*argc2);           \
00705     argv2[0] = NIL;                                             \
00706     for(int i=0;i<n;i++) argv2[i+1]=argv[i] ;                   \
00707     msg = XFORMAT(ctx, argc2, argv2);                           \
00708     rosfuncname("%s", msg->c.str.chars);                        \
00709     free(argv2);                                                \
00710     return (T);                                                 \
00711   }
00712 
00713 def_rosconsole_formatter(ROSEUS_ROSDEBUG, ROS_DEBUG)
00714 def_rosconsole_formatter(ROSEUS_ROSINFO,  ROS_INFO)
00715 def_rosconsole_formatter(ROSEUS_ROSWARN,  ROS_WARN)
00716 def_rosconsole_formatter(ROSEUS_ROSERROR, ROS_ERROR)
00717 def_rosconsole_formatter(ROSEUS_ROSFATAL, ROS_FATAL)
00718 
00719 pointer ROSEUS_EXIT(register context *ctx,int n,pointer *argv)
00720 {
00721   ROS_INFO("%s", __PRETTY_FUNCTION__);
00722   if( s_bInstalled ) {
00723     ROS_INFO("exiting roseus %ld", (n==0)?n:ckintval(argv[0]));
00724     s_mapAdvertised.clear();
00725     s_mapSubscribed.clear();
00726     s_mapServiced.clear();
00727     s_mapHandle.clear();
00728     ros::shutdown();
00729   }
00730   if (n==0) _exit(0);
00731   else _exit(ckintval(argv[0]));
00732 }
00733 
00734 /************************************************************
00735  *   ROSEUS Publisher/Subscriber
00736  ************************************************************/
00737 pointer ROSEUS_SUBSCRIBE(register context *ctx,int n,pointer *argv)
00738 {
00739   isInstalledCheck;
00740   string topicname;
00741   pointer message, fncallback, args;
00742   int queuesize = 1;
00743   NodeHandle *lnode = s_node.get();
00744 
00745   // ;; arguments ;;
00746   // topicname message_type callbackfunc args0 ... argsN [ queuesize ] [ :groupname groupname ]
00747   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00748   else error(E_NOSTRING);
00749 
00750   if (n > 1 && issymbol(argv[n-2]) && isstring(argv[n-1])) {
00751     if (argv[n-2] == K_ROSEUS_GROUPNAME) {
00752       string groupname;
00753       groupname.assign((char *)get_string(argv[n-1]));
00754       map<string, boost::shared_ptr<NodeHandle > >::iterator it = s_mapHandle.find(groupname);
00755       if( it != s_mapHandle.end() ) {
00756         ROS_DEBUG("subscribe with groupname=%s", groupname.c_str());
00757         lnode = (it->second).get();
00758       } else {
00759         ROS_ERROR("Groupname %s is missing. Topic %s is not subscribed. Call (ros::create-nodehandle \"%s\") first.",
00760                   groupname.c_str(), topicname.c_str(), groupname.c_str());
00761         return (NIL);
00762       }
00763       n -= 2;
00764     }
00765   }
00766   if (isint(argv[n-1])) {queuesize = ckintval(argv[n-1]);n--;}
00767   ROS_DEBUG("subscribe %s queuesize=%d", topicname.c_str(), queuesize);
00768   // TODO:need error checking
00769   message = argv[1];
00770   fncallback = argv[2];
00771   args=NIL;
00772   for (int i=n-1;i>=3;i--) args=cons(ctx,argv[i],args);
00773 
00774   EuslispMessage msg(message);
00775    boost::shared_ptr<SubscriptionCallbackHelper> *callback =
00776      (new boost::shared_ptr<SubscriptionCallbackHelper>
00777       (new EuslispSubscriptionCallbackHelper(fncallback, args, message)));
00778   SubscribeOptions so(topicname, queuesize, msg.__getMD5Sum(), msg.__getDataType());
00779   so.helper = *callback;
00780   Subscriber subscriber = lnode->subscribe(so);
00781   boost::shared_ptr<Subscriber> sub = boost::shared_ptr<Subscriber>(new Subscriber(subscriber));
00782   if ( !!sub ) {
00783     s_mapSubscribed[topicname] = sub;
00784   } else {
00785     ROS_ERROR("s_mapSubscribed");
00786   }
00787 
00788   return (T);
00789 }
00790 
00791 pointer ROSEUS_UNSUBSCRIBE(register context *ctx,int n,pointer *argv)
00792 {
00793   string topicname;
00794 
00795   ckarg(1);
00796   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00797   else error(E_NOSTRING);
00798 
00799   bool bSuccess = s_mapSubscribed.erase(topicname)>0;
00800 
00801   return (bSuccess?T:NIL);
00802 }
00803 
00804 pointer ROSEUS_GETNUMPUBLISHERS(register context *ctx,int n,pointer *argv)
00805 {
00806   string topicname;
00807   int ret;
00808 
00809   ckarg(1);
00810   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00811   else error(E_NOSTRING);
00812 
00813   bool bSuccess = false;
00814   map<string, boost::shared_ptr<Subscriber> >::iterator it = s_mapSubscribed.find(topicname);
00815   if( it != s_mapSubscribed.end() ) {
00816     boost::shared_ptr<Subscriber> subscriber = (it->second);
00817     ret = subscriber->getNumPublishers();
00818     bSuccess = true;
00819   }
00820 
00821   if ( ! bSuccess ) {
00822     ROS_ERROR("attempted to getNumPublishers to topic %s, which was not " \
00823               "previously subscribed. call (ros::subscribe \"%s\") first.",
00824               topicname.c_str(), topicname.c_str());
00825   }
00826 
00827   return (bSuccess?(makeint(ret)):NIL);
00828 }
00829 
00830 pointer ROSEUS_GETTOPICSUBSCRIBER(register context *ctx,int n,pointer *argv)
00831 {
00832   string topicname;
00833   string ret;
00834 
00835   ckarg(1);
00836   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00837   else error(E_NOSTRING);
00838 
00839   bool bSuccess = false;
00840   map<string, boost::shared_ptr<Subscriber> >::iterator it = s_mapSubscribed.find(topicname);
00841   if( it != s_mapSubscribed.end() ) {
00842     boost::shared_ptr<Subscriber> subscriber = (it->second);
00843     ret = subscriber->getTopic();
00844     bSuccess = true;
00845   }
00846 
00847   if ( ! bSuccess ) {
00848     ROS_ERROR("attempted to getTopic to topic %s, which was not " \
00849               "previously advertised. call (ros::advertise \"%s\") first.",
00850               topicname.c_str(), topicname.c_str());
00851   }
00852 
00853   return (bSuccess?(makestring((char *)ret.c_str(), ret.length())):NIL);
00854 }
00855 
00856 pointer ROSEUS_ADVERTISE(register context *ctx,int n,pointer *argv)
00857 {
00858   isInstalledCheck;
00859   string topicname;
00860   pointer message;
00861   int queuesize = 1;
00862   bool latch = false;
00863 
00864   ckarg2(2,4);
00865   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00866   else error(E_NOSTRING);
00867   message = argv[1];
00868   if ( n > 2 ) {
00869     queuesize = ckintval(argv[2]);
00870   }
00871   if ( n > 3 ) {
00872     latch = (argv[3]!=NIL ? true : false);
00873   }
00874   ROS_DEBUG("advertise %s %d %d", topicname.c_str(), queuesize, latch);
00875   if( s_mapAdvertised.find(topicname) != s_mapAdvertised.end() ) {
00876     ROS_WARN("topic %s already advertised", topicname.c_str());
00877     return (NIL);
00878   }
00879 
00880   EuslispMessage msg(message);
00881   AdvertiseOptions ao(topicname, queuesize, msg.__getMD5Sum(), msg.__getDataType(), msg.__getMessageDefinition());
00882   ao.latch = latch;
00883   Publisher publisher = s_node->advertise(ao);
00884   boost::shared_ptr<Publisher> pub = boost::shared_ptr<Publisher>(new Publisher(publisher));
00885   if ( !!pub ) {
00886     s_mapAdvertised[topicname] = pub;
00887   } else {
00888     ROS_ERROR("s_mapAdvertised");
00889   }
00890 
00891   return (T);
00892 }
00893 
00894 pointer ROSEUS_UNADVERTISE(register context *ctx,int n,pointer *argv)
00895 {
00896   string topicname;
00897 
00898   ckarg(1);
00899   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00900   else error(E_NOSTRING);
00901 
00902   bool bSuccess = s_mapAdvertised.erase(topicname)>0;
00903 
00904   return (bSuccess?T:NIL);
00905 }
00906 
00907 pointer ROSEUS_PUBLISH(register context *ctx,int n,pointer *argv)
00908 {
00909   isInstalledCheck;
00910   string topicname;
00911   pointer emessage;
00912 
00913   ckarg(2);
00914   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00915   else error(E_NOSTRING);
00916   emessage = argv[1];
00917 
00918   bool bSuccess = false;
00919   map<string, boost::shared_ptr<Publisher> >::iterator it = s_mapAdvertised.find(topicname);
00920   if( it != s_mapAdvertised.end() ) {
00921     boost::shared_ptr<Publisher> publisher = (it->second);
00922     EuslispMessage message(emessage);
00923     publisher->publish(message);
00924     bSuccess = true;
00925   }
00926 
00927   if ( ! bSuccess ) {
00928     ROS_ERROR("attempted to publish to topic %s, which was not " \
00929               "previously advertised. call (ros::advertise \"%s\") first.",
00930               topicname.c_str(), topicname.c_str());
00931   }
00932 
00933   return (T);
00934 }
00935 
00936 pointer ROSEUS_GETNUMSUBSCRIBERS(register context *ctx,int n,pointer *argv)
00937 {
00938   string topicname;
00939   int ret;
00940 
00941   ckarg(1);
00942   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00943   else error(E_NOSTRING);
00944 
00945   bool bSuccess = false;
00946   map<string, boost::shared_ptr<Publisher> >::iterator it = s_mapAdvertised.find(topicname);
00947   if( it != s_mapAdvertised.end() ) {
00948     boost::shared_ptr<Publisher> publisher = (it->second);
00949     ret = publisher->getNumSubscribers();
00950     bSuccess = true;
00951   }
00952 
00953   if ( ! bSuccess ) {
00954     ROS_ERROR("attempted to getNumSubscribers to topic %s, which was not " \
00955               "previously advertised. call (ros::advertise \"%s\") first.",
00956               topicname.c_str(), topicname.c_str());
00957   }
00958 
00959   return (bSuccess?(makeint(ret)):NIL);
00960 }
00961 
00962 pointer ROSEUS_GETTOPICPUBLISHER(register context *ctx,int n,pointer *argv)
00963 {
00964   string topicname;
00965   string ret;
00966 
00967   ckarg(1);
00968   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00969   else error(E_NOSTRING);
00970 
00971   bool bSuccess = false;
00972   map<string, boost::shared_ptr<Publisher> >::iterator it = s_mapAdvertised.find(topicname);
00973   if( it != s_mapAdvertised.end() ) {
00974     boost::shared_ptr<Publisher> publisher = (it->second);
00975     ret = publisher->getTopic();
00976     bSuccess = true;
00977   }
00978 
00979   if ( ! bSuccess ) {
00980     ROS_ERROR("attempted to getTopic to topic %s, which was not " \
00981               "previously advertised. call (ros::advertise \"%s\") first.",
00982               topicname.c_str(), topicname.c_str());
00983   }
00984 
00985   return (bSuccess?(makestring((char *)ret.c_str(), ret.length())):NIL);
00986 }
00987 
00988 /************************************************************
00989  *   ROSEUS ServiceCall
00990  ************************************************************/
00991 pointer ROSEUS_WAIT_FOR_SERVICE(register context *ctx,int n,pointer *argv)
00992 {
00993   isInstalledCheck;
00994   string service;
00995 
00996   ckarg2(1,2);
00997   if (isstring(argv[0])) service.assign((char *)(argv[0]->c.str.chars));
00998   else error(E_NOSTRING);
00999 
01000   int32_t timeout = -1;
01001 
01002   if( n > 1 )
01003     timeout = (int32_t)ckintval(argv[1]);
01004 
01005   bool bSuccess = service::waitForService(ros::names::resolve(service), ros::Duration(timeout));
01006 
01007   return (bSuccess?T:NIL);
01008 }
01009 
01010 pointer ROSEUS_SERVICE_EXISTS(register context *ctx,int n,pointer *argv)
01011 {
01012   isInstalledCheck;
01013   string service;
01014 
01015   ckarg(1);
01016   if (isstring(argv[0])) service.assign((char *)(argv[0]->c.str.chars));
01017   else error(E_NOSTRING);
01018 
01019   bool bSuccess = service::exists(ros::names::resolve(service), true);
01020 
01021   return (bSuccess?T:NIL);
01022 }
01023 
01024 pointer ROSEUS_SERVICE_CALL(register context *ctx,int n,pointer *argv)
01025 {
01026   isInstalledCheck;
01027   string service;
01028   pointer emessage;
01029   bool persist = false;
01030   ckarg2(2,3);
01031   if (isstring(argv[0])) service.assign((char *)(argv[0]->c.str.chars));
01032   else error(E_NOSTRING);
01033   emessage = argv[1];
01034   if ( n > 2 ) {
01035       persist = (argv[2] != NIL ? true : false);
01036   }
01037   static std::map<std::string, ros::ServiceClient> service_cache;
01038   std::string service_name = ros::names::resolve(service);
01039   ServiceClient client;
01040   EuslispMessage request(emessage);
01041   vpush(request._message);      // to avoid GC, it may not be required...
01042   EuslispMessage response(csend(ctx,emessage,K_ROSEUS_RESPONSE,0));
01043   vpush(response._message);     // to avoid GC, its important
01044   if (persist == false) {
01045     ServiceClientOptions sco(service_name, request.__getMD5Sum(), false, M_string());
01046     client = s_node->serviceClient(sco);
01047   }
01048   else {
01049     // check the instance of client
01050     
01051     if (service_cache.find(service_name) != service_cache.end()) {
01052       client = service_cache[service_name];
01053     }
01054     else {
01055       ServiceClientOptions sco(service_name, request.__getMD5Sum(), true, M_string());
01056       client = s_node->serviceClient(sco);
01057       service_cache[service_name] = client;
01058     }
01059   }
01060     // NEED FIX
01061   bool bSuccess =  client.call(request, response, request.__getMD5Sum());
01062   vpop();                       // pop response._message
01063   vpop();                       // pop request._message
01064   if ( ! bSuccess ) {
01065     ROS_ERROR("attempted to call service  %s, but failed ",
01066               ros::names::resolve(service).c_str());
01067     if (persist) {
01068       // cleanup service_cache
01069       service_cache.erase(service_cache.find(service_name));
01070     }
01071   }
01072 
01073   return (response._message);
01074 }
01075 
01076 pointer ROSEUS_ADVERTISE_SERVICE(register context *ctx,int n,pointer *argv)
01077 {
01078   isInstalledCheck;
01079   string service;
01080   pointer emessage;
01081   pointer fncallback, args;
01082 
01083   if (isstring(argv[0])) service.assign((char *)get_string(argv[0]));
01084   else error(E_NOSTRING);
01085   emessage = argv[1];
01086   fncallback = argv[2];
01087   args=NIL;
01088   for (int i=n-1;i>=3;i--) args=cons(ctx,argv[i],args);
01089   if( s_mapServiced.find(service) != s_mapServiced.end() ) {
01090     ROS_INFO("service %s already advertised", service.c_str());
01091     return (NIL);
01092   }
01093 
01094   EuslispMessage message(emessage);
01095   vpush(message._message);      // to avoid GC in csend
01096   pointer request(csend(ctx,emessage,K_ROSEUS_GET,1,K_ROSEUS_REQUEST));
01097   pointer response(csend(ctx,emessage,K_ROSEUS_GET,1,K_ROSEUS_RESPONSE));
01098   vpop();                       // pop message._message
01099   boost::shared_ptr<EuslispServiceCallbackHelper> *callback =
01100     (new boost::shared_ptr<EuslispServiceCallbackHelper>
01101      (new EuslispServiceCallbackHelper(fncallback, args, message.__getMD5Sum(),
01102                                        message.__getDataType(), request, response)));
01103   AdvertiseServiceOptions aso;
01104   aso.service.assign(service);
01105   aso.datatype = (*callback->get()).getDataType();
01106   aso.md5sum = (*callback->get()).getMD5Sum();
01107   aso.req_datatype = (*callback->get()).getRequestDataType();
01108   aso.res_datatype = (*callback->get()).getResponseDataType();
01109   aso.helper = *callback;
01110   ServiceServer server = s_node->advertiseService(aso);
01111   boost::shared_ptr<ServiceServer> ser = boost::shared_ptr<ServiceServer>(new ServiceServer(server));
01112   if ( !!ser ) {
01113     s_mapServiced[service] = ser;
01114   } else {
01115     ROS_ERROR("s_mapServiced");
01116   }
01117 
01118   return (T);
01119 }
01120 
01121 pointer ROSEUS_UNADVERTISE_SERVICE(register context *ctx,int n,pointer *argv)
01122 {
01123   string service;
01124 
01125   ckarg(1);
01126   if (isstring(argv[0])) service.assign((char *)get_string(argv[0]));
01127   else error(E_NOSTRING);
01128 
01129   ROS_DEBUG("unadvertise %s", service.c_str());
01130   bool bSuccess = s_mapServiced.erase(service)>0;
01131 
01132   return (bSuccess?T:NIL);
01133 }
01134 
01135 pointer ROSEUS_SET_PARAM(register context *ctx,int n,pointer *argv)
01136 {
01137   numunion nu;
01138   string key;
01139   string s;
01140   double d;
01141   int i;
01142 
01143   ckarg(2);
01144   if (isstring(argv[0])) key.assign((char *)get_string(argv[0]));
01145   else error(E_NOSTRING);
01146   if ( isstring(argv[1]) ) {
01147     s.assign((char *)get_string(argv[1]));
01148     ros::param::set(key,s);
01149   } else if (isint(argv[1])) {
01150     i = intval(argv[1]);
01151     ros::param::set(key,i);
01152   } else if (isflt(argv[1])) {
01153     d = fltval(argv[1]);
01154     ros::param::set(key,d);
01155   } else if (argv[1] == T) {
01156     bool b = true;
01157     ros::param::set(key, b);
01158   } else if (argv[1] == NIL) {
01159     bool b = false;
01160     ros::param::set(key, b);
01161   } else {
01162     error(E_MISMATCHARG);
01163   }
01164   return (T);
01165 }
01166 
01167 pointer XmlRpcToEusList(register context *ctx, XmlRpc::XmlRpcValue param_list)
01168 {
01169     numunion nu;
01170     pointer ret, first;
01171     ret = cons(ctx, NIL, NIL);
01172     first = ret;
01173     vpush(ret);
01174     if ( param_list.getType() == XmlRpc::XmlRpcValue::TypeArray ){
01175         for ( int i = 0; i < param_list.size(); i++){
01176             if ( param_list[i].getType() == XmlRpc::XmlRpcValue::TypeBoolean ){
01177                 if ( param_list[i] ){
01178                     ccdr(ret) = cons(ctx, T, NIL);
01179                     ret = ccdr(ret);
01180                 } else {
01181                     ccdr(ret) = cons(ctx, NIL, NIL);
01182                     ret = ccdr(ret);
01183                 }
01184             }
01185             else if ( param_list[i].getType() == XmlRpc::XmlRpcValue::TypeDouble ){
01186                 ccdr(ret) = cons(ctx, makeflt((double)param_list[i]), NIL);
01187                 ret = ccdr(ret);
01188             }
01189             else if ( param_list[i].getType() == XmlRpc::XmlRpcValue::TypeInt ){
01190                 ccdr(ret) = cons(ctx, makeint((int)param_list[i]), NIL);
01191                 ret = ccdr(ret);
01192             }
01193             else if ( param_list[i].getType() == XmlRpc::XmlRpcValue::TypeString ){
01194                 std::string str = param_list[i];
01195                 ccdr(ret) = cons(ctx, makestring((char*)str.c_str(), ((std::string)param_list[i]).length()), NIL);
01196                 ret = ccdr(ret);
01197             }
01198             else {
01199                 ROS_FATAL("unkown rosparam type!");
01200                 vpop();         // remove vpush(ret)
01201                 return NIL;
01202             }
01203         }
01204         vpop();                 // remove vpush(ret)
01205         return ccdr(first);
01206     } else
01207         return (NIL);
01208 }
01209 
01210 pointer ROSEUS_GET_PARAM(register context *ctx,int n,pointer *argv)
01211 {
01212   numunion nu;
01213   string key;
01214 
01215   ckarg2(1,2);
01216   if (isstring(argv[0])) key.assign((char *)get_string(argv[0]));
01217   else error(E_NOSTRING);
01218 
01219   string s;
01220   double d;
01221   bool b;
01222   int i;
01223   pointer ret;
01224   XmlRpc::XmlRpcValue param_list;
01225 
01226   if ( ros::param::get(key, s) ) {
01227     ret = makestring((char *)s.c_str(), s.length());
01228   } else if ( ros::param::get(key, d) ) {
01229     ret = makeflt(d);
01230   } else if ( ros::param::get(key, i) ) {
01231     ret = makeint(i);
01232   } else if ( ros::param::get(key, b) ) {
01233       if ( b == true )
01234           ret = T;
01235       else
01236           ret = NIL;
01237   } else if (ros::param::get(key, param_list)){
01238       ret = XmlRpcToEusList(ctx, param_list);
01239   }else {
01240     if ( n == 2 ) {
01241       ret = copyobj(ctx,argv[1]);
01242     } else {
01243       ROS_ERROR("unknown ros::param::get, key=%s", key.c_str());
01244       ret = NIL;
01245     }
01246   }
01247   return (ret);
01248 }
01249 
01250 pointer ROSEUS_GET_PARAM_CASHED(register context *ctx,int n,pointer *argv)
01251 {
01252   numunion nu;
01253   string key;
01254 
01255   ckarg2(1,2);
01256   if (isstring(argv[0])) key.assign((char *)get_string(argv[0]));
01257   else error(E_NOSTRING);
01258 
01259   string s;
01260   double d;
01261   int i;
01262   bool b;
01263   pointer ret;
01264   XmlRpc::XmlRpcValue param_list;
01265   if ( ros::param::getCached(key, s) ) {
01266     ret = makestring((char *)s.c_str(), s.length());
01267   } else if ( ros::param::getCached(key, d) ) {
01268     ret = makeflt(d);
01269   } else if ( ros::param::getCached(key, i) ) {
01270     ret = makeint(i);
01271   } else if ( ros::param::getCached(key, b) ) {
01272       if ( b == true )
01273           ret = T;
01274       else
01275           ret = NIL;
01276   } else if (ros::param::getCached(key, param_list)){
01277       ret = XmlRpcToEusList(ctx, param_list);
01278   } else {
01279     if ( n == 2 ) {
01280       ret = copyobj(ctx,argv[1]);
01281     } else {
01282       ROS_ERROR("unknown ros::param::get, key=%s", key.c_str());
01283       ret = NIL;
01284     }
01285   }
01286   return (ret);
01287 }
01288 
01289 pointer ROSEUS_HAS_PARAM(register context *ctx,int n,pointer *argv)
01290 {
01291   string key;
01292 
01293   ckarg(1);
01294   if (isstring(argv[0])) key.assign((char *)get_string(argv[0]));
01295   else error(E_NOSTRING);
01296 
01297   return((ros::param::has(key))?(T):(NIL));
01298 }
01299 
01300 pointer ROSEUS_ROSPACK_FIND(register context *ctx,int n,pointer *argv)
01301 {
01302   ckarg(1);
01303 
01304   string pkg;
01305   if (isstring(argv[0])) pkg.assign((char *)get_string(argv[0]));
01306   else error(E_NOSTRING);
01307 
01308   try {
01309 #ifdef ROSPACK_EXPORT
01310       rospack::ROSPack rp;
01311       rospack::Package *p = rp.get_pkg(pkg);
01312       if (p!=NULL) return(makestring((char *)p->path.c_str(),p->path.length()));
01313 #else
01314       rospack::Rospack rp;
01315       std::vector<std::string> search_path;
01316       rp.getSearchPathFromEnv(search_path);
01317       rp.crawl(search_path, 1);
01318       std::string path;
01319       if (rp.find(pkg,path)==true) return(makestring((char *)path.c_str(),path.length()));
01320 #endif
01321   } catch (runtime_error &e) {
01322   }
01323   return(NIL);
01324 }
01325 
01326 pointer ROSEUS_RESOLVE_NAME(register context *ctx,int n,pointer *argv)
01327 {
01328   ckarg(1);
01329   if (!isstring(argv[0])) error(E_NOSTRING);
01330   std::string src;
01331   src.assign((char *)(argv[0]->c.str.chars));
01332   std::string dst = ros::names::resolve(src);
01333   return(makestring((char *)dst.c_str(), dst.length()));
01334 }
01335 
01336 pointer ROSEUS_GETNAME(register context *ctx,int n,pointer *argv)
01337 {
01338   ckarg(0);
01339   return(makestring((char *)ros::this_node::getName().c_str(),
01340                     ros::this_node::getName().length()));
01341 }
01342 
01343 pointer ROSEUS_GETNAMESPACE(register context *ctx,int n,pointer *argv)
01344 {
01345   ckarg(0);
01346   return(makestring((char *)ros::this_node::getNamespace().c_str(),
01347                     ros::this_node::getNamespace().length()));
01348 }
01349 
01350 /************************************************************
01351  *   __roseus
01352  ************************************************************/
01353 
01354 pointer ___roseus(register context *ctx, int n, pointer *argv, pointer env)
01355 {
01356   pointer rospkg,p=Spevalof(PACKAGE);
01357   rospkg=findpkg(makestring("ROS",3));
01358   if (rospkg == 0) rospkg=makepkg(ctx,makestring("ROS", 3),NIL,NIL);
01359   Spevalof(PACKAGE)=rospkg;
01360 
01361   QANON=defvar(ctx,"*ANONYMOUS-NAME*",makeint(ros::init_options::AnonymousName),rospkg);
01362   QNOOUT=defvar(ctx,"*NO-ROSOUT*",makeint(ros::init_options::NoRosout),rospkg);
01363   defun(ctx,"SPIN",argv[0],(pointer (*)())ROSEUS_SPIN);
01364   defun(ctx,"SPIN-ONCE",argv[0],(pointer (*)())ROSEUS_SPINONCE);
01365   defun(ctx,"TIME-NOW-RAW",argv[0],(pointer (*)())ROSEUS_TIME_NOW);
01366   defun(ctx,"RATE",argv[0],(pointer (*)())ROSEUS_RATE);
01367   defun(ctx,"SLEEP",argv[0],(pointer (*)())ROSEUS_SLEEP);
01368   defun(ctx,"OK",argv[0],(pointer (*)())ROSEUS_OK);
01369 
01370   defun(ctx,"ROS-DEBUG",argv[0],(pointer (*)())ROSEUS_ROSDEBUG);
01371   defun(ctx,"ROS-INFO",argv[0],(pointer (*)())ROSEUS_ROSINFO);
01372   defun(ctx,"ROS-WARN",argv[0],(pointer (*)())ROSEUS_ROSWARN);
01373   defun(ctx,"ROS-ERROR",argv[0],(pointer (*)())ROSEUS_ROSERROR);
01374   defun(ctx,"ROS-FATAL",argv[0],(pointer (*)())ROSEUS_ROSFATAL);
01375   defun(ctx,"EXIT",argv[0],(pointer (*)())ROSEUS_EXIT);
01376 
01377   defun(ctx,"SUBSCRIBE",argv[0],(pointer (*)())ROSEUS_SUBSCRIBE);
01378   defun(ctx,"UNSUBSCRIBE",argv[0],(pointer (*)())ROSEUS_UNSUBSCRIBE);
01379   defun(ctx,"GET-NUM-PUBLISHERS",argv[0],(pointer (*)())ROSEUS_GETNUMPUBLISHERS);
01380   defun(ctx,"GET-TOPIC-SUBSCRIBER",argv[0],(pointer (*)())ROSEUS_GETTOPICSUBSCRIBER);
01381 
01382   defun(ctx,"ADVERTISE",argv[0],(pointer (*)())ROSEUS_ADVERTISE);
01383   defun(ctx,"UNADVERTISE",argv[0],(pointer (*)())ROSEUS_UNADVERTISE);
01384   defun(ctx,"PUBLISH",argv[0],(pointer (*)())ROSEUS_PUBLISH);
01385   defun(ctx,"GET-NUM-SUBSCRIBERS",argv[0],(pointer (*)())ROSEUS_GETNUMSUBSCRIBERS);
01386   defun(ctx,"GET-TOPIC-PUBLISHER",argv[0],(pointer (*)())ROSEUS_GETTOPICPUBLISHER);
01387 
01388   defun(ctx,"WAIT-FOR-SERVICE",argv[0],(pointer (*)())ROSEUS_WAIT_FOR_SERVICE);
01389   defun(ctx,"SERVICE-EXISTS", argv[0], (pointer (*)())ROSEUS_SERVICE_EXISTS);
01390   defun(ctx,"SERVICE-CALL",argv[0],(pointer (*)())ROSEUS_SERVICE_CALL);
01391   defun(ctx,"ADVERTISE-SERVICE",argv[0],(pointer (*)())ROSEUS_ADVERTISE_SERVICE);
01392   defun(ctx,"UNADVERTISE-SERVICE",argv[0],(pointer (*)())ROSEUS_UNADVERTISE_SERVICE);
01393 
01394   defun(ctx,"SET-PARAM",argv[0],(pointer (*)())ROSEUS_SET_PARAM);
01395   defun(ctx,"GET-PARAM",argv[0],(pointer (*)())ROSEUS_GET_PARAM);
01396   defun(ctx,"GET-PARAM-CASHED",argv[0],(pointer (*)())ROSEUS_GET_PARAM_CASHED);
01397   defun(ctx,"HAS-PARAM",argv[0],(pointer (*)())ROSEUS_HAS_PARAM);
01398 
01399   defun(ctx,"ROSPACK-FIND",argv[0],(pointer (*)())ROSEUS_ROSPACK_FIND);
01400   defun(ctx,"RESOLVE-NAME",argv[0],(pointer (*)())ROSEUS_RESOLVE_NAME);
01401   defun(ctx,"GET-NAME",argv[0],(pointer (*)())ROSEUS_GETNAME);
01402   defun(ctx,"GET-NAMESPACE",argv[0],(pointer (*)())ROSEUS_GETNAMESPACE);
01403 
01404   defun(ctx,"ROSEUS-RAW",argv[0],(pointer (*)())ROSEUS);
01405   defun(ctx,"CREATE-NODEHANDLE", argv[0], (pointer (*)())ROSEUS_CREATE_NODEHANDLE);
01406 
01407   pointer_update(Spevalof(PACKAGE),p);
01408 
01409   pointer l;
01410   l=makestring(REPOVERSION,strlen(REPOVERSION));
01411   vpush(l);
01412   l=stacknlist(ctx,1);
01413   QREPOVERSION=defvar(ctx, "ROSEUS-REPO-VERSION", l, rospkg);
01414 
01415   M_string remappings;
01416   pointer argp = speval(intern(ctx,"*EUSTOP-ARGUMENT*", strlen("*EUSTOP-ARGUMENT*"),lisppkg));
01417   while(argp!=NIL) {
01418     std::string arg = string((char *)(ccar(argp)->c.str.chars));
01419     // copy from roscpp/src/init.cpp : 432
01420     size_t pos = arg.find(":=");
01421     if (pos != std::string::npos) {
01422       std::string local_name = arg.substr(0, pos);
01423       std::string external_name = arg.substr(pos + 2);
01424       remappings[local_name] = external_name;
01425     }
01426     argp=ccdr(argp);
01427   }
01428   ros::master::init(remappings);
01429   //ros::param::init(remappings);
01430 
01431   return 0;
01432 }
01433 


roseus
Author(s): Kei Okada
autogenerated on Mon Oct 6 2014 01:19:15