20 from python_qt_binding
import QtCore
21 from python_qt_binding.QtWidgets
import QUndoStack
67 '''Updates all observers, whenever a command has been undone/redone''' 71 '''Used by commands to add a level for updating''' 74 self.undo_elements.extend(elements)
77 '''Push a command to the stack (blocking)''' 79 self.undo_stack.push(command)
83 '''Updates all registered observers and resets the undo_level''' 91 observer.broadcast(self)
95 y = Frame.tf_buffer.all_frames_as_yaml()
97 if isinstance(d, dict):
100 rospy.logwarn(
'Got invalid yaml from tf2: '+y)
105 return frame_id.startswith(
'_')
109 return [f
for f
in FrameEditor.tf_dict()
if 110 not FrameEditor.frame_is_temporary(f)
or include_temp]
113 for f
in self.frames.itervalues():
121 print(
"> Printing all frames")
131 print(
"> Loading file")
132 data = rosparam.load_file(file_name, self.
namespace)[0][0]
138 self.undo_stack.clear()
144 if not rosparam.list_params(namespace):
145 print(
"> No data to load")
147 data = rosparam.get_param(namespace)
152 self.undo_stack.beginMacro(
"Import file")
155 for name, frame
in data[
"frames"].items():
156 t = frame[
"position"]
157 o = frame[
"orientation"]
160 style = frame[
"style"]
169 color = (0.0, 0.5, 0.5, 0.75)
170 if "package" not in dat:
173 position = (t[
"x"], t[
"y"], t[
"z"])
174 orientation = (o[
"x"], o[
"y"], o[
"z"], o[
"w"])
177 f =
Object_Plane(name, position, orientation, frame[
"parent"], dat[
"length"], dat[
"width"])
179 elif style ==
"cube":
180 f =
Object_Cube(name, position, orientation, frame[
"parent"], dat[
"length"], dat[
"width"], dat[
"height"])
182 elif style ==
"sphere":
183 f =
Object_Sphere(name, position, orientation, frame[
"parent"], dat[
"diameter"])
185 elif style ==
"axis":
186 f =
Object_Axis(name, position, orientation, frame[
"parent"], dat[
"length"], dat[
"width"])
188 elif style ==
"mesh":
189 f =
Object_Mesh(name, position, orientation, frame[
"parent"], dat[
"package"], dat[
"path"], dat[
"scale"])
192 f =
Frame(name, position, orientation, frame[
"parent"])
196 self.undo_stack.endMacro()
198 print(
"> Loading done")
208 t[
"x"] = float(frame.position[0])
209 t[
"y"] = float(frame.position[1])
210 t[
"z"] = float(frame.position[2])
213 o[
"x"] = float(frame.orientation[0])
214 o[
"y"] = float(frame.orientation[1])
215 o[
"z"] = float(frame.orientation[2])
216 o[
"w"] = float(frame.orientation[3])
219 f[
"parent"] = frame.parent
223 f[
"style"] = frame.style
225 if frame.style ==
"plane":
226 f[
"data"] = {
"length": frame.length,
"width":frame.width,
"color": frame.color }
228 elif frame.style ==
"cube":
229 f[
"data"] = {
"length": frame.length,
"width": frame.width,
"height": frame.height ,
"color": frame.color}
231 elif frame.style ==
"sphere":
232 f[
"data"] = {
"diameter": frame.diameter,
"color": frame.color }
234 elif frame.style ==
"axis":
235 f[
"data"] = {
"length": frame.length,
"width": frame.width,
"color": frame.color }
237 elif frame.style ==
"mesh":
239 f[
"data"] = {
"package" : frame.package,
"path" : frame.path,
"scale" : frame.scale,
"color": frame.color }
241 frames[frame.name] = f
243 data[
"frames"] = frames
252 print(
"Saving to file {}".format(filename))
253 rosparam.dump_params(filename, self.
namespace)
260 if frame.package ==
"" and frame.path !=
"":
264 from python_qt_binding
import QtWidgets
265 rospackage = rospkg.get_package_name(frame.path)
266 if rospackage
is not None:
267 rel_path = os.path.relpath(frame.path , rospkg.RosPack().get_path(rospackage))
268 reply = QtWidgets.QMessageBox.question(
None,
"Convert absolute path to rospack+relative path?",
269 "The absolute path to your selected mesh can be converted to rospack+relative path."+
270 "This gives you more reliabilaty to reuse your saved configuration"+
271 "if your meshes are stored in rospackages\n\n"+
272 "Do you want to convert your configuration?\n"+
273 "Convert:\n'{}'\nto:\n'{}' and\n '{}'\n".format(frame.path, rospackage, rel_path),
274 QtWidgets.QMessageBox.Yes |
275 QtWidgets.QMessageBox.No,
276 QtWidgets.QMessageBox.Yes)
278 if reply == QtWidgets.QMessageBox.Yes:
279 print(
"Saving: package: {} + relative path: {}".format(rospackage, rel_path))
280 frame.package = rospackage
281 frame.path = rel_path
291 print(
"> Going for some spins")
292 rate = rospy.Rate(200)
293 while not rospy.is_shutdown():
301 from argparse
import ArgumentParser
302 parser = ArgumentParser()
307 parser.add_argument(
"-l",
"--load", action=
"append",
309 help=
"Load a file at startup. [rospack filepath/file]")
311 args, unknowns = parser.parse_known_args(argv)
312 print(
'arguments: {}'.format(args))
314 print(
'unknown parameters found: {}'.format(unknowns))
319 arg_path = args.file[0].split()
320 if len(arg_path) == 1:
322 filename = arg_path[0]
323 print(
"Loading {}".format(filename))
325 elif len(arg_path) == 2:
327 rospack = rospkg.RosPack()
328 filename = os.path.join(rospack.get_path(arg_path[0]), arg_path[1])
329 print(
"Loading {}".format(filename))
332 print(
"Load argument not understood! --load {}".format(arg_path))
333 print(
"Please use --load 'myRosPackage pathInMyPackage/myYaml.yaml'")
334 print(
"or use --load 'fullPathToMyYaml.yaml'")
339 elif success ==
False:
340 print(
"ERROR LOADING FILE")
350 if __name__ ==
"__main__":
352 rospy.init_node(
'frame_editor')
357 editor.parse_args(sys.argv[1:])
360 print(
"Frame editor ready!")
def load_params(self, namespace)
def load_file(self, file_name)
FILE I/O ##.
def command(self, command)
def frame_is_temporary(frame_id)
def parse_args(self, argv)
Process standalone plugin command-line arguments.
def undo_stack_changed(self, idx)
Undo/Redo ##.
def add_undo_level(self, level, elements=None)
def update_file_format(self, frame)
def load_data(self, data)
def save_file(self, filename)
def iter_frames(self, include_temp=True)
full_file_path
Clear everything.
def print_all(self)
PRINT ##.
def all_frame_ids(include_temp=True)
def get_full_file_path(self)
def update_obsevers(self, level)