2Patches ROS1 classes with ROS2-compatible members, and vice versa.
4------------------------------------------------------------------------------
5This file is part of rosros - simple unified interface to ROS1 / ROS2.
6Released under the BSD License.
11------------------------------------------------------------------------------
13## @namespace rosros.patch
22rospy = rclpy = ros = None
23if os.getenv("ROS_VERSION") != "2":
27 from . rclify.clock
import Clock, ClockType
28 from .
import ros1
as ros
32 import rclpy.publisher
34 import rclpy.subscription
37 from rclpy.clock
import ClockType
39 from .
import ros2
as ros
40 from . rospify
import AnyMsg
57 """Patches ROS1 classes with generic compatibility with ROS2 and rosros."""
61 rospy.Publisher.publish = Publisher__publish
63 rospy.Service.__init__ = Service__init
65 rospy.ServiceProxy.call = ServiceProxy__call
66 rospy.ServiceProxy.call_async = ServiceProxy__call_async
67 rospy.ServiceProxy.wait_for_service = ServiceProxy__wait_for_service
68 rospy.ServiceProxy.service_is_ready = ServiceProxy__service_is_ready
70 rospy.Subscriber.__init__ = Subscriber__init
71 rospy.topics._SubscriberImpl.receive_callback = SubscriberImpl__receive_callback
77 """Patches ROS1 classes with full stand-ins for ROS2 methods and properties."""
80 if PATCHED_FULL:
return
82 rospy.ServiceProxy.destroy = rospy.ServiceProxy.close
83 rospy.ServiceProxy.remove_pending_request = ServiceProxy__remove_pending_request
85 rospy.Service.destroy = rospy.Service.shutdown
87 rospy.Publisher.topic_name = property(
lambda self: self.name)
88 rospy.Publisher.assert_liveliness = Publisher__assert_liveliness
89 rospy.Publisher.destroy = rospy.Publisher.unregister
90 rospy.Publisher.get_subscription_count = rospy.Publisher.get_num_connections
92 rospy.Subscriber.topic_name = property(
lambda self: self.name)
93 rospy.Subscriber.destroy = rospy.Subscriber.unregister
95 rospy.Time.__init__ = Time__init
96 rospy.Time.__del__ = Time__del
97 rospy.Time.nanoseconds = property(rospy.Duration.to_nsec)
98 rospy.Time.clock_type = property(Time__clock_type)
99 rospy.Time.seconds_nanoseconds = Time__seconds_nanoseconds
100 rospy.Time.to_msg = Temporal__to_msg
101 rospy.Time.from_msg = Time__from_msg
103 rospy.Duration.__init__ = Duration__init
104 rospy.Duration.nanoseconds = property(rospy.Duration.to_nsec)
105 rospy.Duration.to_msg = Temporal__to_msg
106 rospy.Duration.from_msg = Duration__from_msg
108 rospy.Rate.destroy =
lambda self:
None
110 rospy.Timer.__init__ = Timer__init
111 rospy.Timer.run = Timer__run
112 rospy.Timer.cancel = Timer__cancel
113 rospy.Timer.reset = Timer__reset
114 rospy.Timer.shutdown = Timer__shutdown
115 rospy.Timer.destroy = Timer__shutdown
116 rospy.Timer.is_canceled = Timer__is_canceled
117 rospy.Timer.is_ready = Timer__is_ready
118 rospy.Timer.time_since_last_call = Timer__time_since_last_call
119 rospy.Timer.time_until_next_call = Timer__time_until_next_call
120 rospy.Timer.clock = property(Timer__clock)
121 rospy.Timer.timer_period_ns = property(Timer__timer_period_ns,
122 Timer__timer_period_ns__setter)
128 """Patches ROS2 classes with full stand-ins for ROS1 methods and properties."""
129 global PATCHED, PATCHED_FULL
134 rclpy.client.Client.__call__ = rclpy.client.Client.call
135 rclpy.client.Client.close = rclpy.client.Client.destroy
136 rclpy.client.Client.service_class = property(
lambda self: self.srv_type)
137 rclpy.client.Client.request_class = property(
lambda self: self.srv_type.Request)
138 rclpy.client.Client.response_class = property(
lambda self: self.srv_type.Response)
139 rclpy.client.Client.resolved_name = property(
lambda self: self.srv_name)
141 rclpy.publisher.Publisher.publish =
publish_wrapper(rclpy.publisher.Publisher.publish)
142 rclpy.publisher.Publisher.get_num_connections = rclpy.publisher.Publisher.get_subscription_count
143 rclpy.publisher.Publisher.unregister = rclpy.publisher.Publisher.destroy
144 rclpy.publisher.Publisher.resolved_name = rclpy.publisher.Publisher.topic_name
145 rclpy.publisher.Publisher.name = property(
lambda self: self.topic)
146 rclpy.publisher.Publisher.data_class = property(
lambda self: self.msg_type)
147 rclpy.publisher.Publisher.type = property(
lambda self: ros.get_message_type(self.msg_type))
148 rclpy.publisher.Publisher.md5sum = property(
lambda self: ros.get_message_type_hash(self.msg_type))
150 rclpy.service.Service.__init__ = Service__init
151 rclpy.service.Service.spin = Service__spin
152 rclpy.service.Service.shutdown = rclpy.service.Service.destroy
153 rclpy.service.Service.service_class = property(
lambda self: self.srv_type)
154 rclpy.service.Service.request_class = property(
lambda self: self.srv_type.Request)
155 rclpy.service.Service.response_class = property(
lambda self: self.srv_type.Response)
156 rclpy.service.Service.resolved_name = property(
lambda self: self.srv_name)
158 rclpy.subscription.Subscription.__init__ = Subscription__init
159 rclpy.subscription.Subscription.get_num_connections =
lambda self: 0
160 rclpy.subscription.Subscription.unregister = rclpy.subscription.Subscription.destroy
161 rclpy.subscription.Subscription.resolved_name = rclpy.subscription.Subscription.topic_name
162 rclpy.subscription.Subscription.name = property(
lambda self: self.topic)
163 rclpy.subscription.Subscription.data_class = property(
lambda self: self.msg_type)
164 rclpy.subscription.Subscription.type = property(
lambda self: ros.get_message_type(self.msg_type))
165 rclpy.subscription.Subscription.md5sum = property(
lambda self: ros.get_message_type_hash(self.msg_type))
166 rclpy.subscription.Subscription.callback_args = property(Subscription__callback_args)
167 rclpy.subscription.Subscription._invoke_callbacks = Subscription__invoke_callbacks
169 rclpy.duration.Duration.__init__ = Duration__init
170 rclpy.duration.Duration.__abs__ = Duration__abs
171 rclpy.duration.Duration.__neg__ = Duration__neg
172 rclpy.duration.Duration.__add__ = Duration__add
173 rclpy.duration.Duration.__radd__ = Duration__add
174 rclpy.duration.Duration.__sub__ = Duration__sub
175 rclpy.duration.Duration.__mul__ = Duration__mul
176 rclpy.duration.Duration.__rmul__ = Duration__mul
177 rclpy.duration.Duration.__floordiv__ = Duration__floordiv
178 rclpy.duration.Duration.__truediv__ = Duration__truediv
179 rclpy.duration.Duration.__mod__ = Duration__mod
180 rclpy.duration.Duration.__divmod__ = Duration__divmod
181 rclpy.duration.Duration.__bool__ = TVal__is_nonzero
182 rclpy.duration.Duration.is_zero = TVal__is_zero
183 rclpy.duration.Duration.to_sec = TVal__to_sec
184 rclpy.duration.Duration.to_nsec = TVal__to_nsec
185 rclpy.duration.Duration.secs = property(TVal__secs)
186 rclpy.duration.Duration.nsecs = property(TVal__nsecs)
188 rclpy.time.Time.__init__ = Time__init
189 rclpy.time.Time.__bool__ = TVal__is_nonzero
190 rclpy.time.Time.is_zero = TVal__is_zero
191 rclpy.time.Time.to_sec = TVal__to_sec
192 rclpy.time.Time.to_nsec = TVal__to_nsec
193 rclpy.time.Time.secs = property(TVal__secs)
194 rclpy.time.Time.nsecs = property(TVal__nsecs)
196 rclpy.timer.Rate.remaining = Rate__remaining
198 rclpy.timer.Timer.shutdown = rclpy.timer.Timer.destroy
199 rclpy.timer.Timer.ident = property(Timer__ident)
200 rclpy.timer.Timer.native_id = property(Timer__ident)
201 rclpy.timer.Timer.getName = Timer__getName
202 rclpy.timer.Timer.setName = Timer__setName
203 rclpy.timer.Timer.name = property(Timer__getName, Timer__setName)
204 rclpy.timer.Timer.isDaemon = Timer__isDaemon
205 rclpy.timer.Timer.setDaemon = Timer__setDaemon
206 rclpy.timer.Timer.daemon = property(Timer__isDaemon, Timer__setDaemon)
207 rclpy.timer.Timer.join = Timer__join
208 rclpy.timer.Timer.is_alive = Timer__is_alive
209 rclpy.timer.Timer.isAlive = Timer__is_alive
212 PATCHED = PATCHED_FULL =
True
216 """Sets value for object patched attribute."""
217 if hasattr(obj, name):
218 setattr(obj, name, value)
220 EXTRA_ATTRS.setdefault(id(obj), {})[name] = value
226 """Returns service serve-function wrapped to ensure return with response instance."""
229 return {}
if resp
is None else resp
230 return functools.update_wrapper(inner, serve)
234 """Does nothing (ROS2 compatibility stand-in)."""
237 ROS1_Publisher__publish = rospy.Publisher.publish
240 """Publishes message, supports giving message field values as dictionary in args[0]."""
241 attributes = functools.partial(ros.get_message_fields, self.data_class)
242 msg = util.ensure_object(self.data_class, attributes, api.dict_to_message, *args, **kwds)
246 ROS1_Service__init = rospy.Service.__init__
248 def Service__init(self, name, service_class, handler, buff_size=65536, error_handler=None):
249 """Wraps Service.__init__() to support returning None from server callback."""
254 ROS1_ServiceProxy__call = rospy.ServiceProxy.call
257 """Calls the service, supports giving request field values as dictionary in args[0]."""
258 reqcls = self.request_class
259 attributes = functools.partial(ros.get_message_fields, reqcls)
260 req = util.ensure_object(reqcls, attributes, api.dict_to_message, *args, **kwargs)
265 Make a service request and asyncronously get the result.
267 Service
is invoked
in a background thread.
269 This accepts either a request message instance,
270 or positional
and keyword arguments to create a new request instance.
272 @return `concurrent.futures.Future`-conforming interface that completes when request does
274 reqcls = self.request_class
275 attributes = functools.partial(ros.get_message_fields, reqcls)
276 req = util.ensure_object(reqcls, attributes, api.dict_to_message, *args, **kwargs)
277 return util.start_future(self.call, req)
281 Does nothing (ROS2 compatibility stand-in).
283 @param future ignored (ROS2 compatibility stand-
in)
288 Returns whether service is ready.
290 Provides rospy.ServiceProxy
with service_is_ready() like rclpy.client.Client has.
292 @return True if a server
is ready,
False otherwise
295 return self.wait_for_service(1E-3)
299 Waits for a service server to become ready.
301 Returns
as soon
as a server becomes ready
or if the timeout expires.
303 Gives rospy.ServiceProxy.wait_for_service the behavior of
304 rclpy.client.Client.wait_for_service.
306 @param timeout time to wait,
as seconds
or ROS Duration. If
None, then wait forever.
307 @param timeout_sec seconds to wait;
if None, wait forever (ROS2 compatibility stand-
in)
308 @return True if server became ready
or False on a timeout
310 if timeout_sec
is not None: timeout = timeout_sec
312 rospy.wait_for_service(self.resolved_name, ros.to_nsec(timeout))
313 except rospy.ROSInterruptException:
raise
314 except rospy.ROSException:
318 ROS1_Subscriber__init = rospy.Subscriber.__init__
319 ROS1_SubscriberImpl__receive_callback = rospy.topics._SubscriberImpl.receive_callback
321 def Subscriber__init(self, name, data_class, callback=None, callback_args=None,
322 queue_size=None, buff_size=65536, tcp_nodelay=False):
323 """Wraps rospy.Subscriber.__init__() to add raw bytes autoconversion support."""
325 queue_size, buff_size, tcp_nodelay)
326 self._anymsg = issubclass(data_class, rospy.AnyMsg)
327 self.impl._interface = self
330 """Wraps rospy.topics.SubscriberImpl.receive_callback() with raw bytes autoconversion."""
331 if not self._interface._anymsg
and issubclass(self.data_class, rospy.AnyMsg):
332 msgs = [x._buff
for x
in msgs]
336 ROS1_Duration__init = rospy.Duration.__init__
338 def Duration__init(self, secs=0, nsecs=0, *, seconds=0, nanoseconds=0):
339 """Constructs a new `Duration`, using either ROS1 or ROS2 arguments."""
340 if secs
or nsecs: seconds, nanoseconds = secs, nsecs
344 """Returns a new Time or Duration from this."""
345 return type(self)(self.secs, self.nsecs)
349 """Returns a new Duration from given."""
350 return cls(msg.secs, msg.nsecs)
353 ROS1_Time__init = rospy.Time.__init__
355 def Time__init(self, secs=0, nsecs=0, *, seconds=0, nanoseconds=0,
356 clock_type=ClockType.SYSTEM_TIME):
357 """Constructs a new ROS1 `Time`, using either ROS1 or ROS2 arguments."""
358 if secs
or nsecs: seconds, nanoseconds = secs, nsecs
361 if clock_type != ClockType.SYSTEM_TIME:
362 EXTRA_ATTRS.setdefault(id(self), {})[
"_clock_type"] = clock_type
365 """Clear object-related data, if any."""
366 EXTRA_ATTRS.pop(id(self),
None)
369 """Returns time as (seconds, nanoseconds)."""
370 return (self.secs, self.nsecs)
373 """Returns the ClockType of this Time."""
374 attrs = EXTRA_ATTRS.get(id(self))
or {}
375 return attrs.get(
"_clock_type", ClockType.SYSTEM_TIME)
379 """Returns a new Time from given."""
380 return cls(msg.secs, msg.nsecs, clock_type=clock_type)
383 ROS1_Timer__init = rospy.Timer.__init__
385 def Timer__init(self, period, callback, oneshot=False, reset=False):
387 Constructs a new ROS1 Timer.
389 Plugs in ROS2 API compatibility: cancelling, resetting,
and public timing info.
391 @param period desired period between callbacks,
as rospy.Duration
392 @param callback callback to be called, taking rospy.TimerEvent
393 @param oneshot
if True, fire only once, otherwise fire continuously
394 until shutdown
is called [default:
False]
395 @param reset
if True, timer
is reset when rostime moved backward. [default:
False]
398 self._wakeable = threading.Event()
399 self._time_last =
None
400 self._time_next =
None
401 self._clock =
Clock()
405 """Stop firing callbacks."""
406 self._shutdown =
True
410 """Override rospy.Timer.run() to support canceling and resetting, and call timestamps."""
411 self._time_last = self._clock.now()
412 self._time_next = self._time_last + self._period
413 last_expected, last_real, last_duration =
None,
None,
None
414 self._wakeable.clear()
415 while not rospy.core.is_shutdown()
and not self._shutdown:
418 except rospy.exceptions.ROSTimeMovedBackwardsException:
421 except rospy.exceptions.ROSInterruptException:
422 if rospy.core.is_shutdown():
428 self._wakeable.wait()
431 if self._paused
is None:
433 self._time_last = self._clock.now()
434 self._time_next = self._time_last + self._period
435 last_expected, last_real, last_duration =
None,
None,
None
436 self._wakeable.clear()
438 current_real = self._clock.now()
440 self._time_last = self._clock.now()
441 self._callback(rospy.timer.TimerEvent(last_expected, last_real, self._time_next,
442 current_real, last_duration))
445 last_duration = time.time() - start
446 last_expected, last_real = self._time_next, current_real
447 self._time_next += self._period
450 """Sets timer on pause, until reset or shutdown."""
451 if self._paused:
return
457 """Sets last call time to now, postponing next callback by full period; uncancels if canceled."""
462 """Returns the Clock used by this timer."""
466 """Returns timer period in nanoseconds."""
467 return self._period.to_nsec()
470 """Sets timer period in nanoseconds, resets timer if running."""
471 self._period = rospy.Duration(nsecs=value)
472 if not self._paused: self._wakeable.set()
475 """Returns whether the timer has been canceled (paused until reset or shutdown)."""
476 return bool(self._paused)
479 """Returns whether timer callback should be called right now."""
480 if self._paused
or self._time_last
is None:
482 return self._period >= (self._time_next - self._time_last)
485 """Returns nanoseconds since last timer callback (ROS2 compatibility stand-in)."""
486 return None if self._time_last
is None else (self._clock.now() - self._time_last).to_nsec()
489 """Returns nanoseconds until next timer callback (ROS2 compatibility stand-in)."""
490 if self._shutdown
or self._paused
or self._time_next
is None:
492 return (self._time_next - self._clock.now()).to_nsec()
498 Sleeps for the specified duration
in ROS time,
or until event gets set.
500 Returns immediately
if duration
is negative
or event
is set.
502 @param duration seconds (
or rospy.Duration) to sleep
503 @param event threading.Event to wait() on,
if any,
504 will
return early
if event gets set
506 @throws ROSInterruptException
if ROS shutdown occurs before sleep completes
507 @throws ROSTimeMovedBackwardsException
if ROS time
is set backwards
509 if event
and event.is_set():
return
511 if rospy.rostime.is_wallclock():
512 if isinstance(duration, genpy.Duration):
513 duration = duration.to_sec()
516 event.wait(duration)
if event
else rospy.rostime.wallsleep(duration)
518 initial_rostime = rospy.rostime.get_rostime()
519 if not isinstance(duration, genpy.Duration):
520 duration = genpy.Duration.from_sec(duration)
522 rostime_cond = rospy.rostime.get_rostime_cond()
524 if initial_rostime == genpy.Time(0):
526 while initial_rostime == genpy.Time(0)
and \
527 not rospy.core.is_shutdown():
529 rostime_cond.wait(0.3)
530 initial_rostime = rospy.rostime.get_rostime()
531 if event
and event.is_set():
return
533 sleep_t = initial_rostime + duration
536 while rospy.rostime.get_rostime() < sleep_t \
537 and rospy.rostime.get_rostime() >= initial_rostime
and not rospy.core.is_shutdown():
539 rostime_cond.wait(0.5)
540 if event
and event.is_set():
return
542 if rospy.rostime.get_rostime() < initial_rostime:
543 time_jump = (initial_rostime - rospy.rostime.get_rostime()).to_sec()
544 raise rospy.exceptions.ROSTimeMovedBackwardsException(time_jump)
545 if rospy.core.is_shutdown():
546 raise rospy.exceptions.ROSInterruptException(
"ROS shutdown request")
553 """Returns service client call-function wrapped to ensure invoke with request instance."""
554 def inner(self, *args, **kwargs):
555 reqcls = self.srv_type.Request
556 attributes = functools.partial(ros.get_message_fields, reqcls)
557 req = util.ensure_object(reqcls, attributes, api.dict_to_message, *args, **kwargs)
558 return call(self, req)
559 return functools.update_wrapper(inner, call)
562 """Returns service serve-function wrapped to ensure return with response instance."""
563 def inner(req, resp):
564 resp0, respcls, args, kwargs = resp, self.srv_type.Response,
None,
None
565 resp = serve(req, resp0)
566 if isinstance(resp, (list, tuple)): args = resp
567 elif isinstance(resp, dict): kwargs = resp
568 elif resp
is None: resp = resp0
569 if args
is not None or kwargs
is not None:
570 attributes = functools.partial(ros.get_message_fields, respcls)
571 args, kwargs = (args
or []), (kwargs
or {})
572 resp = util.ensure_object(respcls, attributes, api.dict_to_message, *args, **kwargs)
574 return functools.update_wrapper(inner, serve)
577 """Returns publish-function wrapped to ensure invoke with message instance."""
578 def inner(self, *args, **kwargs):
579 attrs = functools.partial(ros.get_message_fields, self.msg_type)
580 msg = util.ensure_object(self.msg_type, attrs, api.dict_to_message, *args, **kwargs)
581 return publish(self, msg)
582 return functools.update_wrapper(inner, publish)
586 ROS2_Duration__init = rclpy.duration.Duration.__init__
588 def Duration__init(self, secs=0, nsecs=0, *, seconds=0, nanoseconds=0):
589 """Constructs a new ROS2 `Duration`, using either ROS1 or ROS2 arguments."""
590 if secs
or nsecs: seconds, nanoseconds = secs, nsecs
594 """Returns negative value of this duration."""
595 return self.__class__(nanoseconds=-self.nanoseconds)
598 """Returns absolute value of this duration."""
599 if self.nanoseconds >= 0:
601 return self.__neg__()
605 Returns a new duration, adding given duration to this.
607 @param other another `Duration` instance
608 @returns new `Duration` instance
610 if isinstance(other, rclpy.duration.Duration):
611 return self.__class__(nanoseconds=self.nanoseconds + other.nanoseconds)
612 return NotImplemented
616 Subtracts a duration from this duration.
618 @param other another `Duration` instance
619 @returns new `Duration` instance
621 if isinstance(other, rclpy.duration.Duration):
622 return self.__class__(nanoseconds=self.nanoseconds - other.nanoseconds)
623 return NotImplemented
627 Multiplies this duration by an integer or float.
629 @param val multiplication factor,
as `int`
or `float`
630 @return new `Duration` instance
632 if isinstance(val, numbers.Number):
633 return self.__class__(nanoseconds=self.nanoseconds * val)
634 return NotImplemented
638 Floor-divides this duration by a number or a duration.
640 @param val division factor,
as `int`
or `float`
or `Duration` to divide by
641 @return new `Duration` instance
if divided by a number,
642 or seconds
as integer
if divided by a `Duration`
644 if isinstance(val, numbers.Number):
645 return self.__class__(seconds=self.to_sec() // val)
646 if isinstance(val, rclpy.duration.Duration):
647 return int(self.to_sec() // val.to_sec())
648 return NotImplemented
652 Divides this duration by an integer or float.
654 @param val division factor,
as `int`
or `float`
or `Duration` to divide by
655 @return new `Duration` instance
if divided by a number,
656 or seconds
as float
if divided by a `Duration`
658 if isinstance(val, numbers.Number):
659 return self.__class__(seconds=self.to_sec() / val)
660 if isinstance(val, rclpy.duration.Duration):
661 return self.to_sec() / val.to_sec()
662 return NotImplemented
666 Returns the remainder of dividing this duration by another duration.
668 @param val modulo factor,
as `int`
or `float` to mod by
669 @return new `Duration` instance of remaining time after mod
671 if isinstance(val, rclpy.duration.Duration):
672 return self.__class__(nanoseconds=self.nanoseconds % val.nanoseconds)
673 return NotImplemented
677 Returns the divmod result for this
and another duration.
679 @param val division factor,
as `Duration` to divide by
680 @return (division floored result
as `int`, remaining time
as `Duration`)
682 if isinstance(val, rclpy.duration.Duration):
683 quotient, remainder = divmod(self.nanoseconds, val.nanoseconds)
684 return int(quotient), self.__class__(nanoseconds=remainder)
685 return NotImplemented
688 ROS2_Service__init = rclpy.service.Service.__init__
690 def Service__init(self, service_handle, srv_type, srv_name, callback,
691 callback_group, qos_profile):
692 """Wraps Service.__init__() to support returning list/dict/None from server callback."""
695 callback_group, qos_profile)
698 """Spins ROS2 until service or node shutdown."""
700 while not ros.SHUTDOWN
and self.handle:
702 except KeyboardInterrupt:
703 ros.get_logger().debug(
"keyboard interrupt, shutting down")
706 ROS2_Subscription__init = rclpy.subscription.Subscription.__init__
709 callback_group, qos_profile, raw, event_callbacks):
710 """Wraps Subscription.__init__() to support AnyMsg and multiple callbacks."""
712 callback_group, qos_profile, raw, event_callbacks)
713 self.impl = type(
"", (), {})()
714 self.impl.add_callback = functools.partial(Subscription__add_callback, self)
715 self.impl.remove_callback = functools.partial(Subscription__remove_callback, self)
716 self._callbacks = getattr(self,
"_callbacks", [(callback,
None)])
720 """Returns callback args given in constructor."""
721 return self._callbacks[0][-1]
if self._callbacks
else None
724 """Handler for received message, invokes all added callbacks."""
725 if self._anymsg
and isinstance(msg, bytes):
726 msg = AnyMsg().deserialize(msg)
727 for cb, arg
in list(self._callbacks):
729 cb(msg)
if arg
is None else cb(msg, arg)
731 t = (
"during shutdown, " if ros.SHUTDOWN
else "") +
"bad callback: %s\n%s"
732 ros.get_logger().warning(t, cb, traceback.format_exc())
736 Registers a callback to be invoked whenever a new message is received
738 @param cb callback function to invoke
with message data instance, i.e. fn(data).
739 If callback args
is set, they will be passed
in as the second argument.
740 @param cb_cargs additional arguments to
pass to callback
742 self._callbacks.append((cb, cb_args))
746 Unregisters a message callback.
748 @param cb callback function
749 @param cb_cargs additional arguments associated
with callback
751 @throws KeyError
if no matching callback
753 matches = [x for x
in self._callbacks
if x[0] == cb
and x[1] == cb_args]
755 new_callbacks = self._callbacks[:]
757 new_callbacks.remove(matches[0])
758 self._callbacks = new_callbacks
760 raise KeyError(
"no matching cb")
764 """Returns time remaining for rate to sleep, as `Duration`."""
765 return rclpy.duration.Duration(nanoseconds=self._timer.time_until_next_call())
768 ROS2_Timer__init = rclpy.timer.Timer.__init__
772 def Timer__init(self, callback, callback_group, timer_period_ns, clock, *, context=None):
773 """Constructs a new ROS2 `Timer`."""
775 ROS2_Timer__init(self, callback, callback_group, timer_period_ns, clock, context=context)
777 self._name =
"%s-%s" % (self.handle.name, TIMER_COUNTER)
780 """Returns timer identifier as a non-negative integer."""
784 """Returns timer name."""
788 """Sets timer name."""
792 """Returns `True`."""
797 raise RuntimeError(
"cannot set daemon status of running thread")
800 """Returns when timer has terminated."""
801 while self.handle
and self.is_ready():
805 """Returns whether timer is still running."""
806 return self.handle
and self.is_ready()
809 ROS2_Time__init = rclpy.time.Time.__init__
811 def Time__init(self, secs=0, nsecs=0, *, seconds=0, nanoseconds=0,
812 clock_type=ClockType.SYSTEM_TIME):
813 """Constructs a new ROS2 `Time`, using either ROS1 or ROS2 arguments."""
814 if secs
or nsecs: seconds, nanoseconds = secs, nsecs
815 ROS2_Time__init(self, seconds=seconds, nanoseconds=nanoseconds, clock_type=clock_type)
818 """Returns whether value is not zero."""
819 return self.nanoseconds != 0
822 """Returns whether value is zero."""
823 return self.nanoseconds == 0
826 """Returns value in seconds as `float`."""
827 return ros.to_sec(self)
830 """Returns value in nanoseconds as `int`."""
831 return ros.to_nsec(self)
834 """Returns the seconds portion as `int`."""
835 return self.nanoseconds // 10**9
838 """Returns the nanoseconds portion as `int`."""
839 return self.nanoseconds % 10**9
844 "patch_ros1",
"patch_ros1_rclify",
"patch_ros2",
"set_extra_attribute"
Simple clock interface mimicking `rclpy.clock.Clock`, only providing `now()`.
ServiceProxy__service_is_ready(self)
Returns whether service is ready.
patch_ros1()
Patches ROS1 classes with generic compatibility with ROS2 and rosros.
TVal__is_nonzero(self)
Returns whether value is not zero.
Duration__mod(self, val)
Returns the remainder of dividing this duration by another duration.
Duration__floordiv(self, val)
Floor-divides this duration by a number or a duration.
Time__from_msg(cls, msg, clock_type=ClockType.ROS_TIME)
Returns a new Time from given.
Timer__timer_period_ns__setter(self, value)
Sets timer period in nanoseconds, resets timer if running.
Timer__timer_period_ns(self)
Returns timer period in nanoseconds.
Subscription__remove_callback(self, cb, cb_args)
Unregisters a message callback.
TVal__nsecs(self)
Returns the nanoseconds portion as `int`.
ServiceProxy__call_async(self, *args, **kwargs)
Make a service request and asyncronously get the result.
service_serve_wrapper(self, serve)
Returns service serve-function wrapped to ensure return with response instance.
TVal__secs(self)
Returns the seconds portion as `int`.
Time__init(self, secs=0, nsecs=0, *seconds=0, nanoseconds=0, clock_type=ClockType.SYSTEM_TIME)
Constructs a new ROS1 `Time`, using either ROS1 or ROS2 arguments.
Timer__join(self)
Returns when timer has terminated.
Duration__sub(self, other)
Subtracts a duration from this duration.
Timer__run(self)
Override rospy.Timer.run() to support canceling and resetting, and call timestamps.
ServiceProxy__call(self, *args, **kwargs)
Calls the service, supports giving request field values as dictionary in args[0].
TVal__to_nsec(self)
Returns value in nanoseconds as `int`.
Timer__setName(self, name)
Sets timer name.
Timer__cancel(self)
Sets timer on pause, until reset or shutdown.
ROS1_SubscriberImpl__receive_callback
TVal__is_zero(self)
Returns whether value is zero.
Service__spin(self)
Spins ROS2 until service or node shutdown.
Duration__truediv(self, val)
Divides this duration by an integer or float.
Duration__mul(self, val)
Multiplies this duration by an integer or float.
Rate__remaining(self)
Returns time remaining for rate to sleep, as `Duration`.
Subscription__add_callback(self, cb, cb_args)
Registers a callback to be invoked whenever a new message is received.
Duration__add(self, other)
Returns a new duration, adding given duration to this.
Time__del(self)
Clear object-related data, if any.
Subscription__callback_args(self)
Returns callback args given in constructor.
Publisher__assert_liveliness(self)
Does nothing (ROS2 compatibility stand-in).
Timer__shutdown(self)
Stop firing callbacks.
Timer__isDaemon(self)
Returns `True`.
ServiceProxy__remove_pending_request(self, future)
Does nothing (ROS2 compatibility stand-in).
Duration__divmod(self, val)
Returns the divmod result for this and another duration.
publish_wrapper(publish)
Returns publish-function wrapped to ensure invoke with message instance.
Duration__init(self, secs=0, nsecs=0, *seconds=0, nanoseconds=0)
Constructs a new `Duration`, using either ROS1 or ROS2 arguments.
Timer__init(self, period, callback, oneshot=False, reset=False)
Constructs a new ROS1 Timer.
set_extra_attribute(obj, name, value)
Sets value for object patched attribute.
Subscription__init(self, subscription_handle, msg_type, topic, callback, callback_group, qos_profile, raw, event_callbacks)
Wraps Subscription.__init__() to support AnyMsg and multiple callbacks.
Duration__abs(self)
Returns absolute value of this duration.
Duration__neg(self)
Returns negative value of this duration.
patch_ros1_rclify()
Patches ROS1 classes with full stand-ins for ROS2 methods and properties.
Time__clock_type(self)
Returns the ClockType of this Time.
Temporal__to_msg(self)
Returns a new Time or Duration from this.
Timer__ident(self)
Returns timer identifier as a non-negative integer.
Time__seconds_nanoseconds(self)
Returns time as (seconds, nanoseconds).
Timer__is_alive(self)
Returns whether timer is still running.
Timer__time_since_last_call(self)
Returns nanoseconds since last timer callback (ROS2 compatibility stand-in).
Timer__is_ready(self)
Returns whether timer callback should be called right now.
Duration__from_msg(cls, msg)
Returns a new Duration from given.
Subscription__invoke_callbacks(self, msg)
Handler for received message, invokes all added callbacks.
rostimer_sleep_on_event(duration, event=None)
Sleeps for the specified duration in ROS time, or until event gets set.
Subscriber__init(self, name, data_class, callback=None, callback_args=None, queue_size=None, buff_size=65536, tcp_nodelay=False)
Wraps rospy.Subscriber.__init__() to add raw bytes autoconversion support.
Timer__is_canceled(self)
Returns whether the timer has been canceled (paused until reset or shutdown).
Timer__time_until_next_call(self)
Returns nanoseconds until next timer callback (ROS2 compatibility stand-in).
Timer__reset(self)
Sets last call time to now, postponing next callback by full period; uncancels if canceled.
patch_ros2()
Patches ROS2 classes with full stand-ins for ROS1 methods and properties.
Timer__setDaemon(self, daemonic)
Raises error.
Timer__getName(self)
Returns timer name.
SubscriberImpl__receive_callback(self, msgs, connection)
Wraps rospy.topics.SubscriberImpl.receive_callback() with raw bytes autoconversion.
TVal__to_sec(self)
Returns value in seconds as `float`.
Service__init(self, name, service_class, handler, buff_size=65536, error_handler=None)
Wraps Service.__init__() to support returning None from server callback.
ServiceProxy__wait_for_service(self, timeout=None, timeout_sec=None)
Waits for a service server to become ready.
Timer__clock(self)
Returns the Clock used by this timer.
client_call_wrapper(call)
Returns service client call-function wrapped to ensure invoke with request instance.
Publisher__publish(self, *args, **kwds)
Publishes message, supports giving message field values as dictionary in args[0].