From ffc825757dc05cc6e4dfbd5c2483e993aab35652 Mon Sep 17 00:00:00 2001 From: Joe Fernandez Date: Thu, 28 Mar 2024 11:27:29 -0400 Subject: [PATCH] 2024.3.0 (#321) * switched gripper_joint to fixed and removed from moveit_config (#317) * Gui updates (#320) * * Random parts in conveyor and bins * Cear all bins and conveyor * More warning messages * Save button deactivates if there are no orders * Restricted available pump offsets * Typo * Fixed image rotation * Random parts now save correctly to avoid warnings while saving orders * Updated with newest version --------- Co-authored-by: Justin Albrecht --- ariac_controllers/package.xml | 2 +- ariac_description/package.xml | 2 +- .../vacuum_gripper/vacuum_gripper_macro.xacro | 8 +- ariac_gazebo/package.xml | 2 +- ariac_gui/ariac_gui/trial_generator.py | 127 ++++++++++++++++-- ariac_gui/package.xml | 2 +- ariac_moveit_config/config/ariac_robots.srdf | 7 +- ariac_moveit_config/config/joint_limits.yaml | 10 -- ariac_moveit_config/package.xml | 2 +- ariac_msgs/package.xml | 2 +- ariac_plugins/package.xml | 2 +- ariac_sensors/package.xml | 2 +- 12 files changed, 132 insertions(+), 36 deletions(-) diff --git a/ariac_controllers/package.xml b/ariac_controllers/package.xml index 1937dee60..0f84ad78c 100644 --- a/ariac_controllers/package.xml +++ b/ariac_controllers/package.xml @@ -2,7 +2,7 @@ ariac_controllers - 2024.2.0 + 2024.3.0 ros2 controllers for ARIAC simulation Justin Albrecht NIST diff --git a/ariac_description/package.xml b/ariac_description/package.xml index 0310e0a04..c40133db4 100644 --- a/ariac_description/package.xml +++ b/ariac_description/package.xml @@ -2,7 +2,7 @@ ariac_description - 2024.2.0 + 2024.3.0 Package containing URDF descriptions for all robots in the ARIAC simulation justin NIST diff --git a/ariac_description/urdf/vacuum_gripper/vacuum_gripper_macro.xacro b/ariac_description/urdf/vacuum_gripper/vacuum_gripper_macro.xacro index c1a62e07d..2ff1dea18 100644 --- a/ariac_description/urdf/vacuum_gripper/vacuum_gripper_macro.xacro +++ b/ariac_description/urdf/vacuum_gripper/vacuum_gripper_macro.xacro @@ -32,14 +32,16 @@ - - + - + + true + + diff --git a/ariac_gazebo/package.xml b/ariac_gazebo/package.xml index ec4c279d8..3d2b232dd 100644 --- a/ariac_gazebo/package.xml +++ b/ariac_gazebo/package.xml @@ -2,7 +2,7 @@ ariac_gazebo - 2024.2.0 + 2024.3.0 ARIAC ROS2 port justin NIST diff --git a/ariac_gui/ariac_gui/trial_generator.py b/ariac_gui/ariac_gui/trial_generator.py index 49cb5a7b8..acbccb08f 100644 --- a/ariac_gui/ariac_gui/trial_generator.py +++ b/ariac_gui/ariac_gui/trial_generator.py @@ -57,8 +57,8 @@ RIGHT_COLUMN = 4 FAR_RIGHT_COLUMN = 5 COLUMN_LIST = [LEFT_COLUMN, MIDDLE_COLUMN, RIGHT_COLUMN] -PART_TYPES=["sensor", "pump", "regulator", "battery"] -PART_COLORS=['green', 'red', 'purple','blue','orange'] +PART_TYPES=["battery", "pump", "sensor","regulator"] +PART_COLORS=["red","green","blue","orange","purple"] #Options for kitting trays KITTING_TRAY_OPTIONS = [""]+[str(i) for i in range(10)] @@ -72,6 +72,10 @@ # Menu images GUI_PACKAGE = get_package_share_directory('ariac_gui') MENU_IMAGES = {part_label:Image.open(GUI_PACKAGE + f"/resource/{part_label}.png") for part_label in ["plus","assembly_station","agv", "tray","light_icon","dark_icon"]+[color+pType for color in PART_COLORS for pType in PART_TYPES]+[f"id_0{i}" for i in range(10)]} +for color in PART_COLORS: + MENU_IMAGES[color+"battery"] = MENU_IMAGES[color+"battery"].rotate(90) + MENU_IMAGES[color+"sensor"] = MENU_IMAGES[color+"sensor"].rotate(180) + MENU_IMAGES[color+"regulator"] = MENU_IMAGES[color+"regulator"].rotate(90) QUADRANTS=["1","2","3","4"] AGV_OPTIONS=["1","2","3","4"] @@ -185,7 +189,7 @@ def __init__(self): self.author = ctk.StringVar() self.original_trial_name = ctk.StringVar() self.original_trial_name.set("") - self.time_limit.set('0') + self.time_limit.set('-1') self.trial_name.set('') self.author.set('') @@ -415,7 +419,8 @@ def __init__(self): self.bin_parts_counter.trace_add('write',self.add_bin_parts_to_map) self.add_map_to_frame() - self.save_file_button = ctk.CTkButton(self, text="Save file", command=self.choose_save_location) + self.save_file_button = ctk.CTkButton(self, text="Save file", command=self.choose_save_location, state = tk.DISABLED) + ToolTip(self.save_file_button, msg = self.update_save_file_msg, delay=0.2) self.light_dark_button = ctk.CTkButton(self, text="", image=ctk.CTkImage(MENU_IMAGES["dark_icon"],size=(50,50)), command = self.switch_light_dark, fg_color="#ebebeb", bg_color="#ebebeb", hover_color="#ebebeb") self._build_assembly_parts_pose_direction() @@ -635,7 +640,8 @@ def add_kitting_trays_widgets_to_frame(self): label_coordinates = [(coord[0],coord[1]-35) for coord in menu_coordinates] self.tray_center_coords = {f"slot_{i+1}":(((tray_coords["kts_1"][0]+tray_coords["kts_1"][2])//2 if i <=2 else (tray_coords["kts_2"][0]+tray_coords["kts_2"][2])//2),menu_coordinates[i][1]) for i in range(len(menu_coordinates))} - for i in self.kitting_tray_selections:i.set(KITTING_TRAY_OPTIONS[0]) + for i in self.kitting_tray_selections: + i.set(KITTING_TRAY_OPTIONS[0]) tray_menus = [ctk.CTkOptionMenu(self.kitting_tray_frame, variable=self.kitting_tray_selections[i], values=KITTING_TRAY_OPTIONS, @@ -822,10 +828,21 @@ def add_bin_parts_widgets_to_frame(self): clear_bin_button.grid(column = MIDDLE_COLUMN, columnspan = 2, pady = 5) flipped_meaning_label = ctk.CTkLabel(self.bin_parts_frame, text="When a part is flipped, an \"F\" will show up in the bottom right of the part image.") flipped_meaning_label.grid(column = MIDDLE_COLUMN, columnspan = 2,pady = 10) + random_bins_button = ctk.CTkButton(self.bin_parts_frame, text="Fill all bins with random parts", command=self.fill_bins_random) + random_bins_button.grid(column = MIDDLE_COLUMN, columnspan = 2,pady = 10) + clear_all_bins_button = ctk.CTkButton(self.bin_parts_frame, text="Clear all bins", command=self.clear_all_bins) + clear_all_bins_button.grid(column = MIDDLE_COLUMN, columnspan = 2,pady = 10) self.bin_selection.trace_add('write',partial(self.update_bin_grid, self.bin_selection,self.bin_parts_canvas,self.bin_parts_frame)) self.bin_selection.trace_add('write',partial(self.update_map,bin_map_canvas, self.bin_selection)) self.bin_parts_counter.trace_add('write',partial(self.update_bin_grid, self.bin_selection,self.bin_parts_canvas,self.bin_parts_frame)) self.bin_parts_counter.trace_add('write',partial(self.update_map,bin_map_canvas, self.bin_selection)) + + def clear_all_bins(self): + for i in range(1,9): + self.current_bin_parts[f"bin{i}"] = ["" for _ in range(9)] + self.bin_parts[f"bin{i}"] = [BinPart() for _ in range(9)] + self.bin_parts_counter.set("0") + def clear_bin(self, bin_selection): current_bin = bin_selection.get() self.current_bin_parts[current_bin]=["" for _ in range(9)] @@ -907,6 +924,25 @@ def update_bin_grid(self,bin_selection : ctk.StringVar,canvas:Canvas, main_wind self.current_bin_canvas_elements.clear() self.show_grid(bin_selection,canvas,main_wind) + def fill_bins_random(self): + for bin in ALL_BINS: + for index in range(9): + self.generate_random_bin_part(bin, index) + self.bin_parts_counter.set(str(sum([sum([1 for part in self.current_bin_parts[key] if part!=""]) for key in self.current_bin_parts.keys()]))) + + + def generate_random_bin_part(self, bin, index): + part_color = random.randint(0,4) + part_type = random.randint(10,13) + self.current_bin_parts[bin][index]=PART_COLORS[part_color]+PART_TYPES[part_type-10] + self.all_present_parts.append(PART_COLORS[part_color]+" "+PART_TYPES[part_type-10]) + temp_part = PartMsg() + temp_part.color = part_color + temp_part.type = part_type + self.bin_parts[bin][index].part = temp_part + self.bin_parts[bin][index].rotation = SLIDER_VALUES[random.randint(0,len(SLIDER_VALUES)-1)] + self.bin_parts[bin][index].flipped = "0" + def add_bin_part(self,bin, index): bin_vals = {} add_part_bin_window = ctk.CTkToplevel() @@ -1106,6 +1142,10 @@ def add_conveyor_parts_widgets_to_frame(self): self.add_conveyor_parts_button = ctk.CTkButton(self.conveyor_parts_frame,text="Add part lot", command=partial(self.add_conveyor_parts), state=tk.DISABLED) self.main_conveyor_menu_widgets.append(self.add_conveyor_parts_button) ToolTip(self.add_conveyor_parts_button, msg = self.add_conveyor_parts_hover_message, delay=0.2) + self.generate_random_parts_button = ctk.CTkButton(self.conveyor_parts_frame, text="Generate random parts", command=self.random_conveyor_parts_window_func) + self.main_conveyor_menu_widgets.append(self.generate_random_parts_button) + self.clear_conveyor_button = ctk.CTkButton(self.conveyor_parts_frame, text="Clear conveyor", command=self.clear_conveyor) + self.main_conveyor_menu_widgets.append(self.clear_conveyor_button) current_parts_label = ctk.CTkLabel(self.conveyor_parts_frame, text="Parts on conveyor belt:") self.main_conveyor_menu_widgets.append(current_parts_label) @@ -1119,6 +1159,11 @@ def add_conveyor_parts_widgets_to_frame(self): self.has_parts.trace_add('write', self.activate_deactivate_menu) self.conveyor_parts_counter.trace_add('write',self.show_current_parts) + def clear_conveyor(self): + self.current_conveyor_parts = [] + self.conveyor_parts = [] + self.conveyor_parts_counter.set("0") + def add_conveyor_parts_hover_message(self)->str: msg="" if len(self.current_conveyor_parts)>0: @@ -1248,7 +1293,10 @@ def add_conveyor_parts(self, index = -1): conveyor_part_vals["num_parts"].trace_add('write', partial(self.update_num_parts_slider, conveyor_part_vals["num_parts"], num_parts_label)) offset_label = ctk.CTkLabel(add_parts_conveyor_window,text=f"Offset: {conveyor_part_vals['offset'].get()}") offset_label.pack() - offset_slider = ctk.CTkSlider(add_parts_conveyor_window,variable=conveyor_part_vals["offset"],from_=-1, to=1, number_of_steps=40, orientation="horizontal") + if conveyor_part_vals["pType"].get()=="pump": + offset_slider = ctk.CTkSlider(add_parts_conveyor_window,variable=conveyor_part_vals["offset"],from_=-0.9, to=0.9, number_of_steps=36, orientation="horizontal") + else: + offset_slider = ctk.CTkSlider(add_parts_conveyor_window,variable=conveyor_part_vals["offset"],from_=-1, to=1, number_of_steps=40, orientation="horizontal") offset_slider.pack() conveyor_part_vals["offset"].trace_add('write', partial(self.update_offset_slider, conveyor_part_vals["offset"], offset_label)) rotation_label = ctk.CTkLabel(add_parts_conveyor_window, text=f"Rotation value: {SLIDER_STR[SLIDER_VALUES.index(conveyor_part_vals['rotation'].get())]}") @@ -1262,6 +1310,19 @@ def add_conveyor_parts(self, index = -1): back_button.pack() save_button = ctk.CTkButton(add_parts_conveyor_window,text="Save part",command=partial(self.save_conveyor_parts,add_parts_conveyor_window,conveyor_part_vals, index)) save_button.pack() + + conveyor_part_vals["pType"].trace_add('write', partial(self.update_offset_slider_for_pump, conveyor_part_vals["pType"],offset_slider,conveyor_part_vals["offset"])) + + def update_offset_slider_for_pump(self,part_type,slider,current_offset,_,__,___): + if part_type.get()=="pump": + slider.configure(from_=-0.9, to=0.9, number_of_steps=36) + if current_offset.get()<-0.9: + current_offset.set(-0.9) + if current_offset.get()>0.9: + current_offset.set(0.9) + else: + slider.configure(from_=-1, to=1, number_of_steps=40) + current_offset.set(current_offset.get()) def update_num_parts_slider(self,value : ctk.IntVar, label : ctk.CTkLabel,_,__,___): label.configure(text=f"Number of parts: {value.get()}") @@ -1270,6 +1331,34 @@ def update_offset_slider(self, value : ctk.DoubleVar, label : ctk.CTkLabel,_,__, value.set(round(value.get(),3)) label.configure(text=f"Offset: {value.get()}") + def random_conveyor_parts_window_func(self): + random_parts_conveyor_window = ctk.CTkToplevel() + random_parts_conveyor_window.geometry("400x450 + 700 + 300") + num_diff_parts = ctk.IntVar() + num_diff_parts.set(1) + rand_conv_label = ctk.CTkLabel(random_parts_conveyor_window,text=f"Number of different parts: {num_diff_parts.get()}") + rand_conv_label.pack() + num_parts_slider = ctk.CTkSlider(random_parts_conveyor_window,variable=num_diff_parts,from_=1, to=25, number_of_steps=24, orientation="horizontal") + num_parts_slider.pack() + num_diff_parts.trace_add('write', partial(self.update_rand_conv_label, num_diff_parts, rand_conv_label)) + generate_button = ctk.CTkButton(random_parts_conveyor_window, text="Generate parts", command=partial(self.generate_random_conveyor_part, random_parts_conveyor_window, num_diff_parts)) + generate_button.pack() + + def update_rand_conv_label(self, var : ctk.IntVar, label : ctk.CTkLabel,_,__,___): + label.configure(text=f"Number of different parts: {var.get()}") + + def generate_random_conveyor_part(self, window, num_parts): + for _ in range(num_parts.get()): + part_color = random.randint(0,4) + part_type = random.randint(10,13) + s_part_color = PART_COLORS[part_color] + s_part_type = PART_TYPES[part_type-10] + self.conveyor_parts.append(ConveyorPart(s_part_color, s_part_type,1,(random.uniform(-1.0,1.0)if s_part_type!="pump"else random.uniform(-0.9,0.9)), SLIDER_VALUES[random.randint(0,len(SLIDER_VALUES)-1)], "0")) + self.current_conveyor_parts.append(PART_COLORS[part_color]+PART_TYPES[part_type-10]) + self.all_present_parts.append(f"{s_part_color} {s_part_type}") + self.conveyor_parts_counter.set(str(len(self.conveyor_parts))) + window.destroy() + def save_conveyor_parts(self, window:ctk.CTkToplevel, conveyor_part_vals, index): self.show_conveyor_parts.set("0") color = conveyor_part_vals["color"].get() @@ -1883,8 +1972,14 @@ def save_order_hover_message(self): else: msg="No issue. You can save now" else: - if len(self.order_info["combined_task"]["parts"])<1: + num_slots_with_tray_0 = sum([1 for tray in self.kitting_tray_selections if tray.get()=="0"]) + combined_orders = sum([1 for order in self.current_orders if order.type==2]) + if len(self.order_info["combined_task"]["parts"])<1 and num_slots_with_tray_0-combined_orders<=0: + msg="To save, you need at least one part\nAlso, saving now means that there will be more combined orders than trays with id 0 available" + elif len(self.order_info["combined_task"]["parts"])<1: msg="To save, you need at least one part" + elif num_slots_with_tray_0-combined_orders<=0: + msg="Saving now means that there will be more combined orders than trays with id 0 available" else: msg="No issue. You can save now" for part in self.order_info["combined_task"]["parts"]: @@ -2095,7 +2190,6 @@ def save_order(self, index): new_order.id = self.used_ids[-1] else: new_order.id = self.current_orders[index].id - new_order.type = ORDER_TYPES.index(self.order_info["order_type"].get()) new_order.priority = True if self.order_info["priority"].get() == "1" else False if self.order_info["order_type"].get() == "kitting": @@ -2953,6 +3047,13 @@ def update_current_file_label(self,_,__,___): self.current_file_label.configure("") except: return + try: + if len(self.current_orders) == 0: + self.save_file_button.configure(state = tk.DISABLED) + else: + self.save_file_button.configure(state = tk.NORMAL) + except: + pass self.build_file_dict() new_label = "" new_label = f"# Trial name: {self.trial_name.get()}.yaml\n" @@ -3329,4 +3430,12 @@ def switch_light_dark(self): frame.configure(fg_color="transparent") for c in self.all_canvases: c.configure(bg = "#e0dcdc") - self.update_bin_grid(self.bin_selection,self.bin_parts_canvas,self.bin_parts_frame,1,1,1) \ No newline at end of file + self.update_bin_grid(self.bin_selection,self.bin_parts_canvas,self.bin_parts_frame,1,1,1) + + def update_save_file_msg(self): + num_orders = len(self.current_orders) + if num_orders == 0: + msg = "There must be at least one order to save" + else: + msg = f"There {'is' if num_orders == 1 else 'are'} currently {num_orders} order{'' if num_orders == 1 else 's'}" + return msg \ No newline at end of file diff --git a/ariac_gui/package.xml b/ariac_gui/package.xml index 2401c81ed..7ac58f957 100644 --- a/ariac_gui/package.xml +++ b/ariac_gui/package.xml @@ -2,7 +2,7 @@ ariac_gui - 2024.2.0 + 2024.3.0 GUI for creating trial configurations Joseph Fernandez NIST diff --git a/ariac_moveit_config/config/ariac_robots.srdf b/ariac_moveit_config/config/ariac_robots.srdf index 25c6a2c61..2b233726f 100644 --- a/ariac_moveit_config/config/ariac_robots.srdf +++ b/ariac_moveit_config/config/ariac_robots.srdf @@ -26,8 +26,7 @@ - - + > @@ -37,7 +36,6 @@ - @@ -47,9 +45,6 @@ - - - diff --git a/ariac_moveit_config/config/joint_limits.yaml b/ariac_moveit_config/config/joint_limits.yaml index a8417b071..1aa437b5c 100644 --- a/ariac_moveit_config/config/joint_limits.yaml +++ b/ariac_moveit_config/config/joint_limits.yaml @@ -20,11 +20,6 @@ joint_limits: floor_wrist_3_joint: has_acceleration_limits: true max_acceleration: 5.0 - floor_gripper_joint: - has_velocity_limits: true - max_velocity: 1.0 - has_acceleration_limits: true - max_acceleration: 0.5 gantry_x_axis_joint: has_acceleration_limits: true max_acceleration: 0.5 @@ -52,8 +47,3 @@ joint_limits: ceiling_wrist_3_joint: has_acceleration_limits: true max_acceleration: 5.0 - ceiling_gripper_joint: - has_velocity_limits: true - max_velocity: 1.0 - has_acceleration_limits: true - max_acceleration: 0.5 diff --git a/ariac_moveit_config/package.xml b/ariac_moveit_config/package.xml index ec998e9a3..7d16bf0b3 100644 --- a/ariac_moveit_config/package.xml +++ b/ariac_moveit_config/package.xml @@ -2,7 +2,7 @@ ariac_moveit_config - 2024.2.0 + 2024.3.0 An package with MoveIt2 configurations for ARIAC robots Justin Albrecht NIST diff --git a/ariac_msgs/package.xml b/ariac_msgs/package.xml index 978b63b82..992e8af9e 100644 --- a/ariac_msgs/package.xml +++ b/ariac_msgs/package.xml @@ -2,7 +2,7 @@ ariac_msgs - 2024.2.0 + 2024.3.0 Interface definitions for ARIAC justin NIST diff --git a/ariac_plugins/package.xml b/ariac_plugins/package.xml index b4ca9ad06..a1fa4cec0 100644 --- a/ariac_plugins/package.xml +++ b/ariac_plugins/package.xml @@ -2,7 +2,7 @@ ariac_plugins - 2024.2.0 + 2024.3.0 Gazebo/ROS2 plugins for the ARAIC competition justin albrecht zeid kootbally diff --git a/ariac_sensors/package.xml b/ariac_sensors/package.xml index a56f174e3..7979a50d5 100644 --- a/ariac_sensors/package.xml +++ b/ariac_sensors/package.xml @@ -2,7 +2,7 @@ ariac_sensors - 2024.2.0 + 2024.3.0 Gazebo plugins for the ARIAC sensors justin NIST