17 from __future__
import print_function
23 from os.path
import join
as pjoin
29 from genmsg
import SrvSpec, MsgSpec, MsgContext
30 from genmsg.msg_loader
import load_srv_from_file, load_msg_by_type
31 import genmsg.gentools
32 from copy
import deepcopy
35 from cStringIO
import StringIO
37 from io
import StringIO
44 return t
in [
'int8',
'uint8',
'int16',
'uint16']
47 return is_fixnum(t)
or t
in [
'byte',
'char',
'int32',
'uint32',
'int64',
'uint64']
50 return t
in [
'int8',
'int16',
'int32',
'int64']
53 return t
in [
'uint8',
'uint16',
'uint32',
'uint64']
62 return t
in [
'float32',
'float64']
65 return t
in [
'time',
'duration']
68 if f.base_type ==
'Header':
69 return (
'std_msgs',
'Header')
71 return f.base_type.split(
'/')
74 if t
in [
'int8',
'byte',
'bool']:
76 elif t
in [
'uint8',
'char']:
95 return is_fixnum(t)
or is_float(t)
or t
in [
'byte',
'char',
'bool',
'uint8',
'uint16',
'int8',
'int16',
'uint32',
'int32']
98 """Returns the size in bytes of a builtin type if available. Else None""" 99 if t
in [
'int8',
'uint8',
'byte',
'bool',
'char']:
101 elif t
in [
'int16',
'uint16']:
103 elif t
in [
'int32',
'uint32',
'float32']:
105 elif t
in [
'int64',
'uint64',
'float64',
'time',
'duration']:
110 """Return the default value for a message data field""" 112 if not field.array_len:
115 field_copy = deepcopy(field)
116 field_copy.is_array =
False;
118 return 'new Array({}).fill({})'.format(field.array_len, field_default)
119 elif field.is_builtin:
123 return '{secs: 0, nsecs: 0}' 131 (package, msg_type) = field.base_type.split(
'/')
132 if package == current_message_package:
133 return 'new {}()'.format(msg_type)
135 return 'new {}.msg.{}()'.format(package, msg_type)
138 """Check if a particular message specification has a constant size in bytes""" 139 parsed_fields = spec.parsed_fields()
140 types = [f.base_type
for f
in parsed_fields]
141 variableLengthArrays = [f.is_array
and not f.array_len
for f
in parsed_fields]
142 isBuiltin = [f.is_builtin
for f
in parsed_fields]
143 if 'string' in types:
145 elif True in variableLengthArrays:
147 elif False not in isBuiltin:
150 nonBuiltins = [f
for f
in parsed_fields
if not f.is_builtin]
152 for idx, f
in enumerate(nonBuiltins):
153 field_msg_context = MsgContext.create_default()
154 field_spec = genmsg.msg_loader.load_msg_by_type(field_msg_context, f.base_type, search_path)
161 Return the size of a message. 162 If the message does not have a fixed size, returns None 168 for f
in spec.parsed_fields():
171 if type_size
is None:
172 raise Exception(
'Field {} has a non-constant size'.format(f.base_type))
175 elif not f.array_len:
176 raise Exception(
'Array field {} has a variable length'.format(f.base_type))
178 length += (f.array_len * type_size)
180 field_msg_context = MsgContext.create_default()
181 field_spec = genmsg.msg_loader.load_msg_by_type(field_msg_context, f.base_type, search_path)
183 if field_size
is None:
184 raise Exception(
'Field {} has a non-constant size'.format(f.base_type))
199 def write(self, s, indent=True, newline=True):
235 self.writer.inc_indent(self.
inc)
237 self.writer.block_next_indent()
240 self.writer.dec_indent(self.
inc)
243 cmake_path = os.environ[
'CMAKE_PREFIX_PATH']
244 paths = cmake_path.split(
':')
245 for search_path
in paths:
246 test_path = pjoin(search_path, path)
247 if os.path.exists(test_path):
257 for field
in spec.parsed_fields():
258 if not field.is_builtin:
259 (field_type_package, msg_type) = field.base_type.split(
'/')
260 if field_type_package
in found_packages:
263 if field_type_package == spec.package:
264 if msg_type
not in local_deps:
265 local_deps.append(msg_type)
267 found_packages.append(field_type_package)
269 return found_packages, local_deps
272 "Writes the beginning of the file: a comment saying it's auto-generated and the in-package form" 274 s.write(
'// Auto-generated. Do not edit!\n\n', newline=
False)
275 suffix =
'srv' if is_service
else 'msg' 276 s.write(
'// (in-package %s.%s)\n\n'%(spec.package, suffix), newline=
False)
278 def write_requires(s, spec, previous_packages=None, prev_deps=None, isSrv=False):
279 "Writes out the require fields" 280 if previous_packages
is None:
281 s.write(
'"use strict";')
283 s.write(
'const _serializer = _ros_msg_utils.Serialize;')
284 s.write(
'const _arraySerializer = _serializer.Array;');
285 s.write(
'const _deserializer = _ros_msg_utils.Deserialize;')
286 s.write(
'const _arrayDeserializer = _deserializer.Array;');
287 s.write(
'const _finder = _ros_msg_utils.Find;')
288 s.write(
'const _getByteLength = _ros_msg_utils.getByteLength;');
289 previous_packages = {}
290 if prev_deps
is None:
296 local_deps = [dep
for dep
in local_deps
if dep
not in prev_deps]
301 for dep
in local_deps:
303 s.write(
'let {} = require(\'../msg/{}.js\');'.format(dep, dep))
305 s.write(
'let {} = require(\'./{}.js\');'.format(dep, dep))
308 found_packages = {package
for package
in found_packages
if package
not in previous_packages}
309 for package
in found_packages:
313 s.write(
'let {0} = _finder(\'{0}\');'.format(package))
315 s.write(
'//-----------------------------------------------------------')
317 return found_packages, local_deps
320 s.write(
'if (initObj.hasOwnProperty(\'{}\')) {{'.format(field.name))
322 s.write(
'this.{} = initObj.{}'.format(field.name, field.name))
326 s.write(
'this.{} = {};'.format(field.name,
get_default_value(field, spec.package)))
330 s.write(
'class {} {{'.format(spec.actual_name))
333 s.write(
'constructor(initObj={}) {')
335 s.write(
'if (initObj === null) {')
337 s.write(
'// initObj === null is a special case for deserialization where we don\'t initialize fields')
338 for field
in spec.parsed_fields():
339 s.write(
'this.{} = null;'.format(field.name))
343 for field
in spec.parsed_fields():
350 (field_pkg, msg_type) = field.base_type.split(
'/')
354 return '{}.msg.{}'.format(field_pkg, msg_type)
358 s.write(
'static Resolve(msg) {')
360 s.write(
'// deep-construct a valid message object instance of whatever was passed in');
361 s.write(
'if (typeof msg !== \'object\' || msg === null) {')
365 s.write(
'const resolved = new {}(null);'.format(spec.short_name))
366 for field
in spec.parsed_fields():
367 if not field.is_builtin:
368 s.write(
'if (msg.{} !== undefined) {{'.format(field.name))
371 if field.array_len
is None:
372 s.write(
'resolved.{} = new Array(msg.{}.length);'.format(field.name, field.name))
373 s.write(
'for (let i = 0; i < resolved.{}.length; ++i) {{'.format(field.name))
375 s.write(
'resolved.{}[i] = {}.Resolve(msg.{}[i]);'.format(field.name,
get_message_path_from_field(field, spec.package), field.name))
378 s.write(
'resolved.{} = new Array({})'.format(field.name, field.array_len))
379 s.write(
'for (let i = 0; i < resolved.{}.length; ++i) {{'.format(field.name))
381 s.write(
'if (msg.{}.length > i) {{'.format(field.name))
383 s.write(
'resolved.{}[i] = {}.Resolve(msg.{}[i]);'.format(field.name,
get_message_path_from_field(field, spec.package), field.name))
395 s.write(
'resolved.{} = {}'.format(field.name,
get_default_value(field, spec.package)))
398 s.write(
'if (msg.{} !== undefined) {{'.format(field.name))
400 s.write(
'resolved.{} = msg.{};'.format(field.name, field.name))
404 s.write(
'resolved.{} = {}'.format(field.name,
get_default_value(field, spec.package)))
407 s.write(
'return resolved;')
414 s.write(
'module.exports = {};'.format(spec.actual_name))
417 s.write(
'bufferOffset = {};'.format(rest))
421 s.write(
'// Serialize the length for message field [{}]'.format(name))
425 s.write(
'// Check that the constant length array field [{}] has the right length'.format(field.name))
426 s.write(
'if (obj.{}.length !== {}) {{'.format(field.name, field.array_len))
428 s.write(
'throw new Error(\'Unable to serialize array field {} - length must be {}\')'.format(field.name, field.array_len))
434 write_serialize_base(s,
'_arraySerializer.{}(obj.{}, buffer, bufferOffset, {})'.format(f.base_type, f.name,
'null' if f.array_len
is None else f.array_len))
436 write_serialize_base(s,
'_serializer.{}(obj.{}, buffer, bufferOffset)'.format(f.base_type, f.name))
440 (package, msg_type) = f.base_type.split(
'/')
441 samePackage = package == thisPackage
443 if f.array_len
is None:
445 s.write(
'obj.{}.forEach((val) => {{'.format(f.name))
450 write_serialize_base(s,
'{}.msg.{}.serialize(val, buffer, bufferOffset)'.format(package, msg_type))
456 write_serialize_base(s,
'{}.msg.{}.serialize(obj.{}, buffer, bufferOffset)'.format(package, msg_type, f.name))
461 if f.array_len
is not None:
464 s.write(
'// Serialize message field [{}]'.format(f.name))
472 Write the serialize method 475 s.write(
'static serialize(obj, buffer, bufferOffset) {')
477 s.write(
'// Serializes a message object of type {}'.format(spec.short_name))
478 for f
in spec.parsed_fields():
480 s.write(
'return bufferOffset;')
486 s.write(
'// Deserialize array length for message field [{}]'.format(name))
487 s.write(
'len = _deserializer.uint32(buffer, bufferOffset);')
490 (package, msg_type) = f.base_type.split(
'/')
491 samePackage = package == thisPackage
493 if f.array_len
is None:
496 s.write(
'len = {};'.format(f.array_len))
498 s.write(
'data.{} = new Array(len);'.format(f.name))
499 s.write(
'for (let i = 0; i < len; ++i) {')
502 s.write(
'data.{}[i] = {}.deserialize(buffer, bufferOffset)'.format(f.name, msg_type));
504 s.write(
'data.{}[i] = {}.msg.{}.deserialize(buffer, bufferOffset)'.format(f.name, package, msg_type));
508 s.write(
'data.{} = {}.deserialize(buffer, bufferOffset);'.format(f.name, msg_type))
510 s.write(
'data.{} = {}.msg.{}.deserialize(buffer, bufferOffset);'.format(f.name, package, msg_type))
514 s.write(
'data.{} = _arrayDeserializer.{}(buffer, bufferOffset, {})'.format(f.name, f.base_type,
'null' if f.array_len
is None else f.array_len));
516 s.write(
'data.{} = _deserializer.{}(buffer, bufferOffset);'.format(f.name, f.base_type))
520 s.write(
'// Deserialize message field [{}]'.format(f.name))
529 Write the deserialize method 532 s.write(
'static deserialize(buffer, bufferOffset=[0]) {')
534 s.write(
'//deserializes a message object of type {}'.format(spec.short_name))
536 s.write(
'let data = new {}(null);'.format(spec.short_name))
537 for f
in spec.parsed_fields():
540 s.write(
'return data;')
546 Write a static method to determine the buffer size of a complete message 550 s.write(
'static getMessageSize(object) {')
552 if msg_size
is not None:
554 s.write(
'return {};'.format(msg_size))
556 def get_dynamic_field_length_line(field, query):
559 raise Exception(
'Unexpected field {} with type {} has unknown length'.format(field.name, field.base_type))
561 return 'length += 4 + {}.length;'.format(query)
563 (package, msg_type) = field.base_type.split(
'/')
564 samePackage = spec.package == package
566 return 'length += {}.getMessageSize({});'.format(msg_type, query)
568 return 'length += {}.msg.{}.getMessageSize({});'.format(package, msg_type, query)
571 s.write(
'let length = 0;')
574 len_constant_length_fields = 0;
575 for f
in spec.parsed_fields():
580 field_msg_context = MsgContext.create_default()
581 field_spec = genmsg.msg_loader.load_msg_by_type(field_msg_context, f.base_type, search_path)
585 if f.array_len
and field_size
is not None:
586 len_constant_length_fields += (field_size * f.array_len)
588 elif not f.array_len:
589 len_constant_length_fields += 4
592 s.write(
'length += object.{}.length;'.format(f.name))
593 elif field_size
is not None:
594 s.write(
'length += {} * object.{}.length;'.format(field_size, f.name))
598 raise Exception(
'Unexpected field {} with type {} has unknown length'.format(f.name, f.base_type))
600 line_to_write =
'length += 4 + val.length;' 602 (package, msg_type) = f.base_type.split(
'/')
603 samePackage = spec.package == package
605 line_to_write =
'length += {}.getMessageSize(val);'.format(msg_type,)
607 line_to_write =
'length += {}.msg.{}.getMessageSize(val);'.format(package, msg_type)
608 s.write(
'object.{}.forEach((val) => {{'.format(f.name))
610 s.write(line_to_write)
612 elif field_size
is not None:
613 len_constant_length_fields += field_size
618 raise Exception(
'Unexpected field {} with type {} has unknown length'.format(f.name, f.base_type))
620 len_constant_length_fields += 4
621 line_to_write =
'length += object.{}.length;'.format(f.name)
623 (package, msg_type) = f.base_type.split(
'/')
624 samePackage = spec.package == package
626 line_to_write =
'length += {}.getMessageSize(object.{});'.format(msg_type, f.name)
628 line_to_write =
'length += {}.msg.{}.getMessageSize(object.{});'.format(package, msg_type, f.name)
629 s.write(line_to_write)
631 if len_constant_length_fields > 0:
632 s.write(
'return length + {};'.format(len_constant_length_fields))
634 s.write(
'return length;')
639 s.write(
'"use strict";')
641 s.write(
'module.exports = {')
642 msgExists = os.path.exists(pjoin(package_dir,
'msg/_index.js'))
643 srvExists = os.path.exists(pjoin(package_dir,
'srv/_index.js'))
646 s.write(
'msg: require(\'./msg/_index.js\'),')
648 s.write(
'srv: require(\'./srv/_index.js\')')
653 "Writes an index for the messages" 654 s.write(
'"use strict";')
658 s.write(
'let {} = require(\'./{}.js\');'.format(msg, msg))
660 s.write(
'module.exports = {')
663 s.write(
'{}: {},'.format(msg, msg))
668 "Writes an index for the messages" 669 s.write(
'"use strict";')
672 s.write(
'let {} = require(\'./{}.js\')'.format(srv, srv))
674 s.write(
'module.exports = {')
677 s.write(
'{}: {},'.format(srv, srv))
683 s.write(
'static datatype() {')
685 s.write(
'// Returns string type for a %s object'%spec.component_type)
686 s.write(
'return \'{}\';'.format(spec.full_name))
691 md5sum = genmsg.compute_md5(msg_context, parent
or spec)
693 s.write(
'static md5sum() {')
696 s.write(
'//Returns md5sum for a message object')
697 s.write(
'return \'{}\';'.format(md5sum))
703 s.write(
'static messageDefinition() {')
705 s.write(
'// Returns full string definition for message')
706 definition = genmsg.compute_full_text(msg_context, spec)
707 lines = definition.split(
'\n')
710 s.write(
'{}'.format(line))
717 s.write(
'// Constants for message')
718 s.write(
'{}.Constants = {{'.format(spec.short_name))
720 for c
in spec.constants:
722 s.write(
'{}: \'{}\','.format(c.name.upper(), c.val))
724 s.write(
'{}: {},'.format(c.name.upper(),
'true' if c.val
else 'false'))
726 s.write(
'{}: {},'.format(c.name.upper(), c.val))
731 spec.component_type=
'service' 745 s.write(
'module.exports = {')
746 name = spec.short_name
748 s.write(
'Request: {}Request,'.format(name))
749 s.write(
'Response: {}Response,'.format(name))
750 md5sum = genmsg.compute_md5(context, spec)
751 s.write(
'md5sum() {{ return \'{}\'; }},'.format(md5sum))
752 s.write(
'datatype() {{ return \'{}\'; }}'.format(spec.full_name))
758 Generate javascript code for all messages in a package 760 msg_context = MsgContext.create_default()
762 f = os.path.abspath(f)
763 infile = os.path.basename(f)
764 full_type = genmsg.gentools.compute_full_type_name(pkg, infile)
765 spec = genmsg.msg_loader.load_msg_from_file(msg_context, f, full_type)
770 Generate javascript code for all services in a package 772 msg_context = MsgContext.create_default()
774 f = os.path.abspath(f)
775 infile = os.path.basename(f)
776 full_type = genmsg.gentools.compute_full_type_name(pkg, infile)
777 spec = genmsg.msg_loader.load_srv_from_file(msg_context, f, full_type)
781 dir_list = search_path[pkg]
784 files.extend([f
for f
in os.listdir(d)
if f.endswith(ext)])
785 return [f[:-len(ext)]
for f
in files]
791 @param msg_path: The path to the .msg file 794 genmsg.msg_loader.load_depends(msg_context, spec, search_path)
795 spec.actual_name=spec.short_name
796 spec.component_type=
'message' 797 msgs =
msg_list(package, search_path,
'.msg')
799 genmsg.load_msg_by_type(msg_context,
'%s/%s'%(package, m), search_path)
819 if (
not os.path.exists(output_dir)):
823 os.makedirs(output_dir)
827 with open(
'%s/%s.js'%(output_dir, spec.short_name),
'w')
as f:
828 f.write(io.getvalue() +
"\n")
839 with open(
'{}/_index.js'.format(output_dir),
'w')
as f:
840 f.write(io.getvalue())
850 package_dir = os.path.dirname(output_dir)
852 with open(
'{}/_index.js'.format(package_dir),
'w')
as f:
853 f.write(io.getvalue())
858 "Generate code from .srv file" 859 genmsg.msg_loader.load_depends(msg_context, spec, search_path)
861 srv_path = os.path.dirname(path)
862 srvs =
msg_list(package, {package: [srv_path]}, ext)
864 load_srv_from_file(msg_context,
'%s/%s%s'%(srv_path, srv, ext),
'%s/%s'%(package, srv))
873 found_packages,local_deps =
write_requires(s, spec.request,
None,
None,
True)
874 write_requires(s, spec.response, found_packages, local_deps,
True)
875 spec.request.actual_name=
'%sRequest'%spec.short_name
876 spec.response.actual_name=
'%sResponse'%spec.short_name
881 with open(
'%s/%s.js'%(output_dir, spec.short_name),
'w')
as f:
882 f.write(io.getvalue())
893 with open(
'{}/_index.js'.format(output_dir),
'w')
as f:
894 f.write(io.getvalue())
904 package_dir = os.path.dirname(output_dir)
906 with open(
'{}/_index.js'.format(package_dir),
'w')
as f:
907 f.write(io.getvalue())
def write_serialize(s, spec)
def write_serialize_complex(s, f, thisPackage)
def write_deserialize_builtin(s, f)
def write_deserialize_complex(s, f, thisPackage)
def write(self, s, indent=True, newline=True)
def get_message_path_from_field(field, pkg)
def is_message_fixed_size(spec, search_path)
def write_serialize_base(s, rest)
def get_default_value(field, current_message_package)
def find_path_for_package(package)
def write_resolve(s, spec)
def generate_msg_from_spec(msg_context, spec, search_path, output_dir, package, msgs=None)
def write_package_index(s, package_dir)
def is_fixnum(t)
Built in types.
def write_srv_end(s, context, spec)
def write_srv_component(s, spec, context, parent, search_path)
def msg_list(pkg, search_path, ext)
def find_path_from_cmake_path(path)
def write_get_message_size(s, spec, search_path)
def write_serialize_builtin(s, f)
def get_message_fixed_size(spec, search_path)
def write_md5sum(s, msg_context, spec, parent=None)
def write_constants(s, spec)
def write_deserialize(s, spec)
def write_serialize_length(s, name)
def inc_indent(self, inc=2)
def dec_indent(self, dec=2)
def write_requires(s, spec, previous_packages=None, prev_deps=None, isSrv=False)
def write_serialize_field(s, f, package)
def generate_srv_from_spec(msg_context, spec, search_path, output_dir, package, path)
def write_ros_datatype(s, spec)
def write_msg_constructor_field(s, spec, field)
def generate_srv(pkg, files, out_dir, search_path)
def write_message_definition(s, msg_context, spec)
def __init__(self, w, inc=2, indent_first=True)
def block_next_indent(self)
def write_deserialize_field(s, f, package)
def write_deserialize_length(s, name)
def generate_msg(pkg, files, out_dir, search_path)
def write_msg_index(s, msgs, pkg, context)
def write_serialize_length_check(s, field)
def __exit__(self, type, val, traceback)
def write_begin(s, spec, is_service=False)
def write_srv_index(s, srvs, pkg)