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::roseus \"name\") 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   map<string, Timer > mapTimered; 
00121 
00122   map<string, boost::shared_ptr<NodeHandle> > mapHandle; 
00123 };
00124 
00125 static RoseusStaticData s_staticdata;
00126 static bool s_bInstalled = false;
00127 #define s_node s_staticdata.node
00128 #define s_rate s_staticdata.rate
00129 #define s_mapAdvertised s_staticdata.mapAdvertised
00130 #define s_mapSubscribed s_staticdata.mapSubscribed
00131 #define s_mapServiced s_staticdata.mapServiced
00132 #define s_mapTimered s_staticdata.mapTimered
00133 #define s_mapHandle s_staticdata.mapHandle
00134 
00135 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,K_ROSEUS_ONESHOT,K_ROSEUS_LAST_EXPECTED,K_ROSEUS_LAST_REAL,K_ROSEUS_CURRENT_EXPECTED,K_ROSEUS_CURRENT_REAL,K_ROSEUS_LAST_DURATION,K_ROSEUS_SEC,K_ROSEUS_NSEC,QANON,QNOOUT,QREPOVERSION,QROSDEBUG,QROSINFO,QROSWARN,QROSERROR,QROSFATAL;
00136 extern pointer LAMCLOSURE;
00137 
00138 /***********************************************************
00139  *   Message wrapper
00140  ************************************************************/
00141 
00142 string getString(pointer message, pointer method) {
00143   context *ctx = current_ctx;
00144   pointer r, curclass;
00145   if ((pointer)findmethod(ctx,method,classof(message),&curclass)!=NIL) {
00146     r = csend(ctx,message,method,0);
00147   } else if ((pointer)findmethod(ctx,K_ROSEUS_GET,classof(message),&curclass) != NIL ) {
00148     r = csend(ctx,message,K_ROSEUS_GET,1,method);
00149   } else {
00150     r = NULL;
00151 #ifdef x86_64
00152     ROS_ERROR("could not find method %s for pointer %lx",
00153               get_string(method), (long unsigned int)message);
00154 #else
00155     ROS_ERROR("could not find method %s for pointer %x",
00156               get_string(method), (unsigned int)message);
00157 #endif
00158   }
00159   if ( !isstring(r) ) {
00160     pointer dest=(pointer)mkstream(ctx,K_OUT,makebuffer(64));
00161     prinx(ctx,message,dest);
00162     pointer str = makestring((char *)dest->c.stream.buffer->c.str.chars,
00163                              intval(dest->c.stream.count));
00164     ROS_ERROR("send %s to %s returns nil", get_string(method), get_string(str));
00165   }
00166   ROS_ASSERT(isstring(r));
00167   string ret = (char *)get_string(r);
00168   return ret;
00169 }
00170 
00171 int getInteger(pointer message, pointer method) {
00172   context *ctx = current_ctx;
00173   pointer a,curclass;
00174   vpush(message);
00175   a = (pointer)findmethod(ctx,method,classof(message),&curclass);
00176   if (a!=NIL) {
00177     pointer r = csend(ctx,message,method,0);
00178     vpop();                     // message
00179     return (ckintval(r));
00180   } else {
00181 #ifdef x86_64
00182     ROS_ERROR("could not find method %s for pointer %lx",
00183               get_string(method), (long unsigned int)message);
00184 #else
00185     ROS_ERROR("could not find method %s for pointer %x",
00186               get_string(method), (unsigned int)message);
00187 #endif
00188     vpop();                     // message
00189   }
00190   return 0;
00191 }
00192 
00193 class EuslispMessage
00194 {
00195 public:
00196   pointer _message;
00197 
00198   EuslispMessage(pointer message) : _message(message) {
00199   }
00200   EuslispMessage(const EuslispMessage &r) {
00201     context *ctx = current_ctx;
00202     if (ctx!=euscontexts[0])ROS_WARN("ctx is not correct %d\n",thr_self());
00203     if ( isclass(r._message) ) {
00204       //ROS_ASSERT(isclass(r._message));
00205       vpush(r._message);
00206       _message = makeobject(r._message);
00207       vpush(_message);
00208       csend(ctx,_message,K_ROSEUS_INIT,0);
00209       vpop();                   // _message
00210       vpop();                   // r._message
00211     } else {
00212       ROS_WARN("r._message must be class");prinx(ctx,r._message,ERROUT);flushstream(ERROUT);terpri(ERROUT);
00213       _message = r._message;
00214     }
00215   }
00216   virtual ~EuslispMessage() { }
00217 
00218   virtual void replaceContents (pointer newMessage) {
00219     _message = newMessage;
00220   }
00221 
00222   virtual const string __getDataType() const {
00223     return getString(_message, K_ROSEUS_DATATYPE);
00224   }
00225   virtual const string __getMD5Sum()   const {
00226     return getString(_message, K_ROSEUS_MD5SUM);
00227   }
00228   virtual const string __getMessageDefinition() const {
00229     return getString(_message, K_ROSEUS_DEFINITION);
00230   }
00231   virtual const string __getServiceDataType() const {
00232     return getString(_message, K_ROSEUS_DATATYPE);
00233   }
00234   virtual const string __getServerMD5Sum()    const {
00235     return getString(_message, K_ROSEUS_MD5SUM);
00236   }
00237 
00238   uint32_t serializationLength() const {
00239     context *ctx = current_ctx;
00240     if (ctx!=euscontexts[0])ROS_WARN("ctx is not correct %d\n",thr_self());
00241     pointer a,curclass;
00242     a = (pointer)findmethod(ctx,K_ROSEUS_SERIALIZATION_LENGTH,classof(_message),&curclass);
00243     ROS_ASSERT(a!=NIL);
00244     return getInteger(_message, K_ROSEUS_SERIALIZATION_LENGTH);
00245   }
00246 
00247   virtual uint8_t *serialize(uint8_t *writePtr, uint32_t seqid) const
00248   {
00249     context *ctx = current_ctx;
00250     if (ctx!=euscontexts[0])ROS_WARN("ctx is not correct %d\n",thr_self());
00251     pointer a,curclass;
00252     vpush(_message);            // to avoid GC
00253     uint32_t len = serializationLength();
00254     vpop();                     // pop _message
00255     a = (pointer)findmethod(ctx,K_ROSEUS_SERIALIZE,classof(_message),&curclass);
00256     ROS_ASSERT(a!=NIL);
00257     pointer r = csend(ctx,_message,K_ROSEUS_SERIALIZE,0);
00258     ROS_ASSERT(isstring(r));
00259     memcpy(writePtr, get_string(r), len);
00260     //ROS_INFO("serialize");
00261 
00262     return writePtr + len;
00263   }
00264 
00265   virtual uint8_t *deserialize(uint8_t *readPtr, uint32_t sz)
00266   {
00267     context *ctx = current_ctx;
00268     if (ctx!=euscontexts[0])ROS_WARN("ctx is not correct %d\n",thr_self());
00269     pointer a,curclass;
00270 
00271     if ( sz == 0 ) {
00272       ROS_DEBUG("empty message!");
00273       return readPtr;
00274     }
00275     vpush(_message);
00276     a = (pointer)findmethod(ctx,K_ROSEUS_DESERIALIZE,classof(_message),&curclass);
00277     ROS_ASSERT(a!=NIL);
00278     pointer p = makestring((char *)readPtr, sz);
00279     pointer r = csend(ctx,_message,K_ROSEUS_DESERIALIZE,1,p);
00280     ROS_ASSERT(r!=NIL);
00281     //ROS_INFO("deserialize %d", __serialized_length);
00282     vpop(); // pop _message
00283 
00284     return readPtr + sz;
00285   }
00286 };
00287 
00288 namespace ros{
00289   namespace serialization{
00290 template<> struct Serializer<EuslispMessage> {
00291   template<typename Stream>
00292   inline static void write(Stream& stream, boost::call_traits<EuslispMessage>::param_type t) {
00293     t.serialize(stream.getData(), 0);
00294   }
00295 
00296   template<typename Stream>
00297   inline static void read(Stream& stream, boost::call_traits<EuslispMessage>::reference t) {
00298     t.deserialize(stream.getData(), stream.getLength());
00299   }
00300   inline static uint32_t serializedLength(boost::call_traits<EuslispMessage>::param_type t) {
00301     return t.serializationLength();
00302   }
00303 };
00304   }
00305 }
00306 
00307 /************************************************************
00308  *   Subscriptions
00309  ************************************************************/
00310 class EuslispSubscriptionCallbackHelper : public ros::SubscriptionCallbackHelper {
00311 public:
00312   pointer _scb,_args;
00313   EuslispMessage _msg;
00314 
00315   EuslispSubscriptionCallbackHelper(pointer scb, pointer args,pointer tmpl) :  _args(args), _msg(tmpl) {
00316     context *ctx = current_ctx;
00317     mutex_trylock(&mark_lock);
00318     //ROS_WARN("func");prinx(ctx,scb,ERROUT);flushstream(ERROUT);terpri(ERROUT);
00319     //ROS_WARN("argc");prinx(ctx,args,ERROUT);flushstream(ERROUT);terpri(ERROUT);
00320     if (piscode(scb)) { // compiled code
00321       _scb=scb;
00322     } else if ((ccar(scb))==LAMCLOSURE) { // uncompiled code
00323       if ( ccar(ccdr(scb)) != NIL ) { // function
00324         _scb=ccar(ccdr(scb));
00325       } else { // lambda function
00326         _scb=scb;
00327       }
00328     } else {
00329       ROS_ERROR("subscription callback function install error");
00330     }
00331     // avoid gc
00332     pointer p=gensym(ctx);
00333     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));
00334     mutex_unlock(&mark_lock);
00335   }
00336   ~EuslispSubscriptionCallbackHelper() {
00337       ROS_ERROR("subscription gc");
00338   }
00339   virtual ros::VoidConstPtr deserialize(const ros::SubscriptionCallbackHelperDeserializeParams& param) {
00340 #if DEBUG
00341     cerr << __PRETTY_FUNCTION__ << endl;
00342     cerr << "param.length = " << param.length << endl;
00343     cerr << "param.buffer = " << (param.buffer + 4) << endl;
00344     cerr << "c_header == " << param.connection_header << endl;
00345 #endif
00346     ros::VoidConstPtr ptr(new EuslispMessage(_msg));
00347     EuslispMessage *eus_msg = (EuslispMessage *)(ptr.get());
00348     eus_msg->deserialize(param.buffer, param.length);
00349 
00350     return ptr;
00351   }
00352   virtual void call(ros::SubscriptionCallbackHelperCallParams& param) {
00353     EuslispMessage* eus_msg = (EuslispMessage *)((void *)param.event.getConstMessage().get());
00354     context *ctx = current_ctx;
00355     pointer argp=_args;
00356     int argc=0;
00357     //ROS_WARN("func");prinx(ctx,_scb,ERROUT);flushstream(ERROUT);terpri(ERROUT);
00358     //ROS_WARN("argc");prinx(ctx,argp,ERROUT);flushstream(ERROUT);terpri(ERROUT);
00359     vpush(eus_msg->_message);    // to avoid GC
00360     if ( ! ( issymbol(_scb) || piscode(_scb) || ccar(_scb)==LAMCLOSURE ) ) {
00361       ROS_ERROR("%s : can't find callback function", __PRETTY_FUNCTION__);
00362     }
00363     
00364     while(argp!=NIL){ ckpush(ccar(argp)); argp=ccdr(argp); argc++;}
00365     vpush((pointer)(eus_msg->_message));argc++;
00366     
00367     ufuncall(ctx,(ctx->callfp?ctx->callfp->form:NIL),_scb,(pointer)(ctx->vsp-argc),NULL,argc);
00368     while(argc-->0)vpop();
00369     vpop();    // remove eus_msg._message
00370   }
00371   virtual const std::type_info& getTypeInfo() {
00372     return typeid(EuslispMessage);
00373   }
00374   virtual bool isConst(){
00375     return true;
00376   }
00377   virtual bool hasHeader(){
00378     return true;
00379   }
00380 };
00381 
00382 /************************************************************
00383  *   ServiceCall
00384  ************************************************************/
00385 class EuslispServiceCallbackHelper : public ros::ServiceCallbackHelper {
00386 public:
00387   pointer _scb, _args;
00388   EuslispMessage _req, _res;
00389   string md5, datatype, requestDataType, responseDataType,
00390     requestMessageDefinition, responseMessageDefinition;
00391 
00392   EuslispServiceCallbackHelper(pointer scb, pointer args, string smd5, string sdatatype, pointer reqclass, pointer resclass) : _args(args), _req(reqclass), _res(resclass), md5(smd5), datatype(sdatatype) {
00393     context *ctx = current_ctx;
00394     mutex_trylock(&mark_lock);
00395     //ROS_WARN("func");prinx(ctx,scb,ERROUT);flushstream(ERROUT);terpri(ERROUT);
00396     //ROS_WARN("argc");prinx(ctx,args,ERROUT);flushstream(ERROUT);terpri(ERROUT);
00397 
00398     if (piscode(scb)) { // compiled code
00399       _scb=scb;
00400     } else if ((ccar(scb))==LAMCLOSURE) {
00401       if ( ccar(ccdr(scb)) != NIL ) { // function
00402         _scb=ccar(ccdr(scb));
00403       } else { // lambda function
00404         _scb=scb;
00405       }
00406     } else  {
00407       ROS_ERROR("service callback function install error");
00408     }
00409     // avoid gc
00410     pointer p=gensym(ctx);
00411     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));
00412 
00413     requestDataType = _req.__getDataType();
00414     responseDataType = _res.__getDataType();
00415     requestMessageDefinition = _req.__getMessageDefinition();
00416     responseMessageDefinition = _res.__getMessageDefinition();
00417     mutex_unlock(&mark_lock);
00418   }
00419   ~EuslispServiceCallbackHelper() { }
00420 
00421   virtual boost::shared_ptr<EuslispMessage> createRequest() { return boost::shared_ptr<EuslispMessage>(new EuslispMessage(_req)); }
00422   virtual boost::shared_ptr<EuslispMessage> createResponse() { return boost::shared_ptr<EuslispMessage>(new EuslispMessage(_res)); }
00423 
00424   virtual std::string getMD5Sum() { return md5; }
00425   virtual std::string getDataType() { return datatype; }
00426   virtual std::string getRequestDataType() { return requestDataType; }
00427   virtual std::string getResponseDataType() { return responseDataType; }
00428   virtual std::string getRequestMessageDefinition() { return requestMessageDefinition; }
00429   virtual std::string getResponseMessageDefinition() { return responseMessageDefinition; }
00430 
00431   virtual bool call(ros::ServiceCallbackHelperCallParams& params) {
00432     context *ctx = current_ctx;
00433     pointer r, argp=_args;
00434     int argc=0;
00435 
00436     vpush(_res._message);       // _res._message
00437     vpush(_req._message);       // _res._message, _req._message
00438 
00439     if ( ! ( issymbol(_scb) || piscode(_scb) || ccar(_scb)==LAMCLOSURE ) ) {
00440       ROS_ERROR("%s : can't find callback function", __PRETTY_FUNCTION__);
00441     }
00442     // Deserialization
00443     EuslispMessage eus_msg(_req);
00444     vpush(eus_msg._message);    // _res._message, _req._message, eus_msg._message
00445     eus_msg.deserialize(params.request.message_start, params.request.num_bytes);
00446 
00447     while(argp!=NIL){ ckpush(ccar(argp)); argp=ccdr(argp); argc++;}
00448     vpush((pointer) eus_msg._message);argc++;
00449 
00450     r = ufuncall(ctx, (ctx->callfp?ctx->callfp->form:NIL),
00451                  _scb, (pointer)(ctx->vsp-argc),
00452                  NULL, argc);
00453     while(argc-->0)vpop();// _res._message, _req._message, eus_msg._message
00454     vpush(r); // _res._message, _req._message, eus_msg._message, r, 
00455     // Serializaion
00456     EuslispMessage eus_res(_res);
00457     eus_res.replaceContents(r);
00458     // check return value is valid
00459     pointer ret_serialize_method, ret_class;
00460     ret_serialize_method = (pointer)findmethod(ctx,K_ROSEUS_SERIALIZATION_LENGTH,classof(r),&ret_class);
00461     if (ret_serialize_method == NIL) {
00462       ROS_ERROR("you may not return valid value in service callback");
00463     }
00464     vpush(eus_res._message);    // _res._message, _req._message, eus_msg._message, r, eus_res._message
00465     uint32_t serialized_length = eus_res.serializationLength();
00466     params.response.num_bytes = serialized_length + 5; // add 5 bytes of message header
00467     params.response.buf.reset (new uint8_t[params.response.num_bytes]);
00468     params.response.message_start = 0;
00469 
00470     // SerializedResponseMessage
00471     uint8_t *tmp = params.response.buf.get();
00472     *tmp++ = 1; // 1 byte of success services flag, now always set true
00473     *tmp++ = (uint8_t)((serialized_length >> 0) & 0xFF); // 4bytes of message length
00474     *tmp++ = (uint8_t)((serialized_length >> 8) & 0xFF);
00475     *tmp++ = (uint8_t)((serialized_length >> 16) & 0xFF);
00476     *tmp++ = (uint8_t)((serialized_length >> 24) & 0xFF);
00477     eus_res.serialize(tmp, 0);
00478 #if DEBUG
00479     cerr << "num bytes = " << params.response.num_bytes << endl;
00480     ROS_INFO("message_start =  %X",params.response.message_start);
00481     ROS_INFO("message_ptr =  %X",params.response.buf.get());
00482     tmp = params.response.buf.get();
00483     for(int i=0;i<params.response.num_bytes;i++){
00484       ROS_INFO("%X", tmp[i]);
00485     }
00486 #endif
00487     vpop(); // _res._message, _req._message, eus_msg._message, r, eus_res._message
00488     vpop(); // _res._message, _req._message, eus_msg._message, r
00489     vpop(); // _res._message, _req._message, eus_msg._message
00490     vpop(); // _res._message, _req._message,
00491     vpop(); // _res._message
00492     return(T);
00493   }
00494 };
00495 
00496 void roseusSignalHandler(int sig)
00497 {
00498     // memoize for euslisp handler...
00499     context *ctx=euscontexts[thr_self()];
00500     ctx->intsig = sig;
00501 }
00502 
00503 /************************************************************
00504  *   EUSLISP functions
00505  ************************************************************/
00506 pointer ROSEUS(register context *ctx,int n,pointer *argv)
00507 {
00508   char name[256] = "";
00509   uint32_t options = 0;
00510   int cargc = 0;
00511   char *cargv[32];
00512 
00513   if( s_bInstalled ) {
00514     ROS_WARN("ROSEUS is already installed as %s", ros::this_node::getName().c_str());
00515     return (T);
00516   }
00517 
00518   ckarg(3);
00519   if (isstring(argv[0]))
00520     strncpy(name,(char *)(argv[0]->c.str.chars),255);
00521   else error(E_NOSTRING);
00522   options = ckintval(argv[1]);
00523   pointer p = argv[2];
00524   if (islist(p)) {
00525     while (1) {
00526       if (!iscons(p)) break;
00527       cargv[cargc]=(char *)((ccar(p))->c.str.chars);
00528       cargc++;
00529       p=ccdr(p);
00530     }
00531   } else error(E_NOSEQ);
00532 
00533   for (unsigned int i=0; i < strlen(name); i++)
00534     if ( ! isalpha(name[i]) ) name[i] = '_';
00535 
00536   K_ROSEUS_MD5SUM   = defkeyword(ctx,"MD5SUM-");
00537   K_ROSEUS_DATATYPE = defkeyword(ctx,"DATATYPE-");
00538   K_ROSEUS_DEFINITION = defkeyword(ctx,"DEFINITION-");
00539   K_ROSEUS_SERIALIZATION_LENGTH = defkeyword(ctx,"SERIALIZATION-LENGTH");
00540   K_ROSEUS_SERIALIZE   = defkeyword(ctx,"SERIALIZE");
00541   K_ROSEUS_DESERIALIZE = defkeyword(ctx,"DESERIALIZE");
00542   K_ROSEUS_GET  = defkeyword(ctx,"GET");
00543   K_ROSEUS_INIT = defkeyword(ctx,"INIT");
00544   K_ROSEUS_REQUEST  = defkeyword(ctx,"REQUEST");
00545   K_ROSEUS_RESPONSE = defkeyword(ctx,"RESPONSE");
00546   K_ROSEUS_GROUPNAME = defkeyword(ctx,"GROUPNAME");
00547   K_ROSEUS_ONESHOT = defkeyword(ctx,"ONESHOT");
00548   K_ROSEUS_LAST_EXPECTED = defkeyword(ctx,"LAST-EXPECTED");
00549   K_ROSEUS_LAST_REAL = defkeyword(ctx,"LAST-REAL");
00550   K_ROSEUS_CURRENT_EXPECTED = defkeyword(ctx,"CURRENT-EXPECTED");
00551   K_ROSEUS_CURRENT_REAL = defkeyword(ctx,"CURRENT-REAL");
00552   K_ROSEUS_LAST_DURATION = defkeyword(ctx,"LAST-DURATION");
00553   K_ROSEUS_SEC = defkeyword(ctx,"SEC");
00554   K_ROSEUS_NSEC = defkeyword(ctx,"NSEC");
00555 
00556   s_mapAdvertised.clear();
00557   s_mapSubscribed.clear();
00558   s_mapServiced.clear();
00559   s_mapTimered.clear();
00560   s_mapHandle.clear();
00561   
00562   /*
00563     force to flag ros::init_options::NoSigintHandler.
00564     In fact, this code make no sence, because we steals
00565     SIGINT handler by the following `signal'.
00566    */
00567   options |= ros::init_options::NoSigintHandler;
00568 
00569   /*
00570     clear ros::master::g_uri which is defined in ros::master::init in __roseus.
00571     this occurs if user set unix::setenv("ROS_MASTER_URI") between __roseus and
00572     ROSEUS.
00573    */
00574   if (!ros::master::g_uri.empty()) {
00575     if ( ros::master::g_uri != getenv("ROS_MASTER_URI") ) {
00576       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"));
00577       ros::master::g_uri.clear();
00578     }
00579   }
00580   try {
00581     ros::init(cargc, cargv, name, options);
00582   } catch (const ros::InvalidNameException &e) {
00583     ROS_ERROR("%s",e.what());
00584     error(E_MISMATCHARG);
00585     return(NIL);
00586   }
00587 
00588   s_node.reset(new ros::NodeHandle());
00589   s_rate = new ros::Rate(50);
00590 
00591   s_bInstalled = true;
00592 
00593   // install signal handler for sigint. DO NOT call unix:signal after
00594   // ros::roseus
00595   signal(SIGINT, roseusSignalHandler);
00596   return (T);
00597 }
00598 
00599 pointer ROSEUS_CREATE_NODEHANDLE(register context *ctx,int n,pointer *argv)
00600 {
00601   isInstalledCheck;
00602   string groupname;
00603   string ns;
00604 
00605   ckarg2(1, 2);
00606   // ;; arguments ;;
00607   // groupname [ namespace ]
00608 
00609   if (isstring(argv[0])) groupname.assign((char *)get_string(argv[0]));
00610   else error(E_NOSTRING);
00611   if ( n > 1 ) {
00612     if(isstring(argv[1])) ns.assign((char *)get_string(argv[1]));
00613     else error(E_NOSTRING);
00614   }
00615 
00616   if( s_mapHandle.find(groupname) != s_mapHandle.end() ) {
00617     ROS_DEBUG("groupname %s is already used", groupname.c_str());
00618     return (NIL);
00619   }
00620 
00621   boost::shared_ptr<NodeHandle> hd;
00622   if ( n > 1 ) {
00623     hd = boost::shared_ptr<NodeHandle> (new NodeHandle(ns));
00624     s_mapHandle[groupname] = hd;
00625   } else {
00626     hd = boost::shared_ptr<NodeHandle>(new NodeHandle());
00627     s_mapHandle[groupname] = hd;
00628   }
00629   //add callbackqueue to hd
00630   hd->setCallbackQueue( new CallbackQueue() );
00631 
00632   return (T);
00633 }
00634 
00635 pointer ROSEUS_SPIN(register context *ctx,int n,pointer *argv)
00636 {
00637   isInstalledCheck;
00638   while (ctx->intsig==0) {
00639     ros::spinOnce();
00640     s_rate->sleep();
00641   }
00642   return (NIL);
00643 }
00644 
00645 pointer ROSEUS_SPINONCE(register context *ctx,int n,pointer *argv)
00646 {
00647   isInstalledCheck;
00648   ckarg2(0, 1);
00649   // ;; arguments ;;
00650   // [ groupname ]
00651 
00652   if ( n > 0 ) {
00653     string groupname;
00654     if (isstring(argv[0])) groupname.assign((char *)get_string(argv[0]));
00655     else error(E_NOSTRING);
00656 
00657     map<string, boost::shared_ptr<NodeHandle > >::iterator it = s_mapHandle.find(groupname);
00658     if( it == s_mapHandle.end() ) {
00659       ROS_ERROR("Groupname %s is missing", groupname.c_str());
00660       return (T);
00661     }
00662     boost::shared_ptr<NodeHandle > hdl = (it->second);
00663     // spin this nodehandle
00664     ((CallbackQueue *)hdl->getCallbackQueue())->callAvailable();
00665 
00666     return (NIL);
00667   } else {
00668     ros::spinOnce();
00669     return (NIL);
00670   }
00671 }
00672 
00673 pointer ROSEUS_TIME_NOW(register context *ctx,int n,pointer *argv)
00674 {
00675   isInstalledCheck;
00676   pointer timevec;
00677   ros::Time t = ros::Time::now();
00678 
00679   timevec=makevector(C_INTVECTOR,2);
00680   vpush(timevec);
00681   timevec->c.ivec.iv[0]=t.sec;
00682   timevec->c.ivec.iv[1]=t.nsec;
00683   vpop();
00684   return (timevec);
00685 }
00686 
00687 pointer ROSEUS_RATE(register context *ctx,int n,pointer *argv)
00688 {
00689   isInstalledCheck;
00690   numunion nu;
00691   ckarg(1);
00692   float timeout=ckfltval(argv[0]);
00693   s_rate = new ros::Rate(timeout);
00694   return(T);
00695 }
00696 
00697 pointer ROSEUS_SLEEP(register context *ctx,int n,pointer *argv)
00698 {
00699   isInstalledCheck;
00700   s_rate->sleep();
00701   return (T);
00702 }
00703 
00704 pointer ROSEUS_OK(register context *ctx,int n,pointer *argv)
00705 {
00706   if (ros::ok()) {
00707     return (T);
00708   } else {
00709     return (NIL);
00710   }
00711 }
00712 
00713 
00714 #define def_rosconsole_formatter(funcname, rosfuncname)         \
00715   pointer funcname(register context *ctx,int n,pointer *argv)   \
00716   { pointer *argv2,msg;                                         \
00717     int argc2;                                                  \
00718     argc2 = n+1;                                                \
00719     argv2 = (pointer *)malloc(sizeof(pointer)*argc2);           \
00720     argv2[0] = NIL;                                             \
00721     for(int i=0;i<n;i++) argv2[i+1]=argv[i] ;                   \
00722     msg = XFORMAT(ctx, argc2, argv2);                           \
00723     rosfuncname("%s", msg->c.str.chars);                        \
00724     free(argv2);                                                \
00725     return (T);                                                 \
00726   }
00727 
00728 def_rosconsole_formatter(ROSEUS_ROSDEBUG, ROS_DEBUG)
00729 def_rosconsole_formatter(ROSEUS_ROSINFO,  ROS_INFO)
00730 def_rosconsole_formatter(ROSEUS_ROSWARN,  ROS_WARN)
00731 def_rosconsole_formatter(ROSEUS_ROSERROR, ROS_ERROR)
00732 def_rosconsole_formatter(ROSEUS_ROSFATAL, ROS_FATAL)
00733 
00734 pointer ROSEUS_EXIT(register context *ctx,int n,pointer *argv)
00735 {
00736   ROS_INFO("%s", __PRETTY_FUNCTION__);
00737   if( s_bInstalled ) {
00738     ROS_INFO("exiting roseus %ld", (n==0)?n:ckintval(argv[0]));
00739     s_mapAdvertised.clear();
00740     s_mapSubscribed.clear();
00741     s_mapServiced.clear();
00742     s_mapTimered.clear();
00743     s_mapHandle.clear();
00744     ros::shutdown();
00745   }
00746   if (n==0) _exit(0);
00747   else _exit(ckintval(argv[0]));
00748 }
00749 
00750 /************************************************************
00751  *   ROSEUS Publisher/Subscriber
00752  ************************************************************/
00753 pointer ROSEUS_SUBSCRIBE(register context *ctx,int n,pointer *argv)
00754 {
00755   isInstalledCheck;
00756   string topicname;
00757   pointer message, fncallback, args;
00758   int queuesize = 1;
00759   NodeHandle *lnode = s_node.get();
00760 
00761   // ;; arguments ;;
00762   // topicname message_type callbackfunc args0 ... argsN [ queuesize ] [ :groupname groupname ]
00763   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00764   else error(E_NOSTRING);
00765 
00766   if (n > 1 && issymbol(argv[n-2]) && isstring(argv[n-1])) {
00767     if (argv[n-2] == K_ROSEUS_GROUPNAME) {
00768       string groupname;
00769       groupname.assign((char *)get_string(argv[n-1]));
00770       map<string, boost::shared_ptr<NodeHandle > >::iterator it = s_mapHandle.find(groupname);
00771       if( it != s_mapHandle.end() ) {
00772         ROS_DEBUG("subscribe with groupname=%s", groupname.c_str());
00773         lnode = (it->second).get();
00774       } else {
00775         ROS_ERROR("Groupname %s is missing. Topic %s is not subscribed. Call (ros::create-nodehandle \"%s\") first.",
00776                   groupname.c_str(), topicname.c_str(), groupname.c_str());
00777         return (NIL);
00778       }
00779       n -= 2;
00780     }
00781   }
00782   if (isint(argv[n-1])) {queuesize = ckintval(argv[n-1]);n--;}
00783   ROS_DEBUG("subscribe %s queuesize=%d", topicname.c_str(), queuesize);
00784   // TODO:need error checking
00785   message = argv[1];
00786   fncallback = argv[2];
00787   args=NIL;
00788   for (int i=n-1;i>=3;i--) args=cons(ctx,argv[i],args);
00789 
00790   EuslispMessage msg(message);
00791    boost::shared_ptr<SubscriptionCallbackHelper> *callback =
00792      (new boost::shared_ptr<SubscriptionCallbackHelper>
00793       (new EuslispSubscriptionCallbackHelper(fncallback, args, message)));
00794   SubscribeOptions so(topicname, queuesize, msg.__getMD5Sum(), msg.__getDataType());
00795   so.helper = *callback;
00796   Subscriber subscriber = lnode->subscribe(so);
00797   boost::shared_ptr<Subscriber> sub = boost::shared_ptr<Subscriber>(new Subscriber(subscriber));
00798   if ( !!sub ) {
00799     s_mapSubscribed[topicname] = sub;
00800   } else {
00801     ROS_ERROR("s_mapSubscribed");
00802   }
00803 
00804   return (T);
00805 }
00806 
00807 pointer ROSEUS_UNSUBSCRIBE(register context *ctx,int n,pointer *argv)
00808 {
00809   string topicname;
00810 
00811   ckarg(1);
00812   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00813   else error(E_NOSTRING);
00814 
00815   bool bSuccess = s_mapSubscribed.erase(topicname)>0;
00816 
00817   return (bSuccess?T:NIL);
00818 }
00819 
00820 pointer ROSEUS_GETNUMPUBLISHERS(register context *ctx,int n,pointer *argv)
00821 {
00822   string topicname;
00823   int ret;
00824 
00825   ckarg(1);
00826   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00827   else error(E_NOSTRING);
00828 
00829   bool bSuccess = false;
00830   map<string, boost::shared_ptr<Subscriber> >::iterator it = s_mapSubscribed.find(topicname);
00831   if( it != s_mapSubscribed.end() ) {
00832     boost::shared_ptr<Subscriber> subscriber = (it->second);
00833     ret = subscriber->getNumPublishers();
00834     bSuccess = true;
00835   }
00836 
00837   if ( ! bSuccess ) {
00838     ROS_ERROR("attempted to getNumPublishers to topic %s, which was not " \
00839               "previously subscribed. call (ros::subscribe \"%s\") first.",
00840               topicname.c_str(), topicname.c_str());
00841   }
00842 
00843   return (bSuccess?(makeint(ret)):NIL);
00844 }
00845 
00846 pointer ROSEUS_GETTOPICSUBSCRIBER(register context *ctx,int n,pointer *argv)
00847 {
00848   string topicname;
00849   string ret;
00850 
00851   ckarg(1);
00852   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00853   else error(E_NOSTRING);
00854 
00855   bool bSuccess = false;
00856   map<string, boost::shared_ptr<Subscriber> >::iterator it = s_mapSubscribed.find(topicname);
00857   if( it != s_mapSubscribed.end() ) {
00858     boost::shared_ptr<Subscriber> subscriber = (it->second);
00859     ret = subscriber->getTopic();
00860     bSuccess = true;
00861   }
00862 
00863   return (bSuccess?(makestring((char *)ret.c_str(), ret.length())):NIL);
00864 }
00865 
00866 pointer ROSEUS_ADVERTISE(register context *ctx,int n,pointer *argv)
00867 {
00868   isInstalledCheck;
00869   string topicname;
00870   pointer message;
00871   int queuesize = 1;
00872   bool latch = false;
00873 
00874   ckarg2(2,4);
00875   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00876   else error(E_NOSTRING);
00877   message = argv[1];
00878   if ( n > 2 ) {
00879     queuesize = ckintval(argv[2]);
00880   }
00881   if ( n > 3 ) {
00882     latch = (argv[3]!=NIL ? true : false);
00883   }
00884   ROS_DEBUG("advertise %s %d %d", topicname.c_str(), queuesize, latch);
00885   if( s_mapAdvertised.find(topicname) != s_mapAdvertised.end() ) {
00886     ROS_WARN("topic %s already advertised", topicname.c_str());
00887     return (NIL);
00888   }
00889 
00890   EuslispMessage msg(message);
00891   AdvertiseOptions ao(topicname, queuesize, msg.__getMD5Sum(), msg.__getDataType(), msg.__getMessageDefinition());
00892   ao.latch = latch;
00893   Publisher publisher = s_node->advertise(ao);
00894   boost::shared_ptr<Publisher> pub = boost::shared_ptr<Publisher>(new Publisher(publisher));
00895   if ( !!pub ) {
00896     s_mapAdvertised[topicname] = pub;
00897   } else {
00898     ROS_ERROR("s_mapAdvertised");
00899   }
00900 
00901   return (T);
00902 }
00903 
00904 pointer ROSEUS_UNADVERTISE(register context *ctx,int n,pointer *argv)
00905 {
00906   string topicname;
00907 
00908   ckarg(1);
00909   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00910   else error(E_NOSTRING);
00911 
00912   bool bSuccess = s_mapAdvertised.erase(topicname)>0;
00913 
00914   return (bSuccess?T:NIL);
00915 }
00916 
00917 pointer ROSEUS_PUBLISH(register context *ctx,int n,pointer *argv)
00918 {
00919   isInstalledCheck;
00920   string topicname;
00921   pointer emessage;
00922 
00923   ckarg(2);
00924   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00925   else error(E_NOSTRING);
00926   emessage = argv[1];
00927 
00928   bool bSuccess = false;
00929   map<string, boost::shared_ptr<Publisher> >::iterator it = s_mapAdvertised.find(topicname);
00930   if( it != s_mapAdvertised.end() ) {
00931     boost::shared_ptr<Publisher> publisher = (it->second);
00932     EuslispMessage message(emessage);
00933     publisher->publish(message);
00934     bSuccess = true;
00935   }
00936 
00937   if ( ! bSuccess ) {
00938     ROS_ERROR("attempted to publish to topic %s, which was not " \
00939               "previously advertised. call (ros::advertise \"%s\") first.",
00940               topicname.c_str(), topicname.c_str());
00941   }
00942 
00943   return (T);
00944 }
00945 
00946 pointer ROSEUS_GETNUMSUBSCRIBERS(register context *ctx,int n,pointer *argv)
00947 {
00948   string topicname;
00949   int ret;
00950 
00951   ckarg(1);
00952   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00953   else error(E_NOSTRING);
00954 
00955   bool bSuccess = false;
00956   map<string, boost::shared_ptr<Publisher> >::iterator it = s_mapAdvertised.find(topicname);
00957   if( it != s_mapAdvertised.end() ) {
00958     boost::shared_ptr<Publisher> publisher = (it->second);
00959     ret = publisher->getNumSubscribers();
00960     bSuccess = true;
00961   }
00962 
00963   if ( ! bSuccess ) {
00964     ROS_ERROR("attempted to getNumSubscribers to topic %s, which was not " \
00965               "previously advertised. call (ros::advertise \"%s\") first.",
00966               topicname.c_str(), topicname.c_str());
00967   }
00968 
00969   return (bSuccess?(makeint(ret)):NIL);
00970 }
00971 
00972 pointer ROSEUS_GETTOPICPUBLISHER(register context *ctx,int n,pointer *argv)
00973 {
00974   string topicname;
00975   string ret;
00976 
00977   ckarg(1);
00978   if (isstring(argv[0])) topicname.assign((char *)get_string(argv[0]));
00979   else error(E_NOSTRING);
00980 
00981   bool bSuccess = false;
00982   map<string, boost::shared_ptr<Publisher> >::iterator it = s_mapAdvertised.find(topicname);
00983   if( it != s_mapAdvertised.end() ) {
00984     boost::shared_ptr<Publisher> publisher = (it->second);
00985     ret = publisher->getTopic();
00986     bSuccess = true;
00987   }
00988 
00989   return (bSuccess?(makestring((char *)ret.c_str(), ret.length())):NIL);
00990 }
00991 
00992 /************************************************************
00993  *   ROSEUS ServiceCall
00994  ************************************************************/
00995 pointer ROSEUS_WAIT_FOR_SERVICE(register context *ctx,int n,pointer *argv)
00996 {
00997   isInstalledCheck;
00998   string service;
00999 
01000   ckarg2(1,2);
01001   if (isstring(argv[0])) service.assign((char *)(argv[0]->c.str.chars));
01002   else error(E_NOSTRING);
01003 
01004   int32_t timeout = -1;
01005 
01006   if( n > 1 )
01007     timeout = (int32_t)ckintval(argv[1]);
01008 
01009   bool bSuccess = service::waitForService(ros::names::resolve(service), ros::Duration(timeout));
01010 
01011   return (bSuccess?T:NIL);
01012 }
01013 
01014 pointer ROSEUS_SERVICE_EXISTS(register context *ctx,int n,pointer *argv)
01015 {
01016   isInstalledCheck;
01017   string service;
01018 
01019   ckarg(1);
01020   if (isstring(argv[0])) service.assign((char *)(argv[0]->c.str.chars));
01021   else error(E_NOSTRING);
01022 
01023   bool bSuccess = service::exists(ros::names::resolve(service), true);
01024 
01025   return (bSuccess?T:NIL);
01026 }
01027 
01028 pointer ROSEUS_SERVICE_CALL(register context *ctx,int n,pointer *argv)
01029 {
01030   isInstalledCheck;
01031   string service;
01032   pointer emessage;
01033   bool persist = false;
01034   ckarg2(2,3);
01035   if (isstring(argv[0])) service.assign((char *)(argv[0]->c.str.chars));
01036   else error(E_NOSTRING);
01037   emessage = argv[1];
01038   if ( n > 2 ) {
01039       persist = (argv[2] != NIL ? true : false);
01040   }
01041   static std::map<std::string, ros::ServiceClient> service_cache;
01042   std::string service_name = ros::names::resolve(service);
01043   ServiceClient client;
01044   EuslispMessage request(emessage);
01045   vpush(request._message);      // to avoid GC, it may not be required...
01046   EuslispMessage response(csend(ctx,emessage,K_ROSEUS_RESPONSE,0));
01047   vpush(response._message);     // to avoid GC, its important
01048   if (persist == false) {
01049     ServiceClientOptions sco(service_name, request.__getMD5Sum(), false, M_string());
01050     client = s_node->serviceClient(sco);
01051   }
01052   else {
01053     // check the instance of client
01054     
01055     if (service_cache.find(service_name) != service_cache.end()) {
01056       client = service_cache[service_name];
01057     }
01058     else {
01059       ServiceClientOptions sco(service_name, request.__getMD5Sum(), true, M_string());
01060       client = s_node->serviceClient(sco);
01061       service_cache[service_name] = client;
01062     }
01063   }
01064     // NEED FIX
01065   bool bSuccess =  client.call(request, response, request.__getMD5Sum());
01066   vpop();                       // pop response._message
01067   vpop();                       // pop request._message
01068   if ( ! bSuccess ) {
01069     ROS_ERROR("attempted to call service  %s, but failed ",
01070               ros::names::resolve(service).c_str());
01071     if (persist) {
01072       // cleanup service_cache
01073       service_cache.erase(service_cache.find(service_name));
01074     }
01075   }
01076 
01077   return (response._message);
01078 }
01079 
01080 pointer ROSEUS_ADVERTISE_SERVICE(register context *ctx,int n,pointer *argv)
01081 {
01082   isInstalledCheck;
01083   string service;
01084   pointer emessage;
01085   pointer fncallback, args;
01086 
01087   if (isstring(argv[0])) service.assign((char *)get_string(argv[0]));
01088   else error(E_NOSTRING);
01089   emessage = argv[1];
01090   fncallback = argv[2];
01091   args=NIL;
01092   for (int i=n-1;i>=3;i--) args=cons(ctx,argv[i],args);
01093   if( s_mapServiced.find(service) != s_mapServiced.end() ) {
01094     ROS_INFO("service %s already advertised", service.c_str());
01095     return (NIL);
01096   }
01097 
01098   EuslispMessage message(emessage);
01099   vpush(message._message);      // to avoid GC in csend
01100   pointer request(csend(ctx,emessage,K_ROSEUS_GET,1,K_ROSEUS_REQUEST));
01101   pointer response(csend(ctx,emessage,K_ROSEUS_GET,1,K_ROSEUS_RESPONSE));
01102   vpop();                       // pop message._message
01103   boost::shared_ptr<EuslispServiceCallbackHelper> *callback =
01104     (new boost::shared_ptr<EuslispServiceCallbackHelper>
01105      (new EuslispServiceCallbackHelper(fncallback, args, message.__getMD5Sum(),
01106                                        message.__getDataType(), request, response)));
01107   AdvertiseServiceOptions aso;
01108   aso.service.assign(service);
01109   aso.datatype = (*callback->get()).getDataType();
01110   aso.md5sum = (*callback->get()).getMD5Sum();
01111   aso.req_datatype = (*callback->get()).getRequestDataType();
01112   aso.res_datatype = (*callback->get()).getResponseDataType();
01113   aso.helper = *callback;
01114   ServiceServer server = s_node->advertiseService(aso);
01115   boost::shared_ptr<ServiceServer> ser = boost::shared_ptr<ServiceServer>(new ServiceServer(server));
01116   if ( !!ser ) {
01117     s_mapServiced[service] = ser;
01118   } else {
01119     ROS_ERROR("s_mapServiced");
01120   }
01121 
01122   return (T);
01123 }
01124 
01125 pointer ROSEUS_UNADVERTISE_SERVICE(register context *ctx,int n,pointer *argv)
01126 {
01127   string service;
01128 
01129   ckarg(1);
01130   if (isstring(argv[0])) service.assign((char *)get_string(argv[0]));
01131   else error(E_NOSTRING);
01132 
01133   ROS_DEBUG("unadvertise %s", service.c_str());
01134   bool bSuccess = s_mapServiced.erase(service)>0;
01135 
01136   return (bSuccess?T:NIL);
01137 }
01138 
01139 pointer ROSEUS_SET_PARAM(register context *ctx,int n,pointer *argv)
01140 {
01141   numunion nu;
01142   string key;
01143   string s;
01144   double d;
01145   int i;
01146 
01147   ckarg(2);
01148   if (isstring(argv[0])) key.assign((char *)get_string(argv[0]));
01149   else error(E_NOSTRING);
01150   if ( isstring(argv[1]) ) {
01151     s.assign((char *)get_string(argv[1]));
01152     ros::param::set(key,s);
01153   } else if (isint(argv[1])) {
01154     i = intval(argv[1]);
01155     ros::param::set(key,i);
01156   } else if (isflt(argv[1])) {
01157     d = fltval(argv[1]);
01158     ros::param::set(key,d);
01159   } else if (argv[1] == T) {
01160     bool b = true;
01161     ros::param::set(key, b);
01162   } else if (argv[1] == NIL) {
01163     bool b = false;
01164     ros::param::set(key, b);
01165   } else {
01166     error(E_MISMATCHARG);
01167   }
01168   return (T);
01169 }
01170 
01171 pointer XmlRpcToEusValue(register context *ctx, XmlRpc::XmlRpcValue rpc_value)
01172 {
01173   numunion nu;
01174   pointer ret, first;
01175 
01176   if ( rpc_value.getType() == XmlRpc::XmlRpcValue::TypeBoolean ){
01177     if ( rpc_value ) return T; else return NIL;
01178   }
01179   else if ( rpc_value.getType() == XmlRpc::XmlRpcValue::TypeDouble ){
01180     return makeflt((double)rpc_value);
01181   }
01182   else if ( rpc_value.getType() == XmlRpc::XmlRpcValue::TypeInt ){
01183     return makeint((int)rpc_value);
01184   }
01185   else if ( rpc_value.getType() == XmlRpc::XmlRpcValue::TypeString ){
01186     std::string str = rpc_value;
01187     return makestring((char*)str.c_str(), ((std::string)rpc_value).length());
01188   }
01189   else if ( rpc_value.getType() == XmlRpc::XmlRpcValue::TypeArray ){
01190     ret = cons(ctx, NIL, NIL);
01191     first = ret;
01192     vpush(ret);
01193     for ( int i = 0; i < rpc_value.size(); i++){
01194       ccdr(ret) = cons(ctx, XmlRpcToEusValue(ctx, rpc_value[i]), NIL);
01195       ret = ccdr(ret);
01196     }
01197     vpop(); // vpush(ret);
01198     return ccdr(first);
01199   }
01200   else if ( rpc_value.getType() == XmlRpc::XmlRpcValue::TypeStruct ){
01201     ret = cons(ctx, NIL, NIL);
01202     first = ret;
01203     vpush(ret);
01204     XmlRpc::XmlRpcValue::iterator it = rpc_value.begin();
01205     while(it !=rpc_value.end()) {
01206       std::string key = it->first;
01207       pointer tmp = cons(ctx, makestring((char*)key.c_str(), key.length()), NIL);
01208       vpush(tmp);
01209       ccdr(tmp) = XmlRpcToEusValue(ctx, it->second);
01210       ccdr(ret) = cons(ctx, tmp, NIL);
01211       ret = ccdr(ret);
01212       vpop(); // vpush(tmp);
01213       it++;
01214     }
01215     vpop(); // vpush(ret);
01216     return ccdr(first);
01217   } else {
01218     ROS_FATAL("unkown rosparam type!");
01219     return NIL;
01220   }
01221   return NIL;
01222 }
01223 
01224 pointer XmlRpcToEusList(register context *ctx, XmlRpc::XmlRpcValue param_list)
01225 {
01226     numunion nu;
01227     pointer ret, first;
01228     ret = cons(ctx, NIL, NIL);
01229     first = ret;
01230     vpush(ret);
01231     if ( param_list.getType() == XmlRpc::XmlRpcValue::TypeArray ){
01232         for ( int i = 0; i < param_list.size(); i++){
01233             if ( param_list[i].getType() == XmlRpc::XmlRpcValue::TypeBoolean ){
01234                 if ( param_list[i] ){
01235                     ccdr(ret) = cons(ctx, T, NIL);
01236                     ret = ccdr(ret);
01237                 } else {
01238                     ccdr(ret) = cons(ctx, NIL, NIL);
01239                     ret = ccdr(ret);
01240                 }
01241             }
01242             else if ( param_list[i].getType() == XmlRpc::XmlRpcValue::TypeDouble ){
01243                 ccdr(ret) = cons(ctx, makeflt((double)param_list[i]), NIL);
01244                 ret = ccdr(ret);
01245             }
01246             else if ( param_list[i].getType() == XmlRpc::XmlRpcValue::TypeInt ){
01247                 ccdr(ret) = cons(ctx, makeint((int)param_list[i]), NIL);
01248                 ret = ccdr(ret);
01249             }
01250             else if ( param_list[i].getType() == XmlRpc::XmlRpcValue::TypeString ){
01251                 std::string str = param_list[i];
01252                 ccdr(ret) = cons(ctx, makestring((char*)str.c_str(), ((std::string)param_list[i]).length()), NIL);
01253                 ret = ccdr(ret);
01254             }
01255             else if ( param_list[i].getType() == XmlRpc::XmlRpcValue::TypeStruct ){
01256                 ccdr(ret) = cons(ctx, XmlRpcToEusValue(ctx, param_list[i]), NIL);
01257                 ret = ccdr(ret);
01258             }
01259             else {
01260                 ROS_FATAL("unkown rosparam type!");
01261                 vpop();         // remove vpush(ret)
01262                 return NIL;
01263             }
01264         }
01265         vpop();                 // remove vpush(ret)
01266         return ccdr(first);
01267     } else if ( param_list.getType() == XmlRpc::XmlRpcValue::TypeStruct ) {
01268         return XmlRpcToEusValue(ctx, param_list);
01269     } else
01270         return (NIL);
01271 }
01272 
01273 pointer ROSEUS_GET_PARAM(register context *ctx,int n,pointer *argv)
01274 {
01275   numunion nu;
01276   string key;
01277 
01278   ckarg2(1,2);
01279   if (isstring(argv[0])) key.assign((char *)get_string(argv[0]));
01280   else error(E_NOSTRING);
01281 
01282   string s;
01283   double d;
01284   bool b;
01285   int i;
01286   pointer ret;
01287   XmlRpc::XmlRpcValue param_list;
01288 
01289   if ( ros::param::get(key, s) ) {
01290     ret = makestring((char *)s.c_str(), s.length());
01291   } else if ( ros::param::get(key, d) ) {
01292     ret = makeflt(d);
01293   } else if ( ros::param::get(key, i) ) {
01294     ret = makeint(i);
01295   } else if ( ros::param::get(key, b) ) {
01296       if ( b == true )
01297           ret = T;
01298       else
01299           ret = NIL;
01300   } else if (ros::param::get(key, param_list)){
01301       ret = XmlRpcToEusList(ctx, param_list);
01302   }else {
01303     if ( n == 2 ) {
01304       ret = COPYOBJ(ctx,1,argv+1);
01305     } else {
01306       ROS_ERROR("unknown ros::param::get, key=%s", key.c_str());
01307       ret = NIL;
01308     }
01309   }
01310   return (ret);
01311 }
01312 
01313 pointer ROSEUS_GET_PARAM_CASHED(register context *ctx,int n,pointer *argv)
01314 {
01315   numunion nu;
01316   string key;
01317 
01318   ckarg2(1,2);
01319   if (isstring(argv[0])) key.assign((char *)get_string(argv[0]));
01320   else error(E_NOSTRING);
01321 
01322   string s;
01323   double d;
01324   int i;
01325   bool b;
01326   pointer ret;
01327   XmlRpc::XmlRpcValue param_list;
01328   if ( ros::param::getCached(key, s) ) {
01329     ret = makestring((char *)s.c_str(), s.length());
01330   } else if ( ros::param::getCached(key, d) ) {
01331     ret = makeflt(d);
01332   } else if ( ros::param::getCached(key, i) ) {
01333     ret = makeint(i);
01334   } else if ( ros::param::getCached(key, b) ) {
01335       if ( b == true )
01336           ret = T;
01337       else
01338           ret = NIL;
01339   } else if (ros::param::getCached(key, param_list)){
01340       ret = XmlRpcToEusList(ctx, param_list);
01341   } else {
01342     if ( n == 2 ) {
01343       ret = COPYOBJ(ctx,1,argv+1);
01344     } else {
01345       ROS_ERROR("unknown ros::param::get, key=%s", key.c_str());
01346       ret = NIL;
01347     }
01348   }
01349   return (ret);
01350 }
01351 
01352 pointer ROSEUS_HAS_PARAM(register context *ctx,int n,pointer *argv)
01353 {
01354   string key;
01355 
01356   ckarg(1);
01357   if (isstring(argv[0])) key.assign((char *)get_string(argv[0]));
01358   else error(E_NOSTRING);
01359 
01360   return((ros::param::has(key))?(T):(NIL));
01361 }
01362 
01363 pointer ROSEUS_ROSPACK_FIND(register context *ctx,int n,pointer *argv)
01364 {
01365   ckarg(1);
01366 
01367   string pkg;
01368   if (isstring(argv[0])) pkg.assign((char *)get_string(argv[0]));
01369   else error(E_NOSTRING);
01370 
01371   try {
01372 #ifdef ROSPACK_EXPORT
01373       rospack::ROSPack rp;
01374       rospack::Package *p = rp.get_pkg(pkg);
01375       if (p!=NULL) return(makestring((char *)p->path.c_str(),p->path.length()));
01376 #else
01377       rospack::Rospack rp;
01378       std::vector<std::string> search_path;
01379       rp.getSearchPathFromEnv(search_path);
01380       rp.crawl(search_path, 1);
01381       std::string path;
01382       if (rp.find(pkg,path)==true) return(makestring((char *)path.c_str(),path.length()));
01383 #endif
01384   } catch (runtime_error &e) {
01385   }
01386   return(NIL);
01387 }
01388 
01389 pointer ROSEUS_RESOLVE_NAME(register context *ctx,int n,pointer *argv)
01390 {
01391   ckarg(1);
01392   if (!isstring(argv[0])) error(E_NOSTRING);
01393   std::string src;
01394   src.assign((char *)(argv[0]->c.str.chars));
01395   std::string dst = ros::names::resolve(src);
01396   return(makestring((char *)dst.c_str(), dst.length()));
01397 }
01398 
01399 pointer ROSEUS_GETNAME(register context *ctx,int n,pointer *argv)
01400 {
01401   ckarg(0);
01402   return(makestring((char *)ros::this_node::getName().c_str(),
01403                     ros::this_node::getName().length()));
01404 }
01405 
01406 pointer ROSEUS_GETNAMESPACE(register context *ctx,int n,pointer *argv)
01407 {
01408   ckarg(0);
01409   return(makestring((char *)ros::this_node::getNamespace().c_str(),
01410                     ros::this_node::getNamespace().length()));
01411 }
01412 
01413 pointer ROSEUS_SET_LOGGER_LEVEL(register context *ctx, int n, pointer *argv)
01414 {
01415   ckarg(2);
01416   string logger;
01417   if (isstring(argv[0])) logger.assign((char *)get_string(argv[0]));
01418   else error(E_NOSTRING);
01419   int log_level = intval(argv[1]);
01420   ros::console::levels::Level  level = ros::console::levels::Debug;
01421   switch(log_level){
01422   case 1:
01423     level = ros::console::levels::Debug;
01424     break;
01425   case 2:
01426     level = ros::console::levels::Info;
01427     break;
01428   case 3:
01429     level = ros::console::levels::Warn;
01430     break;
01431   case 4:
01432     level = ros::console::levels::Error;
01433     break;
01434   case 5:
01435     level = ros::console::levels::Fatal;
01436     break;
01437   default:
01438     return (NIL);
01439   }
01440 
01441   bool success = ::ros::console::set_logger_level(logger, level);
01442   if (success)
01443     {
01444       console::notifyLoggerLevelsChanged();
01445       return (T);
01446     }
01447   return (NIL);
01448 }
01449 
01450 pointer ROSEUS_GET_HOST(register context *ctx,int n,pointer *argv)
01451 {
01452   ckarg(0);
01453 
01454   std::string host = ros::master::getHost();
01455   return makestring((char*)host.c_str(), host.length());
01456 }
01457 
01458 pointer ROSEUS_GET_NODES(register context *ctx,int n,pointer *argv)
01459 {
01460   ckarg(0);
01461 
01462   ros::V_string nodes;
01463   if ( ! ros::master::getNodes(nodes) ) {
01464     return NIL;
01465   }
01466 
01467   register pointer ret, first;
01468   ret=cons(ctx, NIL, NIL);
01469   first = ret;
01470   vpush(ret);
01471   for (ros::V_string::iterator it = nodes.begin() ; it != nodes.end(); it++) {
01472     std::string node = *it;
01473     ccdr(ret) = cons(ctx, makestring((char *)node.c_str(), node.length()), NIL);
01474     ret = ccdr(ret);
01475   }
01476   vpop(); // vpush(ret)
01477 
01478   return ccdr(first);
01479 }
01480 
01481 pointer ROSEUS_GET_PORT(register context *ctx,int n,pointer *argv)
01482 {
01483   ckarg(0);
01484 
01485   return makeint(ros::master::getPort());
01486 }
01487 
01488 pointer ROSEUS_GET_URI(register context *ctx,int n,pointer *argv)
01489 {
01490   ckarg(0);
01491 
01492   std::string uri = ros::master::getURI();
01493   return makestring((char*)uri.c_str(), uri.length());
01494 }
01495 
01496 pointer ROSEUS_GET_TOPICS(register context *ctx,int n,pointer *argv)
01497 {
01498   ckarg(0);
01499 
01500   ros::master::V_TopicInfo topics;
01501   if ( !ros::master::getTopics(topics) ) {
01502     return NIL;
01503   }
01504 
01505   register pointer ret, first;
01506   ret=cons(ctx, NIL, NIL);
01507   first = ret;
01508   vpush(ret);
01509   for (ros::master::V_TopicInfo::iterator it = topics.begin() ; it != topics.end(); it++) {
01510     const ros::master::TopicInfo& info = *it;
01511     pointer tmp = cons(ctx,makestring((char*)info.name.c_str(), info.name.length()), makestring((char*)info.datatype.c_str(), info.datatype.length()));
01512     vpush(tmp);
01513     ccdr(ret) = cons(ctx, tmp, NIL);
01514     ret = ccdr(ret);
01515     vpop(); // vpush(tmp)
01516   }
01517   vpop(); // vpush(ret)
01518 
01519   return ccdr(first);
01520 }
01521 
01522 class TimerFunction
01523 {
01524   pointer _scb, _args;
01525 public:
01526   TimerFunction(pointer scb, pointer args) : _scb(scb), _args(args) {
01527     context *ctx = current_ctx;
01528     //ROS_WARN("func");prinx(ctx,scb,ERROUT);flushstream(ERROUT);terpri(ERROUT);
01529     //ROS_WARN("argc");prinx(ctx,args,ERROUT);flushstream(ERROUT);terpri(ERROUT);
01530   }
01531   void operator()(const ros::TimerEvent& event)
01532   {
01533     mutex_trylock(&mark_lock);
01534     context *ctx = current_ctx;
01535     numunion nu;
01536     pointer argp=_args;
01537     int argc=0;
01538 
01539     pointer clsptr = NIL;
01540     for(int i=0; i<nextcix;i++) {
01541       if(!memcmp(classtab[i].def->c.cls.name->c.sym.pname->c.str.chars,(char *)"TIMER-EVENT",11)) {
01542         clsptr = classtab[i].def;
01543       }
01544     }
01545     if ( ! ( issymbol(_scb) || piscode(_scb) || ccar(_scb)==LAMCLOSURE ) ) {
01546       ROS_ERROR("%s : can't find callback function", __PRETTY_FUNCTION__);
01547     }
01548 
01549     pointer tevent = makeobject(clsptr);
01550     csend(ctx,tevent,K_ROSEUS_INIT,0);
01551     csend(ctx,tevent,K_ROSEUS_LAST_EXPECTED,2,K_ROSEUS_SEC,makeint(event.last_expected.sec));
01552     csend(ctx,tevent,K_ROSEUS_LAST_EXPECTED,2,K_ROSEUS_NSEC,makeint(event.last_expected.nsec));
01553     csend(ctx,tevent,K_ROSEUS_LAST_REAL,2,K_ROSEUS_SEC,makeint(event.last_real.sec));
01554     csend(ctx,tevent,K_ROSEUS_LAST_REAL,2,K_ROSEUS_NSEC,makeint(event.last_real.nsec));
01555     csend(ctx,tevent,K_ROSEUS_CURRENT_EXPECTED,2,K_ROSEUS_SEC,makeint(event.current_expected.sec));
01556     csend(ctx,tevent,K_ROSEUS_CURRENT_EXPECTED,2,K_ROSEUS_NSEC,makeint(event.current_expected.nsec));
01557     csend(ctx,tevent,K_ROSEUS_CURRENT_REAL,2,K_ROSEUS_SEC,makeint(event.current_real.sec));
01558     csend(ctx,tevent,K_ROSEUS_CURRENT_REAL,2,K_ROSEUS_NSEC,makeint(event.current_real.nsec));
01559     csend(ctx,tevent,K_ROSEUS_LAST_DURATION,2,K_ROSEUS_SEC,makeint(event.profile.last_duration.sec));
01560     csend(ctx,tevent,K_ROSEUS_LAST_DURATION,2,K_ROSEUS_NSEC,makeint(event.profile.last_duration.nsec));
01561 
01562     while(argp!=NIL){ ckpush(ccar(argp)); argp=ccdr(argp); argc++;}
01563     vpush((pointer)(tevent));argc++;
01564 
01565     ufuncall(ctx,(ctx->callfp?ctx->callfp->form:NIL),_scb,(pointer)(ctx->vsp-argc),NULL,argc);
01566     while(argc-->0)vpop();
01567 
01568     mutex_unlock(&mark_lock);
01569   }
01570 };
01571 
01572 pointer ROSEUS_CREATE_TIMER(register context *ctx,int n,pointer *argv)
01573 {
01574   isInstalledCheck;
01575   numunion nu;
01576   bool oneshot = false;
01577   pointer fncallback, args;
01578   NodeHandle *lnode = s_node.get();
01579   string fncallname;
01580   float period=ckfltval(argv[0]);
01581 
01582   mutex_trylock(&mark_lock);
01583   // period callbackfunc args0 ... argsN [ oneshot ]
01584   // ;; oneshot ;;
01585   if (n > 1 && issymbol(argv[n-2]) && issymbol(argv[n-1])) {
01586     if (argv[n-2] == K_ROSEUS_ONESHOT) {
01587       if ( argv[n-1] != NIL ) {
01588         oneshot = true;
01589       }
01590       n -= 2;
01591     }
01592   }
01593   // ;; functions ;;
01594   if (piscode(argv[1])) { // compiled code
01595     fncallback=argv[1];
01596     std::ostringstream stringstream;
01597     stringstream << reinterpret_cast<long>(argv[2]) << " ";
01598     for (int i=3; i<n;i++)
01599       stringstream << string((char*)(argv[i]->c.sym.pname->c.str.chars)) << " ";
01600     fncallname = stringstream.str();
01601   } else if ((ccar(argv[1]))==LAMCLOSURE) { // uncompiled code
01602     if ( ccar(ccdr(argv[1])) != NIL ) { // function
01603       fncallback=ccar(ccdr(argv[1]));
01604       fncallname = string((char*)(fncallback->c.sym.pname->c.str.chars));
01605     } else { // lambda function
01606       fncallback=argv[1];
01607       std::ostringstream stringstream;
01608       stringstream << reinterpret_cast<long>(argv[1]);
01609       fncallname = stringstream.str();
01610     }
01611   } else {
01612     ROS_ERROR("subscription callback function install error");
01613   }
01614 
01615   // ;; arguments ;;
01616   args=NIL;
01617   for (int i=n-1;i>=2;i--) args=cons(ctx,argv[i],args);
01618 
01619   // avoid gc
01620   pointer p=gensym(ctx);
01621   setval(ctx,intern(ctx,(char*)(p->c.sym.pname->c.str.chars),strlen((char*)(p->c.sym.pname->c.str.chars)),lisppkg),cons(ctx,fncallback,args));
01622 
01623   // ;; store mapTimered
01624   ROS_DEBUG("create timer %s at %f (oneshot=%d)", fncallname.c_str(), period, oneshot);
01625   s_mapTimered[fncallname] = lnode->createTimer(ros::Duration(period), TimerFunction(fncallback, args), oneshot);
01626 
01627   mutex_unlock(&mark_lock);
01628   return (T);
01629 }
01630 
01631 /************************************************************
01632  *   __roseus
01633  ************************************************************/
01634 extern pointer K_FUNCTION_DOCUMENTATION;
01635 pointer _defun(context *ctx, char *name, pointer mod, pointer (*f)(), char *doc) {
01636   pointer sym = defun(ctx,name, mod, f);
01637   if(strcmp(doc, "")) {
01638     pointer pdoc = makestring(doc,strlen(doc));
01639     vpush(pdoc); putprop(ctx,sym,pdoc,K_FUNCTION_DOCUMENTATION); vpop();}
01640   return sym;}
01641 
01642 pointer ___roseus(register context *ctx, int n, pointer *argv, pointer env)
01643 {
01644   pointer rospkg,p=Spevalof(PACKAGE);
01645   rospkg=findpkg(makestring("ROS",3));
01646   if (rospkg == 0) rospkg=makepkg(ctx,makestring("ROS", 3),NIL,NIL);
01647   Spevalof(PACKAGE)=rospkg;
01648 
01649   QANON=defvar(ctx,"*ANONYMOUS-NAME*",makeint(ros::init_options::AnonymousName),rospkg);
01650   QNOOUT=defvar(ctx,"*NO-ROSOUT*",makeint(ros::init_options::NoRosout),rospkg);
01651   QROSDEBUG=defvar(ctx,"*ROSDEBUG*",makeint(1),rospkg);
01652   QROSINFO=defvar(ctx,"*ROSINFO*",makeint(2),rospkg);
01653   QROSWARN=defvar(ctx,"*ROSWARN*",makeint(3),rospkg);
01654   QROSERROR=defvar(ctx,"*ROSERROR*",makeint(4),rospkg);
01655   QROSFATAL=defvar(ctx,"*ROSFATAL*",makeint(5),rospkg);
01656   _defun(ctx,"SPIN",argv[0],(pointer (*)())ROSEUS_SPIN, "Enter simple event loop");
01657 
01658   _defun(ctx,"SPIN-ONCE",argv[0],(pointer (*)())ROSEUS_SPINONCE,
01659          "&optional groupname  ;; spin only group\n\n"
01660          "Process a single round of callbacks.\n");
01661   _defun(ctx,"TIME-NOW-RAW",argv[0],(pointer (*)())ROSEUS_TIME_NOW, "");
01662   _defun(ctx,"RATE",argv[0],(pointer (*)())ROSEUS_RATE, "frequency\n\n" "Construct ros timer for periodic sleeps");
01663   _defun(ctx,"SLEEP",argv[0],(pointer (*)())ROSEUS_SLEEP, "Sleeps for any leftover time in a cycle. Calculated from the last time sleep, reset, or the constructor was called.");
01664   _defun(ctx,"OK",argv[0],(pointer (*)())ROSEUS_OK, "Check whether it's time to exit. ");
01665 
01666   _defun(ctx,"ROS-DEBUG",argv[0],(pointer (*)())ROSEUS_ROSDEBUG,
01667          "write mesage to debug output\n"
01668          "\n"
01669          "      (ros::ros-debug \"this is error ~A\" 0)\n");
01670   _defun(ctx,"ROS-INFO",argv[0],(pointer (*)())ROSEUS_ROSINFO, "write mesage to info output");
01671   _defun(ctx,"ROS-WARN",argv[0],(pointer (*)())ROSEUS_ROSWARN, "write mesage to warn output");
01672   _defun(ctx,"ROS-ERROR",argv[0],(pointer (*)())ROSEUS_ROSERROR, "write mesage to error output");
01673   _defun(ctx,"ROS-FATAL",argv[0],(pointer (*)())ROSEUS_ROSFATAL, "write mesage to fatal output");
01674   _defun(ctx,"EXIT",argv[0],(pointer (*)())ROSEUS_EXIT, "Exit ros clinet");
01675 
01676   _defun(ctx,"SUBSCRIBE",argv[0],(pointer (*)())ROSEUS_SUBSCRIBE,
01677          "topicname message_type callbackfunc args0 ... argsN &optional queuesize %key (:groupname groupname)\n\n"
01678          "Subscribe to a topic, version for class member function with bare pointer.\n"
01679          "This method connects to the master to register interest in a given topic. The node will automatically be connected with publishers on this topic. On each message receipt, fp is invoked and passed a shared pointer to the message received. This message should not be changed in place, as it is shared with any other subscriptions to this topic.\n"
01680          "\n"
01681          "This version of subscribe is a convenience function for using function, member function, lmabda function:\n"
01682          "      ;; callback function\n"
01683          "      (defun string-cb (msg) (print (list 'cb (sys::thread-self) (send msg :data))))\n"
01684          "      (ros::subscribe \"chatter\" std_msgs::string #'string-cb)\n"
01685          "      ;; lambda function\n"
01686          "      (ros::subscribe \"chatter\" std_msgs::string\n"
01687          "                      #'(lambda (msg) (ros::ros-info\n"
01688          "                                       (format nil \"I heard ~A\" (send msg :data)))))\n"
01689          "      ;; method call\n"
01690          "      (defclass string-cb-class\n"
01691          "        :super propertied-object\n"
01692          "        :slots ())\n"
01693          "      (defmethod string-cb-class\n"
01694          "        (:init () (ros::subscribe \"chatter\" std_msgs::string #'send self :string-cb))\n"
01695          "        (:string-cb (msg) (print (list 'cb self (send msg :data)))))\n"
01696          "      (setq m (instance string-cb-class :init))\n"
01697          );
01698   _defun(ctx,"UNSUBSCRIBE",argv[0],(pointer (*)())ROSEUS_UNSUBSCRIBE, "topicname\n\n""Unsubscribe topic");
01699   _defun(ctx,"GET-NUM-PUBLISHERS",argv[0],(pointer (*)())ROSEUS_GETNUMPUBLISHERS, "Returns the number of publishers this subscriber is connected to. ");
01700   _defun(ctx,"GET-TOPIC-SUBSCRIBER",argv[0],(pointer (*)())ROSEUS_GETTOPICSUBSCRIBER, "topicname\n\n""Retuns the name of topic if it already subscribed");
01701   _defun(ctx,"ADVERTISE",argv[0],(pointer (*)())ROSEUS_ADVERTISE,
01702          "topic message_class &optional queuesize latch\n"
01703          "Advertise a topic.\n"
01704          "This call connects to the master to publicize that the node will be publishing messages on the given topic. This method returns a Publisher that allows you to publish a message on this topic.\n"
01705          "      (ros::advertise \"chatter\" std_msgs::string 1)");
01706   _defun(ctx,"UNADVERTISE",argv[0],(pointer (*)())ROSEUS_UNADVERTISE, "Unadvertise topic");
01707   _defun(ctx,"PUBLISH",argv[0],(pointer (*)())ROSEUS_PUBLISH,
01708          "topic message\n\n"
01709          "Publish a message on the topic\n"
01710          "      (ros::roseus \"talker\")\n"
01711          "      (ros::advertise \"chatter\" std_msgs::string 1)\n"
01712          "      (ros::rate 100)\n"
01713          "      (while (ros::ok)\n"
01714          "        (setq msg (instance std_msgs::string :init))\n"
01715          "        (send msg :data (format nil \"hello world ~a\" (send (ros::time-now) :sec-nsec)))\n"
01716          "        (ros::publish \"chatter\" msg)\n"
01717          "        (ros::sleep))\n");
01718   _defun(ctx,"GET-NUM-SUBSCRIBERS",argv[0],(pointer (*)())ROSEUS_GETNUMSUBSCRIBERS, "Retuns number of subscribers this publish is connected to");
01719   _defun(ctx,"GET-TOPIC-PUBLISHER",argv[0],(pointer (*)())ROSEUS_GETTOPICPUBLISHER, "topicname\n\n""Retuns the name of topic if it already published");
01720 
01721   _defun(ctx,"WAIT-FOR-SERVICE",argv[0],(pointer (*)())ROSEUS_WAIT_FOR_SERVICE, "servicename &optional timeout\n\n""Wait for a service to be advertised and available. Blocks until it is.");
01722   _defun(ctx,"SERVICE-EXISTS", argv[0], (pointer (*)())ROSEUS_SERVICE_EXISTS, "servicename\n\n""Checks if a service is both advertised and available.");
01723   _defun(ctx,"SERVICE-CALL",argv[0],(pointer (*)())ROSEUS_SERVICE_CALL, 
01724          "servicename message_type &optional persist\n\n"
01725          "Invoke RPC service\n"
01726          "      (ros::roseus \"add_two_ints_client\")\n"
01727          "      (ros::wait-for-service \"add_two_ints\")\n"
01728          "      (setq req (instance roseus::AddTwoIntsRequest :init))\n"
01729          "      (send req :a (random 10))\n"
01730          "      (send req :b (random 20))\n"
01731          "      (setq res (ros::service-call \"add_two_ints\" req t))\n"
01732          "      (format t \"~d + ~d = ~d~~%\" (send req :a) (send req :b) (send res :sum))\n");
01733   _defun(ctx,"ADVERTISE-SERVICE",argv[0],(pointer (*)())ROSEUS_ADVERTISE_SERVICE,
01734          "servicename message_type callback function\n\n"
01735          "Advertise a service\n"
01736          "      (ros::advertise-service \"add_two_ints\" roseus::AddTwoInts #'add-two-ints)");
01737   _defun(ctx,"UNADVERTISE-SERVICE",argv[0],(pointer (*)())ROSEUS_UNADVERTISE_SERVICE, "Unadvertise service");
01738 
01739   _defun(ctx,"SET-PARAM",argv[0],(pointer (*)())ROSEUS_SET_PARAM, "key value\n\n""Set parameter");
01740   _defun(ctx,"GET-PARAM",argv[0],(pointer (*)())ROSEUS_GET_PARAM, "key\n\n""Get parameter");
01741   _defun(ctx,"GET-PARAM-CASHED",argv[0],(pointer (*)())ROSEUS_GET_PARAM_CASHED, "Get chached parameter");
01742   _defun(ctx,"HAS-PARAM",argv[0],(pointer (*)())ROSEUS_HAS_PARAM, "Check whether a parameter exists on the parameter server.");
01743 
01744   _defun(ctx,"ROSPACK-FIND",argv[0],(pointer (*)())ROSEUS_ROSPACK_FIND, "Returns ros package path");
01745   _defun(ctx,"RESOLVE-NAME",argv[0],(pointer (*)())ROSEUS_RESOLVE_NAME, "Returns ros resolved name");
01746   _defun(ctx,"GET-NAME",argv[0],(pointer (*)())ROSEUS_GETNAME, "Returns current node name");
01747   _defun(ctx,"GET-NAMESPACE",argv[0],(pointer (*)())ROSEUS_GETNAMESPACE, "Returns current node name space");
01748 
01749   _defun(ctx,"ROSEUS-RAW",argv[0],(pointer (*)())ROSEUS, "");
01750   _defun(ctx,"CREATE-NODEHANDLE", argv[0], (pointer (*)())ROSEUS_CREATE_NODEHANDLE, "groupname &optional namespace  ;;\n\n"
01751          "Create ros NodeHandle with given group name. \n"
01752          "\n"
01753          "      (ros::roseus \"test\")\n"
01754          "      (ros::create-node-handle \"mygroup\")\n"
01755          "      (ros::subscribe \"/test\" std_msgs::String #'(lambda (m) (print m)) :groupname \"mygroup\")\n"
01756          "      (while (ros::ok)  (ros::spin-once \"mygroup\"))\n");
01757   _defun(ctx,"SET-LOGGER-LEVEL",argv[0],(pointer (*)())ROSEUS_SET_LOGGER_LEVEL, "");
01758 
01759   _defun(ctx,"GET-HOST",argv[0],(pointer (*)())ROSEUS_GET_HOST, "Get the hostname where the master runs.");
01760   _defun(ctx,"GET-NODES",argv[0],(pointer (*)())ROSEUS_GET_NODES, "Retreives the currently-known list of nodes from the master.");
01761   _defun(ctx,"GET-PORT",argv[0],(pointer (*)())ROSEUS_GET_PORT, "Get the port where the master runs.");
01762   _defun(ctx,"GET-URI",argv[0],(pointer (*)())ROSEUS_GET_URI, "Get the full URI to the master ");
01763   _defun(ctx,"GET-TOPICS",argv[0],(pointer (*)())ROSEUS_GET_TOPICS, "Get the list of topics that are being published by all nodes.");
01764 
01765   defun(ctx,"CREATE-TIMER",argv[0],(pointer (*)())ROSEUS_CREATE_TIMER);
01766 
01767   pointer_update(Spevalof(PACKAGE),p);
01768 
01769   pointer l;
01770   l=makestring(REPOVERSION,strlen(REPOVERSION));
01771   vpush(l);
01772   l=stacknlist(ctx,1);
01773   QREPOVERSION=defvar(ctx, "ROSEUS-REPO-VERSION", l, rospkg);
01774 
01775   M_string remappings;
01776   pointer argp = speval(intern(ctx,"*EUSTOP-ARGUMENT*", strlen("*EUSTOP-ARGUMENT*"),lisppkg));
01777   while(argp!=NIL) {
01778     std::string arg = string((char *)(ccar(argp)->c.str.chars));
01779     // copy from roscpp/src/init.cpp : 432
01780     size_t pos = arg.find(":=");
01781     if (pos != std::string::npos) {
01782       std::string local_name = arg.substr(0, pos);
01783       std::string external_name = arg.substr(pos + 2);
01784       remappings[local_name] = external_name;
01785     }
01786     argp=ccdr(argp);
01787   }
01788   ros::master::init(remappings);
01789   //ros::param::init(remappings);
01790 
01791   return 0;
01792 }
01793 


roseus
Author(s): Kei Okada
autogenerated on Wed Sep 16 2015 10:23:58