From 61891e86beb0d2b7fe2d904cb73b4272fd96fa09 Mon Sep 17 00:00:00 2001 From: m-guberina <gubi.guberina@gmail.com> Date: Mon, 27 Nov 2023 12:58:54 +0100 Subject: [PATCH] more changes --- .../manipulator_visual_motion_analyzer.py | 433 +++++++++--------- 1 file changed, 211 insertions(+), 222 deletions(-) diff --git a/python/ur_simple_control/visualize/manipulator_visual_motion_analyzer.py b/python/ur_simple_control/visualize/manipulator_visual_motion_analyzer.py index 11fb982..1442111 100644 --- a/python/ur_simple_control/visualize/manipulator_visual_motion_analyzer.py +++ b/python/ur_simple_control/visualize/manipulator_visual_motion_analyzer.py @@ -148,16 +148,16 @@ class ManipulatorVisualMotionAnalyzer: # LAYOUT OF THE GUI # # putting plots into: frames -> notebooks -> tabs # ##################################################### - self.notebook_left = Notebook(root, height=int(SCREEN_HEIGHT)) - self.notebook_right = Notebook(root, height=int(SCREEN_HEIGHT)) - self.frame_manipulator = Frame(notebook_left) - self.frame_manip_graphs = Frame(notebook_right) - self.frame_imu = Frame(notebook_right) - self.frame_ee = Frame(notebook_left) - self.tabs_left = notebook_left.add(frame_manipulator, text='manipulator') - self.tabs_left = notebook_left.add(frame_ee, text="end-effector") - self.tabs_right = notebook_right.add(frame_manip_graphs, text='manipulator-graphs') - self.tabs_right = notebook_right.add(frame_imu, text="ee-graphs") + self.notebook_left = Notebook(root, height=int(self.SCREEN_HEIGHT)) + self.notebook_right = Notebook(root, height=int(self.SCREEN_HEIGHT)) + self.frame_manipulator = Frame(self.notebook_left) + self.frame_manip_graphs = Frame(self.notebook_right) + self.frame_imu = Frame(self.notebook_right) + self.frame_ee = Frame(self.notebook_left) + self.tabs_left = self.notebook_left.add(self.frame_manipulator, text='manipulator') + self.tabs_left = self.notebook_left.add(self.frame_ee, text="end-effector") + self.tabs_right = self.notebook_right.add(self.frame_manip_graphs, text='manipulator-graphs') + self.tabs_right = self.notebook_right.add(self.frame_imu, text="ee-graphs") self.notebook_left.grid(row=0, column=0, sticky='ew') self.notebook_right.grid(row=0, column=1, sticky='ew') @@ -201,6 +201,11 @@ class ManipulatorVisualMotionAnalyzer: self.fig_ee = Figure(figsize=(SCREEN_WIDTH/DPI*SCALING_FACTOR_WIDTH, SCREEN_HEIGHT/DPI*SCALING_FACTOR_HEIGHT), dpi=DPI) self.rec3D_ax = self.fig_ee.add_subplot(projection='3d') self.rec3D_ax.set(xticklabels=[], yticklabels=[], zticklabels=[]) + self.canvas_ee = FigureCanvasTkAgg(self.fig_ee, master=self.frame_ee) + self.canvas_ee_widget = self.canvas_ee.get_tk_widget() + self.canvas_ee_widget.grid(row=0, column=0) + self.canvas_ee._tkcanvas.grid(row=1, column=0) + self.canvas_ee.draw() ####################################################################### # MANIPULATOR PLOT # @@ -252,6 +257,21 @@ class ManipulatorVisualMotionAnalyzer: color='pink', linewidth=0.1, alpha=0.3, shade=True)) + # tkinterize the figure/canvas + self.canvas_manipulator = FigureCanvasTkAgg(self.fig_manipulator, master=self.frame_manipulator) + # need to hit it with the first draw before saving background + self.canvas_manipulator.draw() + # save background - in manual blitting you reload and update yourself + self.background_manipulator = self.canvas_manipulator.copy_from_bbox(self.fig_manipulator.bbox) + # take and put the matplotlib toolbar below the plot. + # these are quite nifty (zooming, adjusting axes etc) + self.canvas_manipulator_widget = self.canvas_manipulator.get_tk_widget() + self.canvas_manipulator_widget.grid(row=0, column=0) + self.canvas_manipulator._tkcanvas.grid(row=1, column=0) + # i probably don't need this draw, but who cares + self.canvas_manipulator.draw() + + ####################################################################### # manipulability plots # ####################################################################### @@ -298,6 +318,13 @@ class ManipulatorVisualMotionAnalyzer: dist_to_goal_lines.append(dist_to_goal_line) # TODO: blit this line self.point_in_time_dist_to_goal_line = ax.axvline(x=0, color='red') + # tkinterize canvas + self.canvas_manip_graphs = FigureCanvasTkAgg(self.fig_manip_graphs, master=self.frame_manip_graphs) + # put matplotlib toolbar below the plot + self.canvas_manip_graphs_widget = self.canvas_manip_graphs.get_tk_widget() + self.canvas_manip_graphs_widget.grid(row=0, column=0) + self.canvas_manip_graphs._tkcanvas.grid(row=1, column=0) + self.canvas_manip_graphs.draw() ####################################################################### @@ -357,220 +384,28 @@ class ManipulatorVisualMotionAnalyzer: self.point_in_time_ax_omega_y_line = ax_omega_y.axvline(x=0, color='red') self.point_in_time_ax_omega_z_line = ax_omega_z.axvline(x=0, color='red') + self.canvas_imu = FigureCanvasTkAgg(self.fig_imu, master=self.frame_imu) + self.canvas_imu_widget = self.canvas_manip_graphs.get_tk_widget() + self.canvas_imu_widget.grid(row=0, column=0) + self.canvas_imu._tkcanvas.grid(row=1, column=0) + self.canvas_imu.draw() + + # i don't even remember what these toolbars are lol + # pack_toolbar=False will make it easier to use a layout manager later on. + toolbar_manipulator = NavigationToolbar2Tk(canvas_manipulator, frame_manipulator, pack_toolbar=False) + toolbar_manipulator.update() + toolbar_manipulator.grid(column=0, row=2) + toolbar_manip_graphs = NavigationToolbar2Tk(canvas_manip_graphs, frame_manip_graphs, pack_toolbar=False) + toolbar_manip_graphs.update() + toolbar_manip_graphs.grid(column=0, row=2) + toolbar_ee = NavigationToolbar2Tk(canvas_ee, frame_ee, pack_toolbar=False) + toolbar_ee.update() + toolbar_ee.grid(column=0, row=2) + toolbar_imu = NavigationToolbar2Tk(canvas_imu, frame_imu, pack_toolbar=False) + toolbar_imu.update() + toolbar_imu.grid(column=0, row=2) -# tkinterize these plots -canvas_manipulator = FigureCanvasTkAgg(fig_manipulator, master=frame_manipulator) -canvas_manipulator.draw() -# NEW -# TODO maybe you want another background idk -# worked elsewhere with figure.bbox -background_manipulator = canvas_manipulator.copy_from_bbox(fig_manipulator.bbox) -#background_manipulator = canvas_manipulator.copy_from_bbox(canvas_manipulator.bbox) - -canvas_manipulator_widget = canvas_manipulator.get_tk_widget() -canvas_manipulator_widget.grid(row=0, column=0) -canvas_manipulator._tkcanvas.grid(row=1, column=0) -canvas_manipulator.draw() - -canvas_ee = FigureCanvasTkAgg(fig_ee, master=frame_ee) -canvas_ee_widget = canvas_ee.get_tk_widget() -canvas_ee_widget.grid(row=0, column=0) -canvas_ee._tkcanvas.grid(row=1, column=0) -canvas_ee.draw() - -canvas_manip_graphs = FigureCanvasTkAgg(fig_manip_graphs, master=frame_manip_graphs) -canvas_manip_graphs_widget = canvas_manip_graphs.get_tk_widget() -canvas_manip_graphs_widget.grid(row=0, column=0) -canvas_manip_graphs._tkcanvas.grid(row=1, column=0) -canvas_manip_graphs.draw() - -canvas_imu = FigureCanvasTkAgg(self.fig_imu, master=frame_imu) -canvas_imu_widget = canvas_manip_graphs.get_tk_widget() -canvas_imu_widget.grid(row=0, column=0) -canvas_imu._tkcanvas.grid(row=1, column=0) -canvas_imu.draw() - -# pack_toolbar=False will make it easier to use a layout manager later on. -toolbar_manipulator = NavigationToolbar2Tk(canvas_manipulator, frame_manipulator, pack_toolbar=False) -toolbar_manipulator.update() -toolbar_manipulator.grid(column=0, row=2) -toolbar_manip_graphs = NavigationToolbar2Tk(canvas_manip_graphs, frame_manip_graphs, pack_toolbar=False) -toolbar_manip_graphs.update() -toolbar_manip_graphs.grid(column=0, row=2) -toolbar_ee = NavigationToolbar2Tk(canvas_ee, frame_ee, pack_toolbar=False) -toolbar_ee.update() -toolbar_ee.grid(column=0, row=2) -toolbar_imu = NavigationToolbar2Tk(canvas_imu, frame_imu, pack_toolbar=False) -toolbar_imu.update() -toolbar_imu.grid(column=0, row=2) - -####################################################################### -# functions for widgets to control the plots # -####################################################################### - -# keyboard inputs -# whatever, doesn't hurt, could be used -#canvas.mpl_connect( -# "key_press_event", lambda event: print(f"you pressed {event.key}")) -#canvas.mpl_connect("key_press_event", key_press_handler) - -# new_val is what the widget gives you -# you define what needs to happen to plots in Figure below, -# and call canvas.draw -def update_points(new_val): -# ee plot -########################################################################### - start = ttime.time() - #fig_manipulator.canvas.restore_region(background_manipulator) - canvas_manipulator.restore_region(background_manipulator) - index = int(np.floor(float(new_val))) - - # Update 3D reconstruction plot - # plot3D_camera(recP[index], scale=scale) -# C, Q = camera_data_for_plot3D(recP[cam_indices[index]]) -# camera_center.set_data_3d(*C) -# C = C.flatten() -# for ii in range(len(camera_coordinate_system)): -# camera_coordinate_system[ii].set_data([C[0], C[0] + scale * Q[0,ii]], -# [C[1], C[1] + scale * Q[1,ii]]) -# camera_coordinate_system[ii].set_3d_properties([C[2], C[2] + scale * Q[2,ii]]) -# recX_ = recX[:,X_indices[:num_pts_subset*(index+1)]] -# rec_points3D.set_data_3d(recX_[0,:], recX_[1,:], recX_[2,:]) -########################################################################### - - ik_env.ax.set_title(str(index) + 'th iteration toward goal') - # animate 3d manipulator - for robot_index, robot in enumerate(ik_env.robots): - ik_env.robots[robot_index].setJoints(ik_env.data[robot_index]["qs"][index]) - ik_env.robots[robot_index].drawStateAnim() - - # NEW AND BROKEN - for link in robot.lines: - for line in link: - ik_env.ax.draw_artist(line) - # all these are in lists as that's what the line plot wants, - # despite the fact that we have single points - point_in_time_eigen1_line.set_xdata([time[index]]) - point_in_time_manip_index_line.set_xdata([time[index]]) - point_in_time_dist_to_goal_line.set_xdata([time[index]]) - point_in_time_ax_v_x_line.set_xdata([time[index]]) - point_in_time_ax_v_y_line.set_xdata([time[index]]) - point_in_time_ax_v_z_line.set_xdata([time[index]]) - point_in_time_ax_omega_x_line.set_xdata([time[index]]) - point_in_time_ax_omega_y_line.set_xdata([time[index]]) - point_in_time_ax_omega_z_line.set_xdata([time[index]]) - - # ellipsoid update - radii = 1.0/ik_env.data[robot_index]["manip_ell_eigenvals"][index] * 0.1 - u = np.linspace(0.0, 2.0 * np.pi, 60) - v = np.linspace(0.0, np.pi, 60) - x = radii[0] * np.outer(np.cos(u), np.sin(v)) - y = radii[1] * np.outer(np.sin(u), np.sin(v)) - z = radii[2] * np.outer(np.ones_like(u), np.cos(v)) - for i in range(len(x)): - for j in range(len(x)): - [x[i,j],y[i,j],z[i,j]] = np.dot([x[i,j],y[i,j],z[i,j]], ik_env.data[robot_index]["manip_elip_svd_rots"][index]) + ik_env.data[robot_index]['p_es'][index] - - if ellipse_on_off_var.get(): - try: - ik_env.ellipsoid_surf_plots[robot_index].remove() - except ValueError: - pass - ik_env.ellipsoid_surf_plots[robot_index] = ik_env.ax.plot_surface(x, y, z, rstride=3, cstride=3, - color='pink', linewidth=0.1, - alpha=0.3, shade=True) - - ik_env.p_e_point_plots[robot_index].set_data([ik_env.data[robot_index]['p_es'][index][0]], [ik_env.data[robot_index]['p_es'][index][1]]) - ik_env.p_e_point_plots[robot_index].set_3d_properties([ik_env.data[robot_index]['p_es'][index][2]]) - canvas_ee.draw() - # NEW AND BROKEN -# fig_manipulator.canvas.blit(fig_manipulator.bbox) -# fig_manipulator.canvas.flush_events() - canvas_manipulator.blit(fig_manipulator.bbox) - canvas_manipulator.flush_events() - #canvas_manipulator.draw() - # might need to manually update all artists here from ax_something - #canvas_manipulator.blit(fig_manipulator.bbox) - canvas_manip_graphs.draw() - canvas_imu.draw() - # TODO update may not be needed as we're going by slider here - root.update() - end = ttime.time() - print("time per update:", end - start) - print("fps", 1 / (end - start)) - - -def update_goal_x(new_val): - goal_x = float(new_val) - ik_env.goal[0] = goal_x - ik_env.goal_point_plot.set_data([ik_env.goal[0]], [ik_env.goal[1]]) - ik_env.goal_point_plot.set_3d_properties([ik_env.goal[2]]) - canvas_ee.draw() - canvas_manipulator.draw() - canvas_manip_graphs.draw() - # TODO update may not be needed as we're going by slider here - root.update() - -def update_goal_y(new_val): - goal_y = float(new_val) - ik_env.goal[1] = goal_y - ik_env.goal_point_plot.set_data([ik_env.goal[0]], [ik_env.goal[1]]) - ik_env.goal_point_plot.set_3d_properties([ik_env.goal[2]]) - canvas_ee.draw() - canvas_manipulator.draw() - canvas_manip_graphs.draw() - # TODO update may not be needed as we're going by slider here - root.update() - -def update_goal_z(new_val): - goal_z = float(new_val) - ik_env.goal[2] = goal_z - ik_env.goal_point_plot.set_data([ik_env.goal[0]], [ik_env.goal[1]]) - ik_env.goal_point_plot.set_3d_properties([ik_env.goal[2]]) - canvas_ee.draw() - canvas_manipulator.draw() - canvas_manip_graphs.draw() - # TODO update may not be needed as we're going by slider here - root.update() - - - -def reset(): - ik_env.reset() -# ik_env.goal_point_plot.remove() -# ik_env.goal_point_plot = drawPoint(ik_env.ax, ik_env.goal, 'red', 'o') -# print(controller_string1.get()) -# print(controller_string2.get()) - controller1 = getController(controller_string1.get()) - controller2 = getController(controller_string2.get()) - controllers = [controller1, controller2] - for robot_index, robot in enumerate(ik_env.robots): - ik_env.data.append(makeRun(controllers[robot_index], ik_env, n_iters, robot_index)) - trajectory_plots[robot_index].set_data(ik_env.data[robot_index]['p_es'][:,0], ik_env.data[robot_index]['p_es'][:,1]) - trajectory_plots[robot_index].set_3d_properties(ik_env.data[robot_index]['p_es'][:,2]) - eigen1_lines[robot_index].set_ydata(ik_env.data[robot_index]["manip_ell_eigenvals"][:,0]) - eigen2_lines[robot_index].set_ydata(ik_env.data[robot_index]["manip_ell_eigenvals"][:,1]) - eigen3_lines[robot_index].set_ydata(ik_env.data[robot_index]["manip_ell_eigenvals"][:,2]) - manip_index_lines[robot_index].set_ydata(ik_env.data[robot_index]['manip_indeces']) - dist_to_goal_lines[robot_index].set_ydata(ik_env.data[robot_index]['dists_to_goal']) - update_points(0) - canvas_ee.draw() - canvas_manipulator.draw() - canvas_manip_graphs.draw() - root.update() - -def play(): - pass - -# ellipse on/off -def add_remove_ellipse(): - try: - for robot_index, robot in enumerate(ik_env.robots): - ik_env.ellipsoid_surf_plots[robot_index].remove() - except ValueError: - pass - # NOTE: this thing is not used same_starting_position_on_off_var = IntVar() @@ -586,6 +421,7 @@ same_starting_position_checkbutton= Checkbutton(root, text = "same starting posi ####################################################################### # PLACING ELEMENTS IN THE GUI # ####################################################################### + # TODO put this into init # LEFT PANE BELOW MANIP/EE PLOTS frame_below_manipulator_plot = Frame(frame_manipulator) @@ -697,6 +533,159 @@ slider_goal_x.set(ik_env.goal[0]) slider_goal_y.set(ik_env.goal[1]) slider_goal_z.set(ik_env.goal[2]) + + +####################################################################### +# functions for widgets to control the plots # +####################################################################### + +# keyboard inputs +# whatever, doesn't hurt, could be used +#canvas.mpl_connect( +# "key_press_event", lambda event: print(f"you pressed {event.key}")) +#canvas.mpl_connect("key_press_event", key_press_handler) + +# new_val is what the widget gives you +# you define what needs to happen to plots in Figure below, +# and call canvas.draw + def update_points(self, new_val): + start = ttime.time() + #fig_manipulator.canvas.restore_region(background_manipulator) + self.canvas_manipulator.restore_region(self.background_manipulator) + index = int(np.floor(float(new_val))) + # ee plot here, but NOTE: UNUSED + + self.ik_env.ax.set_title(str(index) + 'th iteration toward goal') + # animate 3d manipulator + for robot_index, robot in enumerate(self.ik_env.robots): + self.ik_env.robots[robot_index].setJoints(self.ik_env.data[robot_index]["qs"][index]) + self.ik_env.robots[robot_index].drawStateAnim() + + # NEW AND BROKEN + for link in robot.lines: + for line in link: + self.ik_env.ax.draw_artist(line) + # all these are in lists as that's what the line plot wants, + # despite the fact that we have single points + self.point_in_time_eigen1_line.set_xdata([time[index]]) + self.point_in_time_manip_index_line.set_xdata([time[index]]) + self.point_in_time_dist_to_goal_line.set_xdata([time[index]]) + self.point_in_time_ax_v_x_line.set_xdata([time[index]]) + self.point_in_time_ax_v_y_line.set_xdata([time[index]]) + self.point_in_time_ax_v_z_line.set_xdata([time[index]]) + self.point_in_time_ax_omega_x_line.set_xdata([time[index]]) + self.point_in_time_ax_omega_y_line.set_xdata([time[index]]) + self.point_in_time_ax_omega_z_line.set_xdata([time[index]]) + + # ellipsoid update + radii = 1.0/self.ik_env.data[robot_index]["manip_ell_eigenvals"][index] * 0.1 + u = np.linspace(0.0, 2.0 * np.pi, 60) + v = np.linspace(0.0, np.pi, 60) + x = radii[0] * np.outer(np.cos(u), np.sin(v)) + y = radii[1] * np.outer(np.sin(u), np.sin(v)) + z = radii[2] * np.outer(np.ones_like(u), np.cos(v)) + for i in range(len(x)): + for j in range(len(x)): + [x[i,j],y[i,j],z[i,j]] = np.dot([x[i,j],y[i,j],z[i,j]], self.ik_env.data[robot_index]["manip_elip_svd_rots"][index]) + self.ik_env.data[robot_index]['p_es'][index] + + if self.ellipse_on_off_var.get(): + try: + self.ik_env.ellipsoid_surf_plots[robot_index].remove() + except ValueError: + pass + self.ik_env.ellipsoid_surf_plots[robot_index] = self.ik_env.ax.plot_surface(x, y, z, rstride=3, cstride=3, + color='pink', linewidth=0.1, + alpha=0.3, shade=True) + + self.ik_env.p_e_point_plots[robot_index].set_data([ik_env.data[robot_index]['p_es'][index][0]], [ik_env.data[robot_index]['p_es'][index][1]]) + self.ik_env.p_e_point_plots[robot_index].set_3d_properties([ik_env.data[robot_index]['p_es'][index][2]]) + # TODO: blit the rest + canvas_manipulator.blit(fig_manipulator.bbox) + canvas_manipulator.flush_events() + canvas_manip_graphs.draw() + # non blitted (bad) + canvas_imu.draw() + self.canvas_ee.draw() + # TODO update may not be needed as we're going by slider here + root.update() + end = ttime.time() + print("time per update:", end - start) + print("fps", 1 / (end - start)) + + + def update_goal_x(self, new_val): + goal_x = float(new_val) + self.ik_env.goal[0] = goal_x + self.ik_env.goal_point_plot.set_data([self.ik_env.goal[0]], [self.ik_env.goal[1]]) + self.ik_env.goal_point_plot.set_3d_properties([self.ik_env.goal[2]]) + self.canvas_ee.draw() + self.canvas_manipulator.draw() + self.canvas_manip_graphs.draw() + # TODO update may not be needed as we're going by slider here + self.root.update() + + def update_goal_y(self, new_val): + goal_y = float(new_val) + self.ik_env.goal[1] = goal_y + self.ik_env.goal_point_plot.set_data([self.ik_env.goal[0]], [self.ik_env.goal[1]]) + self.ik_env.goal_point_plot.set_3d_properties([self.ik_env.goal[2]]) + self.canvas_ee.draw() + self.canvas_manipulator.draw() + self.canvas_manip_graphs.draw() + # TODO update may not be needed as we're going by slider here + self.root.update() + + def update_goal_z(self, new_val): + goal_z = float(new_val) + self.ik_env.goal[2] = goal_z + self.ik_env.goal_point_plot.set_data([self.ik_env.goal[0]], [self.ik_env.goal[1]]) + self.ik_env.goal_point_plot.set_3d_properties([self.ik_env.goal[2]]) + self.canvas_ee.draw() + self.canvas_manipulator.draw() + self.canvas_manip_graphs.draw() + # TODO update may not be needed as we're going by slider here + self.root.update() + + + +# TODO fix + def reset(): + ik_env.reset() + # ik_env.goal_point_plot.remove() + # ik_env.goal_point_plot = drawPoint(ik_env.ax, ik_env.goal, 'red', 'o') + # print(controller_string1.get()) + # print(controller_string2.get()) + controller1 = getController(controller_string1.get()) + controller2 = getController(controller_string2.get()) + controllers = [controller1, controller2] + for robot_index, robot in enumerate(ik_env.robots): + ik_env.data.append(makeRun(controllers[robot_index], ik_env, n_iters, robot_index)) + trajectory_plots[robot_index].set_data(ik_env.data[robot_index]['p_es'][:,0], ik_env.data[robot_index]['p_es'][:,1]) + trajectory_plots[robot_index].set_3d_properties(ik_env.data[robot_index]['p_es'][:,2]) + eigen1_lines[robot_index].set_ydata(ik_env.data[robot_index]["manip_ell_eigenvals"][:,0]) + eigen2_lines[robot_index].set_ydata(ik_env.data[robot_index]["manip_ell_eigenvals"][:,1]) + eigen3_lines[robot_index].set_ydata(ik_env.data[robot_index]["manip_ell_eigenvals"][:,2]) + manip_index_lines[robot_index].set_ydata(ik_env.data[robot_index]['manip_indeces']) + dist_to_goal_lines[robot_index].set_ydata(ik_env.data[robot_index]['dists_to_goal']) + update_points(0) + canvas_ee.draw() + canvas_manipulator.draw() + canvas_manip_graphs.draw() + root.update() + + def play(): + pass + + # ellipse on/off + def add_remove_ellipse(): + try: + for robot_index, robot in enumerate(ik_env.robots): + ik_env.ellipsoid_surf_plots[robot_index].remove() + except ValueError: + pass + + + if name == "__main__": queue = Queue() root = Tk() -- GitLab