class DaemonNode: def __init__(self, args): self._args = args self._proxy = ServerProxy('http://localhost:%d/ros2cli/' % get_daemon_port(), allow_none=True) self._methods = [] def __enter__(self): self._proxy.__enter__() try: methods = self._proxy.system.listMethods() except ProtocolError as e: if e.errcode != 404: raise # remote daemon returned 404, likely using different rmw impl. self._proxy.__exit__() # fall back to use direct node self._proxy = DirectNode(self._args) self._proxy.__enter__() else: self._methods = [m for m in methods if not m.startswith('system.')] return self def __getattr__(self, name): return getattr(self._proxy, name) def __exit__(self, exc_type, exc_value, traceback): self._proxy.__exit__(exc_type, exc_value, traceback)
class NetworkAwareNode: """A direct node, that resets itself when a network interface changes.""" def __init__(self, args): self.args = args # TODO(ivanpauno): A race condition is possible here, since it isn't possible to know # exactly which interfaces were available at node creation. self.node = DirectNode(args) self.addresses_at_start = get_interfaces_ip_addresses() def __enter__(self): self.node.__enter__() return self def __getattr__(self, name): attr = getattr(self.node, name) if inspect.ismethod(attr): return before_invocation(attr, self.reset_if_addresses_changed) self.reset_if_addresses_changed() return attr def __exit__(self, exc_type, exc_value, traceback): self.node.__exit__(exc_type, exc_value, traceback) def reset_if_addresses_changed(self): new_addresses = get_interfaces_ip_addresses() if new_addresses != self.addresses_at_start: self.addresses_at_start = new_addresses self.node.destroy_node() rclpy.shutdown() self.node = DirectNode(self.args) self.node.__enter__() print('Daemon node was reset')
class NodeStrategy: def __init__(self, args): if is_daemon_running(args): self.node = DaemonNode(args) else: spawn_daemon(args) self.node = DirectNode(args) def __enter__(self): self.node.__enter__() return self def __getattr__(self, name): return self.node.__getattr__(name) def __exit__(self, exc_type, exc_value, traceback): self.node.__exit__(exc_type, exc_value, traceback)
class NodeStrategy: def __init__(self, args): use_daemon = not getattr(args, 'no_daemon', False) if use_daemon and is_daemon_running(args): self._daemon_node = DaemonNode(args) self._direct_node = None else: if use_daemon: spawn_daemon(args) self._direct_node = DirectNode(args) self._daemon_node = None self._args = args self._in_scope = False @property def daemon_node(self): return self._daemon_node @property def direct_node(self): if self._direct_node is None: self._direct_node = DirectNode(self._args) if self._in_scope: self._direct_node.__enter__() return self._direct_node def __enter__(self): if self._daemon_node: self._daemon_node.__enter__() if self._direct_node: self._direct_node.__enter__() self._in_scope = True return self def __getattr__(self, name): if self.daemon_node and name in self.daemon_node.methods: return getattr(self.daemon_node, name) return getattr(self.direct_node, name) def __exit__(self, exc_type, exc_value, traceback): self._in_scope = False if self._direct_node: self._direct_node.__exit__(exc_type, exc_value, traceback) if self._daemon_node: self._daemon_node.__exit__(exc_type, exc_value, traceback)
class NodeStrategy: def __init__(self, args): use_daemon = not getattr(args, 'no_daemon', False) if use_daemon and is_daemon_running(args): self.node = DaemonNode(args) else: if use_daemon: spawn_daemon(args) self.node = DirectNode(args) def __enter__(self): self.node.__enter__() return self def __getattr__(self, name): return getattr(self.node, name) def __exit__(self, exc_type, exc_value, traceback): self.node.__exit__(exc_type, exc_value, traceback)