00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 import roslib; roslib.load_manifest('roscpp')
00040 import roscpp.msg_gen as genmsg_cpp
00041
00042 import sys
00043 import os
00044 import traceback
00045
00046
00047 import roslib.srvs
00048 import roslib.packages
00049 import roslib.gentools
00050
00051 from cStringIO import StringIO
00052
00053 def write_begin(s, spec, file):
00054 """
00055 Writes the beginning of the header file: a comment saying it's auto-generated and the include guards
00056
00057 @param s: The stream to write to
00058 @type s: stream
00059 @param spec: The spec
00060 @type spec: roslib.srvs.SrvSpec
00061 @param file: The file this service is being generated for
00062 @type file: str
00063 """
00064 s.write("/* Auto-generated by genmsg_cpp for file %s */\n"%(file))
00065 s.write('#ifndef %s_SERVICE_%s_H\n'%(spec.package.upper(), spec.short_name.upper()))
00066 s.write('#define %s_SERVICE_%s_H\n'%(spec.package.upper(), spec.short_name.upper()))
00067
00068 def write_end(s, spec):
00069 """
00070 Writes the end of the header file: the ending of the include guards
00071
00072 @param s: The stream to write to
00073 @type s: stream
00074 @param spec: The spec
00075 @type spec: roslib.srvs.SrvSpec
00076 """
00077 s.write('#endif // %s_SERVICE_%s_H\n'%(spec.package.upper(), spec.short_name.upper()))
00078
00079 def write_generic_includes(s):
00080 """
00081 Writes the includes that all service need
00082
00083 @param s: The stream to write to
00084 @type s: stream
00085 """
00086 s.write('#include "ros/service_traits.h"\n\n')
00087
00088 def write_trait_char_class(s, class_name, cpp_msg, value):
00089 """
00090 Writes a class trait for traits which have static value() members that return const char*
00091
00092 e.g. write_trait_char_class(s, "MD5Sum", "std_srvs::Empty", "hello") yields:
00093 template<>
00094 struct MD5Sum<std_srvs::Empty>
00095 {
00096 static const char* value() { return "hello"; }
00097 static const char* value(const std_srvs::Empty&) { return value(); }
00098 };
00099
00100 @param s: The stream to write to
00101 @type s: stream
00102 @param class_name: The name of the trait class
00103 @type class_name: str
00104 @param cpp_msg: The C++ message declaration, e.g. "std_srvs::Empty"
00105 @type cpp_msg: str
00106 @param value: The string value to return from the value() function
00107 @type value: str
00108 """
00109 s.write('template<>\nstruct %s<%s> {\n'%(class_name, cpp_msg))
00110 s.write(' static const char* value() \n {\n return "%s";\n }\n\n'%(value))
00111 s.write(' static const char* value(const %s&) { return value(); } \n'%(cpp_msg))
00112 s.write('};\n\n')
00113
00114 def write_traits(s, spec, cpp_name_prefix):
00115 """
00116 Write all the service traits for a message
00117
00118 @param s: The stream to write to
00119 @type s: stream
00120 @param spec: The service spec
00121 @type spec: roslib.srvs.SrvSpec
00122 @param cpp_name_prefix: The C++ prefix to prepend when referencing the service, e.g. "std_srvs::"
00123 @type cpp_name_prefix: str
00124 """
00125 gendeps_dict = roslib.gentools.get_dependencies(spec, spec.package)
00126 md5sum = roslib.gentools.compute_md5(gendeps_dict)
00127
00128 s.write('namespace ros\n{\n')
00129 s.write('namespace service_traits\n{\n')
00130
00131 request_with_allocator = '%s%s_<ContainerAllocator> '%(cpp_name_prefix, spec.request.short_name)
00132 response_with_allocator = '%s%s_<ContainerAllocator> '%(cpp_name_prefix, spec.response.short_name)
00133
00134 write_trait_char_class(s, 'MD5Sum', '%s%s'%(cpp_name_prefix, spec.short_name), md5sum);
00135 write_trait_char_class(s, 'DataType', '%s%s'%(cpp_name_prefix, spec.short_name), spec.full_name);
00136 genmsg_cpp.write_trait_char_class(s, 'MD5Sum', request_with_allocator, md5sum)
00137 genmsg_cpp.write_trait_char_class(s, 'DataType', request_with_allocator, spec.full_name)
00138 genmsg_cpp.write_trait_char_class(s, 'MD5Sum', response_with_allocator, md5sum)
00139 genmsg_cpp.write_trait_char_class(s, 'DataType', response_with_allocator, spec.full_name)
00140 s.write('} // namespace service_traits\n')
00141 s.write('} // namespace ros\n\n')
00142
00143 def generate(srv_path):
00144 """
00145 Generate a service
00146
00147 @param srv_path: the path to the .srv file
00148 @type srv_path: str
00149 """
00150 (package_dir, package) = roslib.packages.get_dir_pkg(srv_path)
00151 (_, spec) = roslib.srvs.load_from_file(srv_path, package)
00152
00153 s = StringIO()
00154 cpp_prefix = '%s::'%(package)
00155 write_begin(s, spec, srv_path)
00156 genmsg_cpp.write_generic_includes(s)
00157 write_generic_includes(s)
00158 genmsg_cpp.write_includes(s, spec.request)
00159 s.write('\n')
00160 genmsg_cpp.write_includes(s, spec.response)
00161
00162 gendeps_dict = roslib.gentools.get_dependencies(spec, spec.package)
00163 md5sum = roslib.gentools.compute_md5(gendeps_dict)
00164
00165 s.write('namespace %s\n{\n'%(package))
00166 genmsg_cpp.write_struct(s, spec.request, cpp_prefix, {'ServerMD5Sum': md5sum})
00167 s.write('\n')
00168 genmsg_cpp.write_struct(s, spec.response, cpp_prefix, {'ServerMD5Sum': md5sum})
00169 s.write('struct %s\n{\n'%(spec.short_name))
00170 s.write('\n')
00171 s.write('typedef %s Request;\n'%(spec.request.short_name))
00172 s.write('typedef %s Response;\n'%(spec.response.short_name))
00173 s.write('Request request;\n')
00174 s.write('Response response;\n\n')
00175 s.write('typedef Request RequestType;\n')
00176 s.write('typedef Response ResponseType;\n')
00177 s.write('}; // struct %s\n'%(spec.short_name))
00178 s.write('} // namespace %s\n\n'%(package))
00179
00180 request_cpp_name = "Request"
00181 response_cpp_name = "Response"
00182 genmsg_cpp.write_traits(s, spec.request, cpp_prefix)
00183 s.write('\n')
00184 genmsg_cpp.write_traits(s, spec.response, cpp_prefix)
00185 genmsg_cpp.write_serialization(s, spec.request, cpp_prefix)
00186 s.write('\n')
00187 genmsg_cpp.write_serialization(s, spec.response, cpp_prefix)
00188
00189 write_traits(s, spec, cpp_prefix)
00190
00191 write_end(s, spec)
00192
00193 output_dir = '%s/srv_gen/cpp/include/%s'%(package_dir, package)
00194 if (not os.path.exists(output_dir)):
00195
00196
00197 try:
00198 os.makedirs(output_dir)
00199 except OSError, e:
00200 pass
00201
00202 f = open('%s/%s.h'%(output_dir, spec.short_name), 'w')
00203 print >> f, s.getvalue()
00204
00205 s.close()
00206
00207 def generate_services(argv):
00208 for arg in argv[1:]:
00209 generate(arg)
00210
00211 if __name__ == "__main__":
00212 roslib.msgs.set_verbose(False)
00213 generate_services(sys.argv)
00214
00215