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