wip genmsg_lisp
This commit is contained in:
parent
2544bd8416
commit
a459e5c24c
|
@ -143,3 +143,9 @@ tutorials/rospy_tutorials/srv/lisp
|
||||||
util/rosthread/build
|
util/rosthread/build
|
||||||
.build_version
|
.build_version
|
||||||
.rosgcov_files
|
.rosgcov_files
|
||||||
|
3rdparty/gtest/gtest
|
||||||
|
/core/genmsg_cpp/genmsg_java
|
||||||
|
/core/genmsg_cpp/genmsg_oct
|
||||||
|
/core/genmsg_cpp/gensrv_java
|
||||||
|
/core/genmsg_cpp/gensrv_oct
|
||||||
|
/core/roslib/src/roslib
|
||||||
|
|
|
@ -48,18 +48,57 @@ import roslib.gentools
|
||||||
|
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
|
|
||||||
MSG_TYPE_TO_CPP = {'byte': 'int8_t', 'char': 'uint8_t',
|
############################################################
|
||||||
'bool': 'uint8_t',
|
# Built in types
|
||||||
'uint8': 'uint8_t', 'int8': 'int8_t',
|
############################################################
|
||||||
'uint16': 'uint16_t', 'int16': 'int16_t',
|
|
||||||
'uint32': 'uint32_t', 'int32': 'int32_t',
|
|
||||||
'uint64': 'uint64_t', 'int64': 'int64_t',
|
|
||||||
'float32': 'float',
|
|
||||||
'float64': 'double',
|
|
||||||
'string': 'std::basic_string<char, std::char_traits<char>, typename ContainerAllocator::template rebind<char>::other > ',
|
|
||||||
'time': 'ros::Time',
|
|
||||||
'duration': 'ros::Duration'}
|
|
||||||
|
|
||||||
|
def is_fixnum(t):
|
||||||
|
return t in ['char', 'byte', 'int8', 'uint8', 'int16', 'uint16']
|
||||||
|
|
||||||
|
def is_integer(t):
|
||||||
|
return is_fixnum(t) or t in ['int32', 'uint32', 'int64', 'uint64']
|
||||||
|
|
||||||
|
def is_bool(t):
|
||||||
|
return t == 'bool'
|
||||||
|
|
||||||
|
def is_string(t):
|
||||||
|
return t == 'string'
|
||||||
|
|
||||||
|
def is_float(t):
|
||||||
|
return t in ['float16', 'float32', 'float64']
|
||||||
|
|
||||||
|
def is_time(t):
|
||||||
|
return t in ['time', 'duration']
|
||||||
|
|
||||||
|
def lisp_type(t):
|
||||||
|
if is_fixnum(t):
|
||||||
|
return 'fixnum'
|
||||||
|
elif is_integer(t):
|
||||||
|
return 'integer'
|
||||||
|
elif is_bool(t):
|
||||||
|
return 'boolean'
|
||||||
|
elif is_float(t):
|
||||||
|
return 'float'
|
||||||
|
elif is_time(t):
|
||||||
|
return 'real'
|
||||||
|
elif is_string(t):
|
||||||
|
return 'string'
|
||||||
|
else:
|
||||||
|
raise ValueError('%s is not a recognized primitive type'%t)
|
||||||
|
|
||||||
|
def lisp_initform(t):
|
||||||
|
if is_integer(t):
|
||||||
|
return '0'
|
||||||
|
elif is_bool(t):
|
||||||
|
return 'nil'
|
||||||
|
elif is_float(t):
|
||||||
|
return '0.0'
|
||||||
|
elif is_time(t):
|
||||||
|
return 0
|
||||||
|
elif is_string(t):
|
||||||
|
return '\"\"'
|
||||||
|
|
||||||
|
# todo remove
|
||||||
def msg_type_to_cpp(type):
|
def msg_type_to_cpp(type):
|
||||||
"""
|
"""
|
||||||
Converts a message type (e.g. uint32, std_msgs/String, etc.) into the C++ declaration
|
Converts a message type (e.g. uint32, std_msgs/String, etc.) into the C++ declaration
|
||||||
|
@ -92,24 +131,6 @@ def msg_type_to_cpp(type):
|
||||||
else:
|
else:
|
||||||
return cpp_type
|
return cpp_type
|
||||||
|
|
||||||
def cpp_message_declarations(name_prefix, msg):
|
|
||||||
"""
|
|
||||||
Returns the different possible C++ declarations for a message given the message itself.
|
|
||||||
|
|
||||||
@param name_prefix: The C++ prefix to be prepended to the name, e.g. "std_msgs::"
|
|
||||||
@type name_prefix: str
|
|
||||||
@param msg: The message type
|
|
||||||
@type msg: str
|
|
||||||
@return: A tuple of 3 different names. cpp_message_decelarations("std_msgs::", "String") returns the tuple
|
|
||||||
("std_msgs::String_", "std_msgs::String_<ContainerAllocator>", "std_msgs::String")
|
|
||||||
@rtype: str
|
|
||||||
"""
|
|
||||||
pkg, basetype = roslib.names.package_resource_name(msg)
|
|
||||||
cpp_name = '%s%s'%(name_prefix, msg)
|
|
||||||
if (pkg):
|
|
||||||
cpp_name = '%s::%s'%(pkg, basetype)
|
|
||||||
return ('%s_'%(cpp_name), '%s_<ContainerAllocator> '%(cpp_name), '%s'%(cpp_name))
|
|
||||||
|
|
||||||
def write_begin(s, spec, path):
|
def write_begin(s, spec, path):
|
||||||
"""
|
"""
|
||||||
Writes the beginning of the file: a comment saying it's auto-generated and the in-package form
|
Writes the beginning of the file: a comment saying it's auto-generated and the in-package form
|
||||||
|
@ -121,8 +142,20 @@ def write_begin(s, spec, path):
|
||||||
@param path: The file this message is being generated for
|
@param path: The file this message is being generated for
|
||||||
@type path: str
|
@type path: str
|
||||||
"""
|
"""
|
||||||
s.write(';; Auto-generated by genmsg_lisp for file %s\n'%path)
|
s.write('; Auto-generated. Do not edit!\n\n\n')
|
||||||
s.write('(in-package %s-msg)\n\n'%spec.package)
|
s.write('(in-package %s-msg)\n\n\n'%spec.package)
|
||||||
|
s.write(';//! \\htmlinclude %s.msg.html\n\n'%spec.short_name) # Can get rid of this
|
||||||
|
|
||||||
|
def write_slot_definition(s, field):
|
||||||
|
"""
|
||||||
|
Write the definition of a slot corresponding to a single message field
|
||||||
|
"""
|
||||||
|
s.write('(%s\n '%field.name)
|
||||||
|
s.write(':reader %s-val\n '%field.name)
|
||||||
|
s.write(':initarg :%s\n '%field.name)
|
||||||
|
s.write(':type %s\n '%lisp_type(field.type))
|
||||||
|
s.write(':initform %s)'%lisp_initform(field.type))
|
||||||
|
|
||||||
|
|
||||||
def write_defclass(s, spec):
|
def write_defclass(s, spec):
|
||||||
"""
|
"""
|
||||||
|
@ -134,6 +167,14 @@ def write_defclass(s, spec):
|
||||||
@type spec: roslib.msgs.MsgSpec
|
@type spec: roslib.msgs.MsgSpec
|
||||||
"""
|
"""
|
||||||
s.write('(defclass %s (ros-message)\n ('%message_class(spec))
|
s.write('(defclass %s (ros-message)\n ('%message_class(spec))
|
||||||
|
first_field = True
|
||||||
|
for field in spec.parsed_fields():
|
||||||
|
# Can get rid of this first_field stuff
|
||||||
|
if not first_field:
|
||||||
|
s.write('\n ')
|
||||||
|
first_field = False
|
||||||
|
write_slot_definition(s, field)
|
||||||
|
s.write(')\n)\n')
|
||||||
|
|
||||||
|
|
||||||
def message_class(spec):
|
def message_class(spec):
|
||||||
|
@ -691,6 +732,87 @@ def write_ostream_operator(s, spec, cpp_name_prefix):
|
||||||
s.write('template<typename ContainerAllocator>\nstd::ostream& operator<<(std::ostream& s, const %s& v)\n{\n'%(cpp_msg_with_alloc))
|
s.write('template<typename ContainerAllocator>\nstd::ostream& operator<<(std::ostream& s, const %s& v)\n{\n'%(cpp_msg_with_alloc))
|
||||||
s.write(' ros::message_operations::Printer<%s>::stream(s, "", v);\n return s;}\n\n'%(cpp_msg_with_alloc))
|
s.write(' ros::message_operations::Printer<%s>::stream(s, "", v);\n return s;}\n\n'%(cpp_msg_with_alloc))
|
||||||
|
|
||||||
|
def write_serialize_length(s, v):
|
||||||
|
s.write(' (let ((__ros_str_len (length %s)))'%v)
|
||||||
|
for x in range(0, 32, 8):
|
||||||
|
s.write('\n (write-byte (ldb (byte 8 %s) __ros_str_len) ostream)'%x)
|
||||||
|
s.write(')\n')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def write_serialize_builtin(s, f):
|
||||||
|
if f.type == 'string':
|
||||||
|
v = '(slot-value msg \'%s)'%f.name
|
||||||
|
write_serialize_length(s, v)
|
||||||
|
s.write(' (map nil #\'(lambda (c) (write-byte (char-code c) ostream)) %s)\n'%v)
|
||||||
|
|
||||||
|
|
||||||
|
def write_serialize(s, spec):
|
||||||
|
"""
|
||||||
|
Write the serialize method
|
||||||
|
"""
|
||||||
|
s.write('(defmethod serialize ((msg %s) ostream)\n'%message_class(spec))
|
||||||
|
s.write(' "Serializes a message object of type \'%s"\n'%message_class(spec))
|
||||||
|
for field in spec.parsed_fields():
|
||||||
|
if field.is_array:
|
||||||
|
pass # todo
|
||||||
|
else:
|
||||||
|
if field.is_builtin:
|
||||||
|
write_serialize_builtin(s, field)
|
||||||
|
else:
|
||||||
|
pass # todo
|
||||||
|
|
||||||
|
def write_deserialize_length(s):
|
||||||
|
s.write(' (let ((__ros_str_len 0))')
|
||||||
|
for x in range(0, 32, 8):
|
||||||
|
s.write('\n (setf (ldb (byte 8 %s) __ros_str_len) (read-byte istream))'%x)
|
||||||
|
|
||||||
|
def write_deserialize_builtin(s, f):
|
||||||
|
if f.type == 'string':
|
||||||
|
v = '(slot-value msg \'%s)'%f.name
|
||||||
|
write_deserialize_length(s)
|
||||||
|
s.write('\n (setf %s (make-string __ros_str_len))'%v)
|
||||||
|
s.write('\n (dotimes (__ros_str_idx __ros_str_len msg)')
|
||||||
|
s.write('\n (setf (char %s __ros_str_idx) (code-char (read-byte istream)))))\n'%v)
|
||||||
|
|
||||||
|
|
||||||
|
def write_deserialize(s, spec):
|
||||||
|
"""
|
||||||
|
Write the deserialize method
|
||||||
|
"""
|
||||||
|
s.write('(defmethod deserialize ((msg %s) istream)\n'%message_class(spec))
|
||||||
|
s.write(' "Deserializes a message object of type \'%s"\n'%message_class(spec))
|
||||||
|
for field in spec.parsed_fields():
|
||||||
|
if field.is_array:
|
||||||
|
pass # todo
|
||||||
|
else:
|
||||||
|
if field.is_builtin:
|
||||||
|
write_deserialize_builtin(s, field)
|
||||||
|
else:
|
||||||
|
pass # todo
|
||||||
|
s.write(' msg\n)\n')
|
||||||
|
|
||||||
|
def write_ros_datatype(s, spec):
|
||||||
|
c = message_class(spec)
|
||||||
|
s.write('(defmethod ros-datatype ((msg (eql \'%s)))\n'%c)
|
||||||
|
s.write(' "Returns string type for a message object of type \'%s"\n'%c)
|
||||||
|
s.write(' "%s")\n'%spec.full_name)
|
||||||
|
|
||||||
|
def write_md5sum(s, spec):
|
||||||
|
gendeps_dict = roslib.gentools.get_dependencies(spec, spec.package,
|
||||||
|
compute_files=False)
|
||||||
|
md5sum = roslib.gentools.compute_md5(gendeps_dict)
|
||||||
|
c = message_class(spec)
|
||||||
|
s.write('(defmethod md5sum ((type (eql \'%s)))\n'%c)
|
||||||
|
s.write(' "Returns md5sum for a message object of type \'%s"\n'%c)
|
||||||
|
s.write(' "%s")\n'%md5sum)
|
||||||
|
|
||||||
|
def write_message_definition(s, spec):
|
||||||
|
c = message_class(spec)
|
||||||
|
s.write('(defmethod message-definition ((type (eql \'%s)))\n'%c)
|
||||||
|
s.write(' "Returns full string definition for a message object of type \'%s"\n'%c)
|
||||||
|
|
||||||
|
|
||||||
def generate(msg_path):
|
def generate(msg_path):
|
||||||
"""
|
"""
|
||||||
Generate a message
|
Generate a message
|
||||||
|
@ -703,12 +825,12 @@ def generate(msg_path):
|
||||||
|
|
||||||
s = StringIO()
|
s = StringIO()
|
||||||
write_begin(s, spec, msg_path)
|
write_begin(s, spec, msg_path)
|
||||||
|
|
||||||
write_defclass(s, spec)
|
write_defclass(s, spec)
|
||||||
|
write_serialize(s, spec)
|
||||||
write_constant_definitions(s, spec)
|
write_deserialize(s, spec)
|
||||||
s.write('} // namespace %s\n\n'%(package))
|
write_ros_datatype(s, spec)
|
||||||
|
write_md5sum(s, spec)
|
||||||
|
write_message_definition(s, spec)
|
||||||
|
|
||||||
output_dir = '%s/msg_gen/lisp'%package_dir
|
output_dir = '%s/msg_gen/lisp'%package_dir
|
||||||
if (not os.path.exists(output_dir)):
|
if (not os.path.exists(output_dir)):
|
||||||
|
@ -724,11 +846,7 @@ def generate(msg_path):
|
||||||
|
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
def generate_messages(argv):
|
|
||||||
for arg in argv[1:]:
|
|
||||||
generate(arg)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
roslib.msgs.set_verbose(True)
|
roslib.msgs.set_verbose(True)
|
||||||
generate_messages(sys.argv)
|
generate(sys.argv[1])
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
PKG=`rospack find $1`
|
||||||
|
FILENAME=$PKG/msg/$2.msg
|
||||||
|
echo "Running original genmsg_lisp on $FILENAME"
|
||||||
|
rosrun genmsg_cpp genmsg_lisp $FILENAME
|
||||||
|
echo "Running new genmsg_lisp.py"
|
||||||
|
rosrun roslisp genmsg_lisp.py $FILENAME
|
||||||
|
echo "Checking diffs"
|
||||||
|
diff $PKG/msg/lisp/$1/$2.lisp $PKG/msg_gen/lisp/$2.lisp | head -n 10
|
Loading…
Reference in New Issue