20 from python_qt_binding
import QtCore
21 from python_qt_binding.QtWidgets
import QUndoStack
33 self.
static = FrameEditor.parse_args_static(context.argv())
70 '''Updates all observers, whenever a command has been undone/redone'''
74 '''Used by commands to add a level for updating'''
80 '''Push a command to the stack (blocking)'''
86 '''Updates all registered observers and resets the undo_level'''
94 observer.broadcast(self)
98 y = Frame.tf_buffer.all_frames_as_yaml()
100 if isinstance(d, dict):
103 rospy.logwarn(
'Got invalid yaml from tf2: {}'.format(y))
108 return frame_id.startswith(
'_')
112 return [f
for f
in FrameEditor.tf_dict()
if
113 not FrameEditor.frame_is_temporary(f)
or include_temp]
116 return [f
for f
in self.
frames.keys()
if
117 not FrameEditor.frame_is_temporary(f)
or include_temp]
120 for f
in self.
frames.values():
128 rospy.loginfo(
"> Printing all frames")
138 rospy.loginfo(
"> Loading file")
139 data = rosparam.load_file(file_name, self.
namespace)[0][0]
151 if not rosparam.list_params(namespace):
152 rospy.logwarn(
"> No data to load")
154 data = rosparam.get_param(namespace)
162 for name, frame
in data[
"frames"].items():
163 t = frame[
"position"]
164 o = frame[
"orientation"]
167 style = frame[
"style"]
172 group = frame[
"group"]
181 color = (0.0, 0.5, 0.5, 0.75)
182 if "package" not in dat:
185 position = (t[
"x"], t[
"y"], t[
"z"])
186 orientation = (o[
"x"], o[
"y"], o[
"z"], o[
"w"])
189 f =
Object_Plane(name, position, orientation, frame[
"parent"], dat[
"length"], dat[
"width"])
191 elif style ==
"cube":
192 f =
Object_Cube(name, position, orientation, frame[
"parent"], dat[
"length"], dat[
"width"], dat[
"height"])
194 elif style ==
"sphere":
195 f =
Object_Sphere(name, position, orientation, frame[
"parent"], dat[
"diameter"])
197 elif style ==
"axis":
198 f =
Object_Axis(name, position, orientation, frame[
"parent"], dat[
"length"], dat[
"width"])
200 elif style ==
"mesh":
201 f =
Object_Mesh(name, position, orientation, frame[
"parent"], dat[
"package"], dat[
"path"], dat[
"scale"])
204 f =
Frame(name, position, orientation, frame[
"parent"], group=group)
210 rospy.loginfo(
"> Loading done")
220 t[
"x"] = float(frame.position[0])
221 t[
"y"] = float(frame.position[1])
222 t[
"z"] = float(frame.position[2])
225 o[
"x"] = float(frame.orientation[0])
226 o[
"y"] = float(frame.orientation[1])
227 o[
"z"] = float(frame.orientation[2])
228 o[
"w"] = float(frame.orientation[3])
231 f[
"parent"] = frame.parent
235 f[
"style"] = frame.style
236 f[
"group"] = frame.group
238 if frame.style ==
"plane":
239 f[
"data"] = {
"length": frame.length,
"width":frame.width,
"color": frame.color }
241 elif frame.style ==
"cube":
242 f[
"data"] = {
"length": frame.length,
"width": frame.width,
"height": frame.height ,
"color": frame.color}
244 elif frame.style ==
"sphere":
245 f[
"data"] = {
"diameter": frame.diameter,
"color": frame.color }
247 elif frame.style ==
"axis":
248 f[
"data"] = {
"length": frame.length,
"width": frame.width,
"color": frame.color }
250 elif frame.style ==
"mesh":
252 f[
"data"] = {
"package" : frame.package,
"path" : frame.path,
"scale" : frame.scale,
"color": frame.color }
254 frames[frame.name] = f
256 data[
"frames"] = frames
260 rospy.loginfo(rospy.get_param(self.
namespace))
265 rospy.loginfo(
"Saving to file {}".format(filename))
266 rosparam.dump_params(filename, self.
namespace)
267 rospy.loginfo(
"Saving done")
273 if frame.package ==
"" and frame.path !=
"":
277 from python_qt_binding
import QtWidgets
278 rospackage = rospkg.get_package_name(frame.path)
279 if rospackage
is not None:
280 rel_path = os.path.relpath(frame.path , rospkg.RosPack().get_path(rospackage))
281 reply = QtWidgets.QMessageBox.question(
None,
"Convert absolute path to rospack+relative path?",
282 "The absolute path to your selected mesh can be converted to rospack+relative path."+
283 "This gives you more reliabilaty to reuse your saved configuration"+
284 "if your meshes are stored in rospackages\n\n"+
285 "Do you want to convert your configuration?\n"+
286 "Convert:\n'{}'\nto:\n'{}' and\n '{}'\n".format(frame.path, rospackage, rel_path),
287 QtWidgets.QMessageBox.Yes |
288 QtWidgets.QMessageBox.No,
289 QtWidgets.QMessageBox.Yes)
291 if reply == QtWidgets.QMessageBox.Yes:
292 rospy.loginfo(
"Saving: package: {} + relative path: {}".format(rospackage, rel_path))
293 frame.package = rospackage
294 frame.path = rel_path
304 rospy.loginfo(
"> Going for some spins")
305 rate = rospy.Rate(self.
hz)
306 while not rospy.is_shutdown():
312 from argparse
import ArgumentParser
313 parser = ArgumentParser()
315 parser.add_argument(
"-s",
"--static", action=
"store_true", help=
"Use static tf broadcaster")
316 args, unknowns = parser.parse_known_args(argv)
324 from argparse
import ArgumentParser
325 parser = ArgumentParser()
330 parser.add_argument(
"-l",
"--load", action=
"append",
332 help=
"Load a file at startup. [rospack filepath/file]")
336 choices=[
"grey",
"hide"],
337 help=
"Choose the filter style: 'grey' or 'hide' (default: 'hide')",
341 parser.add_argument(
"-r",
"--rate", type=int, help=
"Rate for broadcasting. Does not involve tf frames. Only effective for non-static broadcaster.")
342 parser.add_argument(
"-s",
"--static", action=
"store_true", help=
"Use static tf broadcaster")
344 args, unknowns = parser.parse_known_args(argv)
345 rospy.loginfo(
'arguments: {}'.format(args))
347 rospy.logwarn(
'unknown parameters found: {}'.format(unknowns))
356 if args.filter_style:
361 arg_path = args.file[0].split()
362 if len(arg_path) == 1:
364 filename = arg_path[0]
365 rospy.loginfo(
"Loading {}".format(filename))
367 elif len(arg_path) == 2:
369 rospack = rospkg.RosPack()
370 filename = os.path.join(rospack.get_path(arg_path[0]), arg_path[1])
371 rospy.loginfo(
"Loading {}".format(filename))
374 rospy.logwarn(
"Load argument not understood! --load {}".format(arg_path))
375 rospy.logwarn(
"Please use --load 'myRosPackage pathInMyPackage/myYaml.yaml'")
376 rospy.logwarn(
"or use --load 'fullPathToMyYaml.yaml'")
381 elif success ==
False:
382 rospy.logerr(
"ERROR LOADING FILE")
392 if __name__ ==
"__main__":
394 rospy.init_node(
'frame_editor')
397 editor.parse_args(sys.argv[1:])
400 rospy.loginfo(
"Frame editor ready!")