After being able to draw lines with varying intensity, we started building a graphical user interface, to control the robotic arm more efficiently. The two libraries we decided to use are Tkinter for the interface, and Matplotlib for graphing. At first, we simply built a text field that takes in float numbers for controlling the robot's wrist torque. We then added three buttons, which, respectively, starts the grip, moves the wrist according to the decimal numbers in the text field, and stops all motors - our supervisor was delighted with our work.
Then, over the weekend, we upgraded our GUI by adding a real-time graphing function. Earlier in this project, we monitored our motor's functionality by looking at the position-vs-time, velocity-vs-time, and current-ve-time graphs of each motor movement. We were able to observe the smoothness of the rotation and in which direction the motors are moving. Making this, we fed the y-axis of each graph with a list of data, and set the x-axis as time.
ani = animation.FuncAnimation(fig, animate, interval=1000)
In essence, this "real-time" component of this graphing feature works by reading the list of data every 1000 milliseconds, or a second. As an effect, the graph updates itself with the newest data set. Finally, we were able to embed the graphs onto a Tkinter frame by using FigureCanvasTkAgg from matplotlib.backends.backend_tkagg.
Currently, even though the arm can draw lines with varying intensity, it can not yet illustrate a picture by itself. Our supervisor has ordered a stage for the arm which will laterally control the arm and allow it to draw anything by itself!
Note: we collaborated through an online IDE repl.it. It was great.import matplotlib from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure import matplotlib.animation as animation from matplotlib import style import tkinter as Tk matplotlib.use('TkAgg') def start(): th = textfield.get("1.0", Tk.END) q = th.split("\n") for torque in q: try: torque_float = float(torque) print(torque_float) except ValueError: pass def stop(): #run MotorStop here print("Stopped") style.use("dark_background") fig = Figure(figsize=(3,1), dpi=100) fig.suptitle('Robot Arm Graphs', fontsize=16) ax_pos = fig.add_subplot(1,3,1) #numRows,numCols,index 1-3 ax_pos.set_title("Position") ax_vel = fig.add_subplot(1,3,2) ax_vel.set_title("Velocity") ax_current = fig.add_subplot(1,3,3) ax_current.set_title("Current") def animate(i): ### Position ### position_data = open('position.txt','r').read() lines = position_data.split('\n') times = [] wrist_data = [] thumb_data = [] index_data = [] for line in lines: if len(line) > 1: # if the line contains data time_x, wrist, thumb, index = line.split(',') times.append(float(time_x)) wrist_data.append(float(wrist)) thumb_data.append(float(thumb)) index_data.append(float(index)) ax_pos.clear() ax_pos.plot(times, wrist_data, "g", label="Wrist") ax_pos.plot(times, thumb_data, "--r", label="Thumb") ax_pos.plot(times, index_data, "--b", label="Index") _ = ax_pos.legend() ax_pos.set_xlabel('Time') ax_pos.set_ylabel('Position') ### Velocity ### velocity_data = open('velocity.txt','r').read() lines = velocity_data.split('\n') times = [] wrist_data = [] thumb_data = [] index_data = [] for line in lines: if len(line) > 1: # if the line contains data time_x, wrist, thumb, index = line.split(',') times.append(float(time_x)) wrist_data.append(float(wrist)) thumb_data.append(float(thumb)) index_data.append(float(index)) ax_vel.clear() ax_vel.plot(times, wrist_data, "g", label="Wrist") ax_vel.plot(times, thumb_data, "--r", label="Thumb") ax_vel.plot(times, index_data, "--b", label="Index") _ = ax_vel.legend() ax_vel.set_xlabel('Time') ax_vel.set_ylabel('Velocity') ### Current ### current_data = open('current.txt','r').read() lines = current_data.split('\n') times = [] wrist_data = [] thumb_data = [] index_data = [] for line in lines: if len(line) > 1: # if the line contains data time_x, wrist, thumb, index = line.split(',') times.append(float(time_x)) wrist_data.append(float(wrist)) thumb_data.append(float(thumb)) index_data.append(float(index)) ax_current.clear() ax_current.plot(times, wrist_data, "g", label="Wrist") ax_current.plot(times, thumb_data, "--r", label="Thumb") ax_current.plot(times, index_data, "--b", label="Index") _ = ax_current.legend() ax_current.set_xlabel('Time') ax_current.set_ylabel('Current') root = Tk.Tk() root.title("ARM control") root.geometry("1300x460") # a tk.DrawingArea canvas = FigureCanvasTkAgg(fig, master=root) canvas.draw() #canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) canvas._tkcanvas.pack(side=Tk.RIGHT, fill=Tk.BOTH, expand=1, padx=20, pady=20) ani = animation.FuncAnimation(fig, animate, interval=1000) stop_button = Tk.Button( text="Stop", width=5, height=1, bg="blue", fg="yellow", command=stop ) tf = Tk.Frame() tf.pack(fill=Tk.X, ipadx=5, ipady=5) textfield = Tk.Text( width=20, height=20, master=tf ) textfield.pack(ipadx=10, padx=10, pady=20) buttons = Tk.Frame() buttons.pack(fill=Tk.X) start_button = Tk.Button( text="Start", width=5, height=1, bg="blue", fg="red", command=start, master=buttons ) stop_button = Tk.Button( text="Stop", width=5, height=1, bg="blue", fg="red", command=stop, master=buttons ) grip_start_button = Tk.Button( text="Start grip", width=5, height=1, bg="blue", fg="red", #command=grip, master=buttons ) start_button.pack(side=Tk.RIGHT, padx=20, pady=5) stop_button.pack(side=Tk.LEFT, padx=20, pady=5) grip_start_button.pack(side=Tk.RIGHT) root.mainloop()