I have created a TKinter application that calculates the offsets and ratios that map robot plane to camera cordinate in pixels. I have several features that require the control of the robot via tkinter buttons. The app is done and working but trying to stop the worry of spamming a button, and the robot moving for another 15 seconds because it is executing each click. This is my attempt at having tkinter not execute all the presses.
my custom image button:
class ImageButton(ctk.CTkButton):
def __init__(self, parent, text,function, col, row, image, padx, pady, width, color = 'dark-gray'):
super().__init__(
master = parent,
text = text,
command= function,
image = image,
fg_color= MINT,
hover_color = DARK_BLUE,
text_color = LIGHT_BLUE,
width = width
)
self.grid(column = col, row = row, sticky = 'NSEW', pady =pady, padx = padx)
and my robot class with layout and junk deleted:
import math
import os
import sys
import customtkinter as ctk
import tkinter as tk
from tkinter import *
import numpy as np
from settings import *
from PIL import Image
import cv2 as cv
class MoveRobotWelcome(ctk.CTkFrame):
def __init__(self, parent, controller, frame, robot = None):
ctk.CTkFrame.__init__(self, parent)
self.robot = robot
self.gripperOpen = True
self.increment = tk.DoubleVar()
self.increment.set(0.001) # Default value
self.roll = 180
self.pitch = -.0001
self.yaw = 30
self.buttons = []
#self.robot = Robot()
Pximage = Image.open(r'increase_x.png')
Nximage = Image.open(r'decrease_x.png')
Pyimage = Image.open(r'increase_y.png')
Nyimage = Image.open(r'decrease_y.png')
Przimage = Image.open(r'increase_rz.png')
Nrzimage = Image.open(r'decrease_rz.png')
Pzimage = Image.open(r'increase_z.png')
Nzimage = Image.open(r'decrease_z.png')
grip_image = Image.open(r'gripper.png')
Px = ImageButton(controller_frame, text = '', function = self.move_pos_x, col = 1, row = 0, image = Pxinvert_image, padx=10, pady=10, width = 40)
Nx = ImageButton(controller_frame, text = '', function = self.move_neg_x, col = 1, row = 1, image = Nxinvert_image, padx=10, pady=10, width = 40)
Py = ImageButton(controller_frame, text = '', function = self.move_pos_y, col = 1, row = 2, image = Pyinvert_image, padx=10, pady=10, width = 40)
Ny = ImageButton(controller_frame, text = '', function = self.move_neg_y, col = 1, row = 3, image = Nyinvert_image, padx=10, pady=10, width = 40)
Pz = ImageButton(controller_frame, text = '', function = self.move_pos_z, col = 1, row = 4, image = Pzinvert_image, padx=10, pady=10, width = 40)
Nz = ImageButton(controller_frame, text = '', function = self.move_neg_z, col = 1, row = 5, image = Nzinvert_image, padx=10, pady=10, width = 40)
Prz = ImageButton(controller_frame, text = '', function = self.move_pos_rz, col = 1, row = 6, image = Przinvert_image, padx=10, pady=10, width = 40)
Nrz = ImageButton(controller_frame, text = '', function = self.move_neg_rz, col = 1, row = 7, image = Nrzinvert_image, padx=10, pady=10, width = 40)
gripper = ImageButton(controller_frame, text = '', function = self.toggle_gripper, col = 1, row = 8, image = grip_invert_image, padx=10, pady=10, width = 40)
self.buttons.append(Px)
self.buttons.append(Nx)
self.buttons.append(Py)
self.buttons.append(Ny)
self.buttons.append(Pz)
self.buttons.append(Nz)
self.buttons.append(Prz)
self.buttons.append(Nrz)
self.buttons.append(gripper)
Px_label= ctk.CTkLabel(controller_frame, text = "+ X", text_color= DARK_BLUE)
Nx_label= ctk.CTkLabel(controller_frame, text = "- X", text_color= DARK_BLUE)
Py_label= ctk.CTkLabel(controller_frame, text = "+ Y", text_color= DARK_BLUE)
Ny_label= ctk.CTkLabel(controller_frame, text = "- Y", text_color= DARK_BLUE)
Prz_label= ctk.CTkLabel(controller_frame, text = "+ Z", text_color= DARK_BLUE)
Nry_label= ctk.CTkLabel(controller_frame, text = "- Z", text_color= DARK_BLUE)
gripper_label= ctk.CTkLabel(controller_frame, text = "Toggle Gripper : ", text_color= DARK_BLUE)
Pz_label= ctk.CTkLabel(controller_frame, text = "+ Rz", text_color= DARK_BLUE)
Nz_label= ctk.CTkLabel(controller_frame, text = "- Rz", text_color= DARK_BLUE)
Px_label.grid(row = 0, column = 0)
Nx_label.grid(row = 1,column = 0)
Py_label.grid(row = 2,column = 0)
Ny_label.grid(row = 3,column = 0)
Prz_label.grid(row = 4,column = 0)
Nry_label.grid(row = 5,column = 0)
gripper_label.grid(row = 8,column = 0)
Pz_label.grid(row = 6,column = 0)
Nz_label.grid(row = 7,column = 0)
radio_frame = ctk.CTkFrame(main_frame, fg_color = MINT)
radio_frame.grid(row = 0, column = 1, columnspan = 2, sticky = 's', pady = (20,10))
for i in range(0, 4):
radio_frame.grid_rowconfigure(i, weight = 1)
radio_frame.grid_rowconfigure(1, weight = 1)
self.radio1 = ctk.CTkRadioButton(radio_frame, text="0.001", variable=self.increment, value=0.001, command=self.update_increment, text_color=DARK_BLUE, border_color = DARK_BLUE, fg_color = LIGHT_BLUE)
self.radio2 = ctk.CTkRadioButton(radio_frame, text="0.01 ", variable=self.increment, value=0.01, command=self.update_increment, text_color=DARK_BLUE, border_color = DARK_BLUE, fg_color = LIGHT_BLUE)
self.radio3 = ctk.CTkRadioButton(radio_frame, text="0.05 ", variable=self.increment, value=0.05, command=self.update_increment, text_color=DARK_BLUE, border_color = DARK_BLUE, fg_color = LIGHT_BLUE)
def disable_buttons(self):
for button in self.buttons:
button.configure(state=DISABLED)
def enable_buttons(self):
for button in self.buttons:
button.configure(state=NORMAL)
def update_increment(self):
# Update the label to show the current increment
self.label.configure(text=f"Current Increment: {self.increment.get()}")
def move_pos_x(self):
self.disable_buttons()
try:
actual_tcp_pose = self.robot.rtde_r.getActualTCPPose()
rrx = math.radians(self.roll)
rry = math.radians(self.pitch)
rrz = math.radians(self.yaw)
rpx, rpy, rpz = self.robot.rpy2rv(rrx, rry, rrz)
actual_tcp_pose[3] = rpx
actual_tcp_pose[4] = rpy
actual_tcp_pose[5] = rpz
actual_tcp_pose[0] += self.increment.get()
self.robot.moveL(actual_tcp_pose, .1, .1)
finally:
self.enable_buttons()
def move_pos_y(self):
self.disable_buttons()
try:
actual_tcp_pose = self.robot.rtde_r.getActualTCPPose()
rrx = math.radians(self.roll)
rry = math.radians(self.pitch)
rrz = math.radians(self.yaw)
rpx, rpy, rpz = self.robot.rpy2rv(rrx, rry, rrz)
actual_tcp_pose[3] = rpx
actual_tcp_pose[4] = rpy
actual_tcp_pose[5] = rpz
actual_tcp_pose[1] += self.increment.get()
self.robot.moveL(actual_tcp_pose, .1, .1)
finally:
self.enable_buttons()
Setting the state to disabled for each button on my page so that while robot is executing move after first click other/extra button presses aren't registered/queued
.after()
, or running them in a separate thread - so that the disabling of the buttons actually does something.self.update()
at the end ofdisable_buttons()
andenable_buttons()
.