Package rosh :: Package impl :: Module node
[frames] | no frames]

Source Code for Module rosh.impl.node

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2010, Willow Garage, Inc. 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Willow Garage, Inc. nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32  # 
 33  # Revision $Id: node.py 11682 2010-10-22 07:53:07Z kwc $ 
 34   
 35  from __future__ import with_statement 
 36   
 37  import rosnode 
 38  import rospy 
 39   
 40  from rosh.impl.exceptions import ROSHException 
 41  from rosh.impl.namespace import Namespace, Concept, NSResourceList 
 42   
43 -class NodeInfo(object):
44
45 - def __init__(self, config, name, pubs, subs, srvs):
46 self.name, self._pubs, self._subs, self._srvs = name, pubs, subs, srvs 47 48 # we need to use the config from the relevant concept so that 49 # we are allocating off of pre-existing instances. We also 50 # need to fetch the relevant Namespace class for instantiating 51 # resources. 52 t = config.ctx.topics 53 s = config.ctx.services 54 topic_config = t._config 55 service_config = s._config 56 TopicNS = t._nstype 57 ServiceNS = s._nstype 58 59 self.pubs = NSResourceList('', topic_config, pubs, TopicNS) 60 self.subs = NSResourceList('', topic_config, subs, TopicNS) 61 self.srvs = NSResourceList('', service_config, srvs, ServiceNS)
62
63 - def _update(self, pubs, subs, srvs):
64 """ 65 In-place update of resource lists 66 """ 67 self._pubs, self._subs, self._srvs = pubs, subs, srvs 68 self.pubs._set_resources(pubs) 69 self.subs._set_resources(subs) 70 self.srvs._set_resources(srvs)
71
72 - def __repr__(self):
73 return self.__str__()
74
75 - def __str__(self):
76 pubs, subs, srvs = self._pubs, self._subs, self._srvs 77 buff = 'Node [%s]\n'%(self.name) 78 if pubs: 79 buff += "\nPublications: \n" 80 buff += '\n'.join([" * %s"%(l) for l in pubs]) + '\n' 81 else: 82 buff += "\nPublications: None\n" 83 if subs: 84 buff += "\nSubscriptions: \n" 85 buff += '\n'.join([" * %s"%(l) for l in subs]) + '\n' 86 else: 87 buff += "\nSubscriptions: None\n" 88 if srvs: 89 buff += "\nServices: \n" 90 buff += '\n'.join([" * %s"%l for l in srvs]) + '\n' 91 else: 92 buff += "\nServices: None\n" 93 94 return buff
95
96 -def node_info(config, node_name, node_info_obj=None):
97 """ 98 @param config: Namespace config object to use for scoping. 99 @type config: NamespaceConfig 100 @param node_name: ROS Name of Node 101 @type node_name: str 102 @param node_info_obj: (optional) If a NodeInfo instance is 103 provided, it will be updated with the resulting 104 information. Otherwise, a new instance will be generated. 105 @type node_info_obj: NodeInfo 106 """ 107 # go through the master system state first 108 state = config.ctx.master.getSystemState() 109 pubs = [t for t, l in state[0] if node_name in l] 110 subs = [t for t, l in state[1] if node_name in l] 111 srvs = [t for t, l in state[2] if node_name in l] 112 if node_info_obj is None: 113 return NodeInfo(config, node_name, pubs, subs, srvs) 114 else: 115 node_info_obj._update(pubs, subs, srvs)
116
117 -class NodeNS(Namespace):
118
119 - def __init__(self, name, config):
120 """ 121 ctor. 122 @param config: Namespace configuration instance. 123 @type config: L{NamespaceConfig} 124 """ 125 super(NodeNS, self).__init__(name, config) 126 self._uri = None 127 self._init_uri() 128 self._info_obj = None
129
130 - def _list(self):
131 """ 132 Override Namespace._list() 133 """ 134 return rosnode.get_node_names(namespace=self._ns)
135
136 - def _kill(self):
137 if self._process is not None: 138 # kill attached process directly 139 self._process._kill() 140 self._process = None 141 else: 142 # TODO: enhance roslaunch API to allow more direct kill 143 rosnode.kill_nodes([self._name])
144
145 - def _init_uri(self):
146 if self._name and self._uri is None: 147 try: 148 self._uri = rosnode.get_api_uri(self._config.master.handle, self._name) 149 except: 150 pass
151
152 - def _show(self):
153 """ 154 show() handler 155 """ 156 show_graph(self._ns)
157
158 - def __repr__(self):
159 return self.__str__()
160
161 - def __str__(self):
162 """ 163 String representation of node. Provides node's URI. 164 """ 165 if self._uri is None: 166 self._init_uri() 167 if self._uri is None: 168 return self._ns 169 else: 170 return "Name: %s\nURI: %s"%(self._name, self._uri)
171
172 - def _info(self):
173 """ 174 info() API. 175 176 @return: node info object that provides access to pubs, subs, and srvs 177 @rtype: L{NodeInfo} 178 """ 179 # if we don't cache the info obj, we would leak memory in the 180 # shell each time the user calls info. This keeps the memory 181 # allocation fixed. 182 if self._info_obj is None: 183 self._info_obj = node_info(self._config, self._name) 184 else: 185 node_info(self._config, self._name, self._info_obj) 186 return self._info_obj
187
188 - def __call__(self):
189 """ 190 Ping the node. 191 """ 192 return rosnode.rosnode_ping(self._name, max_count=1, verbose=False)
193
194 -class Nodes(Concept):
195
196 - def __init__(self, ctx, lock):
197 super(Nodes, self).__init__(ctx, lock, NodeNS)
198
199 - def _show(self):
200 show_graph('/')
201
202 -def show_graph(ns):
203 import subprocess 204 cmd = ['rxgraph', '--nodens', ns] 205 # TODO: check for error return code? 206 subprocess.Popen(cmd, stderr=subprocess.PIPE)
207