1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 """
36 L{WtfContext} object, which is commonly used throughout the roswtf
37 APIs to pass state.
38 """
39
40 import os
41 import sys
42
43 import roslib.manifest
44 import roslib.packages
45 import roslib.stacks
46 import roslib.rosenv
47 import roslib.rospack
48 import roslib.substitution_args
49
50 import roslaunch.depends
51
52 from roswtf.model import WtfWarning
55 """
56 Base exception class of roswtf-related issues.
57 """
58 pass
59
60 -class WtfContext(object):
61 """
62 WtfContext stores common state about the ROS filesystem and online
63 environment. The primary use of this is for convenience (not
64 having to load this state manually) and performance (not having to
65 do the same calculation repeatedly).
66 """
67 __slots__ = ['pkg', 'pkg_dir', 'pkgs',
68 'stack', 'stack_dir', 'stacks',
69 'manifest_file', 'manifest',
70 'env', 'ros_root', 'ros_package_path', 'pythonpath',
71 'ros_master_uri',
72 'roslaunch_uris',
73 'ros_bindeps_path',
74 'ros_boost_root',
75 'launch_files',
76 'launch_file_deps',
77 'launch_file_missing_deps',
78 'system_state',
79 'service_providers',
80 'topics', 'services',
81 'nodes', 'uri_node_map',
82 'expected_edges',
83 'actual_edges',
84 'unconnected_subscriptions',
85 'use_sim_time',
86 'warnings', 'errors']
87
89
90 self.pkg = None
91 self.pkg_dir = None
92
93 self.stack = None
94 self.stack_dir = None
95
96
97 self.pkgs = []
98
99 self.stacks = []
100
101
102 self.manifest_file = None
103
104 self.manifest = None
105
106
107 self.env = {}
108
109
110 self.ros_root = None
111 self.ros_package_path = None
112 self.pythonpath = None
113 self.ros_bindeps_path = None
114 self.ros_boost_root = None
115
116
117 self.launch_files = None
118 self.launch_file_deps = None
119 self.launch_file_missing_deps = None
120
121
122 self.roslaunch_uris = None
123 self.system_state = None
124 self.topics = None
125 self.services = None
126 self.service_providers = None
127 self.nodes = None
128 self.uri_node_map = {}
129 self.expected_edges = None
130 self.actual_edges = None
131 self.unconnected_subscriptions = None
132 self.use_sim_time = None
133
134
135 self.warnings = []
136
137 self.errors = []
138
139 - def as_dictionary(self):
140 """
141 @return: dictionary representation of context, which is
142 useful for producing error messages
143 @rtype: dict
144 """
145 return dict((s, getattr(self, s)) for s in self.__slots__)
146
147 @staticmethod
148 - def from_roslaunch(roslaunch_files, env=os.environ):
149 """
150 @param roslaunch_file: roslaunch_file to load from
151 @type roslaunch_file: str
152 """
153
154 l, c = roslaunch.XmlLoader(), roslaunch.ROSLaunchConfig()
155 for f in roslaunch_files:
156 try:
157 l.load(f, c, verbose=False)
158 except roslaunch.RLException, e:
159 raise WtfException("Unable to load roslaunch file [%s]: %s"%(f, str(e)))
160
161 ctx = WtfContext()
162 ctx.launch_files = roslaunch_files
163 _load_roslaunch(ctx, roslaunch_files)
164
165 _load_pkg(ctx, ctx.pkg)
166 if ctx.stack:
167 _load_stack(ctx, ctx.stack)
168 _load_env(ctx, env)
169 return ctx
170
171 @staticmethod
172 - def from_stack(stack, env=os.environ):
173 """
174 Initialize WtfContext from stack.
175 @param stack: stack name
176 @type stack: str
177 @raise WtfException: if context state cannot be initialized
178 """
179 ctx = WtfContext()
180 _load_stack(ctx, stack)
181 try:
182 ctx.pkgs = roslib.stacks.packages_of(stack)
183 except roslib.stacks.InvalidROSStackException:
184
185 ctx.pkgs = []
186 _load_env(ctx, env)
187 return ctx
188
189 @staticmethod
190 - def from_package(pkg, env=os.environ):
191 """
192 Initialize WtfContext from package name.
193
194 @param pkg: package name
195 @type pkg: str
196 @raise WtfException: if context state cannot be initialized
197 """
198 ctx = WtfContext()
199 _load_pkg(ctx, pkg)
200 stack = roslib.stacks.stack_of(pkg)
201 if stack:
202 _load_stack(ctx, stack)
203 _load_env(ctx, env)
204 return ctx
205
206 @staticmethod
207 - def from_env(env=os.environ):
208 """
209 Initialize WtfContext from environment.
210
211 @raise WtfException: if context state cannot be initialized
212 """
213 ctx = WtfContext()
214 _load_env(ctx, env)
215 return ctx
216
218 """
219 Utility for initializing WtfContext state from roslaunch file
220 """
221 try:
222 base_pkg, file_deps, missing = roslaunch.depends.roslaunch_deps(roslaunch_files)
223 ctx.pkg = base_pkg
224 ctx.launch_file_deps = file_deps
225 ctx.launch_file_missing_deps = missing
226 except roslib.substitution_args.SubstitutionException, se:
227 raise WtfException("Cannot load roslaunch file(s): "+str(se))
228 except roslaunch.depends.RoslaunchDepsException, e:
229 raise WtfException(str(e))
230
246
248 """
249 Utility for initializing WtfContext state
250 @raise WtfException: if context state cannot be initialized
251 """
252 try:
253 ctx.stack = stack
254 ctx.stacks = [stack] + roslib.rospack.rosstack_depends(stack)
255 try:
256 ctx.stack_dir = roslib.stacks.get_stack_dir(stack)
257 except roslib.stacks.InvalidROSStackException:
258 raise WtfException("[%s] appears to be a stack, but it's not on your ROS_PACKAGE_PATH"%stack)
259 except roslib.stacks.InvalidROSStackException:
260 raise WtfException("[%s] appears to be a stack, but it's not on your ROS_PACKAGE_PATH"%stack)
261
264 """
265 Utility for initializing WtfContext state
266
267 @raise WtfException: if context state cannot be initialized
268 """
269 ctx.env = env
270 try:
271 ctx.ros_root = env[roslib.rosenv.ROS_ROOT]
272 except KeyError:
273 raise WtfException("ROS_ROOT is not set")
274 ctx.ros_package_path = env.get(roslib.rosenv.ROS_PACKAGE_PATH, None)
275 ctx.pythonpath = env.get('PYTHONPATH', None)
276 ctx.ros_master_uri = env.get(roslib.rosenv.ROS_MASTER_URI, None)
277 ctx.ros_bindeps_path = env.get(roslib.rosenv.ROS_BINDEPS_PATH, None)
278 ctx.ros_boost_root = env.get(roslib.rosenv.ROS_BOOST_ROOT, None)
279