diff --git a/python/examples/comparing_logs_example.py b/python/examples/comparing_logs_example.py index c59097852b909e385717e42dec7a4779de0de1a0..3a8ca95e5f2d01570c7b9335f7b664045f600cda 100644 --- a/python/examples/comparing_logs_example.py +++ b/python/examples/comparing_logs_example.py @@ -17,7 +17,7 @@ and that the same things are logged. key = list(cmp_manager.logm1.loop_logs.keys())[0] cmp_manager.createRunningPlot(cmp_manager.logm1.loop_logs[key], 0, len(cmp_manager.logm1.loop_logs[key]['qs'])) -cmp_manager.createRunningPlot(cmp_manager.logm2.loop_logs[key], 0, len(cmp_manager.logm2.loop_logs[key]['qs'])) +#cmp_manager.createRunningPlot(cmp_manager.logm2.loop_logs[key], 0, len(cmp_manager.logm2.loop_logs[key]['qs'])) cmp_manager.visualizeWholeRuns() cmp_manager.manipulator_visualizer_cmd_queue.put("befree") print("main done") diff --git a/python/ur_simple_control/visualize/__pycache__/visualize.cpython-312.pyc b/python/ur_simple_control/visualize/__pycache__/visualize.cpython-312.pyc index cdb303e8174d784085e917dde458ea4c3b6b14d9..87272c72c0cd219d816377f13d47be8b84d16980 100644 Binary files a/python/ur_simple_control/visualize/__pycache__/visualize.cpython-312.pyc and b/python/ur_simple_control/visualize/__pycache__/visualize.cpython-312.pyc differ diff --git a/python/ur_simple_control/visualize/manipulator_comparison_visualizer.py b/python/ur_simple_control/visualize/manipulator_comparison_visualizer.py index 9537c1573b4cd6ace510792eeb22e1f23c9d07f1..5b6415d36806149fd3b3c298a39c29ed60116294 100644 --- a/python/ur_simple_control/visualize/manipulator_comparison_visualizer.py +++ b/python/ur_simple_control/visualize/manipulator_comparison_visualizer.py @@ -6,7 +6,7 @@ from itertools import zip_longest from multiprocessing import Process, Queue from ur_simple_control.managers import getMinimalArgParser, RobotManager from ur_simple_control.util.logging_utils import LogManager -from ur_simple_control.visualize.visualize import manipulatorComparisonVisualizer, logPlotter +from ur_simple_control.visualize.visualize import manipulatorComparisonVisualizer, LogPlotter def getLogComparisonArgs(): parser = getMinimalArgParser() @@ -78,7 +78,7 @@ class ManipulatorComparisonManager: ########################################### # in case you will want log plotters too # ########################################### - self.log_plotters = [] + self.running_plotters = [] # NOTE i assume what you want to plot is a time-indexed with @@ -91,21 +91,22 @@ class ManipulatorComparisonManager: self.time_stop = log_plotter_time_stop self.cmd_queue = Queue() self.ack_queue = Queue() - self.process = Process(target=logPlotter, - args=(args, log, self.cmd_queue, + log_plotter = LogPlotter(args, log) + self.process = Process(target=log_plotter.runLogPlotter, + args=(self.cmd_queue, self.ack_queue)) self.process.start() self.ack_queue.get() def createRunningPlot(self, log, log_plotter_time_start, log_plotter_time_stop): - self.log_plotters.append(self.RunningPlotter(self.args, log, log_plotter_time_start, log_plotter_time_stop)) + self.running_plotters.append(self.RunningPlotter(self.args, log, log_plotter_time_start, log_plotter_time_stop)) def updateViz(self, q1, q2, time_index): self.manipulator_visualizer_cmd_queue.put((q1, q2)) - for log_plotter in self.log_plotters: - if (time_index >= log_plotter.time_start) and (time_index < log_plotter.time_stop): - log_plotter.cmd_queue.put(time_index - log_plotter.time_start) - log_plotter.ack_queue.get() + for running_plotter in self.running_plotters: + if (time_index >= running_plotter.time_start) and (time_index < running_plotter.time_stop): + running_plotter.cmd_queue.put(time_index - running_plotter.time_start) + running_plotter.ack_queue.get() self.manipulator_visualizer_ack_queue.get() # NOTE: this uses slightly fancy python to make it bareable to code diff --git a/python/ur_simple_control/visualize/visualize.py b/python/ur_simple_control/visualize/visualize.py index 6d1cfde6bbbbe4a4a7780e4fc7713f79819658d6..6b51acfcb131f5089d3bf3db45a8e4a98795783d 100644 --- a/python/ur_simple_control/visualize/visualize.py +++ b/python/ur_simple_control/visualize/visualize.py @@ -305,7 +305,7 @@ def manipulatorComparisonVisualizer(args, model, collision_model, visual_model, # but otherwise i can't pass arguments to that. # even if i could with partial, i can't return them, # so no cigar from that -def logPlotter(args, log, cmd_queue, ack_queue): +class LogPlotter: """ logPlotter --------------- @@ -318,90 +318,89 @@ def logPlotter(args, log, cmd_queue, ack_queue): as then you don't need to think about IPC - just use what's here. - this might be shoved into a tkinter gui if i decide i really need buttons """ - if len(log) == 0: - print("you've send me nothing, so no real-time plotting for you") - return + def __init__(self, args, log): + self.log = log + self.args = args + if len(self.log) == 0: + print("you've send me nothing, so no real-time plotting for you") + return - plt.ion() - fig = plt.figure() - canvas = fig.canvas - AxisAndArtists = namedtuple("AxAndArtists", "ax artists") - axes_and_updating_artists = {} + plt.ion() + self.fig = plt.figure() + self.canvas = self.fig.canvas + self.AxisAndArtists = namedtuple("AxAndArtists", "ax artists") + self.axes_and_updating_artists = {} - n_cols, n_rows = getNRowsMColumnsFromTotalNumber(len(log)) - # this is what subplot wants - subplot_col_row = str(n_cols) + str(n_rows) - # preload some zeros and initialize plots - for i, data_key in enumerate(log): - # you give single-vector numpy arrays, i instantiate and plot lists of these - # so for your (6,) vector, i plot (N, 6) ndarrays resulting in 6 lines of length N. - # i manage N because plot data =/= all data for efficiency reasons. - assert type(log[data_key]) == np.ndarray + n_cols, n_rows = getNRowsMColumnsFromTotalNumber(len(log)) + # this is what subplot wants + subplot_col_row = str(n_cols) + str(n_rows) + # preload some zeros and initialize plots + for i, data_key in enumerate(self.log): + # you give single-vector numpy arrays, i instantiate and plot lists of these + # so for your (6,) vector, i plot (N, 6) ndarrays resulting in 6 lines of length N. + # i manage N because plot data =/= all data for efficiency reasons. + assert type(self.log[data_key]) == np.ndarray - colors = plt.cm.jet(np.linspace(0, 1, log[data_key].shape[1])) - ax = fig.add_subplot(int(subplot_col_row + str(i + 1))) - ax.set_title(data_key) - # we plot each line separately so that they have different colors - # we assume (N_timesteps, your_vector) shapes. - # values do not update - for j in range(log[data_key].shape[1]): - # NOTE the same length assumption plays a part for correctness, - # but i don't want that to be an error in case you know what you're doing - ax.plot(np.arange(len(log[data_key])), log[data_key][:,j], - color=colors[j], label=data_key + "_" + str(j)) + colors = plt.cm.jet(np.linspace(0, 1, log[data_key].shape[1])) + ax = self.fig.add_subplot(int(subplot_col_row + str(i + 1))) + ax.set_title(data_key) + # we plot each line separately so that they have different colors + # we assume (N_timesteps, your_vector) shapes. + # values do not update + for j in range(log[data_key].shape[1]): + # NOTE the same length assumption plays a part for correctness, + # but i don't want that to be an error in case you know what you're doing + ax.plot(np.arange(len(log[data_key])), log[data_key][:,j], + color=colors[j], label=data_key + "_" + str(j)) - # vertical bar does update - point_in_time_line = ax.axvline(x=0, color='red', animated=True) - axes_and_updating_artists[data_key] = AxisAndArtists(ax, point_in_time_line) - axes_and_updating_artists[data_key].ax.legend(loc='upper left') + # vertical bar does update + point_in_time_line = ax.axvline(x=0, color='red', animated=True) + self.axes_and_updating_artists[data_key] = self.AxisAndArtists(ax, point_in_time_line) + self.axes_and_updating_artists[data_key].ax.legend(loc='upper left') - # need to call it once to start, more if something breaks - canvas.draw() - canvas.flush_events() - background = canvas.copy_from_bbox(fig.bbox) + # need to call it once to start, more if something breaks + self.canvas.draw() + self.canvas.flush_events() + self.background = self.canvas.copy_from_bbox(self.fig.bbox) - # we need to have an event that triggers redrawing - #cid = fig.canvas.mpl_connect('button_press_event', onclick) - def onEvent(event): - print("drawing") - canvas.draw() - canvas.flush_events() - background = canvas.copy_from_bbox(fig.bbox) - print("copied canvas") + # we need to have an event that triggers redrawing + #cid = fig.canvas.mpl_connect('button_press_event', onclick) - cid = fig.canvas.mpl_connect('button_press_event', onEvent) + self.cid = self.fig.canvas.mpl_connect('button_press_event', self.onEvent) + self.cid = self.fig.canvas.mpl_connect('resize_event', self.onEvent) + def onEvent(self, event): + print("re-drawing") + self.canvas.draw() + self.canvas.flush_events() + self.background = self.canvas.copy_from_bbox(self.fig.bbox) - ack_queue.put("ready") - if args.debug_prints: - print("LOG_PLOTTER: FULLY ONLINE") - try: - counter = 0 - while True: - counter += 1 - time_index = cmd_queue.get() - if time_index == "befree": - if args.debug_prints: - print("LOG_PLOTTER: got befree, logPlotter out") - break - canvas.restore_region(background) - for data_key in log: - axes_and_updating_artists[data_key].artists.set_xdata([time_index]) - axes_and_updating_artists[data_key].ax.draw_artist(axes_and_updating_artists[data_key].artists) - # NOTE: this is stupid, i just want to catch the resize event - if not (counter % 50 == 0): - #if True: + def runLogPlotter(self, cmd_queue, ack_queue): + ack_queue.put("ready") + if self.args.debug_prints: + print("LOG_PLOTTER: FULLY ONLINE") + try: + counter = 0 + while True: + counter += 1 + time_index = cmd_queue.get() + if time_index == "befree": + if self.args.debug_prints: + print("LOG_PLOTTER: got befree, logPlotter out") + break + self.canvas.restore_region(self.background) + for data_key in self.log: + self.axes_and_updating_artists[data_key].artists.set_xdata([time_index]) + self.axes_and_updating_artists[data_key].ax.draw_artist(self.axes_and_updating_artists[data_key].artists) + # NOTE: this is stupid, i just want to catch the resize event print(counter) - canvas.blit(fig.bbox) - canvas.flush_events() - else: - print("drawing") - canvas.draw() - canvas.flush_events() - background = canvas.copy_from_bbox(fig.bbox) - print("copied canvas") - ack_queue.put("ready") - except KeyboardInterrupt: - if args.debug_prints: - print("LOG_PLOTTER: caught KeyboardInterrupt, i'm out") - plt.close(fig) + #self.canvas.blit(self.fig.bbox) + #self.canvas.flush_events() + self.onEvent(None) + print("putting ready") + ack_queue.put("ready") + print("put ready") + except KeyboardInterrupt: + if self.args.debug_prints: + print("LOG_PLOTTER: caught KeyboardInterrupt, i'm out") + plt.close(self.fig)