$search
00001 #!/usr/bin/env python 00002 00003 ##################################################################### 00004 # Software License Agreement (BSD License) 00005 # 00006 # Copyright (c) 2011, Willow Garage, Inc. 00007 # All rights reserved. 00008 # 00009 # Redistribution and use in source and binary forms, with or without 00010 # modification, are permitted provided that the following conditions 00011 # are met: 00012 # 00013 # * Redistributions of source code must retain the above copyright 00014 # notice, this list of conditions and the following disclaimer. 00015 # * Redistributions in binary form must reproduce the above 00016 # copyright notice, this list of conditions and the following 00017 # disclaimer in the documentation and/or other materials provided 00018 # with the distribution. 00019 # * Neither the name of Willow Garage, Inc. nor the names of its 00020 # contributors may be used to endorse or promote products derived 00021 # from this software without specific prior written permission. 00022 # 00023 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00024 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00025 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00026 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00027 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00028 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00029 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00032 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00033 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00034 # POSSIBILITY OF SUCH DAMAGE. 00035 00036 __author__ = "mferguson@willowgarage.com (Michael Ferguson)" 00037 00038 __usage__ = """ 00039 make_library.py generates the Arduino rosserial library files. It 00040 requires the location of your arduino libraries folder and the name of 00041 one or more packages for which you want to make libraries. 00042 00043 rosrun rosserial_client make_library.py <output_path> pkg_name [pkg2 pkg3 ...] 00044 """ 00045 00046 import roslib; roslib.load_manifest("rosserial_client") 00047 import roslib.gentools, roslib.srvs 00048 import roslib.rospack 00049 import rospy 00050 00051 import os, sys, subprocess, re 00052 00053 def type_to_var(ty): 00054 lookup = { 00055 1 : 'uint8_t', 00056 2 : 'uint16_t', 00057 4 : 'uint32_t', 00058 8 : 'uint64_t', 00059 } 00060 return lookup[ty] 00061 00062 ##################################################################### 00063 # Data Types 00064 00065 class EnumerationType: 00066 """ For data values. """ 00067 00068 def __init__(self, name, ty, value): 00069 self.name = name 00070 self.type = ty 00071 self.value = value 00072 00073 def make_declaration(self, f): 00074 f.write(' enum { %s = %s };\n' % (self.name, self.value)) 00075 00076 class PrimitiveDataType: 00077 """ Our datatype is a C/C++ primitive. """ 00078 00079 def __init__(self, name, ty, bytes): 00080 self.name = name 00081 self.type = ty 00082 self.bytes = bytes 00083 00084 def make_declaration(self, f): 00085 f.write(' %s %s;\n' % (self.type, self.name) ) 00086 00087 def serialize(self, f): 00088 cn = self.name.replace("[","").replace("]","").split(".")[-1] 00089 if self.type != type_to_var(self.bytes): 00090 f.write(' union {\n') 00091 f.write(' %s real;\n' % self.type) 00092 f.write(' %s base;\n' % type_to_var(self.bytes)) 00093 f.write(' } u_%s;\n' % cn) 00094 f.write(' u_%s.real = this->%s;\n' % (cn,self.name)) 00095 for i in range(self.bytes): 00096 f.write(' *(outbuffer + offset + %d) = (u_%s.base >> (8 * %d)) & 0xFF;\n' % (i, cn, i) ) 00097 else: 00098 for i in range(self.bytes): 00099 f.write(' *(outbuffer + offset + %d) = (this->%s >> (8 * %d)) & 0xFF;\n' % (i, self.name, i) ) 00100 f.write(' offset += sizeof(this->%s);\n' % self.name) 00101 00102 def deserialize(self, f): 00103 cn = self.name.replace("[","").replace("]","").split(".")[-1] 00104 if self.type != type_to_var(self.bytes): 00105 f.write(' union {\n') 00106 f.write(' %s real;\n' % self.type) 00107 f.write(' %s base;\n' % type_to_var(self.bytes)) 00108 f.write(' } u_%s;\n' % cn) 00109 f.write(' u_%s.base = 0;\n' % cn) 00110 for i in range(self.bytes): 00111 f.write(' u_%s.base |= ((%s) (*(inbuffer + offset + %d))) << (8 * %d);\n' % (cn,type_to_var(self.bytes),i,i) ) 00112 f.write(' this->%s = u_%s.real;\n' % (self.name, cn) ) 00113 else: 00114 f.write(' this->%s = ((%s) (*(inbuffer + offset)));\n' % (self.name,self.type) ) 00115 for i in range(self.bytes-1): 00116 f.write(' this->%s |= ((%s) (*(inbuffer + offset + %d))) << (8 * %d);\n' % (self.name,self.type,i+1,i+1) ) 00117 f.write(' offset += sizeof(this->%s);\n' % self.name) 00118 00119 00120 class MessageDataType(PrimitiveDataType): 00121 """ For when our data type is another message. """ 00122 def serialize(self, f): 00123 f.write(' offset += this->%s.serialize(outbuffer + offset);\n' % self.name) 00124 00125 def deserialize(self, f): 00126 f.write(' offset += this->%s.deserialize(inbuffer + offset);\n' % self.name) 00127 00128 00129 class Float64DataType(PrimitiveDataType): 00130 """ AVR C/C++ has no native 64-bit support, we automatically convert to 32-bit float. """ 00131 00132 def make_declaration(self, f): 00133 f.write(' float %s;\n' % self.name ) 00134 00135 def serialize(self, f): 00136 cn = self.name.replace("[","").replace("]","") 00137 f.write(' int32_t * val_%s = (long *) &(this->%s);\n' % (cn,self.name)) 00138 f.write(' int32_t exp_%s = (((*val_%s)>>23)&255);\n' % (cn,cn)) 00139 f.write(' if(exp_%s != 0)\n' % cn) 00140 f.write(' exp_%s += 1023-127;\n' % cn) 00141 f.write(' int32_t sig_%s = *val_%s;\n' % (cn,cn)) 00142 f.write(' *(outbuffer + offset++) = 0;\n') # 29 blank bits 00143 f.write(' *(outbuffer + offset++) = 0;\n') 00144 f.write(' *(outbuffer + offset++) = 0;\n') 00145 f.write(' *(outbuffer + offset++) = (sig_%s<<5) & 0xff;\n' % cn) 00146 f.write(' *(outbuffer + offset++) = (sig_%s>>3) & 0xff;\n' % cn) 00147 f.write(' *(outbuffer + offset++) = (sig_%s>>11) & 0xff;\n' % cn) 00148 f.write(' *(outbuffer + offset++) = ((exp_%s<<4) & 0xF0) | ((sig_%s>>19)&0x0F);\n' % (cn,cn)) 00149 f.write(' *(outbuffer + offset++) = (exp_%s>>4) & 0x7F;\n' % cn) 00150 f.write(' if(this->%s < 0) *(outbuffer + offset -1) |= 0x80;\n' % self.name) 00151 00152 def deserialize(self, f): 00153 cn = self.name.replace("[","").replace("]","") 00154 f.write(' uint32_t * val_%s = (uint32_t*) &(this->%s);\n' % (cn,self.name)) 00155 f.write(' offset += 3;\n') # 29 blank bits 00156 f.write(' *val_%s = ((uint32_t)(*(inbuffer + offset++))>>5 & 0x07);\n' % cn) 00157 f.write(' *val_%s |= ((uint32_t)(*(inbuffer + offset++)) & 0xff)<<3;\n' % cn) 00158 f.write(' *val_%s |= ((uint32_t)(*(inbuffer + offset++)) & 0xff)<<11;\n' % cn) 00159 f.write(' *val_%s |= ((uint32_t)(*(inbuffer + offset)) & 0x0f)<<19;\n' % cn) 00160 f.write(' uint32_t exp_%s = ((uint32_t)(*(inbuffer + offset++))&0xf0)>>4;\n' % cn) 00161 f.write(' exp_%s |= ((uint32_t)(*(inbuffer + offset)) & 0x7f)<<4;\n' % cn) 00162 f.write(' if(exp_%s !=0)\n' % cn) 00163 f.write(' *val_%s |= ((exp_%s)-1023+127)<<23;\n' % (cn,cn)) 00164 f.write(' if( ((*(inbuffer+offset++)) & 0x80) > 0) this->%s = -this->%s;\n' % (self.name,self.name)) 00165 00166 00167 class StringDataType(PrimitiveDataType): 00168 """ Need to convert to signed char *. """ 00169 00170 def make_declaration(self, f): 00171 f.write(' char * %s;\n' % self.name) 00172 00173 def serialize(self, f): 00174 cn = self.name.replace("[","").replace("]","") 00175 f.write(' uint32_t * length_%s = (uint32_t *)(outbuffer + offset);\n' % cn) 00176 f.write(' *length_%s = strlen( (const char*) this->%s);\n' % (cn,self.name)) 00177 f.write(' offset += 4;\n') 00178 f.write(' memcpy(outbuffer + offset, this->%s, *length_%s);\n' % (self.name,cn)) 00179 f.write(' offset += *length_%s;\n' % cn) 00180 00181 def deserialize(self, f): 00182 cn = self.name.replace("[","").replace("]","") 00183 f.write(' uint32_t length_%s = *(uint32_t *)(inbuffer + offset);\n' % cn) 00184 f.write(' offset += 4;\n') 00185 f.write(' for(unsigned int k= offset; k< offset+length_%s; ++k){\n'%cn) #shift for null character 00186 f.write(' inbuffer[k-1]=inbuffer[k];\n') 00187 f.write(' }\n') 00188 f.write(' inbuffer[offset+length_%s-1]=0;\n'%cn) 00189 f.write(' this->%s = (char *)(inbuffer + offset-1);\n' % self.name) 00190 f.write(' offset += length_%s;\n' % cn) 00191 00192 00193 class TimeDataType(PrimitiveDataType): 00194 00195 def __init__(self, name, ty, bytes): 00196 self.name = name 00197 self.type = ty 00198 self.sec = PrimitiveDataType(name+'.sec','uint32_t',4) 00199 self.nsec = PrimitiveDataType(name+'.nsec','uint32_t',4) 00200 00201 def make_declaration(self, f): 00202 f.write(' %s %s;\n' % (self.type, self.name)) 00203 00204 def serialize(self, f): 00205 self.sec.serialize(f) 00206 self.nsec.serialize(f) 00207 00208 def deserialize(self, f): 00209 self.sec.deserialize(f) 00210 self.nsec.deserialize(f) 00211 00212 00213 class ArrayDataType(PrimitiveDataType): 00214 00215 def __init__(self, name, ty, bytes, cls, array_size=None): 00216 self.name = name 00217 self.type = ty 00218 self.bytes = bytes 00219 self.size = array_size 00220 self.cls = cls 00221 00222 def make_declaration(self, f): 00223 c = self.cls("*"+self.name, self.type, self.bytes) 00224 if self.size == None: 00225 f.write(' uint8_t %s_length;\n' % self.name) 00226 f.write(' %s st_%s;\n' % (self.type, self.name)) # static instance for copy 00227 f.write(' %s * %s;\n' % (self.type, self.name)) 00228 else: 00229 f.write(' %s %s[%d];\n' % (self.type, self.name, self.size)) 00230 00231 def serialize(self, f): 00232 c = self.cls(self.name+"[i]", self.type, self.bytes) 00233 if self.size == None: 00234 # serialize length 00235 f.write(' *(outbuffer + offset++) = %s_length;\n' % self.name) 00236 f.write(' *(outbuffer + offset++) = 0;\n') 00237 f.write(' *(outbuffer + offset++) = 0;\n') 00238 f.write(' *(outbuffer + offset++) = 0;\n') 00239 f.write(' for( uint8_t i = 0; i < %s_length; i++){\n' % self.name) 00240 c.serialize(f) 00241 f.write(' }\n') 00242 else: 00243 f.write(' unsigned char * %s_val = (unsigned char *) this->%s;\n' % (self.name, self.name)) 00244 f.write(' for( uint8_t i = 0; i < %d; i++){\n' % (self.size) ) 00245 c.serialize(f) 00246 f.write(' }\n') 00247 00248 def deserialize(self, f): 00249 if self.size == None: 00250 c = self.cls("st_"+self.name, self.type, self.bytes) 00251 # deserialize length 00252 f.write(' uint8_t %s_lengthT = *(inbuffer + offset++);\n' % self.name) 00253 f.write(' if(%s_lengthT > %s_length)\n' % (self.name, self.name)) 00254 f.write(' this->%s = (%s*)realloc(this->%s, %s_lengthT * sizeof(%s));\n' % (self.name, self.type, self.name, self.name, self.type)) 00255 f.write(' offset += 3;\n') 00256 f.write(' %s_length = %s_lengthT;\n' % (self.name, self.name)) 00257 # copy to array 00258 f.write(' for( uint8_t i = 0; i < %s_length; i++){\n' % (self.name) ) 00259 c.deserialize(f) 00260 f.write(' memcpy( &(this->%s[i]), &(this->st_%s), sizeof(%s));\n' % (self.name, self.name, self.type)) 00261 f.write(' }\n') 00262 else: 00263 c = self.cls(self.name+"[i]", self.type, self.bytes) 00264 f.write(' uint8_t * %s_val = (uint8_t*) this->%s;\n' % (self.name, self.name)) 00265 f.write(' for( uint8_t i = 0; i < %d; i++){\n' % (self.size) ) 00266 c.deserialize(f) 00267 f.write(' }\n') 00268 00269 00270 ros_to_arduino_types = { 00271 'bool' : ('bool', 1, PrimitiveDataType, []), 00272 'int8' : ('int8_t', 1, PrimitiveDataType, []), 00273 'uint8' : ('uint8_t', 1, PrimitiveDataType, []), 00274 'int16' : ('int16_t', 2, PrimitiveDataType, []), 00275 'uint16' : ('uint16_t', 2, PrimitiveDataType, []), 00276 'int32' : ('int32_t', 4, PrimitiveDataType, []), 00277 'uint32' : ('uint32_t', 4, PrimitiveDataType, []), 00278 'int64' : ('int64_t', 4, PrimitiveDataType, []), 00279 'uint64' : ('uint64_t', 4, PrimitiveDataType, []), 00280 'float32' : ('float', 4, PrimitiveDataType, []), 00281 'float64' : ('float', 4, Float64DataType, []), 00282 'time' : ('ros::Time', 8, TimeDataType, ['ros/time']), 00283 'duration': ('ros::Duration', 8, TimeDataType, ['ros/duration']), 00284 'string' : ('char*', 0, StringDataType, []), 00285 'Header' : ('std_msgs::Header', 0, MessageDataType, ['std_msgs/Header']) 00286 } 00287 00288 00289 ##################################################################### 00290 # Messages 00291 00292 class Message: 00293 """ Parses message definitions into something we can export. """ 00294 00295 def __init__(self, name, package, definition, md5): 00296 00297 self.name = name # name of message/class 00298 self.package = package # package we reside in 00299 self.md5 = md5 # checksum 00300 self.includes = list() # other files we must include 00301 00302 self.data = list() # data types for code generation 00303 self.enums = list() 00304 00305 # parse definition 00306 for line in definition: 00307 # prep work 00308 line = line.strip().rstrip() 00309 value = None 00310 if line.find("#") > -1: 00311 line = line[0:line.find("#")] 00312 if line.find("=") > -1: 00313 try: 00314 value = line[line.find("=")+1:] 00315 except: 00316 value = '"' + line[line.find("=")+1:] + '"'; 00317 line = line[0:line.find("=")] 00318 00319 # find package/class name 00320 line = line.replace("\t", " ") 00321 l = line.split(" ") 00322 while "" in l: 00323 l.remove("") 00324 if len(l) < 2: 00325 continue 00326 ty, name = l[0:2] 00327 if value != None: 00328 self.enums.append( EnumerationType(name, ty, value)) 00329 continue 00330 00331 try: 00332 type_package, type_name = ty.split("/") 00333 except: 00334 type_package = None 00335 type_name = ty 00336 type_array = False 00337 if type_name.find('[') > 0: 00338 type_array = True 00339 try: 00340 type_array_size = int(type_name[type_name.find('[')+1:type_name.find(']')]) 00341 except: 00342 type_array_size = None 00343 type_name = type_name[0:type_name.find('[')] 00344 00345 # convert to C type if primitive, expand name otherwise 00346 try: 00347 code_type = ros_to_arduino_types[type_name][0] 00348 size = ros_to_arduino_types[type_name][1] 00349 cls = ros_to_arduino_types[type_name][2] 00350 for include in ros_to_arduino_types[type_name][3]: 00351 if include not in self.includes: 00352 self.includes.append(include) 00353 except: 00354 if type_package == None: 00355 type_package = self.package 00356 if type_package+"/"+type_name not in self.includes: 00357 self.includes.append(type_package+"/"+type_name) 00358 cls = MessageDataType 00359 code_type = type_package + "::" + type_name 00360 size = 0 00361 if type_array: 00362 self.data.append( ArrayDataType(name, code_type, size, cls, type_array_size ) ) 00363 else: 00364 self.data.append( cls(name, code_type, size) ) 00365 00366 def _write_serializer(self, f): 00367 # serializer 00368 f.write('\n') 00369 f.write(' virtual int serialize(unsigned char *outbuffer) const\n') 00370 f.write(' {\n') 00371 f.write(' int offset = 0;\n') 00372 for d in self.data: 00373 d.serialize(f) 00374 f.write(' return offset;\n'); 00375 f.write(' }\n') 00376 f.write('\n') 00377 00378 def _write_deserializer(self, f): 00379 # deserializer 00380 f.write(' virtual int deserialize(unsigned char *inbuffer)\n') 00381 f.write(' {\n') 00382 f.write(' int offset = 0;\n') 00383 for d in self.data: 00384 d.deserialize(f) 00385 f.write(' return offset;\n'); 00386 f.write(' }\n') 00387 f.write('\n') 00388 00389 def _write_std_includes(self, f): 00390 f.write('#include <stdint.h>\n') 00391 f.write('#include <string.h>\n') 00392 f.write('#include <stdlib.h>\n') 00393 f.write('#include "ros/msg.h"\n') 00394 00395 def _write_msg_includes(self,f): 00396 for i in self.includes: 00397 f.write('#include "%s.h"\n' % i) 00398 00399 def _write_data(self, f): 00400 for d in self.data: 00401 d.make_declaration(f) 00402 for e in self.enums: 00403 e.make_declaration(f) 00404 00405 def _write_getType(self, f): 00406 f.write(' const char * getType(){ return "%s/%s"; };\n'%(self.package, self.name)) 00407 00408 def _write_getMD5(self, f): 00409 f.write(' const char * getMD5(){ return "%s"; };\n'%self.md5) 00410 00411 def _write_impl(self, f): 00412 f.write(' class %s : public ros::Msg\n' % self.name) 00413 f.write(' {\n') 00414 f.write(' public:\n') 00415 self._write_data(f) 00416 self._write_serializer(f) 00417 self._write_deserializer(f) 00418 self._write_getType(f) 00419 self._write_getMD5(f) 00420 f.write('\n') 00421 f.write(' };\n') 00422 00423 def make_header(self, f): 00424 f.write('#ifndef _ROS_%s_%s_h\n'%(self.package, self.name)) 00425 f.write('#define _ROS_%s_%s_h\n'%(self.package, self.name)) 00426 f.write('\n') 00427 self._write_std_includes(f) 00428 self._write_msg_includes(f) 00429 00430 f.write('\n') 00431 f.write('namespace %s\n' % self.package) 00432 f.write('{\n') 00433 f.write('\n') 00434 self._write_impl(f) 00435 f.write('\n') 00436 f.write('}\n') 00437 00438 f.write('#endif') 00439 00440 class Service: 00441 def __init__(self, name, package, definition, md5req, md5res): 00442 """ 00443 @param name - name of service 00444 @param package - name of service package 00445 @param definition - list of lines of definition 00446 """ 00447 00448 self.name = name 00449 self.package = package 00450 00451 sep_line = None 00452 sep = re.compile('---*') 00453 for i in range(0, len(definition)): 00454 if (None!= re.match(sep, definition[i]) ): 00455 sep_line = i 00456 break 00457 self.req_def = definition[0:sep_line] 00458 self.resp_def = definition[sep_line+1:] 00459 00460 self.req = Message(name+"Request", package, self.req_def, md5req) 00461 self.resp = Message(name+"Response", package, self.resp_def, md5res) 00462 00463 def make_header(self, f): 00464 f.write('#ifndef _ROS_SERVICE_%s_h\n' % self.name) 00465 f.write('#define _ROS_SERVICE_%s_h\n' % self.name) 00466 00467 self.req._write_std_includes(f) 00468 includes = self.req.includes 00469 includes.extend(self.resp.includes) 00470 includes = list(set(includes)) 00471 for inc in includes: 00472 f.write('#include "%s.h"\n' % inc) 00473 00474 f.write('\n') 00475 f.write('namespace %s\n' % self.package) 00476 f.write('{\n') 00477 f.write('\n') 00478 f.write('static const char %s[] = "%s/%s";\n'%(self.name.upper(), self.package, self.name)) 00479 00480 def write_type(out, name): 00481 out.write(' const char * getType(){ return %s; };\n'%(name)) 00482 _write_getType = lambda out: write_type(out, self.name.upper()) 00483 self.req._write_getType = _write_getType 00484 self.resp._write_getType = _write_getType 00485 00486 f.write('\n') 00487 self.req._write_impl(f) 00488 f.write('\n') 00489 self.resp._write_impl(f) 00490 f.write('\n') 00491 f.write(' class %s {\n' % self.name ) 00492 f.write(' public:\n') 00493 f.write(' typedef %s Request;\n' % self.req.name ) 00494 f.write(' typedef %s Response;\n' % self.resp.name ) 00495 f.write(' };\n') 00496 f.write('\n') 00497 00498 f.write('}\n') 00499 00500 f.write('#endif') 00501 00502 00503 00504 ##################################################################### 00505 # Make a Library 00506 00507 def MakeLibrary(package, output_path): 00508 print "Exporting " + package + "\n", 00509 00510 pkg_dir = roslib.packages.get_pkg_dir(package) 00511 00512 sys.stdout.write(' Messages:') 00513 # find the messages in this package 00514 messages = list() 00515 if os.path.exists(pkg_dir+"/msg"): 00516 sys.stdout.write('\n ') 00517 for f in os.listdir(pkg_dir+"/msg"): 00518 if f.endswith(".msg"): 00519 file = pkg_dir + "/msg/" + f 00520 # add to list of messages 00521 print "%s," % f[0:-4], 00522 definition = open(file).readlines() 00523 md5sum = roslib.gentools.compute_md5(roslib.gentools.get_file_dependencies(file)) 00524 messages.append( Message(f[0:-4], package, definition, md5sum) ) 00525 print "\n" 00526 00527 sys.stdout.write(' Services:') 00528 # find the services in this package 00529 services = list() 00530 if (os.path.exists(pkg_dir+"/srv/")): 00531 sys.stdout.write('\n ') 00532 for f in os.listdir(pkg_dir+"/srv"): 00533 if f.endswith(".srv"): 00534 file = pkg_dir + "/srv/" + f 00535 # add to list of messages 00536 print "%s," % f[0:-4], 00537 definition, service = roslib.srvs.load_from_file(file) 00538 definition = open(file).readlines() 00539 md5req = roslib.gentools.compute_md5(roslib.gentools.get_dependencies(service.request, package)) 00540 md5res = roslib.gentools.compute_md5(roslib.gentools.get_dependencies(service.response, package)) 00541 messages.append( Service(f[0:-4], package, definition, md5req, md5res ) ) 00542 print "\n" 00543 00544 # generate for each message 00545 output_path = output_path + "/" + package 00546 for msg in messages: 00547 if not os.path.exists(output_path): 00548 os.makedirs(output_path) 00549 header = open(output_path + "/" + msg.name + ".h", "w") 00550 msg.make_header(header) 00551 header.close() 00552 00553 00554 def add_depends(packages, package): 00555 depend = [package] + roslib.rospack.rospack_depends(package) 00556 for p in depend: 00557 if not p in packages: 00558 packages.append(p) 00559 packages = add_depends(packages, p) 00560 return packages 00561 00562 if __name__=="__main__": 00563 00564 # need correct inputs 00565 if (len(sys.argv) <3): 00566 print __usage__ 00567 exit() 00568 00569 # get output path 00570 path = sys.argv[1] 00571 if path[-1] == "/": 00572 path = path[0:-1] 00573 path += "/ros_lib" 00574 print "\nExporting to %s" % path 00575 00576 packages = list() 00577 # make libraries 00578 for package in sys.argv[2:]: 00579 packages = add_depends(packages, package) 00580 00581 print packages 00582 for package in packages: 00583 MakeLibrary(package, path) 00584