3Utilities for ROS built-in types, and message and service types.
5------------------------------------------------------------------------------
6This file is part of rosros - simple unified interface to ROS1 / ROS2.
7Released under the BSD License.
12------------------------------------------------------------------------------
14## @namespace rosros.api
21if os.getenv("ROS_VERSION") == "2":
29ROS_NUMERIC_TYPES = [
"byte",
"char",
"int8",
"int16",
"int32",
"int64",
"uint8",
30 "uint16",
"uint32",
"uint64",
"float32",
"float64",
"bool"]
33ROS_STRING_TYPES = [
"string",
"wstring"]
36ROS_BUILTIN_TYPES = ROS_NUMERIC_TYPES + ROS_STRING_TYPES
39ROS_BUILTIN_CTORS = {
"byte": int,
"char": int,
"int8": int,
"int16": int,
40 "int32": int,
"int64": int,
"uint8": int,
"uint16": int,
41 "uint32": int,
"uint64": int,
"float32": float,
"float64": float,
42 "bool": bool,
"string": str,
"wstring": str}
45ROS_TIME_TYPES = ros.ROS_TIME_TYPES
48ROS_TIME_CLASSES = ros.ROS_TIME_CLASSES
51ROS_COMMON_TYPES = ROS_BUILTIN_TYPES + ROS_TIME_TYPES
54ROS_ALIAS_TYPES = ros.ROS_ALIAS_TYPES
57PARAM_SEPARATOR = ros.PARAM_SEPARATOR
60PRIVATE_PREFIX = ros.PRIVATE_PREFIX
66ROSLogHandler = ros.ROSLogHandler
70 """Returns "pkg/Type" for "pkg/subdir/Type"."""
71 return ros.canonical(typename)
75 """Returns parameter name with correct separator for ROS version, and leading sigils stripped."""
76 return ros.format_param_name(name)
81 Returns ROS message / service class object.
83 @param msg_or_type full
or canonical
class name,
84 like
"std_msgs/Bool" or "std_srvs/SetBool" or "std_srvs/SetBoolRequest";
85 or class instance like `std_msgs.msg.Bool()`
86 @return ROS message / service
class object, like `std_msgs.msg.Bool`
87 or `std_srvs.srv.SetBool`
or `std_srvs.srv.SetBoolRequest`,
90 return ros.get_message_class(msg_or_type)
95 Returns ROS message or service request/response type definition text.
97 Text will include subtype definitions by default.
99 @param msg_or_type canonical
or full
class name like
"std_msgs/Bool" or
"std_msgs/msg/Bool",
100 or class instance like `std_msgs.msg.Bool()`,
101 or class object like `std_msgs.msg.Bool`
102 @param full include definitions of nested types, separated by
"\n---\nMSG: pkg/Type\n"
103 (ignored
for service request/response types)
104 @return message type definition text
106 return ros.get_message_definition(msg_or_type, full)
111 Returns {field name: field type name} if ROS message
or service request/response,
else {}.
113 @param val ROS message
or service request/response instance,
or class object
115 return ros.get_message_fields(val)
120 Returns message `std_msgs/Header`-attribute if any,
else `
None`.
122 @param val ROS message
or service request/response instance
124 return ros.get_message_header(val)
129 Returns ROS message / service canonical type name, like "std_msgs/Header".
131 Returns
"*" for `AnyMsg`.
133 @param msg_or_cls
class instance like `std_msgs.msg.Bool()`,
134 or class object like `std_msgs.msg.Bool`
135 @return canonical name,
or `
None`
if not ROS message / service
137 return ros.get_message_type(msg_or_cls)
142 Returns ROS message / service type MD5 hash.
144 @param msg_or_type full
or canonical
class name
145 like
"std_msgs/Bool" or "std_srvs/SetBool" or "std_srvs/SetBoolRequest",
146 or class instance like `std_msgs.msg.Bool()`,
147 or class object like `std_msgs.msg.Bool`
149 return ros.get_message_type_hash(msg_or_type)
154 Returns object attribute value, with numeric arrays converted to lists.
156 @param name message attribute name; may also be (nested, path)
or "nested.path"
157 @param default value to
return if attribute does
not exist; raises exception otherwise
159 return ros.get_message_value(msg, name, default)
164 Returns ROS service type definition text.
166 @param srv_or_type canonical
or full
class name
167 like
"std_srvs/SetBool" or "std_srvs/srv/SetBool",
168 or class instance like `std_srvs.srv.SetBool()`,
169 or class object like `std_srvs.srv.SetBool`
170 @return ROS service type definition text
172 return ros.get_service_definition(srv_or_type)
177 Returns ROS service request class object.
179 @param srv_or_type canonical
or full
class name
180 like
"std_srvs/SetBool" or "std_srvs/srv/SetBool",
181 or class instance like `std_srvs.srv.SetBool()`,
182 or class object like `std_srvs.srv.SetBool`
183 @return ROS service request
class object, like `std_srvs.srv.SetBoolRequest`
185 return ros.get_service_request_class(srv_or_type)
190 Returns ROS service response class object.
192 @param srv_or_type canonical
or full
class name
193 like
"std_srvs/SetBool" or "std_srvs/srv/SetBool",
194 or class instance like `std_srvs.srv.SetBool()`,
195 or class object like `std_srvs.srv.SetBool`
196 @return ROS service response
class object, like `std_srvs.srv.SetBoolResponse`
198 return ros.get_service_response_class(srv_or_type)
203 Returns alias like "char" for ROS built-
in type,
if any; reverse of
get_alias_type().
205 In ROS1, byte
and char are aliases
for int8
and uint8;
in ROS2 the reverse.
207 return next((k
for k, v
in ROS_ALIAS_TYPES.items()
if v == typename),
None)
212 Returns ROS built-in type
for alias like
"char",
if any; reverse of
get_type_alias().
214 In ROS1, byte
and char are aliases
for int8
and uint8;
in ROS2 the reverse.
216 return ROS_ALIAS_TYPES.get(typename)
221 Returns whether value is a ROS message
or service request/response
class or instance.
223 @param val like `std_msgs.msg.Bool()`
or `std_srvs.srv.SetBoolRequest`
224 @return True if value
is a ROS message
or service request/response
class or instance,
227 return ros.is_ros_message(val)
231 """Returns whether value is a ROS service class object."""
232 return ros.is_ros_service(val)
236 """Returns whether value is a ROS time/duration class or instance."""
237 return ros.is_ros_time(val)
241 """Returns a ROS duration."""
242 return ros.make_duration(secs=secs, nsecs=nsecs)
246 """Returns a ROS time."""
247 return ros.make_time(secs=secs, nsecs=nsecs)
252 Returns "pkg/msg/Type" for "pkg/Type".
254 @param category type category like
"msg" or "srv"
256 INTER = "/%s/" % category
257 if INTER
in typename
or "/" not in typename
or typename.startswith(
"%s/" % FAMILY):
259 return INTER.join(next((x[0], x[-1])
for x
in [typename.split(
"/")]))
264 Returns ROS message populated from Python dictionary.
266 Raises TypeError on attribute value type mismatch.
268 @param msg_or_type canonical
or full
class name like
"std_msgs/Bool" or
"std_msgs/msg/Bool",
269 or class instance like `std_msgs.msg.Bool()`,
270 or class object like `std_msgs.msg.Bool`
272 msg = get_message_class(msg_or_type) if isinstance(msg_or_type, str)
else msg_or_type
273 msg = msg()
if inspect.isclass(msg)
else msg
274 for name, typename
in ros.get_message_fields(msg).items():
277 v, msgv = dct[name], ros.get_message_value(msg, name)
279 if ros.is_ros_message(msgv):
281 elif isinstance(msgv, (list, tuple)):
282 scalarname = ros.scalar(typename)
283 if scalarname
in ROS_BUILTIN_TYPES:
284 cls = ROS_BUILTIN_CTORS[scalarname]
285 v = [x
if isinstance(x, cls)
else cls(x)
for x
in v]
287 cls = ros.get_message_class(scalarname)
288 v = [x
if ros.is_ros_message(x)
else dict_to_message(x, cls())
for x
in v]
292 setattr(msg, name, v)
298 Returns ROS message as nested Python dictionary.
300 @param replace mapping of {value: replaced value},
301 e.g. {math.nan:
None, math.inf:
None}
303 result = {} if ros.is_ros_message(msg)
else msg
304 for name, typename
in ros.get_message_fields(msg).items():
305 v = ros.get_message_value(msg, name)
306 if ros.is_ros_time(v):
308 elif ros.is_ros_message(v):
310 elif isinstance(v, (list, tuple)):
311 if ros.scalar(typename)
not in ROS_BUILTIN_TYPES:
314 v = [replace.get(x, x)
for x
in v]
316 v = replace.get(v, v)
323 Returns ROS message as an evaluatable string, e.g.
"std_msgs.msg.UInt8(data=0)".
325 @param indent multi-line indentation level to use
if not returning one-liner;
326 as the number of spaces
or the string to indent
with
330 indent =
" " * indent
if isinstance(indent, int)
else indent
or ""
331 sep, start, end = (
",\n",
"\n%s" % indent,
"\n")
if indent
else (
", ",
"",
"")
338 v = v.replace(
"\n", start)
339 elif isinstance(v, bytes):
340 v =
"bytes(%s)" % list(v)
341 elif isinstance(v, list)
and v:
344 nested = indent + nested.replace(
"\n",
"\n%s" % (indent * 2))
345 v =
"[%s%s%s%s]" % (start, nested, end, indent)
348 parts.append(
"%s=%s" % (k, v))
350 return "%s(%s%s%s)" % (name, start, (sep + indent).join(parts), end)
354 """Returns ROS message or service request/response as a serialized binary of `bytes()`."""
355 return ros.serialize_message(msg)
359 """Returns ROS message or service request/response instantiated from serialized binary."""
360 return ros.deserialize_message(raw, cls_or_typename)
365 Returns scalar type from ROS message data type, like
"uint8" from uint8-array.
367 Returns type unchanged
if an ordinary type. In ROS2, returns unbounded type,
368 e.g.
"string" from "string<=10[<=5]".
370 return ros.scalar(typename)
375 Returns "time" or "duration" for time/duration type,
else original value.
377 @param msg_or_type full
or canonical
class name
378 like
"duration" or "builtin_interfaces/Time",
379 or class instance like `rospy.Time()`,
380 or class object like `rclpy.time.Time`
382 typename = msg_or_type
383 if not isinstance(typename, str):
384 cls = msg_or_type
if inspect.isclass(msg_or_type)
else type(msg_or_type)
385 typename = cls.__name__
if issubclass(cls, tuple(ROS_TIME_CLASSES))
else None
386 return msg_or_type
if not typename
else "duration" if "duration" in typename.lower()
else "time"
391 Converts ROS2 time/duration between `rclpy` and `builtin_interfaces` objects.
393 @param val ROS2 time/duration object
from `rclpy`
or `builtin_interfaces`
394 @param to_message whether to convert
from `rclpy` to `builtin_interfaces`
or vice versa
395 @param clock_type ClockType
for converting to `rclpy.Time`, defaults to `ROS_TIME`
396 @return value converted to appropriate type,
or original value
if not convertible
399 return ros2.time_message(val, to_message, clock_type=clock_type)
403 """Returns value as datetime.datetime if value is ROS time/duration, else value."""
404 sec = ros.to_sec(val)
405 return datetime.datetime.fromtimestamp(sec)
if sec
is not val
else val
409 """Returns value as decimal.Decimal if value is ROS time/duration, else value."""
410 if ros.is_ros_time(val)
and not inspect.isclass(val):
411 return decimal.Decimal(
"%d.%09d" % ros.to_sec_nsec(val))
416 """Returns value as ROS duration if convertible (int/float/time/datetime/decimal), else value."""
417 return ros.to_duration(val)
421 """Returns value in nanoseconds if value is ROS time/duration, else value."""
422 return ros.to_nsec(val)
426 """Returns value in seconds if value is ROS time/duration, else value."""
427 return ros.to_sec(val)
431 """Returns value as (seconds, nanoseconds) if value is ROS time/duration, else value."""
432 return ros.to_sec_nsec(val)
436 """Returns value as ROS time if convertible (int/float/duration/datetime/decimal), else value."""
437 return ros.to_time(val)
441 "ROSLogHandler",
"FAMILY",
"PARAM_SEPARATOR",
"PRIVATE_PREFIX",
"ROS_ALIAS_TYPES",
442 "ROS_BUILTIN_CTORS",
"ROS_BUILTIN_TYPES",
"ROS_COMMON_TYPES",
"ROS_NUMERIC_TYPES",
443 "ROS_STRING_TYPES",
"ROS_TIME_CLASSES",
"ROS_TIME_TYPES",
"canonical",
444 "deserialize_message",
"dict_to_message",
"format_param_name",
"get_alias_type",
445 "get_message_class",
"get_message_definition",
"get_message_fields",
446 "get_message_type",
"get_message_type_hash",
"get_message_value",
"get_service_definition",
447 "get_service_request_class",
"get_service_response_class",
"get_type_alias",
"is_ros_message",
448 "is_ros_service",
"is_ros_time",
"make_duration",
"make_full_typename",
"make_time",
449 "message_to_dict",
"scalar",
"serialize_message",
"time_message",
"to_datetime",
"to_decimal",
450 "to_duration",
"to_nsec",
"to_sec",
"to_sec_nsec",
"to_time"
dict_to_message(dct, msg_or_type)
Returns ROS message populated from Python dictionary.
format_param_name(name)
Returns parameter name with correct separator for ROS version, and leading sigils stripped.
get_message_fields(val)
Returns {field name: field type name} if ROS message or service request/response, else {}.
deserialize_message(raw, cls_or_typename)
Returns ROS message or service request/response instantiated from serialized binary.
get_message_header(val)
Returns message `std_msgs/Header`-attribute if any, else `None`.
get_message_value(msg, name, default=...)
Returns object attribute value, with numeric arrays converted to lists.
to_decimal(val)
Returns value as decimal.Decimal if value is ROS time/duration, else value.
is_ros_message(val)
Returns whether value is a ROS message or service request/response class or instance.
canonical(typename)
Returns "pkg/Type" for "pkg/subdir/Type".
time_category(msg_or_type)
Returns "time" or "duration" for time/duration type, else original value.
get_type_alias(typename)
Returns alias like "char" for ROS built-in type, if any; reverse of get_alias_type().
is_ros_service(val)
Returns whether value is a ROS service class object.
get_message_type_hash(msg_or_type)
Returns ROS message / service type MD5 hash.
to_nsec(val)
Returns value in nanoseconds if value is ROS time/duration, else value.
to_sec_nsec(val)
Returns value as (seconds, nanoseconds) if value is ROS time/duration, else value.
scalar(typename)
Returns scalar type from ROS message data type, like "uint8" from uint8-array.
to_time(val)
Returns value as ROS time if convertible (int/float/duration/datetime/decimal), else value.
get_service_request_class(srv_or_type)
Returns ROS service request class object.
get_message_type(msg_or_cls)
Returns ROS message / service canonical type name, like "std_msgs/Header".
to_duration(val)
Returns value as ROS duration if convertible (int/float/time/datetime/decimal), else value.
serialize_message(msg)
Returns ROS message or service request/response as a serialized binary of `bytes()`.
get_message_class(msg_or_type)
Returns ROS message / service class object.
make_full_typename(typename, category="msg")
Returns "pkg/msg/Type" for "pkg/Type".
make_time(secs=0, nsecs=0)
Returns a ROS time.
to_datetime(val)
Returns value as datetime.datetime if value is ROS time/duration, else value.
get_alias_type(typename)
Returns ROS built-in type for alias like "char", if any; reverse of get_type_alias().
message_to_dict(msg, replace=None)
Returns ROS message as nested Python dictionary.
get_message_definition(msg_or_type, full=True)
Returns ROS message or service request/response type definition text.
message_to_str(msg, indent=None)
Returns ROS message as an evaluatable string, e.g.
to_sec(val)
Returns value in seconds if value is ROS time/duration, else value.
get_service_response_class(srv_or_type)
Returns ROS service response class object.
get_service_definition(srv_or_type)
Returns ROS service type definition text.
is_ros_time(val)
Returns whether value is a ROS time/duration class or instance.
time_message(val, to_message=True, clock_type=None)
Converts ROS2 time/duration between `rclpy` and `builtin_interfaces` objects.
make_duration(secs=0, nsecs=0)
Returns a ROS duration.