gensrv_cpp.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # Software License Agreement (BSD License)
00003 #
00004 # Copyright (c) 2009, 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 ## ROS message source code generation for C++
00036 ## 
00037 ## Converts ROS .msg files in a package into C++ source code implementations.
00038 
00039 import msg_gen as genmsg_cpp
00040  
00041 import sys
00042 import os
00043 import traceback
00044 
00045 # roslib.msgs contains the utilities for parsing .msg specifications. It is meant to have no rospy-specific knowledge
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 #Python 2.x
00053 except ImportError:
00054     from io import StringIO #Python 3.x
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         # if we're being run concurrently, the above test can report false but os.makedirs can still fail if
00202         # another copy just created the directory
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     


roscpp
Author(s): Morgan Quigley, Josh Faust, Brian Gerkey, Troy Straszheim
autogenerated on Mon Oct 6 2014 11:46:44