commit 4176f04a610453271f1249f8e07b78c1a8560415 Author: junhui324 Date: Tue Aug 4 14:30:00 2026 +0900 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1885fee --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +__pycache__/ +*.py[cod] +.venv/ +venv/ +.env diff --git a/SDK/jakaAPI.dll b/SDK/jakaAPI.dll new file mode 100644 index 0000000..8795ea0 Binary files /dev/null and b/SDK/jakaAPI.dll differ diff --git a/SDK/jakaAPI.exp b/SDK/jakaAPI.exp new file mode 100644 index 0000000..d53f70d Binary files /dev/null and b/SDK/jakaAPI.exp differ diff --git a/SDK/jakaAPI.lib b/SDK/jakaAPI.lib new file mode 100644 index 0000000..8f491b9 Binary files /dev/null and b/SDK/jakaAPI.lib differ diff --git a/SDK/jkrc.exp b/SDK/jkrc.exp new file mode 100644 index 0000000..4663a22 Binary files /dev/null and b/SDK/jkrc.exp differ diff --git a/SDK/jkrc.lib b/SDK/jkrc.lib new file mode 100644 index 0000000..309ed93 Binary files /dev/null and b/SDK/jkrc.lib differ diff --git a/SDK/jkrc.pyd b/SDK/jkrc.pyd new file mode 100644 index 0000000..450c267 Binary files /dev/null and b/SDK/jkrc.pyd differ diff --git a/api_routes.py b/api_routes.py new file mode 100644 index 0000000..a1f6f85 --- /dev/null +++ b/api_routes.py @@ -0,0 +1,3257 @@ +from flask import Blueprint, request, jsonify, flash +import time +import json +import os +import sys +import threading +from math import radians +import minimalmodbus +import serial +import re +from datetime import datetime, timedelta +import socket + +log_folder_path = r"C:\palletizing_log" + +current_dir = os.path.dirname(os.path.abspath(__file__)) +sdk_path = os.path.join(current_dir, 'SDK') +sys.path.insert(0, sdk_path) + +import jkrc + +robot_ip_address = '10.5.5.100' +# robot_ip_address = '192.168.56.102' +robot = jkrc.RC(robot_ip_address) + +IO_CABINET = 0 +PI = 3.1415926 + +api_routes = Blueprint('api_routes', __name__) + +current_dir = os.path.dirname(os.path.abspath(__file__)) +cache_json_file_path = os.path.join(current_dir, 'static/json/cache.json') +oneLine_json_file_path = os.path.join(current_dir, 'static/json/oneLine.json') + +wooden_wheel_pallet_height = 653 +iron_wheel_pallet_height = 633 + +pallet_width = 0 +pallet_length = 0 +pallet_height = 0 +book_center_positions = [] + +grid_id = 0 + +wheel_max_current_layer_height = 720 # 현재 레이어 최대 적재 높이 - 120 mm +flat_max_current_layer_height = 1080 # 현재 레이어 최대 적재 높이 - 120 mm + +oneline_wheel_max_current_layer_height = 720 + +robot_start_clicked = False +terminate_robot_button_clicked = False +stacker_thread_running = False + + +stacker_thread_operator = None +action = None +immediately_take_book = None + +is_one_line_stop_clicked = None + +btn_id = None + +flag = 0 # 비상정지버튼 눌렸는지 안눌렸는지에 대한 플래그 + +speed = 7000 +acc = 2300 + +grid_speed = 10 +grid_acc = 1 + +is_in_pose_time = 0.1 + +is_emo_disabled = True + +save_time = 2 + +stacker_vertical_cyl_sensor = 0 +stacker_vertical_cyl_down_sensor = 0 + +stacker_book_ready_sensor = 0 + + +wooden_wheel_pallet_max_z_pos = 864 +iron_wheel_pallet_max_z_pos = 884 +wooden_Flat_pallet_max_z_pos = 1192 # 227 + + +port = 'COM3' +baudrate = 115200 +timeout = 2 + + +# 모드버스 디바이스 설정 +slave_id = 1 # Slave ID는 1 +# Function code: 0x02 (Read Discrete Inputs) +start_address = 0x0000 # 시작 주소 +num_points = 8 # 읽을 포인트 수 (8개) +num_coils = 8 # 쓰기 할 코일의 개수 +instrument = minimalmodbus.Instrument(port, slave_id) # 포트와 슬레이브 ID 지정 +instrument.serial.baudrate = baudrate # 보드레이트 설정 +instrument.serial.timeout = timeout # 타임아웃 설정 +instrument.mode = minimalmodbus.MODE_RTU # RTU 모드 설정 +instrument.close_port_after_each_call = True # 포트를 자동으로 닫음 + + + + +def Write_All_Do(coils_values): + global instrument + coils_values = coils_values + # 최소한의 모드버스 연결 객체 생성 + try: + # Function Code 15 - 여러 코일 값 쓰기 + instrument.write_bits(start_address, coils_values) + print(f"Successfully wrote {num_coils} coils to slave {slave_id}") + except IOError as e: + print(f"Error writing coils: {e}") + +Write_All_Do([0,0,0,0,0,0,0,0]) +def write_log(message): + try: + #폴더 없으면 생성 + if not os.path.exists(log_folder_path): + os.makedirs(log_folder_path) + + #현재 날짜로 파일 이름 설정 + current = datetime.now().strftime("%Y%m%d") + filename = f"log_{current}.txt" + log_file_path = os.path.join(log_folder_path, filename) + + #현재 시간 + current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + #적을 내용 + msg = f"[{current_time}] {message}\n" + + #로그 파일에 메시지 기록 + with open(log_file_path, "a") as log_file: + log_file.write(msg) + + #30일전 로그 삭제 + delete_old_logs(30) + + return True + except Exception as e: + #에러 + print(f"Error log: {e}") + return False + + +def delete_old_logs(days): + try: + #현재 날짜 - days 계산 + deletion_date = datetime.now() - timedelta(days=days) + + #폴더 내의 모든 파일 검사 + for filename in os.listdir(log_folder_path): + #파일 이름 날짜 추출 + if filename.startswith("log_") and filename.endswith(".txt"): + file_date_str = filename[4:12] # "log_YYYYMMDD.txt"에서 YYYYMMDD 추출 + file_date = datetime.strptime(file_date_str, "%Y%m%d") + + #기준일보다 오래된 경우 파일 삭제 + if file_date < deletion_date: + file_path = os.path.join(log_folder_path, filename) + os.remove(file_path) + print(f"Deleted log: {file_path}") + + except Exception as e: + #에러 + print(f"Error deleting logs: {e}") + + +@api_routes.route('/writelog', methods=["POST"]) +def writelog(): + try: + #적을 내용 + message = request.get_data(as_text=True) + #메시지가 없을 때 + if not message: + return "Not Message" + # 로그 기록 + if write_log(message): + return "Success" + # 실패 + else: + return "Failed" + #실패 + except Exception as e: + return "Failed to " + str(e) + +@api_routes.route('/update_pallet', methods=['GET', 'POST']) +def update_pallet(): + global pallet_width, pallet_length, pallet_height, wooden_Flat_pallet_max_z_pos + + data = request.json + + pallet_width = data.get('palletWidth') + pallet_length = data.get('palletLength') + pallet_height = data.get('palletHeight') + + + wooden_Flat_pallet_max_z_pos = 1192 # 227 + wooden_Flat_pallet_max_z_pos = wooden_Flat_pallet_max_z_pos - (pallet_height - 227) + print(wooden_Flat_pallet_max_z_pos) + + + print(pallet_height) + + l = pallet_width / 2 + x_cord = pallet_length + + err_sum = 188 + 18 # 188 : 책 놓았을때 오차 / 18 : 팔레트 width 오차 + new_coord_data = [-l - err_sum, 881.7 + x_cord, -764 + pallet_height, 0, -PI, -PI] + + change_user_frame_coordiante(new_coord_data) + write_log(f"BE: update_pallet function successfully completed") + return 'Success' + + +global selectedPalletId +@api_routes.route('/robot_start', methods=['POST']) +def robot_start(): + global robot_start_clicked + global book_center_positions + global terminate_robot_button_clicked + global action + global btn_id + global selectedPalletId + + data = request.json + + robot_start_clicked = True + terminate_robot_button_clicked = False + action = None + + pallet_height = data['selectedPallet']['palletHeight'] + btn_id = data['btnId'] + selectedPalletId = data['selectedPalletId'] + + print("selectedPalletId : ", selectedPalletId) + + print(f"pallet_height: {pallet_height}, btn_id: {btn_id}") + write_log(f"BE: robot_start function start - pallet_height: {pallet_height}, btn_id: {btn_id}") + + if data: + if btn_id == 'normalButton': + stacker_thread_start_function() + if pallet_height == wooden_wheel_pallet_height: + book_center_positions = data['selectedPallet']['bookCenterPosition_Wheel'] + wooden_wheel_pallet() + elif pallet_height == iron_wheel_pallet_height: + book_center_positions = data['selectedPallet']['bookCenterPosition_Wheel'] + iron_wheel_pallet() + else: + book_center_positions = data['selectedPallet']['bookCenterPosition_Flat'] + print("납작 함수 호출!!!!!!!!!!!!!!!!!!!") + wooden_Flat_pallet() + write_log("BE: robot_start function successfully completed") + return 'Success' + elif btn_id == 'oneLineButton': + if pallet_height == wooden_wheel_pallet_height: + book_center_positions = data['selectedPallet']['bookCenterPosition_Wheel'] + elif pallet_height == iron_wheel_pallet_height: + book_center_positions = data['selectedPallet']['bookCenterPosition_Wheel'] + write_log("BE: robot_start function successfully completed") + return 'Success' + + else: + return 'Error: No data' + +@api_routes.route('/robot_finish_action', methods=['POST']) +def robot_finish_action(): + global action + + req_data = request.json + action = req_data.get('action') + + if action == 'robot_finish_action': + oneLine_data = { + "grid1": {"currentDataIndex": 0, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid2": {"currentDataIndex": 1, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid3": {"currentDataIndex": 2, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid4": {"currentDataIndex": 3, "currentLayerIndex": 0, "currentLayerHeight": 0} + } + with open(oneLine_json_file_path, 'w', encoding='utf-8') as file: + json.dump(oneLine_data, file, indent=4, ensure_ascii=False) + + robot.set_digital_output(IO_CABINET, 5, 0) + write_log("BE: robot_finish_action function successfully completed") + + return 'Robot finish action successful' + else: + return 'Invalid action', 400 + +@api_routes.route('/robot_immediately_take_book', methods=['POST']) +def robot_immediately_take_book(): + global immediately_take_book + + req_data = request.json + immediately_take_book = req_data.get('immediately_take_book') + + if immediately_take_book == 'robot_immediately_take_book': + write_log("BE: robot_immediately_take_book function successfully completed") + return 'robot_immediately_take_book successful' + else: + return 'Invalid action', 400 + + +@api_routes.route('/reset_data', methods=['POST']) +def reset_data(): + data = request.json + + if data.get('message') == 'Reset button clicked': + cache_data = { + "currentDataIndex": 0, + "currentLayerIndex": 0, + "currentLayerHeight": 0 + } + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + oneLine_data = { + "grid1": {"currentDataIndex": 0, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid2": {"currentDataIndex": 1, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid3": {"currentDataIndex": 2, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid4": {"currentDataIndex": 3, "currentLayerIndex": 0, "currentLayerHeight": 0} + } + with open(oneLine_json_file_path, 'w', encoding='utf-8') as file: + json.dump(oneLine_data, file, indent=4, ensure_ascii=False) + + write_log("BE: reset_data function successfully completed") + + return 'Success' + else: + return 'Error: Invalid message' + +@api_routes.route('/one_line_run', methods=['POST']) +def one_line_run(): + global grid_id + global terminate_robot_button_clicked + global action + global robot_start_clicked + global is_one_line_stop_clicked + + robot_start_clicked = True + terminate_robot_button_clicked = False + action = None + is_one_line_stop_clicked = None + + data = request.json + + grid_id = data.get('gridId') + + write_log(f"BE: one_line_run function start - pallet_height: {pallet_height}, grid_id: {grid_id}") + + stacker_thread_start_function() + + if data.get('message') == 'one_line_run': + if pallet_height == wooden_wheel_pallet_height: + one_line_wooden_wheel_pallet() + elif pallet_height == iron_wheel_pallet_height: + one_line_iron_wheel_pallet() + + write_log("BE: one_line_run function successfully completed") + return 'Success' + else: + return 'Error: Invalid message' + +@api_routes.route('/one_line_stop', methods=['POST']) +def one_line_stop(): + global is_one_line_stop_clicked + + data = request.json + is_one_line_stop_clicked = data.get('message') + + if data.get('message') == 'one_line_stop': + write_log("BE: one_line_stop function successfully completed") + return 'Success' + else: + return 'Error: Invalid message' + +@api_routes.route('/stacker_start', methods=['POST']) +def stacker_start(): + data = request.json + + if data.get('action') == 'stacker_start': + if stacker_thread_running: + print("이미 스태커가 실행 중입니다.") + write_log("BE: stacker_start function successfully completed 1") + return 'Success' + else: + # robot.set_digital_output(IO_CABINET, 2, 0) + instrument.write_bit(0, False) + stacker_thread_start_function() + print("스태커 실행") + write_log("BE: stacker_start function successfully completed 2") + return 'Success' + else: + return jsonify({'error': 'Invalid message'}), 400 + +@api_routes.route('/stacker_stop', methods=['POST']) +def stacker_stop(): + global stacker_thread_running + + data = request.json + if data.get('action') == 'stacker_stop': + if stacker_thread_running: + stacker_thread_running = False + print("스태커 멈춤") + write_log("BE: stacker_stop function successfully completed 1") + return 'Success' + else: + print("이미 스태커가 멈춰있습니다.") + write_log("BE: stacker_stop function successfully completed 2") + return 'Success' + else: + return jsonify({'error': 'Invalid message'}), 400 + +@api_routes.route('/updown_on', methods=['POST']) +def updown_on(): + global stacker_thread_running + + data = request.json + + print(data) + if data.get('action') == 'updown_on' and stacker_thread_running == False: + # robot.set_digital_output(IO_CABINET, 2, 1) + instrument.write_bit(0, True) + print("수직 실린더 on") + write_log("BE: updown_on function successfully completed") + return 'Success' + else: + return jsonify({'error': 'Invalid message'}), 400 + +@api_routes.route('/updown_off', methods=['POST']) +def updown_off(): + global stacker_thread_running + + data = request.json + + print(data) + if data.get('action') == 'updown_off' and stacker_thread_running == False: + # robot.set_digital_output(IO_CABINET, 2, 0) + instrument.write_bit(0, False) + print("수직 실린더 off") + write_log("BE: updown_off function successfully completed") + return 'Success' + else: + return jsonify({'error': 'Invalid message'}), 400 + +@api_routes.route('/leftright_on', methods=['POST']) +def leftright_on(): + global stacker_thread_running + + data = request.json + + print(data) + if data.get('action') == 'leftright_on' and stacker_thread_running == False: + # robot.set_digital_output(IO_CABINET, 3, 1) + instrument.write_bit(1, True) + print("수평 실린더 on") + write_log("BE: leftright_on function successfully completed") + return 'Success' + else: + return jsonify({'error': 'Invalid message'}), 400 + +@api_routes.route('/leftright_off', methods=['POST']) +def leftright_off(): + global stacker_thread_running + + data = request.json + + if data.get('action') == 'leftright_off' and stacker_thread_running == False: + # robot.set_digital_output(IO_CABINET, 3, 0) + instrument.write_bit(1, False) + print("수평 실린더 off") + write_log("BE: leftright_off function successfully completed") + return 'Success' + else: + return jsonify({'error': 'Invalid message'}), 400 + +def change_user_frame_coordiante(new_coord_data): + robot.login() + robot.power_on() + robot.enable_robot() + robot.set_user_frame_data(6, new_coord_data, "ScreenFlask") + write_log("BE: change_user_frame_coordiante function successfully completed") + return 'Success' + +# 나무 바퀴 팔레트 일 때 (즉, ㅁ 모양으로 놓을때) +def wooden_wheel_pallet(): + write_log("BE: wooden_wheel_pallet function started") + global action, immediately_take_book + global emergency_stop, protected_stop_stat + global power_on_stat, enabled_stat + global robot_start_clicked, terminate_robot_button_clicked + global pallet_width, pallet_length, pallet_height, book_center_positions + global stacker_thread_running, stacker_thread_operator + global is_emo_disabled, stacker_vertical_cyl_sensor, stacker_book_ready_sensor + global z_pos + global wooden_wheel_pallet_max_z_pos, stacker_vertical_cyl_down_sensor + + + is_move_pose = True + + robot.linear_move_extend([0, 0, -350, 0, 0, 0], 1, True, 7000, 2000, 0.1) + write_log("BE: linear_move_extend : [0, 0, -350, 0, 0, 0] successfully completed - wooden_wheel_pallet") + home_pos = [radians(-58.423), radians(95.567), radians(66.994), radians(107.440), radians(-90), radians(31.577)] + lower_pallet_enter_pose = [radians(-61.533), radians(107.484), radians(55.576), radians(106.940), radians(-90), radians(-61.533)] + lower_pallet_enter_pose1 = [radians(-66.797), radians(136.143), radians(6.799), radians(127.058), radians(-90), radians(-66.797)] + + robot.login() + write_log("BE: login successfully completed - wooden_wheel_pallet") + robot.power_on() + write_log("BE: power_on successfully completed - wooden_wheel_pallet") + robot.enable_robot() + write_log("BE: enable_robot successfully completed - wooden_wheel_pallet") + robot.joint_move_extend(home_pos, 0, True, 10, 1, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - wooden_wheel_pallet") + + if os.path.exists(cache_json_file_path) and os.path.getsize(cache_json_file_path) > 0: + with open(cache_json_file_path, 'r', encoding='utf-8') as file: + cache_data = json.load(file) + + current_data_index_cache = cache_data.get('currentDataIndex') + current_layer_index_cache = cache_data.get('currentLayerIndex') + current_layer_height_cache = cache_data.get('currentLayerHeight') + + current_data_index = current_data_index_cache + current_layer_index = current_layer_index_cache + current_layer_height = current_layer_height_cache + else: + cache_data = { + "currentDataIndex": 0, + "currentLayerIndex": 0, + "currentLayerHeight": 0 + } + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + current_data_index = 0 + current_layer_index = 0 + current_layer_height = 0 + + while True: + if (EMO(0, 0)): + is_move_pose = True + continue + + if action == 'robot_finish_action': + action = None + current_data_index = 0 + current_layer_index = 0 + current_layer_height = 0 + terminate_robot_button_clicked = True + + cache_data['currentLayerIndex'] = current_layer_index + cache_data['currentDataIndex'] = current_data_index + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + stacker_thread_running = False + if stacker_thread_operator: + stacker_thread_operator.join() + + robot.set_digital_output(IO_CABINET, 5, 0) + write_log("BE: robot.set_digital_output(IO_CABINET, 4, 0) (conveyor belt stopped) successfully completed - wooden_wheel_pallet") + + write_log("BE: action == 'robot_finish_action' successfully completed - wooden_wheel_pallet") + break + + if current_layer_height + 130 > wheel_max_current_layer_height and current_data_index == 4: + action = None + current_data_index = 0 + current_layer_index = 0 + current_layer_height = 0 + terminate_robot_button_clicked = True + + cache_data['currentLayerIndex'] = current_layer_index + cache_data['currentDataIndex'] = current_data_index + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + stacker_thread_running = False + if stacker_thread_operator: + stacker_thread_operator.join() + + robot.set_digital_output(IO_CABINET, 5, 0) + write_log("BE: robot.set_digital_output(IO_CABINET, 5, 0) (conveyor belt stopped) successfully completed - wooden_wheel_pallet") + + write_log("BE: current_layer_height > wheel_max_current_layer_height successfully completed - wooden_wheel_pallet") + break + + # 4권 다 놓으면 레이어 index + 1 + if(current_data_index == 4): + current_layer_index += 1 + current_data_index = 0 + + cache_data['currentLayerIndex'] = current_layer_index + cache_data['currentDataIndex'] = current_data_index + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + if is_move_pose == True and is_emo_disabled == True: + is_move_pose = False + if current_layer_index % 2 == 0: + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - wooden_wheel_pallet") + is_in_pose() + + pickup_pose = [radians(-47.102), radians(84.387), radians(78.169), radians(107.444), radians(-90), radians(131.510)] + + robot.joint_move_extend(pickup_pose, 0, False, 8000, 3000, 0.1) # 책 뜨기 공중 준비 자세 + write_log("BE: joint_move_extend : pickup_pose successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,666.816,0,0,0], 1,False, 8000, 3000, 0.1) # 공중에서 z축 내리기(-247.633) + write_log("BE: linear_move_extend : [0,0,666.816,0,0,0] (ready pose) successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + else: + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - wooden_wheel_pallet") + is_in_pose() + + pickup_pose_opposite = [radians(-24.283), radians(120.475), radians(32.213), radians(117.312), radians(-90), radians(-25.671)] + + robot.joint_move_extend(pickup_pose_opposite, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : pickup_pose_opposite successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,681.817,0,0,0], 1, False, 8000, 3000, 0.1) # (-273.633) -253.633 --> -249.633 + write_log("BE: linear_move_extend : [0,0,681.817,0,0,0] (ready pose) successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)): + immediately_take_book = None + + if current_layer_index % 2 == 0: # 홀수 번째 레이어 + write_log("BE: load book on pallet's if condition started - wooden_wheel_pallet") + current_data_list = list(book_center_positions) + current_data = current_data_list[current_data_index] + + centerX = current_data['x'] + centerY = current_data['y'] + + robot.set_digital_output(IO_CABINET, 1, 0) + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (for safety purposes : parallel gripper cylinder off) successfully completed - wooden_wheel_pallet") + robot.set_digital_output(IO_CABINET, 0, 0) + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (for safety purposes : vertical gripper cylinder off) successfully completed - wooden_wheel_pallet") + + time.sleep(save_time) + + robot.linear_move_extend([-298.306, 0, 0,0,0,0], 1, False, 8000, 3000, 0.1) # x축 -해서 책 집을 위치로 가기 (-67.025) + write_log("BE: linear_move_extend : [-298.306, 0, 0,0,0,0] (move toward stacker to grip book) successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 0, 1) # 그리퍼 수직 작동 + write_log("BE: set_digital_output(IO_CABINET, 0, 1) (turn ON vertical gripper cylinder to grip book) successfully completed - wooden_wheel_pallet") + time.sleep(0.3) + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0, 0, -694.816,0,0,0], 1, False, speed, acc, 0.1) # 책 떠서 올림 + write_log("BE: linear_move_extend : [0, 0, -694.816,0,0,0] (lift with book placed on gripper) successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + time.sleep(0.3) + + if centerY > pallet_length / 2: + # 아래 팔레트 집입 자세 + robot.joint_move_extend(lower_pallet_enter_pose, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : lower_pallet_enter_pose for odd layer grid #2 and #4 successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 1: # grid 2 + robot.joint_move_extend([radians(-83.398), radians(102.810), radians(61.767), radians(105.424), radians(-90), radians(-85.698)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_wheel_pallet(odd layer) grid 2 Ready pose/ joint_move_extend [radians(-83.398), radians(102.810), radians(61.767), radians(105.424), radians(-90), radians(-85.698)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 9, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend : [{centerX + 31}, {centerY + 9}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + if current_data_index == 3: # grid 4 + robot.joint_move_extend([radians(-66.699), radians(105.342), radians(58.472), radians(106.187), radians(-90), radians(-68.999)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_wheel_pallet(odd layer) grid 4 Ready pose/ joint_move_extend[[radians(-62.833), radians(107.457), radians(55.613), radians(106.930), radians(-90), radians(25.779)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 9, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 2: [{centerX + 24}, {centerY + 9}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + else: + # 위에 팔레트 집입 자세 + robot.joint_move_extend(lower_pallet_enter_pose1, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : lower_pallet_enter_pose1 for grid 1 and 3 successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 0: # grid 1 + robot.joint_move_extend([radians(-84.575), radians(122.286), radians(32.836), radians(114.878), radians(-90), radians(-86.875)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_wheel_pallet(odd layer) grid 1 Ready pose/ joint_move_extend [radians(-84.575), radians(122.286), radians(32.836), radians(114.878), radians(-90), radians(-86.875)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 5, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 1 : [{centerX + 31}, {centerY + 5}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + if current_data_index == 2: # grid 3 + robot.joint_move_extend([radians(-70.674), radians(125.675), radians(26.930), radians(117.394), radians(-90), radians(-72.974)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_wheel_pallet(odd layer) grid 3 Ready pose/ joint_move_extend [radians(-70.674), radians(125.675), radians(26.930), radians(117.394), radians(-90), radians(-72.974)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 5, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 3 : [{centerX + 24}, {centerY + 5}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + current_layer_height = z_pos + + robot.set_digital_output(IO_CABINET, 0, 0) # 그리퍼 수직 off + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (gripper vertical cylinder off after put on pallet) successfully completed - wooden_wheel_pallet") + time.sleep(0.3) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 1) # 그리퍼 수평 on + write_log("BE: set_digital_output(IO_CABINET, 1, 1) (gripper parallel cylinder on after put on pallet) successfully completed - wooden_wheel_pallet") + time.sleep(1) + if (EMO(1, 1)): + continue + + robot.linear_move_extend([0, 0, -180, 0, 0, 0], 1, False, 8000, 3000, 0.1) + write_log(f"BE: linear_move_extend : [0, 0, -180, 0, 0, 0] (move robot little bit up) successfully completed - wooden_wheel_pallet") + is_in_pose() + time.sleep(0.5) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 0) # 그리퍼 수평 off + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (after lift up turn OFF gripper parallel cylinder) successfully completed - wooden_wheel_pallet") + if (EMO(1, 0)): + continue + + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(1, 0)): + continue + + current_data_index += 1 + cache_data['currentDataIndex'] = current_data_index + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + is_move_pose = True + + + + else: # 짝수 번째 레이어 (그리퍼 돌려서 책 들기) + write_log("BE: load book on pallet's else condition started - wooden_wheel_pallet") + current_data_list = list(book_center_positions) + current_data = current_data_list[current_data_index] + + centerX = current_data['x'] + centerY = current_data['y'] + + robot.set_digital_output(IO_CABINET, 1, 0) + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (for safety purposes : parallel gripper cylinder off) successfully completed - wooden_wheel_pallet") + robot.set_digital_output(IO_CABINET, 0, 0) + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (for safety purposes : vertical gripper cylinder off) successfully completed - wooden_wheel_pallet") + + time.sleep(save_time) + + robot.linear_move_extend([194.344,0,0,0,0,0], 1, False, 8000, 3000, 0.1) # (-386.213) --> -387.213으로 하기 -->-384.208 + write_log("BE: linear_move_extend : [194.344,0,0,0,0,0] (move toward stacker to grip book) successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 0, 1) # 그리퍼 수직 on + write_log("BE: set_digital_output(IO_CABINET, 0, 1) (turn ON vertical gripper cylinder to grip book) successfully completed - wooden_wheel_pallet") + time.sleep(0.1) + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,-703.816,0,0,0], 1, False, speed, acc, 0.1) # (-927.623) + write_log("BE: linear_move_extend : [0,0,-703.816,0,0,0] (lift with book placed on gripper) successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + time.sleep(0.3) + + if centerY > pallet_length /2: + robot.joint_move_extend(lower_pallet_enter_pose, 0, False, 5, 1, 0.1) # 만약 책이 미끄러진다면 속도 조절 둘다 + write_log("BE: joint_move_extend : lower_pallet_enter_pose for even layer grid 2 and 4 successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 1: # grid 2 + robot.joint_move_extend([radians(-83.398), radians(102.810), radians(61.767), radians(105.424), radians(-90), radians(-85.698)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_wheel_pallet(even layer) grid 2 Ready pose/ joint_move_extend [radians(-83.398), radians(102.810), radians(61.767), radians(105.424), radians(-90), radians(-85.698)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 9, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 2 : [{centerX + 31}, {centerY + 9}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + if current_data_index == 3: # grid 4 + robot.joint_move_extend([radians(-66.699), radians(105.342), radians(58.472), radians(106.187), radians(-90), radians(-68.999)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_wheel_pallet(even layer) grid 4 Ready pose/ joint_move_extend [radians(-66.699), radians(105.342), radians(58.472), radians(106.187), radians(-90), radians(-68.999)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 9, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 4 : [{centerX + 24}, {centerY + 9}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + else: + robot.joint_move_extend(lower_pallet_enter_pose1, 0, False, 5, 1, 0.1) + write_log("BE: joint_move_extend : lower_pallet_enter_pose1 for grid 1 and 3 successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 0: # grid 1 + robot.joint_move_extend([radians(-84.575), radians(122.286), radians(32.836), radians(114.878), radians(-90), radians(-86.875)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_wheel_pallet(even layer) grid 1 Ready pose/ joint_move_extend [radians(-84.575), radians(122.286), radians(32.836), radians(114.878), radians(-90), radians(-86.875)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 5, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 1 : [{centerX + 31}, {centerY + 5}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + if current_data_index == 2: # grid 3 + robot.joint_move_extend([radians(-70.674), radians(125.675), radians(26.930), radians(117.394), radians(-90), radians(-72.974)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_wheel_pallet(even layer) grid 3 Ready pose/ joint_move_extend [radians(-70.674), radians(125.675), radians(26.930), radians(117.394), radians(-90), radians(-72.974)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 5, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 3: [{centerX + 24}, {centerY + 5}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + current_layer_height = z_pos + + robot.set_digital_output(IO_CABINET, 0, 0) # 그리퍼 수직 off + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (gripper vertical cylinder off after put on pallet) successfully completed - wooden_wheel_pallet") + time.sleep(0.2) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 1) # 그리퍼 수평 on + write_log("BE: set_digital_output(IO_CABINET, 1, 1) (gripper parallel cylinder on after put on pallet) successfully completed - wooden_wheel_pallet") + time.sleep(1) + if (EMO(1, 1)): + continue + + robot.linear_move_extend([0, 0, -180, 0,0, 0], 1, False, 8000, 3000, 0.1) + write_log(f"BE: linear_move_extend : [0, 0, -180, 0, 0, 0] (move robot little bit up) successfully completed - wooden_wheel_pallet") + is_in_pose() + time.sleep(0.5) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 0) # 그리퍼 수평 off + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (after lift up turn OFF gripper parallel cylinder) successfully completed - wooden_wheel_pallet") + if (EMO(1, 0)): + continue + + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - wooden_wheel_pallet") + is_in_pose() + if (EMO(1, 0)): + continue + + current_data_index += 1 + cache_data['currentDataIndex'] = current_data_index + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + is_move_pose = True + + + +# 철제 바퀴 팔레트 일 때 (즉, ㅁ 모양으로 놓을때) +def iron_wheel_pallet(): + write_log("BE: iron_wheel_pallet function started") + global action, immediately_take_book + global emergency_stop, protected_stop_stat + global power_on_stat, enabled_stat + global robot_start_clicked, terminate_robot_button_clicked + global pallet_width, pallet_length, pallet_height, book_center_positions + global stacker_thread_running, stacker_thread_operator + + global is_emo_disabled, stacker_vertical_cyl_sensor, stacker_book_ready_sensor, stacker_vertical_cyl_down_sensor + + # @@@ 새로 추가한 변수 + global z_pos + + global iron_wheel_pallet_max_z_pos + # @@@ + + is_move_pose = True + + robot.linear_move_extend([0, 0, -350, 0, 0, 0], 1, True, 7000, 2000, 0.1) + write_log("BE: linear_move_extend : [0, 0, -350, 0, 0, 0] successfully completed - iron_wheel_pallet") + home_pos = [radians(-58.423), radians(95.567), radians(66.994), radians(107.440), radians(-90), radians(31.577)] + lower_pallet_enter_pose = [radians(-61.533), radians(107.484), radians(55.576), radians(106.940), radians(-90), radians(-61.533)] + lower_pallet_enter_pose1 = [radians(-66.797), radians(136.143), radians(6.799), radians(127.058), radians(-90), radians(-66.797)] + + robot.login() + write_log("BE: login successfully completed - iron_wheel_pallet") + robot.power_on() + write_log("BE: power_on successfully completed - iron_wheel_pallet") + robot.enable_robot() + write_log("BE: enable_robot successfully completed - iron_wheel_pallet") + robot.joint_move_extend(home_pos, 0, True, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - iron_wheel_pallet") + + if os.path.exists(cache_json_file_path) and os.path.getsize(cache_json_file_path) > 0: + with open(cache_json_file_path, 'r', encoding='utf-8') as file: + cache_data = json.load(file) + + current_data_index_cache = cache_data.get('currentDataIndex') + current_layer_index_cache = cache_data.get('currentLayerIndex') + current_layer_height_cache = cache_data.get('currentLayerHeight') + + current_data_index = current_data_index_cache + current_layer_index = current_layer_index_cache + current_layer_height = current_layer_height_cache + else: + cache_data = { + "currentDataIndex": 0, + "currentLayerIndex": 0, + "currentLayerHeight": 0 + } + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + current_data_index = 0 + current_layer_index = 0 + current_layer_height = 0 + + while True: + if (EMO(0, 0)): + is_move_pose = True + continue + + if action == 'robot_finish_action': + action = None + current_data_index = 0 + current_layer_index = 0 + current_layer_height = 0 + terminate_robot_button_clicked = True + + cache_data['currentLayerIndex'] = current_layer_index + cache_data['currentDataIndex'] = current_data_index + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + stacker_thread_running = False + if stacker_thread_operator: + stacker_thread_operator.join() + + robot.set_digital_output(IO_CABINET, 5, 0) + write_log("BE: robot.set_digital_output(IO_CABINET, 5, 0) (conveyor belt off) successfully completed - iron_wheel_pallet") + + write_log("BE: action == 'robot_finish_action' successfully completed - iron_wheel_pallet") + break + + if current_layer_height + 130 > wheel_max_current_layer_height and current_data_index == 4: + action = None + current_data_index = 0 + current_layer_index = 0 + current_layer_height = 0 + terminate_robot_button_clicked = True + + cache_data['currentLayerIndex'] = current_layer_index + cache_data['currentDataIndex'] = current_data_index + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + stacker_thread_running = False + if stacker_thread_operator: + stacker_thread_operator.join() + + robot.set_digital_output(IO_CABINET, 5, 0) + write_log("BE: robot.set_digital_output(IO_CABINET, 5, 0) (conveyor belt off) successfully completed - iron_wheel_pallet") + + write_log("BE: current_layer_height > wheel_max_current_layer_height successfully completed - iron_wheel_pallet") + break + + # 4권 다 놓으면 레이어 index + 1 + if(current_data_index == 4): + current_layer_index += 1 + current_data_index = 0 + + cache_data['currentLayerIndex'] = current_layer_index + cache_data['currentDataIndex'] = current_data_index + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + if is_move_pose == True and is_emo_disabled == True: + is_move_pose = False + if current_layer_index % 2 == 0: + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - iron_wheel_pallet") + is_in_pose() + + pickup_pose = [radians(-47.102), radians(84.387), radians(78.169), radians(107.444), radians(-90), radians(131.510)] + + robot.joint_move_extend(pickup_pose, 0, False, 8000, 3000, 0.1) # 책 뜨기 공중 준비 자세 + write_log("BE: joint_move_extend : pickup_pose successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,666.816,0,0,0], 1,False, 8000, 3000, 0.1) # 공중에서 z축 내리기(-247.633) + write_log("BE: linear_move_extend : [0,0,666.816,0,0,0] (ready pose) successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + else: + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - iron_wheel_pallet") + is_in_pose() + + pickup_pose_opposite = [radians(-24.283), radians(120.475), radians(32.213), radians(117.312), radians(-90), radians(-25.671)] + + robot.joint_move_extend(pickup_pose_opposite, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : pickup_pose_opposite successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,681.817,0,0,0], 1, False, 8000, 3000, 0.1) # (-273.633) -253.633 --> -249.633 + write_log("BE: linear_move_extend : [0,0,681.817,0,0,0] (ready pose) successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)): + immediately_take_book = None + + if current_layer_index % 2 == 0: # 홀수 번째 레이어 + write_log("BE: load book on pallet's if condition started - iron_wheel_pallet") + current_data_list = list(book_center_positions) + current_data = current_data_list[current_data_index] + + centerX = current_data['x'] + centerY = current_data['y'] + + robot.set_digital_output(IO_CABINET, 1, 0) + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (for safety purposes : parallel gripper cylinder off) successfully completed - iron_wheel_pallet") + robot.set_digital_output(IO_CABINET, 0, 0) + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (for safety purposes : vertical gripper cylinder off) successfully completed - iron_wheel_pallet") + + time.sleep(save_time) + + robot.linear_move_extend([-298.306, 0, 0,0,0,0], 1, False, 8000, 3000, 0.1) # x축 -해서 책 집을 위치로 가기 (-67.025) + write_log("BE: linear_move_extend : [-298.306, 0, 0,0,0,0] (move toward stacker to grip book) successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 0, 1) # 그리퍼 수직 작동 + write_log("BE: set_digital_output(IO_CABINET, 0, 1) (turn ON vertical gripper cylinder to grip book) successfully completed - iron_wheel_pallet") + time.sleep(0.3) + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0, 0, -694.816,0,0,0], 1, False, speed, acc, 0.1) # 책 떠서 올림 + write_log("BE: linear_move_extend : [0, 0, -694.816,0,0,0] (lift with book placed on gripper) successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + time.sleep(0.3) + + if centerY > pallet_length / 2: + # 아래 팔레트 집입 자세 + robot.joint_move_extend(lower_pallet_enter_pose, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : lower_pallet_enter_pose for odd layer grid 2 and 4 successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 1: # grid 2 + robot.joint_move_extend([radians(-83.418), radians(103.042), radians(61.470), radians(105.488), radians(-90), radians(-85.718)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: iron_wheel_pallet(odd layer) grid 2 Ready pose/ joint_move_extend [radians(-83.418), radians(103.042), radians(61.470), radians(105.488), radians(-90), radians(-85.718)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 6, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 2 : [{centerX + 31}, {centerY + 6}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + if current_data_index == 3: # grid 4 + robot.joint_move_extend([radians(-66.765), radians(105.573), radians(58.163), radians(106.263), radians(-90), radians(-69.065)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: iron_wheel_pallet(odd layer) grid 4 Ready pose/ joint_move_extend [radians(-66.765), radians(105.573), radians(58.163), radians(106.263), radians(-90), radians(-69.065)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 6, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 4 : [{centerX + 24}, {centerY + 6}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + else: + # 위에 팔레트 집입 자세 + robot.joint_move_extend(lower_pallet_enter_pose1, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : lower_pallet_enter_pose1 for odd layer grid 1 and 3 successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 0: # grid 1 + robot.joint_move_extend([radians(-84.588), radians(122.643), radians(32.227), radians(115.130), radians(-90), radians(-86.888)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: iron_wheel_pallet(odd layer) grid 1 Ready pose/ joint_move_extend [radians(-84.588), radians(122.643), radians(32.227), radians(115.130), radians(-90), radians(-86.888)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 2, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 1 : [{centerX + 31}, {centerY + 2}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + if current_data_index == 2: # grid 3 + robot.joint_move_extend([radians(-70.720), radians(126.085), radians(26.197), radians(117.718), radians(-90), radians(-73.020)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: iron_wheel_pallet(odd layer) grid 3 Ready pose/ joint_move_extend [radians(-70.720), radians(126.085), radians(26.197), radians(117.718), radians(-90), radians(-73.020)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 2, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 3 : [{centerX + 24}, {centerY + 2}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + current_layer_height = z_pos + + robot.set_digital_output(IO_CABINET, 0, 0) # 그리퍼 수직 off + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (gripper vertical cylinder off after put on pallet) successfully completed - iron_wheel_pallet") + time.sleep(0.3) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 1) # 그리퍼 수평 on + write_log("BE: set_digital_output(IO_CABINET, 1, 1) (gripper parallel cylinder on after put on pallet) successfully completed - iron_wheel_pallet") + time.sleep(1) + if (EMO(1, 1)): + continue + + robot.linear_move_extend([0,0, -180, 0,0, 0], 1, False, 8000, 3000, 0.1) + write_log(f"BE: linear_move_extend : [0, 0, -180, 0, 0, 0] (move robot little bit up) successfully completed - iron_wheel_pallet") + is_in_pose() + time.sleep(0.5) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 0) # 그리퍼 수평 off + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (after lift up turn OFF gripper parallel cylinder) successfully completed - iron_wheel_pallet") + if (EMO(1, 0)): + continue + + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(1, 0)): + continue + + current_data_index += 1 + cache_data['currentDataIndex'] = current_data_index + # @@@ current_layer_height는 모든 동작이 무사히 완료된 후에 json에 저장하는 걸로..? " + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + is_move_pose = True + + + else: # 짝수 번째 레이어 (그리퍼 돌려서 책 들기) + write_log("BE: load book on pallet's else condition started - iron_wheel_pallet") + current_data_list = list(book_center_positions) + current_data = current_data_list[current_data_index] + + centerX = current_data['x'] + centerY = current_data['y'] + + robot.set_digital_output(IO_CABINET, 1, 0) + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (for safety purposes : parallel gripper cylinder off) successfully completed - iron_wheel_pallet") + robot.set_digital_output(IO_CABINET, 0, 0) + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (for safety purposes : vertical gripper cylinder off) successfully completed - iron_wheel_pallet") + + time.sleep(save_time) + + robot.linear_move_extend([194.344,0,0,0,0,0], 1, False, 8000, 3000, 0.1) # (-386.213) --> -387.213으로 하기 -->-384.208 + write_log("BE: linear_move_extend : [194.344,0,0,0,0,0] (move toward stacker to grip book) successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 0, 1) # 그리퍼 수직 on + write_log("BE: set_digital_output(IO_CABINET, 0, 1) (turn ON vertical gripper cylinder to grip book) successfully completed - iron_wheel_pallet") + time.sleep(0.1) + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,-703.816,0,0,0], 1, False, speed, acc, 0.1) # (-927.623) + write_log("BE: linear_move_extend : [0,0,-703.816,0,0,0] (lift with book placed on gripper) successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + time.sleep(0.3) + + if centerY > pallet_length /2: + robot.joint_move_extend(lower_pallet_enter_pose, 0, False, 5, 1, 0.1) # 만약 책이 미끄러진다면 속도 조절 둘다 + write_log("BE: joint_move_extend : lower_pallet_enter_pose for even layer gird 2 and 4 successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 1: # grid 2 + robot.joint_move_extend([radians(-83.418), radians(103.042), radians(61.470), radians(105.488), radians(-90), radians(-85.718)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: iron_wheel_pallet(even layer) grid 2 Ready pose/ joint_move_extend [radians(-83.418), radians(103.042), radians(61.470), radians(105.488), radians(-90), radians(-85.718)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 6, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 2 : [{centerX + 31}, {centerY + 6}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + if current_data_index == 3: # grid 4 + robot.joint_move_extend([radians(-66.765), radians(105.573), radians(58.163), radians(106.263), radians(-90), radians(-69.065)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: iron_wheel_pallet(even layer) grid 4 Ready pose/ joint_move_extend [radians(-66.765), radians(105.573), radians(58.163), radians(106.263), radians(-90), radians(-69.065)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 6, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 4: [{centerX + 24}, {centerY + 6}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + else: + robot.joint_move_extend(lower_pallet_enter_pose1, 0, False, 5, 1, 0.1) + write_log("BE: joint_move_extend : lower_pallet_enter_pose1 for even layer gird 1 and 3 successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 0: # grid 1 + robot.joint_move_extend([radians(-84.588), radians(122.643), radians(32.227), radians(115.130), radians(-90), radians(-86.888)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: iron_wheel_pallet(even layer) grid 1 Ready pose/ joint_move_extend [radians(-84.588), radians(122.643), radians(32.227), radians(115.130), radians(-90), radians(-86.888)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 2, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 1 : [{centerX + 31}, {centerY + 2}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + if current_data_index == 2: # grid 3 + robot.joint_move_extend([radians(-70.720), radians(126.085), radians(26.197), radians(117.718), radians(-90), radians(-73.020)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: iron_wheel_pallet(even layer) grid 3 Ready pose/ joint_move_extend [radians(-70.720), radians(126.085), radians(26.197), radians(117.718), radians(-90), radians(-73.020)]") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 2, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 3 : [{centerX + 24}, {centerY + 2}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + + # @@@@@@@@@@@@@@@@@@@current_layer_height 에 z값 저장 (z값은 is_in_pose 함수에서 가져옴, )@@@@@@@@@@@@@@@@@@@@@ + current_layer_height = z_pos + + robot.set_digital_output(IO_CABINET, 0, 0) # 그리퍼 수직 off + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (gripper vertical cylinder off after put on pallet) successfully completed - iron_wheel_pallet") + time.sleep(0.2) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 1) # 그리퍼 수평 on + write_log("BE: set_digital_output(IO_CABINET, 1, 1) (gripper parallel cylinder on after put on pallet) successfully completed - iron_wheel_pallet") + time.sleep(1) + if (EMO(1, 1)): + continue + + robot.linear_move_extend([0,0, -180, 0,0, 0], 1, False, 8000, 3000, 0.1) + write_log(f"BE: linear_move_extend : [0,0, -180, 0,0, 0] (move robot little bit up) successfully completed - iron_wheel_pallet") + is_in_pose() + time.sleep(0.5) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 0) # 그리퍼 수평 off + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (after lift up turn OFF gripper parallel cylinder) successfully completed - iron_wheel_pallet") + if (EMO(1, 0)): + continue + + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - iron_wheel_pallet") + is_in_pose() + if (EMO(1, 0)): + continue + + current_data_index += 1 + cache_data['currentDataIndex'] = current_data_index + # @@@ current_layer_height는 모든 동작이 무사히 완료된 후에 json에 저장하는 걸로..? " + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + is_move_pose = True + + +# 나무 납작 팔레트 일 때 +def wooden_Flat_pallet(): + write_log("BE: wooden_Flat_pallet function started") + global action, immediately_take_book + global emergency_stop, protected_stop_stat + global power_on_stat, enabled_stat + global robot_start_clicked, terminate_robot_button_clicked + global pallet_width, pallet_length, pallet_height, book_center_positions + global stacker_thread_running, stacker_thread_operator + + global is_emo_disabled, stacker_vertical_cyl_sensor, stacker_book_ready_sensor, stacker_vertical_cyl_down_sensor + + # @@@ 새로 추가한 변수 + global z_pos + + global wooden_Flat_pallet_max_z_pos + # @@@ + + is_move_pose = True + + robot.linear_move_extend([0, 0, -350, 0, 0, 0], 1, True, 7000, 2000, 0.1) + write_log("BE: linear_move_extend : [0, 0, -350, 0, 0, 0] successfully completed - wooden_Flat_pallet") + home_pos = [radians(-58.423), radians(95.567), radians(66.994), radians(107.440), radians(-90), radians(31.577)] + low_profile_1_to_4_enter_pose = [radians(-63.525), radians(133.785), radians(21.038), radians(115.177), radians(-90), radians(-155.138)] + low_profile_5_to_7_enter_pose = [radians(-56.413), radians(106.471), radians(65.326), radians(98.204), radians(-90), radians(-148.025)] # 로봇 쪽(5,6,7,8) + pallet_8th_enter_pose = [radians(-62.445), radians(103.812), radians(68.820), radians(97.369), radians(-90), radians(-154.057)] + + robot.login() + write_log("BE: login successfully completed - wooden_Flat_pallet") + robot.power_on() + write_log("BE: power_on successfully completed - wooden_Flat_pallet") + robot.enable_robot() + write_log("BE: enable_robot successfully completed - wooden_Flat_pallet") + robot.joint_move_extend(home_pos, 0, True, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - wooden_Flat_pallet") + + if os.path.exists(cache_json_file_path) and os.path.getsize(cache_json_file_path) > 0: + with open(cache_json_file_path, 'r', encoding='utf-8') as file: + cache_data = json.load(file) + + current_data_index_cache = cache_data.get('currentDataIndex') + current_layer_index_cache = cache_data.get('currentLayerIndex') + current_layer_height_cache = cache_data.get('currentLayerHeight') + + current_data_index = current_data_index_cache + current_layer_index = current_layer_index_cache + current_layer_height = current_layer_height_cache + else: + cache_data = { + "currentDataIndex": 0, + "currentLayerIndex": 0, + "currentLayerHeight": 0 + } + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + current_data_index = 0 + current_layer_index = 0 + current_layer_height = 0 + + + while True: + if (EMO(0, 0)): + is_move_pose = True + continue + + if action == 'robot_finish_action': + action = None + current_data_index = 0 + current_layer_index = 0 + current_layer_height = 0 + terminate_robot_button_clicked = True + + cache_data['currentLayerIndex'] = current_layer_index + cache_data['currentDataIndex'] = current_data_index + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + stacker_thread_running = False + if stacker_thread_operator: + stacker_thread_operator.join() + + robot.set_digital_output(IO_CABINET, 5, 0) + write_log("BE: robot.set_digital_output(IO_CABINET, 5, 0) (conveyor belt off) successfully completed - wooden_Flat_pallet") + + write_log("BE: action == 'robot_finish_action' successfully completed - wooden_Flat_pallet") + break + + if current_layer_height + 130 > flat_max_current_layer_height and current_data_index == 8: + action = None + current_data_index = 0 + current_layer_index = 0 + current_layer_height = 0 + terminate_robot_button_clicked = True + + cache_data['currentLayerIndex'] = current_layer_index + cache_data['currentDataIndex'] = current_data_index + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + stacker_thread_running = False + if stacker_thread_operator: + stacker_thread_operator.join() + + robot.set_digital_output(IO_CABINET, 5, 0) + write_log("BE: robot.set_digital_output(IO_CABINET, 5, 0) (conveyor belt off) successfully completed - wooden_Flat_pallet") + + write_log("BE: current_layer_height > flat_max_current_layer_height successfully completed - wooden_Flat_pallet") + break + + # 8권 다 놓으면 레이어 index + 1 + if(current_data_index == 8): + current_layer_index += 1 + current_data_index = 0 + + cache_data['currentLayerIndex'] = current_layer_index + cache_data['currentDataIndex'] = current_data_index + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + if is_move_pose == True and is_emo_disabled == True: + is_move_pose = False + if current_layer_index % 2 == 0: + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - wooden_Flat_pallet") + is_in_pose() + + pickup_pose = [radians(-47.102), radians(84.387), radians(78.169), radians(107.444), radians(-90), radians(131.510)] + + robot.joint_move_extend(pickup_pose, 0, False, 8000, 3000, 0.1) # 책 뜨기 공중 준비 자세 + write_log("BE: joint_move_extend : pickup_pose successfully completed - wooden_Flat_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,666.816,0,0,0], 1,False, 8000, 3000, 0.1) # 공중에서 z축 내리기(-247.633) + write_log("BE: linear_move_extend : [0,0,666.816,0,0,0] (ready pose) successfully completed - wooden_Flat_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + else: + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - wooden_Flat_pallet") + is_in_pose() + + pickup_pose_opposite = [radians(-24.283), radians(120.475), radians(32.213), radians(117.312), radians(-90), radians(-25.671)] + + robot.joint_move_extend(pickup_pose_opposite, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : pickup_pose_opposite successfully completed - wooden_Flat_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,681.817,0,0,0], 1, False, 8000, 3000, 0.1) # (-273.633) -253.633 --> -249.633 + write_log("BE: linear_move_extend : [0,0,681.817,0,0,0] (ready pose) successfully completed - wooden_Flat_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)): + immediately_take_book = None + + if current_layer_index % 2 == 0: # 홀수 번째 레이어 + write_log("BE: load book on pallet's if condition started - wooden_Flat_pallet") + current_data_list = list(book_center_positions) + current_data = current_data_list[current_data_index] + + centerX = current_data['x'] + centerY = current_data['y'] + + robot.set_digital_output(IO_CABINET, 1, 0) + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (for safety purposes : parallel gripper cylinder off) successfully completed - wooden_Flat_pallet") + robot.set_digital_output(IO_CABINET, 0, 0) + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (for safety purposes : vertical gripper cylinder off) successfully completed - wooden_Flat_pallet") + + time.sleep(save_time) + + robot.linear_move_extend([-298.306, 0, 0,0,0,0], 1, False, 8000, 3000, 0.1) # x축 -해서 책 집을 위치로 가기 (-67.025) + write_log("BE: linear_move_extend : [-298.306, 0, 0,0,0,0] (move toward stacker to grip book) successfully completed - wooden_Flat_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 0, 1) # 그리퍼 수직 작동 + write_log("BE: set_digital_output(IO_CABINET, 0, 1) (turn ON vertical gripper cylinder to grip book) successfully completed - wooden_Flat_pallet") + time.sleep(0.3) + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0, 0, -694.816,0,0,0], 1, False, speed, acc, 0.1) # 책 떠서 올림 + write_log("BE: linear_move_extend : [0, 0, -694.816,0,0,0] (lift with book placed on gripper) successfully completed - wooden_Flat_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + time.sleep(0.3) + + if centerY < pallet_length / 2: + # 4 3 2 1 + robot.joint_move_extend(low_profile_1_to_4_enter_pose, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : low_profile_1_to_4_enter_pose for odd layer grid 1,2,3,4 successfully completed - wooden_Flat_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 0: # 1번 + robot.joint_move_extend([radians(-97.824), radians(132.232), radians(23.979), radians(113.789), radians(-90), radians(-190.124)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(odd layer) grid 1 Ready pose/ joint_move_extend [radians(-84.588), radians(122.643), radians(32.227), radians(115.130), radians(-90), radians(-86.888)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 246, centerY + 155, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 1 : [{centerX + 246}, {centerY + 155}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + if current_data_index == 1: # 2번 + robot.joint_move_extend([radians(-88.388), radians(127.129), radians(33.265), radians(109.606), radians(-90), radians(-180.688)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(odd layer) grid 2 Ready pose/ joint_move_extend [radians(-88.388), radians(127.129), radians(33.265), radians(109.606), radians(-90), radians(-180.688)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 240, centerY + 155, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 2 : [{centerX + 240}, {centerY + 155}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + if current_data_index == 2: # 3번 + robot.joint_move_extend([radians(-78.851), radians(126.862), radians(33.735), radians(109.403), radians(-90), radians(-171.151)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(odd layer) grid 3 Ready pose/ joint_move_extend [radians(-78.851), radians(126.862), radians(33.735), radians(109.403), radians(-90), radians(-171.151)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 234, centerY + 155, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 3 : [{centerX + 234}, {centerY + 155}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + if current_data_index == 3:# 4번 + robot.joint_move_extend([radians(-69.724), radians(131.237), radians(25.835), radians(112.928), radians(-90), radians(-162.024)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(odd layer) grid 4 Ready pose/ joint_move_extend [radians(-69.724), radians(131.237), radians(25.835), radians(112.928), radians(-90), radians(-162.024)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 228, centerY + 155, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 4 : [{centerX + 228}, {centerY + 155}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + else: + if current_data_index == 7: #8번 + robot.joint_move_extend(pallet_8th_enter_pose, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : pallet_8th_enter_pose(odd layer) successfully completed - wooden_Flat_pallet") + is_in_pose() + + robot.joint_move_extend([radians(-63.913), radians(103.999), radians(68.579), radians(97.422), radians(-90.000), radians(-156.213)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(odd layer) grid 8 Ready pose/ joint_move_extend [radians(-63.913), radians(103.999), radians(68.579), radians(97.422), radians(-90.000), radians(-156.213)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 228, centerY + 159, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 8 : [{centerX + 228}, {centerY + 159}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + else: + robot.joint_move_extend(low_profile_5_to_7_enter_pose, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : low_profile_5_to_7_enter_pose for odd layer grid 5,6,7 successfully completed - wooden_Flat_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 4: # 5번 + robot.joint_move_extend([radians(-100.110), radians(104.625), radians(67.768), radians(97.607), radians(-90), radians(-192.410)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(odd layer) grid 5 Ready pose/ joint_move_extend [radians(-100.110), radians(104.625), radians(67.768), radians(97.607), radians(-90), radians(-192.410)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 246, centerY + 159, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 5 : [{centerX + 246}, {centerY + 159}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + if current_data_index == 5: # 6번 + robot.joint_move_extend([radians(-87.895), radians(101.029), radians(72.323), radians(96.648), radians(-90), radians(-180.195)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(odd layer) grid 6 Ready pose/ joint_move_extend [radians(-87.895), radians(101.029), radians(72.323), radians(96.648), radians(-90), radians(-180.195)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 240, centerY + 159, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 6 : [{centerX + 240}, {centerY + 159}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + if current_data_index == 6: # 7번 + robot.joint_move_extend([radians(-75.459), radians(100.816), radians(72.585), radians(96.599), radians(-90), radians(-167.759)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(odd layer) grid 7 Ready pose/ joint_move_extend [radians(-75.459), radians(100.816), radians(72.585), radians(96.599), radians(-90), radians(-167.759)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 234, centerY + 159, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 7 : [{centerX + 234}, {centerY + 159}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + # @@@@@@@@@@@@@@@@@@@current_layer_height 에 z값 저장 (z값은 is_in_pose 함수에서 가져옴, )@@@@@@@@@@@@@@@@@@@@@ + current_layer_height = z_pos + + robot.set_payload(mass= 14, centroid =[0,0,0]) + write_log("Set payload 14") + + robot.set_digital_output(IO_CABINET, 0, 0) # 그리퍼 수직 off + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (gripper vertical cylinder off after put on pallet) successfully completed - wooden_Flat_pallet") + time.sleep(0.3) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 1) # 그리퍼 수평 on + write_log("BE: set_digital_output(IO_CABINET, 1, 1) (gripper parallel cylinder on after put on pallet) successfully completed - wooden_Flat_pallet") + time.sleep(1) + if (EMO(1, 1)): + continue + + robot.linear_move_extend([0,0, -180, 0,0, 0], 1, False, 8000, 3000, 0.1) + write_log(f"BE: linear_move_extend : [0, 0, -180, 0, 0, 0] (move robot little bit up) successfully completed - wooden_Flat_pallet") + is_in_pose() + time.sleep(0.5) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 0) # 그리퍼 수평 off + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (after lift up turn OFF gripper parallel cylinder) successfully completed - wooden_Flat_pallet") + if (EMO(1, 0)): + continue + + robot.linear_move_extend([0,0,-(wooden_Flat_pallet_max_z_pos - (current_layer_height)), 0, 0, 0], 1, False, 8000, 3000, 0.1) + write_log(f"BE: linear_move_extend : [0, 0, {-(wooden_Flat_pallet_max_z_pos - (current_layer_height))}, 0, 0, 0] successfully completed - wooden_Flat_pallet") + is_in_pose() + + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - wooden_Flat_pallet") + is_in_pose() + if (EMO(1, 0)): + continue + + current_data_index += 1 + cache_data['currentDataIndex'] = current_data_index + # @@@ current_layer_height는 모든 동작이 무사히 완료된 후에 json에 저장하는 걸로..? " + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + is_move_pose = True + + + else: # 짝수 번째 레이어 (그리퍼 돌려서 책 들기) + write_log("BE: load book on pallet's else condition started - wooden_Flat_pallet") + current_data_list = list(book_center_positions) + current_data = current_data_list[current_data_index] + + centerX = current_data['x'] + centerY = current_data['y'] + + robot.set_digital_output(IO_CABINET, 1, 0) + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (for safety purposes : parallel gripper cylinder off) successfully completed - wooden_Flat_pallet") + robot.set_digital_output(IO_CABINET, 0, 0) + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (for safety purposes : vertical gripper cylinder off) successfully completed - wooden_Flat_pallet") + + time.sleep(save_time) + + robot.linear_move_extend([194.344,0,0,0,0,0], 1, False, 8000, 3000, 0.1) # (-386.213) --> -387.213으로 하기 -->-384.208 + write_log("BE: linear_move_extend : [194.344,0,0,0,0,0] (move toward stacker to grip book) successfully completed - wooden_Flat_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 0, 1) # 그리퍼 수직 on + write_log("BE: set_digital_output(IO_CABINET, 0, 1) (turn ON vertical gripper cylinder to grip book) successfully completed - wooden_Flat_pallet") + time.sleep(0.1) + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,-703.816,0,0,0], 1, False, speed, acc, 0.1) # (-927.623) + write_log("BE: linear_move_extend : [0,0,-703.816,0,0,0] (lift with book placed on gripper) successfully completed - wooden_Flat_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + time.sleep(0.3) + + if centerY < pallet_length /2: + robot.joint_move_extend(low_profile_1_to_4_enter_pose, 0, False, 8000, 3000, 0.1) # 만약 책이 미끄러진다면 속도 조절 둘다 + write_log("BE: joint_move_extend : low_profile_1_to_4_enter_pose for even layer gird 1,2,3,4 successfully completed - wooden_Flat_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 0: # 1번 + robot.joint_move_extend([radians(-97.824), radians(132.232), radians(23.979), radians(113.789), radians(-90), radians(-190.124)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(even layer) grid 1 Ready pose/ joint_move_extend [radians(-97.824), radians(132.232), radians(23.979), radians(113.789), radians(-90), radians(-190.124)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 246, centerY + 155, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 1 : [{centerX + 246}, {centerY + 155}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + if current_data_index == 1: # 2번 + robot.joint_move_extend([radians(-88.388), radians(127.129), radians(33.265), radians(109.606), radians(-90), radians(-180.688)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(even layer) grid 2 Ready pose/ joint_move_extend [radians(-88.388), radians(127.129), radians(33.265), radians(109.606), radians(-90), radians(-180.688)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 240, centerY + 155, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 2 : [{centerX + 240}, {centerY + 155}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + if current_data_index == 2: # 3번 + robot.joint_move_extend([radians(-78.851), radians(126.862), radians(33.735), radians(109.403), radians(-90), radians(-171.151)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(even layer) grid 3 Ready pose/ joint_move_extend [radians(-78.851), radians(126.862), radians(33.735), radians(109.403), radians(-90), radians(-171.151)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 234, centerY + 155, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 3 : [{centerX + 234}, {centerY + 155}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + if current_data_index == 3:# 4번 + robot.joint_move_extend([radians(-69.724), radians(131.237), radians(25.835), radians(112.928), radians(-90), radians(-162.024)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(even layer) grid 4 Ready pose/ joint_move_extend [radians(-69.724), radians(131.237), radians(25.835), radians(112.928), radians(-90), radians(-162.024)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 228, centerY + 155, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 4 : [{centerX + 228}, {centerY + 155}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + else: + if current_data_index == 7: # GRID 8 + robot.joint_move_extend(pallet_8th_enter_pose, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : pallet_8th_enter_pose for even layer successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + robot.joint_move_extend([radians(-63.913), radians(103.999), radians(68.579), radians(97.422), radians(-90.000), radians(-156.213)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(even layer) grid 8 Ready pose/ joint_move_extend [radians(-63.913), radians(103.999), radians(68.579), radians(97.422), radians(-90.000), radians(-156.213)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 228, centerY + 159, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 8 : [{centerX + 228}, {centerY + 159}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + else: + robot.joint_move_extend(low_profile_5_to_7_enter_pose, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : low_profile_5_to_7_enter_pose for even layer grid 5,6,7 successfully completed - wooden_Flat_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 4: # 5번 + robot.joint_move_extend([radians(-100.110), radians(104.625), radians(67.768), radians(97.607), radians(-90), radians(-192.410)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(even layer) grid 5 Ready pose/ joint_move_extend [radians(-100.110), radians(104.625), radians(67.768), radians(97.607), radians(-90), radians(-192.410)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 246, centerY + 159, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 5: [{centerX + 246}, {centerY + 159}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + if current_data_index == 5: # 6번 + robot.joint_move_extend([radians(-87.895), radians(101.029), radians(72.323), radians(96.648), radians(-90), radians(-180.195)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(even layer) grid 6 Ready pose/ joint_move_extend [radians(-87.895), radians(101.029), radians(72.323), radians(96.648), radians(-90), radians(-180.195)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 240, centerY + 159, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 6 : [{centerX + 240}, {centerY + 159}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + if current_data_index == 6: # 7번 + robot.joint_move_extend([radians(-75.459), radians(100.816), radians(72.585), radians(96.599), radians(-90), radians(-167.759)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: wooden_Flat_pallet(even layer) grid 7 Ready pose/ joint_move_extend [radians(-75.459), radians(100.816), radians(72.585), radians(96.599), radians(-90), radians(-167.759)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 234, centerY + 159, -wooden_Flat_pallet_max_z_pos, 0, 0, radians(-92.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 7 : [{centerX + 234}, {centerY + 159}, {-wooden_Flat_pallet_max_z_pos}, 0, 0, radians(-92.3)] successfully completed - wooden_Flat_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_Flat_pallet_max_z_pos) + + # @@@@@@@@@@@@@@@@@@@current_layer_height 에 z값 저장 (z값은 is_in_pose 함수에서 가져옴, )@@@@@@@@@@@@@@@@@@@@@ + current_layer_height = z_pos + + robot.set_payload(mass= 14, centroid =[0,0,0]) + write_log("Set payload 14") + + robot.set_digital_output(IO_CABINET, 0, 0) # 그리퍼 수직 off + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (gripper vertical cylinder off after put on pallet) successfully completed - wooden_Flat_pallet") + time.sleep(0.3) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 1) # 그리퍼 수평 on + write_log("BE: set_digital_output(IO_CABINET, 1, 1) (gripper parallel cylinder on after put on pallet) successfully completed - wooden_Flat_pallet") + time.sleep(1) + if (EMO(1, 1)): + continue + + robot.linear_move_extend([0, 0, -180, 0, 0, 0], 1, False, 8000, 3000, 0.1) + write_log(f"BE: linear_move_extend : [0,0, -180, 0, 0, 0] (move robot little bit up) successfully completed - wooden_Flat_pallet") + is_in_pose() + time.sleep(0.5) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 0) # 그리퍼 수평 off + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (after lift up turn OFF gripper parallel cylinder) successfully completed - wooden_Flat_pallet") + if (EMO(1, 0)): + continue + + robot.linear_move_extend([0, 0, -(wooden_Flat_pallet_max_z_pos - (current_layer_height)), 0, 0, 0], 1, False, 8000, 3000, 0.1) + write_log(f"BE: linear_move_extend : [0, 0, {-(wooden_Flat_pallet_max_z_pos - (current_layer_height))}, 0, 0, 0] successfully completed - wooden_Flat_pallet") + is_in_pose() + + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - wooden_Flat_pallet") + is_in_pose() + if (EMO(1, 0)): + continue + + current_data_index += 1 + cache_data['currentDataIndex'] = current_data_index + # @@@ current_layer_height는 모든 동작이 무사히 완료된 후에 json에 저장하는 걸로..? " + cache_data['currentLayerHeight'] = current_layer_height + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + is_move_pose = True + +# currentDataIndex는 고정값인 것 잊지 않기 +def one_line_wooden_wheel_pallet(): + write_log("BE: one_line_wooden_wheel_pallet function started") + global action, immediately_take_book + global emergency_stop, protected_stop_stat + global power_on_stat, enabled_stat + global robot_start_clicked, terminate_robot_button_clicked + global pallet_width, pallet_length, pallet_height, book_center_positions + global stacker_thread_running, stacker_thread_operator + global is_one_line_stop_clicked + + global is_emo_disabled, stacker_vertical_cyl_sensor, stacker_book_ready_sensor, stacker_vertical_cyl_down_sensor + + # @@@ 새로 추가한 변수 + global z_pos + + global wooden_wheel_pallet_max_z_pos + # @@@ + + is_move_pose = True + + robot.linear_move_extend([0, 0, -350, 0, 0, 0], 1, True, 7000, 2000, 0.1) + write_log("BE: linear_move_extend : [0, 0, -350, 0, 0, 0] successfully completed - one_line_wooden_wheel_pallet") + home_pos = [radians(-58.423), radians(95.567), radians(66.994), radians(107.440), radians(-90), radians(31.577)] + lower_pallet_enter_pose = [radians(-61.533), radians(107.484), radians(55.576), radians(106.940), radians(-90), radians(-61.533)] + lower_pallet_enter_pose1 = [radians(-66.797), radians(136.143), radians(6.799), radians(127.058), radians(-90), radians(-66.797)] + + robot.login() + write_log("BE: login successfully completed - one_line_wooden_wheel_pallet") + robot.power_on() + write_log("BE: power_on successfully completed - one_line_wooden_wheel_pallet") + robot.enable_robot() + write_log("BE: enable_robot successfully completed - one_line_wooden_wheel_pallet") + robot.joint_move_extend(home_pos, 0, True, 10, 1, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - one_line_wooden_wheel_pallet") + + if os.path.exists(oneLine_json_file_path) and os.path.getsize(oneLine_json_file_path) > 0: + with open(oneLine_json_file_path, 'r', encoding='utf-8') as file: + oneLine_data = json.load(file) + + grid_data = oneLine_data.get(grid_id, {"currentDataIndex": 0, "currentLayerIndex": 0, "currentLayerHeight": 0}) + current_data_index = grid_data.get('currentDataIndex', 0) + current_layer_index = grid_data.get('currentLayerIndex', 0) + current_layer_height = grid_data.get('currentLayerHeight', 0) + else: + oneLine_data = { + "grid1": {"currentDataIndex": 0, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid2": {"currentDataIndex": 1, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid3": {"currentDataIndex": 2, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid4": {"currentDataIndex": 3, "currentLayerIndex": 0, "currentLayerHeight": 0} + } + with open(oneLine_json_file_path, 'w', encoding='utf-8') as file: + json.dump(oneLine_data, file, indent=4, ensure_ascii=False) + + current_data_index = 0 + current_layer_index = 0 + current_layer_height = 0 + + while True: + if (EMO(0, 0)): + is_move_pose = True + continue + + # 로봇 동작 종료 누르면 초기화 및 while 탈출 / 스태커 멈춤 + if action == 'robot_finish_action': + action = None + current_layer_index = 0 + current_layer_height = 0 + terminate_robot_button_clicked = True + + oneLine_data = { + "grid1": {"currentDataIndex": 0, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid2": {"currentDataIndex": 1, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid3": {"currentDataIndex": 2, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid4": {"currentDataIndex": 3, "currentLayerIndex": 0, "currentLayerHeight": 0} + } + with open(oneLine_json_file_path, 'w', encoding='utf-8') as file: + json.dump(oneLine_data, file, indent=4, ensure_ascii=False) + + stacker_thread_running = False + if stacker_thread_operator: + stacker_thread_operator.join() # Wait for the thread to terminate + + robot.set_digital_output(IO_CABINET, 5, 0) + write_log("BE: robot.set_digital_output(IO_CABINET, 5, 0) (conveyor belt off) successfully completed - one_line_wooden_wheel_pallet") + + write_log("BE: action == 'robot_finish_action' successfully completed - one_line_wooden_wheel_pallet") + break + + # 모든 그리드가 다 6단을 쌓으면 로봇 동작 종료 + if all(oneLine_data[grid]['currentLayerHeight'] > oneline_wheel_max_current_layer_height for grid in oneLine_data): + action = 'robot_finish_action' + write_log("BE: all(oneLine_data[grid]['currentLayerHeight'] > oneline_wheel_max_current_layer_height for grid in oneLine_data) successfully completed - one_line_wooden_wheel_pallet") + continue + + # 한줄쌓기멈춤 버튼을 누르면 while 탈출 / 스태커 멈춤 + if is_one_line_stop_clicked == 'one_line_stop': + is_one_line_stop_clicked = None + terminate_robot_button_clicked = True + + stacker_thread_running = False + if stacker_thread_operator: + stacker_thread_operator.join() + + robot.set_digital_output(IO_CABINET, 5, 0) + write_log("BE: robot.set_digital_output(IO_CABINET, 5, 0) (conveyor belt off) successfully completed - one_line_wooden_wheel_pallet") + write_log("BE: is_one_line_stop_clicked == 'one_line_stop' successfully completed - one_line_wooden_wheel_pallet") + break + + # 만약 6단(최고높이)을 쌓으면 while 탈출 / 스태커 멈춤 + if current_layer_height + 130 > oneline_wheel_max_current_layer_height: + action = None + terminate_robot_button_clicked = True + + stacker_thread_running = False + if stacker_thread_operator: + stacker_thread_operator.join() + + robot.set_digital_output(IO_CABINET, 5, 0) + write_log("BE: robot.set_digital_output(IO_CABINET, 5, 0) (conveyor belt off) successfully completed - one_line_wooden_wheel_pallet") + write_log("BE: current_layer_height > oneline_wheel_max_current_layer_height successfully completed - one_line_wooden_wheel_pallet") + break + + if is_move_pose == True and is_emo_disabled == True: + is_move_pose = False + if current_layer_index % 2 == 0: + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + + pickup_pose = [radians(-47.102), radians(84.387), radians(78.169), radians(107.444), radians(-90), radians(131.510)] + + robot.joint_move_extend(pickup_pose, 0, False, 8000, 3000, 0.1) # 책 뜨기 공중 준비 자세 + write_log("BE: joint_move_extend : pickup_pose successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,666.816,0,0,0], 1,False, 8000, 3000, 0.1) # 공중에서 z축 내리기(-247.633) + write_log("BE: linear_move_extend : [0,0,666.816,0,0,0] (reday pose) successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + else: + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + + pickup_pose_opposite = [radians(-24.283), radians(120.475), radians(32.213), radians(117.312), radians(-90), radians(-25.671)] + + robot.joint_move_extend(pickup_pose_opposite, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : pickup_pose_opposite successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,681.817,0,0,0], 1, False, 8000, 3000, 0.1) # (-273.633) -253.633 --> -249.633 + write_log("BE: linear_move_extend : [0,0,681.817,0,0,0] (ready pose) successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)): + immediately_take_book = None + + if current_layer_index % 2 == 0: # 홀수 번째 레이어 + write_log("BE: load book on pallet's if condition started - one_line_wooden_wheel_pallet") + current_data_list = list(book_center_positions) + current_data = current_data_list[current_data_index] + + centerX = current_data['x'] + centerY = current_data['y'] + + robot.set_digital_output(IO_CABINET, 1, 0) + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (for safety purposes : parallel gripper cylinder off) successfully completed - one_line_wooden_wheel_pallet") + robot.set_digital_output(IO_CABINET, 0, 0) + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (for safety purposes : vertical gripper cylinder off) successfully completed - one_line_wooden_wheel_pallet") + + time.sleep(save_time) + + robot.linear_move_extend([-298.306, 0, 0,0,0,0], 1, False, 8000, 3000, 0.1) # x축 -해서 책 집을 위치로 가기 (-67.025) + write_log("BE: linear_move_extend : [-298.306, 0, 0,0,0,0] (move toward stacker to grip book) successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 0, 1) # 그리퍼 수직 작동 + write_log("BE: set_digital_output(IO_CABINET, 0, 1) (turn ON vertical gripper cylinder to grip book) successfully completed - one_line_wooden_wheel_pallet") + time.sleep(0.3) + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0, 0, -694.816,0,0,0], 1, False, speed, acc, 0.1) # 책 떠서 올림 + write_log("BE: linear_move_extend : [0, 0, -694.816,0,0,0] (lift with book placed on gripper) successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + time.sleep(0.3) + + if centerY > pallet_length / 2: + # 아래 팔레트 집입 자세 + robot.joint_move_extend(lower_pallet_enter_pose, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : lower_pallet_enter_pose for odd layer grid 2 and 4 successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 1: # 2번 grid + robot.joint_move_extend([radians(-83.398), radians(102.810), radians(61.767), radians(105.424), radians(-90), radians(-85.698)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_wooden_wheel_pallet(odd layer) grid 2 Ready pose/ joint_move_extend [radians(-83.398), radians(102.810), radians(61.767), radians(105.424), radians(-90), radians(-85.698)]") + is_in_pose() + if (EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 9, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 2 : [{centerX + 31}, {centerY + 9}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0,0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + if current_data_index == 3: # 4번 grid + robot.joint_move_extend([radians(-66.699), radians(105.342), radians(58.472), radians(106.187), radians(-90), radians(-68.999)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_wooden_wheel_pallet(odd layer) grid 4 Ready pose/ joint_move_extend [radians(-66.699), radians(105.342), radians(58.472), radians(106.187), radians(-90), radians(-68.999)]") + is_in_pose() + if (EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 9, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 4 : [{centerX + 24}, {centerY + 9}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0,0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + else: + # 위에 팔레트 집입 자세 + robot.joint_move_extend(lower_pallet_enter_pose1, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : lower_pallet_enter_pose1 for odd layer grid 1 and 3 successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 0: # grid 1번 + robot.joint_move_extend([radians(-84.575), radians(122.286), radians(32.836), radians(114.878), radians(-90), radians(-86.875)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_wooden_wheel_pallet(odd layer) grid 1 Ready pose/ joint_move_extend [radians(-84.575), radians(122.286), radians(32.836), radians(114.878), radians(-90), radians(-86.875)]") + is_in_pose() + if (EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 5, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 1 : [{centerX + 31}, {centerY + 5}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0,0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + if current_data_index == 2: # grid 3번 + robot.joint_move_extend([radians(-70.674), radians(125.675), radians(26.930), radians(117.394), radians(-90), radians(-72.974)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_wooden_wheel_pallet(odd layer) grid 3 Ready pose/ joint_move_extend [radians(-70.674), radians(125.675), radians(26.930), radians(117.394), radians(-90), radians(-72.974)]") + is_in_pose() + if (EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 5, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 3 : [{centerX + 24}, {centerY + 5}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0,0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + # @@@@@@@@@@@@@@@@@@@current_layer_height 에 z값 저장 (z값은 is_in_pose 함수에서 가져옴, )@@@@@@@@@@@@@@@@@@@@@ + current_layer_height = z_pos + + robot.set_digital_output(IO_CABINET, 0, 0) # 그리퍼 수직 off + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (gripper vertical cylinder off after put on pallet) successfully completed - one_line_wooden_wheel_pallet") + time.sleep(0.3) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 1) # 그리퍼 수평 on + write_log("BE: set_digital_output(IO_CABINET, 1, 1) (gripper parallel cylinder on after put on pallet) successfully completed - one_line_wooden_wheel_pallet") + time.sleep(1) + if (EMO(1, 1)): + continue + + robot.linear_move_extend([0, 0, -(wooden_wheel_pallet_max_z_pos - (current_layer_height)), 0, 0, 0], 1, False, 8000, 3000, 0.1) + write_log(f"BE:linear_move_extend : [0, 0, {-(wooden_wheel_pallet_max_z_pos - (current_layer_height))}, 0, 0, 0] (move robot little bit up) successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 0) # 그리퍼 수평 off + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (after lift up turn OFF gripper parallel cylinder) successfully completed - one_line_wooden_wheel_pallet") + if (EMO(1, 0)): + continue + + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(1, 0)): + continue + + + current_layer_index += 1 + oneLine_data[grid_id]['currentLayerIndex'] = current_layer_index + oneLine_data[grid_id]['currentLayerHeight'] = current_layer_height + with open(oneLine_json_file_path, 'w', encoding='utf-8') as file: + json.dump(oneLine_data, file, indent=4, ensure_ascii=False) + + is_move_pose = True + + + else: # 짝수 번째 레이어 (그리퍼 돌려서 책 들기) + write_log("BE: load book on pallet's else condition started - one_line_wooden_wheel_pallet") + current_data_list = list(book_center_positions) + current_data = current_data_list[current_data_index] + + centerX = current_data['x'] + centerY = current_data['y'] + + robot.set_digital_output(IO_CABINET, 1, 0) + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (for safety purposes : parallel gripper cylinder off) successfully completed - one_line_wooden_wheel_pallet") + robot.set_digital_output(IO_CABINET, 0, 0) + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (for safety purposes : vertical gripper cylinder off) successfully completed - one_line_wooden_wheel_pallet") + + time.sleep(save_time) + + robot.linear_move_extend([194.344,0,0,0,0,0], 1, False, 8000, 3000, 0.1) # (-386.213) --> -387.213으로 하기 -->-384.208 + write_log("BE: linear_move_extend : [194.344,0,0,0,0,0] (move toward stacker to grip book) successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 0, 1) # 그리퍼 수직 on + write_log("BE: set_digital_output(IO_CABINET, 0, 1) (turn ON vertical gripper cylinder to grip book) successfully completed - one_line_wooden_wheel_pallet") + time.sleep(0.1) + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,-703.816,0,0,0], 1, False, speed, acc, 0.1) # (-927.623) + write_log("BE: linear_move_extend : [0,0,-703.816,0,0,0] (lift with book placed on gripper) successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + time.sleep(0.3) + + if centerY > pallet_length /2: + robot.joint_move_extend(lower_pallet_enter_pose, 0, False, 5, 1, 0.1) # 만약 책이 미끄러진다면 속도 조절 둘다 + write_log("BE: joint_move_extend : lower_pallet_enter_pose for even layer 2 and 4 successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 1: # grid 2번 + robot.joint_move_extend([radians(-83.398), radians(102.810), radians(61.767), radians(105.424), radians(-90), radians(-85.698)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_wooden_wheel_pallet(even layer) grid 2 Ready pose/ joint_move_extend [radians(-83.398), radians(102.810), radians(61.767), radians(105.424), radians(-90), radians(-85.698)]") + is_in_pose() + if (EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 9, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 2 : [{centerX + 31}, {centerY + 9}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0,0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + if current_data_index == 3: # grid 4번 + robot.joint_move_extend([radians(-66.699), radians(105.342), radians(58.472), radians(106.187), radians(-90), radians(-68.999)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_wooden_wheel_pallet(even layer) grid 4 Ready pose/ joint_move_extend [radians(-66.699), radians(105.342), radians(58.472), radians(106.187), radians(-90), radians(-68.999)]") + is_in_pose() + if (EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 9, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 4 : [{centerX + 24}, {centerY + 9}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0,0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + else: + robot.joint_move_extend(lower_pallet_enter_pose1, 0, False, 5, 1, 0.1) + write_log("BE: joint_move_extend : lower_pallet_enter_pose1 for even layer grid 1 and 3 successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 0: # grid 1번 + robot.joint_move_extend([radians(-84.575), radians(122.286), radians(32.836), radians(114.878), radians(-90), radians(-86.875)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_wooden_wheel_pallet(even layer) grid 1 Ready pose/ joint_move_extend [radians(-84.575), radians(122.286), radians(32.836), radians(114.878), radians(-90), radians(-86.875)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 5, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 1 : [{centerX + 31}, {centerY + 5}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + if current_data_index == 2: # grid 3번 + robot.joint_move_extend([radians(-70.674), radians(125.675), radians(26.930), radians(117.394), radians(-90), radians(-72.974)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_wooden_wheel_pallet(even layer) grid 3 Ready pose/ joint_move_extend [radians(-70.674), radians(125.675), radians(26.930), radians(117.394), radians(-90), radians(-72.974)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 5, -wooden_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 3 : [{centerX + 24}, {centerY + 5}, {-wooden_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0,0)): + continue + + get_distance_to_base(wooden_wheel_pallet_max_z_pos) + + # @@@@@@@@@@@@@@@@@@@current_layer_height 에 z값 저장 (z값은 is_in_pose 함수에서 가져옴, )@@@@@@@@@@@@@@@@@@@@@ + current_layer_height = z_pos + + robot.set_digital_output(IO_CABINET, 0, 0) # 그리퍼 수직 off + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (gripper vertical cylinder off after put on pallet) successfully completed - one_line_wooden_wheel_pallet") + time.sleep(0.2) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 1) # 그리퍼 수평 on + write_log("BE: set_digital_output(IO_CABINET, 1, 1) (gripper parallel cylinder on after put on pallet) successfully completed - one_line_wooden_wheel_pallet") + time.sleep(1) + if (EMO(1, 1)): + continue + + robot.linear_move_extend([0, 0, -(wooden_wheel_pallet_max_z_pos - (current_layer_height)), 0, 0, 0], 1, False, 8000, 3000, 0.1) + write_log(f"BE:linear_move_extend : [0, 0, {-(wooden_wheel_pallet_max_z_pos - (current_layer_height))}, 0, 0, 0] (move robot little bit up) successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 0) # 그리퍼 수평 off + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (after lift up turn OFF gripper parallel cylinder) successfully completed - one_line_wooden_wheel_pallet") + if (EMO(1, 0)): + continue + + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - one_line_wooden_wheel_pallet") + is_in_pose() + if (EMO(1, 0)): + continue + + + current_layer_index += 1 + oneLine_data[grid_id]['currentLayerHeight'] = current_layer_height + oneLine_data[grid_id]['currentLayerIndex'] = current_layer_index + with open(oneLine_json_file_path, 'w', encoding='utf-8') as file: + json.dump(oneLine_data, file, indent=4, ensure_ascii=False) + + is_move_pose = True + + +def one_line_iron_wheel_pallet(): + write_log("BE: one_line_iron_wheel_pallet function started") + global action, immediately_take_book + global emergency_stop, protected_stop_stat + global power_on_stat, enabled_stat + global robot_start_clicked, terminate_robot_button_clicked + global pallet_width, pallet_length, pallet_height, book_center_positions + global stacker_thread_running, stacker_thread_operator + global is_one_line_stop_clicked + + global is_emo_disabled, stacker_vertical_cyl_sensor, stacker_book_ready_sensor, stacker_vertical_cyl_down_sensor + + # @@@ 새로 추가한 변수 + global z_pos + + global iron_wheel_pallet_max_z_pos + # @@@ + + is_move_pose = True + + robot.linear_move_extend([0, 0, -350, 0, 0, 0], 1, True, 7000, 2000, 0.1) + write_log("BE: linear_move_extend : [0, 0, -350, 0, 0, 0] successfully completed - one_line_iron_wheel_pallet") + home_pos = [radians(-58.423), radians(95.567), radians(66.994), radians(107.440), radians(-90), radians(31.577)] + lower_pallet_enter_pose = [radians(-61.533), radians(107.484), radians(55.576), radians(106.940), radians(-90), radians(-61.533)] + lower_pallet_enter_pose1 = [radians(-66.797), radians(136.143), radians(6.799), radians(127.058), radians(-90), radians(-66.797)] + + robot.login() + write_log("BE: login successfully completed - one_line_iron_wheel_pallet") + robot.power_on() + write_log("BE: power_on successfully completed - one_line_iron_wheel_pallet") + robot.enable_robot() + write_log("BE: enable_robot successfully completed - one_line_iron_wheel_pallet") + robot.joint_move_extend(home_pos, 0, True, 10, 1, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - one_line_iron_wheel_pallet") + + if os.path.exists(oneLine_json_file_path) and os.path.getsize(oneLine_json_file_path) > 0: + with open(oneLine_json_file_path, 'r', encoding='utf-8') as file: + oneLine_data = json.load(file) + + grid_data = oneLine_data.get(grid_id, {"currentDataIndex": 0, "currentLayerIndex": 0, "currentLayerHeight": 0}) + current_data_index = grid_data.get('currentDataIndex', 0) + current_layer_index = grid_data.get('currentLayerIndex', 0) + current_layer_height = grid_data.get('currentLayerHeight', 0) + else: + oneLine_data = { + "grid1": {"currentDataIndex": 0, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid2": {"currentDataIndex": 1, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid3": {"currentDataIndex": 2, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid4": {"currentDataIndex": 3, "currentLayerIndex": 0, "currentLayerHeight": 0} + } + with open(oneLine_json_file_path, 'w', encoding='utf-8') as file: + json.dump(oneLine_data, file, indent=4, ensure_ascii=False) + + current_data_index = 0 + current_layer_index = 0 + current_layer_height = 0 + + while True: + + if (EMO(0, 0)): + is_move_pose = True + continue + + if action == 'robot_finish_action': + action = None + current_layer_index = 0 + current_layer_height = 0 + terminate_robot_button_clicked = True + + oneLine_data = { + "grid1": {"currentDataIndex": 0, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid2": {"currentDataIndex": 1, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid3": {"currentDataIndex": 2, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid4": {"currentDataIndex": 3, "currentLayerIndex": 0, "currentLayerHeight": 0} + } + with open(oneLine_json_file_path, 'w', encoding='utf-8') as file: + json.dump(oneLine_data, file, indent=4, ensure_ascii=False) + + stacker_thread_running = False + if stacker_thread_operator: + stacker_thread_operator.join() + + robot.set_digital_output(IO_CABINET, 5, 0) + write_log("BE: robot.set_digital_output(IO_CABINET, 5, 0) (conveyor belt off) successfully completed - one_line_iron_wheel_pallet") + + write_log("BE: action == 'robot_finish_action' successfully completed - one_line_iron_wheel_pallet") + break + + if all(oneLine_data[grid]['currentLayerHeight'] > oneline_wheel_max_current_layer_height for grid in oneLine_data): + action = 'robot_finish_action' + write_log("BE: all(oneLine_data[grid]['currentLayerHeight'] > oneline_wheel_max_current_layer_height for grid in oneLine_data) successfully completed - one_line_iron_wheel_pallet") + continue + + if is_one_line_stop_clicked == 'one_line_stop': + is_one_line_stop_clicked = None + terminate_robot_button_clicked = True + + stacker_thread_running = False + if stacker_thread_operator: + stacker_thread_operator.join() + + robot.set_digital_output(IO_CABINET, 5, 0) + write_log("BE: robot.set_digital_output(IO_CABINET, 5, 0) (conveyor belt off) successfully completed - one_line_iron_wheel_pallet") + write_log("BE: is_one_line_stop_clicked == 'one_line_stop' successfully completed - one_line_iron_wheel_pallet") + break + + if current_layer_height + 130 > oneline_wheel_max_current_layer_height: + action = None + terminate_robot_button_clicked = True + + stacker_thread_running = False + if stacker_thread_operator: + stacker_thread_operator.join() + + robot.set_digital_output(IO_CABINET, 5, 0) + write_log("BE: robot.set_digital_output(IO_CABINET, 5, 0) (conveyor belt off) successfully completed - one_line_iron_wheel_pallet") + write_log("BE: current_layer_height > oneline_wheel_max_current_layer_height successfully completed - one_line_iron_wheel_pallet") + break + + if is_move_pose == True and is_emo_disabled == True: + is_move_pose = False + if current_layer_index % 2 == 0: + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + + pickup_pose = [radians(-47.102), radians(84.387), radians(78.169), radians(107.444), radians(-90), radians(131.510)] + + robot.joint_move_extend(pickup_pose, 0, False, 8000, 3000, 0.1) # 책 뜨기 공중 준비 자세 + write_log("BE: joint_move_extend : pickup_pose successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,666.816,0,0,0], 1,False, 8000, 3000, 0.1) # 공중에서 z축 내리기(-247.633) + write_log("BE: linear_move_extend : [0,0,666.816,0,0,0] (ready pose) successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + else: + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + + pickup_pose_opposite = [radians(-24.283), radians(120.475), radians(32.213), radians(117.312), radians(-90), radians(-25.671)] + + robot.joint_move_extend(pickup_pose_opposite, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : pickup_pose_opposite successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,681.817,0,0,0], 1, False, 8000, 3000, 0.1) # (-273.633) -253.633 --> -249.633 + write_log("BE: linear_move_extend : [0,0,681.817,0,0,0] (ready pose) successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)): + immediately_take_book = None + + if current_layer_index % 2 == 0: # 홀수 번째 레이어 + write_log("BE: load book on pallet's if condition started - one_line_iron_wheel_pallet") + current_data_list = list(book_center_positions) + current_data = current_data_list[current_data_index] + + centerX = current_data['x'] + centerY = current_data['y'] + + robot.set_digital_output(IO_CABINET, 1, 0) + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (for safety purposes : parallel gripper cylinder off) successfully completed - one_line_iron_wheel_pallet") + robot.set_digital_output(IO_CABINET, 0, 0) + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (for safety purposes : vertical gripper cylinder off) successfully completed - one_line_iron_wheel_pallet") + + time.sleep(save_time) + + robot.linear_move_extend([-298.306, 0, 0,0,0,0], 1, False, 8000, 3000, 0.1) # x축 -해서 책 집을 위치로 가기 (-67.025) + write_log("BE: linear_move_extend : [-298.306, 0, 0,0,0,0] (move toward stacker to grip book) successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 0, 1) # 그리퍼 수직 작동 + write_log("BE: set_digital_output(IO_CABINET, 0, 1) (turn ON vertical gripper cylinder to grip book) successfully completed - one_line_iron_wheel_pallet") + time.sleep(0.3) + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0, 0, -694.816,0,0,0], 1, False, speed, acc, 0.1) # 책 떠서 올림 + write_log("BE: linear_move_extend : [0, 0, -694.816,0,0,0] (lift with book placed on gripper) successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + time.sleep(0.3) + + if centerY > pallet_length / 2: + # 아래 팔레트 집입 자세 + robot.joint_move_extend(lower_pallet_enter_pose, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : lower_pallet_enter_pose for odd layer grid 2 and 4 successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 1: # grid 2번 + robot.joint_move_extend([radians(-83.418), radians(103.042), radians(61.470), radians(105.488), radians(-90), radians(-85.718)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_iron_wheel_pallet(odd layer) grid 2 Ready pose/ joint_move_extend [radians(-83.418), radians(103.042), radians(61.470), radians(105.488), radians(-90), radians(-85.718)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 6, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 2 : [{centerX + 31}, {centerY + 6}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + if current_data_index == 3: # grid 4번 + robot.joint_move_extend([radians(-66.765), radians(105.573), radians(58.163), radians(106.263), radians(-90), radians(-69.065)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_iron_wheel_pallet(odd layer) grid 3 Ready pose/ joint_move_extend [radians(-66.765), radians(105.573), radians(58.163), radians(106.263), radians(-90), radians(-69.065)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 6, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 4 : [{centerX + 24}, {centerY + 6}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + else: + # 위에 팔레트 집입 자세 + robot.joint_move_extend(lower_pallet_enter_pose1, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : lower_pallet_enter_pose1 odd layer grid 1 and 3 successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 0: # grid 1번 + robot.joint_move_extend([radians(-84.588), radians(122.643), radians(32.227), radians(115.130), radians(-90), radians(-86.888)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_iron_wheel_pallet(odd layer) grid 1 Ready pose/ joint_move_extend [radians(-84.588), radians(122.643), radians(32.227), radians(115.130), radians(-90), radians(-86.888)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 2, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 1 : [{centerX + 31}, {centerY + 2}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + if current_data_index == 2: # grid 3번 + robot.joint_move_extend([radians(-70.720), radians(126.085), radians(26.197), radians(117.718), radians(-90), radians(-73.020)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_iron_wheel_pallet(odd layer) grid 3 Ready pose/ joint_move_extend [radians(-70.720), radians(126.085), radians(26.197), radians(117.718), radians(-90), radians(-73.020)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 2, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 3 : [{centerX + 24}, {centerY + 2}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + # @@@@@@@@@@@@@@@@@@@current_layer_height 에 z값 저장 (z값은 is_in_pose 함수에서 가져옴, )@@@@@@@@@@@@@@@@@@@@@ + current_layer_height = z_pos + + robot.set_digital_output(IO_CABINET, 0, 0) # 그리퍼 수직 off + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (gripper vertical cylinder off after put on pallet) successfully completed - one_line_iron_wheel_pallet") + time.sleep(0.3) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 1) # 그리퍼 수평 on + write_log("BE: set_digital_output(IO_CABINET, 1, 1) (gripper parallel cylinder on after put on pallet) successfully completed - one_line_iron_wheel_pallet") + time.sleep(1) + if (EMO(1, 1)): + continue + + robot.linear_move_extend([0, 0, -(iron_wheel_pallet_max_z_pos - (current_layer_height)), 0, 0, 0], 1, False, 8000, 3000, 0.1) + write_log(f"BE:linear_move_extend : [0, 0, {-(iron_wheel_pallet_max_z_pos - (current_layer_height))}, 0, 0, 0] (move robot little bit up) successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 0) # 그리퍼 수평 off + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (after lift up turn OFF gripper parallel cylinder) successfully completed - one_line_iron_wheel_pallet") + if (EMO(1, 0)): + continue + + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(1, 0)): + continue + + + current_layer_index += 1 + oneLine_data[grid_id]['currentLayerIndex'] = current_layer_index + oneLine_data[grid_id]['currentLayerHeight'] = current_layer_height + with open(oneLine_json_file_path, 'w', encoding='utf-8') as file: + json.dump(oneLine_data, file, indent=4, ensure_ascii=False) + + is_move_pose = True + + + else: # 짝수 번째 레이어 (그리퍼 돌려서 책 들기) + write_log("BE: load book on pallet's else condition started - one_line_iron_wheel_pallet") + current_data_list = list(book_center_positions) + current_data = current_data_list[current_data_index] + + centerX = current_data['x'] + centerY = current_data['y'] + + robot.set_digital_output(IO_CABINET, 1, 0) + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (for safety purposes : parallel gripper cylinder off) successfully completed - one_line_iron_wheel_pallet") + robot.set_digital_output(IO_CABINET, 0, 0) + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (for safety purposes : vertical gripper cylinder off) successfully completed - one_line_iron_wheel_pallet") + + time.sleep(save_time) + + robot.linear_move_extend([194.344,0,0,0,0,0], 1, False, 8000, 3000, 0.1) # (-386.213) --> -387.213으로 하기 -->-384.208 + write_log("BE: linear_move_extend : [194.344,0,0,0,0,0] (move toward stacker to grip book) successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 0, 1) # 그리퍼 수직 on + write_log("BE: set_digital_output(IO_CABINET, 0, 1) (turn ON vertical gripper cylinder to grip book) successfully completed - one_line_iron_wheel_pallet") + time.sleep(0.1) + if (EMO(0, 0)): + continue + + robot.linear_move_extend([0,0,-703.816,0,0,0], 1, False, speed, acc, 0.1) # (-927.623) + write_log("BE: linear_move_extend : [0,0,-703.816,0,0,0] (lift with book placed on gripper) successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + time.sleep(0.3) + + if centerY > pallet_length /2: + robot.joint_move_extend(lower_pallet_enter_pose, 0, False, 5, 1, 0.1) # 만약 책이 미끄러진다면 속도 조절 둘다 + write_log("BE: joint_move_extend : lower_pallet_enter_pose for even layer grid 2 and 4 successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 1: # grid 2번 + robot.joint_move_extend([radians(-83.418), radians(103.042), radians(61.470), radians(105.488), radians(-90), radians(-85.718)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_iron_wheel_pallet(even layer) grid 2 Ready pose/ joint_move_extend [radians(-83.418), radians(103.042), radians(61.470), radians(105.488), radians(-90), radians(-85.718)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 6, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 2 : [{centerX + 31}, {centerY + 6}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + if current_data_index == 3: # grid 4번 + robot.joint_move_extend([radians(-66.765), radians(105.573), radians(58.163), radians(106.263), radians(-90), radians(-69.065)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_iron_wheel_pallet(even layer) grid 4 Ready pose/ joint_move_extend [radians(-66.765), radians(105.573), radians(58.163), radians(106.263), radians(-90), radians(-69.065)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 6, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 4 : [{centerX + 24}, {centerY + 6}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + else: + robot.joint_move_extend(lower_pallet_enter_pose1, 0, False, 5, 1, 0.1) + write_log("BE: joint_move_extend : lower_pallet_enter_pose1 for even layer 1 and 3 successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(0, 1)): + continue + + if current_data_index == 0: # grid 1번 + robot.joint_move_extend([radians(-84.588), radians(122.643), radians(32.227), radians(115.130), radians(-90), radians(-86.888)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_iron_wheel_pallet(even layer) grid 1 Ready pose/ joint_move_extend [radians(-84.588), radians(122.643), radians(32.227), radians(115.130), radians(-90), radians(-86.888)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 31, centerY + 2, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 1 : [{centerX + 31}, {centerY + 2}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + if current_data_index == 2: # grid 3번 + robot.joint_move_extend([radians(-70.720), radians(126.085), radians(26.197), radians(117.718), radians(-90), radians(-73.020)], 0, False, grid_speed, grid_acc, 0.1) + write_log("BE: one_line_iron_wheel_pallet(even layer) grid 3 Ready pose/ joint_move_extend [radians(-70.720), radians(126.085), radians(26.197), radians(117.718), radians(-90), radians(-73.020)]") + is_in_pose() + if(EMO(0,0)): + continue + + robot.linear_move_extend([centerX + 24, centerY + 2, -iron_wheel_pallet_max_z_pos, 0, 0, radians(-2.3)], 0, False, speed, acc, 0.1) + write_log(f"BE: linear_move_extend grid 3 : [{centerX + 24}, {centerY + 2}, {-iron_wheel_pallet_max_z_pos}, 0, 0, radians(-2.3)] successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if(EMO(0,0)): + continue + + get_distance_to_base(iron_wheel_pallet_max_z_pos) + + # @@@@@@@@@@@@@@@@@@@current_layer_height 에 z값 저장 (z값은 is_in_pose 함수에서 가져옴, )@@@@@@@@@@@@@@@@@@@@@ + current_layer_height = z_pos + + robot.set_digital_output(IO_CABINET, 0, 0) # 그리퍼 수직 off + write_log("BE: set_digital_output(IO_CABINET, 0, 0) (gripper vertical cylinder off after put on pallet) successfully completed - one_line_iron_wheel_pallet") + time.sleep(0.2) + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 1) # 그리퍼 수평 on + write_log("BE: set_digital_output(IO_CABINET, 1, 1) (gripper parallel cylinder on after put on pallet) successfully completed - one_line_iron_wheel_pallet") + time.sleep(1) + if (EMO(1, 1)): + continue + + robot.linear_move_extend([0, 0, -(iron_wheel_pallet_max_z_pos - (current_layer_height)), 0, 0, 0], 1, False, 8000, 3000, 0.1) + write_log(f"BE:linear_move_extend : [0, 0, {-(iron_wheel_pallet_max_z_pos - (current_layer_height))}, 0, 0, 0] (move robot little bit up) successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(0, 0)): + continue + + robot.set_digital_output(IO_CABINET, 1, 0) # 그리퍼 수평 off + write_log("BE: set_digital_output(IO_CABINET, 1, 0) (after lift up turn OFF gripper parallel cylinder) successfully completed - one_line_iron_wheel_pallet") + if (EMO(1, 0)): + continue + + robot.joint_move_extend(home_pos, 0, False, 8000, 3000, 0.1) + write_log("BE: joint_move_extend : home_pos successfully completed - one_line_iron_wheel_pallet") + is_in_pose() + if (EMO(1, 0)): + continue + + + current_layer_index += 1 + oneLine_data[grid_id]['currentLayerHeight'] = current_layer_height + oneLine_data[grid_id]['currentLayerIndex'] = current_layer_index + with open(oneLine_json_file_path, 'w', encoding='utf-8') as file: + json.dump(oneLine_data, file, indent=4, ensure_ascii=False) + print(f"현재{current_layer_index}층, 현재 높이 : {current_layer_height}") + + is_move_pose = True + +power_on_stat = 0 +enabled_stat = 0 +emergency_stop = 0 +protected_stop_stat = 0 +current_DI_9_status = 0 +# jks_status = 0 + +def robot_get_status_realtime(): + def get_status_thread(): + global power_on_stat + global enabled_stat + global emergency_stop + global protected_stop_stat + global current_DI_9_status + global action + global terminate_robot_button_clicked, robot_start_clicked + global stacker_thread_running, stacker_thread_operator + global flag + global btn_id + + global is_emo_disabled, stacker_vertical_cyl_sensor, stacker_book_ready_sensor, stacker_vertical_cyl_down_sensor + + + + if os.path.exists(cache_json_file_path) and os.path.getsize(cache_json_file_path) > 0: + with open(cache_json_file_path, 'r', encoding='utf-8') as file: + cache_data = json.load(file) + + current_layer_height_cache = cache_data.get('currentLayerHeight') + current_layer_height = current_layer_height_cache + else: + cache_data = { + "currentDataIndex": 0, + "currentLayerIndex": 0, + "currentLayerHeight" : 0 + } + with open(cache_json_file_path, 'w', encoding='utf-8') as file: + json.dump(cache_data, file, indent=4, ensure_ascii=False) + + current_layer_height = 0 + + + if os.path.exists(oneLine_json_file_path) and os.path.getsize(oneLine_json_file_path) > 0: + with open(oneLine_json_file_path, 'r', encoding='utf-8') as file: + oneLine_data = json.load(file) + + grid_data = oneLine_data.get(grid_id, {"currentDataIndex": 0, "currentLayerIndex": 0, "currentLayerHeight": 0}) + current_layer_height_oneLine = grid_data.get('currentLayerHeight', 0) + else: + oneLine_data = { + "grid1": {"currentDataIndex": 0, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid2": {"currentDataIndex": 1, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid3": {"currentDataIndex": 2, "currentLayerIndex": 0, "currentLayerHeight": 0}, + "grid4": {"currentDataIndex": 3, "currentLayerIndex": 0, "currentLayerHeight": 0} + } + with open(oneLine_json_file_path, 'w', encoding='utf-8') as file: + json.dump(oneLine_data, file, indent=4, ensure_ascii=False) + + current_layer_height_oneLine = 0 + + + while True: + try: + status = robot.get_robot_status() + power_on_stat = status[1][2] + enabled_stat = status[1][3] + emergency_stop = status[1][23] + protected_stop_stat = status[1][5] + + current_DI_9_status = status[1][11][0] # 스태커 수직 반사판 센서 + stacker_book_ready_sensor = status[1][11][1] # 스태커 수평 반사판 샌서 + stacker_vertical_cyl_sensor = status[1][11][2] # 스태커 수직 실린더 위에 센서 + stacker_vertical_cyl_down_sensor = status[1][11][3] # 스태커 수직 실린더 아래 센서 + + + + # 경광등 조작하기 위해서 쌓인 책 높이 받아오기 + with open(cache_json_file_path, 'r', encoding='utf-8') as file: + cache_data = json.load(file) + + current_layer_height_cache = cache_data.get('currentLayerHeight') + current_layer_height = current_layer_height_cache + + with open(oneLine_json_file_path, 'r', encoding='utf-8') as file: + oneLine_data = json.load(file) + + grid_data = oneLine_data.get(grid_id, {"currentDataIndex": 0, "currentLayerIndex": 0, "currentLayerHeight": 0}) + current_layer_height_oneLine = grid_data.get('currentLayerHeight', 0) + + if stacker_vertical_cyl_down_sensor == 0 or terminate_robot_button_clicked == True: # stacker_vertical_cyl_sensor == 0 + robot.set_digital_output(IO_CABINET, 5, 0) # 동력 장치 멈춤 (수직 실린더 올라가기 시작하자마자) + elif stacker_vertical_cyl_sensor == 0 and (enabled_stat == 1 and (emergency_stop == 0 or protected_stop_stat == 0)) and terminate_robot_button_clicked == False: + robot.set_digital_output(IO_CABINET, 5, 1) # 동력 장치 재시작 (수직 실린더 완전히 내려갔을때) + + # elif stacker_vertical_cyl_down_sensor == 1 and (enabled_stat == 1 and (emergency_stop == 0 or protected_stop_stat == 0)): + # robot.set_digital_output(IO_CABINET, 5, 1) # 동력 장치 재시작 (수직 실린더 완전히 내려갔을때) + + + if((terminate_robot_button_clicked == True) or + (((wheel_max_current_layer_height < current_layer_height + 130 < wheel_max_current_layer_height + 130) or + (wheel_max_current_layer_height < current_layer_height_oneLine + 130 < wheel_max_current_layer_height + 130)) and + (pallet_height == wooden_wheel_pallet_height or pallet_height == iron_wheel_pallet_height)) or + (flat_max_current_layer_height < current_layer_height + 130 < flat_max_current_layer_height + 130)): + robot.set_digital_output(IO_CABINET, 2, 0) # 경광등 주황색 off + robot.set_digital_output(IO_CABINET, 3, 0) # 경광등 초록색 off + robot.set_digital_output(IO_CABINET, 4, 1) # 경광등 빨간색 on + elif((enabled_stat == 1) and (emergency_stop == 0 or protected_stop_stat == 0) and + (((wheel_max_current_layer_height - 130 < current_layer_height + 130 < wheel_max_current_layer_height) or + (wheel_max_current_layer_height - 130 < current_layer_height_oneLine + 130 < wheel_max_current_layer_height)) and + (pallet_height == wooden_wheel_pallet_height or pallet_height == iron_wheel_pallet_height)) or + (flat_max_current_layer_height - 130 < current_layer_height + 130 < flat_max_current_layer_height)): + robot.set_digital_output(IO_CABINET, 2, 1) # 경광등 주황색 on + robot.set_digital_output(IO_CABINET, 3, 0) # 경광등 초록색 off + robot.set_digital_output(IO_CABINET, 4, 0) # 경광등 빨간색 off + elif(enabled_stat == 1 and (robot_start_clicked == True) and (emergency_stop == 0 or protected_stop_stat == 0)): + robot.set_digital_output(IO_CABINET, 2, 0) # 경광등 주황색 off + robot.set_digital_output(IO_CABINET, 3, 1) # 경광등 초록색 on + robot.set_digital_output(IO_CABINET, 4, 0) # 경광등 빨간색 off + elif(emergency_stop == 1 or protected_stop_stat == 1): + robot.set_digital_output(IO_CABINET, 2, 0) # 경광등 주황색 off + robot.set_digital_output(IO_CABINET, 3, 0) # 경광등 초록색 off + robot.set_digital_output(IO_CABINET, 4, 1) # 경광등 빨간색 on + + if(emergency_stop == 1 or protected_stop_stat == 1): + write_log("BE: emergency or protected enabled") + is_emo_disabled = False + flag = 1 + + stacker_thread_running = False + if stacker_thread_operator: + stacker_thread_operator.join() + + robot.set_digital_output(IO_CABINET, 5, 0) + write_log("BE: robot.set_digital_output(IO_CABINET, 5, 0) conveyor belt off") + + if(flag == 1 and enabled_stat == 1 and (emergency_stop == 0 and protected_stop_stat == 0)): + write_log("BE: after emergency or protected disabled") + is_emo_disabled = True + flag = 0 + robot.linear_move_extend([0, 0, -350, 0, 0, 0], 1, True, 7000, 2000, 0.1) + write_log("BE: linear_move_extend : [0, 0, -350, 0, 0, 0] successfully completed - get_status_thread") + time.sleep(0.3) + home_pos = [radians(-58.423), radians(95.567), radians(66.994), radians(107.440), radians(-90), radians(31.577)] + robot.joint_move_extend(home_pos, 0, True, 8000, 3000, 0.1) + robot.set_digital_output(IO_CABINET, 1, 0) + write_log("BE: joint_move_extend : home_pos successfully completed - get_status_thread") + stacker_thread_start_function() + + except Exception as e: + # pass + print(e) + finally: + time.sleep(0.1) + status_thread = threading.Thread(target=get_status_thread, daemon=True) + status_thread.start() + + +def stacker_thread_start_function(): + global stacker_thread_running, stacker_thread_operator + def stacker_thread(): + Write_All_Do([0,0,0,0,0,0,0,0]) + global emergency_stop + global protected_stop_stat + global current_DI_9_status + global stacker_thread_running + + global stacker_book_ready_sensor # 스태커에 책이 어느정도 스택되면 가려지는 센서 (이 센서가 활성화 되면 스태커 동작을 멈추어야 함) + global stacker_vertical_cyl_down_sensor, instrument + + robot.set_digital_output(IO_CABINET, 5, 1) # 동력장치 시작 + + while stacker_thread_running: + try: + instrument.write_bit(1, True) # 수평 + + if stacker_book_ready_sensor == 1: + time.sleep(2) # 이 센서가 활성화 되면 로봇이 가져가야하기 때문에 time을 주어야 할 것 같음. + elif current_DI_9_status == 1 and stacker_book_ready_sensor == 0 and (emergency_stop == 0 or protected_stop_stat == 0): + print(f"스태커 스레드 current_DI_9_status: {current_DI_9_status}") + time.sleep(0.5) + instrument.write_bit(0, True) + time.sleep(0.05) + # robot.set_digital_output(IO_CABINET, 5, 0) # 동력 off + instrument.write_bit(1, False) + time.sleep(1.2) + instrument.write_bit(1, True) + time.sleep(0.2) + instrument.write_bit(0, False) + # robot.set_digital_output(IO_CABINET, 5, 1) # 동력 ON + + if emergency_stop == 1 or protected_stop_stat == 1: + instrument.write_bit(1, False) + + except Exception as e: + pass + finally: + time.sleep(0.1) + stacker_thread_running = True + stacker_thread_operator = threading.Thread(target=stacker_thread, daemon=True) + stacker_thread_operator.start() + +def is_in_pose(): + time.sleep(0.1) + in_pose = 0 + while not in_pose: + err, in_pose = robot.is_in_pos() + +z_pos = 0 +def get_distance_to_base(max_z_pos): + global btn_id + global z_pos + + if btn_id == "normalButton": + if os.path.exists(cache_json_file_path) and os.path.getsize(cache_json_file_path) > 0: + with open(cache_json_file_path, 'r', encoding='utf-8') as file: + cache_data = json.load(file) + current_layer_index_cache = cache_data.get('currentLayerIndex') + current_layer_height_cache = cache_data.get('currentLayerHeight') + + current_layer_index = current_layer_index_cache + current_layer_height = current_layer_height_cache + + if current_layer_index >= 2: + robot.linear_move_extend([0, 0, max_z_pos - (current_layer_height + 130), 0, 0, 0], 1, False, speed, acc, 0.1) + write_log(f"BE: normalButton / linear_move_extend : [0, 0, {max_z_pos - (current_layer_height + 130)}, 0, 0, 0] successfully completed - get_distance_to_base") + is_in_pose() + else: + if(selectedPalletId == "woodenFlatPallet"): + robot.set_payload(mass= 15, centroid =[0,0,0]) + write_log("Set payload 15") + + print("woodenFlatPallet : currnet_layer_index 가 2보다 작아서 여기 실행") + robot.linear_move_extend([0, 0, max_z_pos - (current_layer_index * 130) - 50, 0, 0, 0], 1, False, 2500, 1000, 0.1) + write_log(f"BE: normalButton / linear_move_extend : [0, 0, {max_z_pos - (current_layer_index * 130)}, 0, 0, 0] successfully completed - get_distance_to_base") + is_in_pose() + else: + print("currnet_layer_index 가 2보다 작아서 여기 실행") + robot.linear_move_extend([0, 0, max_z_pos - (current_layer_index * 130), 0, 0, 0], 1, False, speed, acc, 0.1) + write_log(f"BE: normalButton / linear_move_extend : [0, 0, {max_z_pos - (current_layer_index * 130)}, 0, 0, 0] successfully completed - get_distance_to_base") + is_in_pose() + + elif btn_id == "oneLineButton": + if os.path.exists(oneLine_json_file_path) and os.path.getsize(oneLine_json_file_path) > 0: + with open(oneLine_json_file_path, 'r', encoding='utf-8') as file: + oneLine_data = json.load(file) + + grid_data = oneLine_data.get(grid_id, {"currentDataIndex": 0, "currentLayerIndex": 0, "currentLayerHeight": 0}) + current_layer_index_oneline = grid_data.get('currentLayerIndex', 0) + current_layer_height_oneline = grid_data.get('currentLayerHeight', 0) + if current_layer_index_oneline >= 2: + robot.linear_move_extend([0, 0, max_z_pos - (current_layer_height_oneline + 130), 0, 0, 0], 1, False, speed, acc, 0.1) + write_log(f"BE: oneLineButton / linear_move_extend : [0, 0, {max_z_pos - (current_layer_height_oneline + 130)}, 0, 0, 0] successfully completed - get_distance_to_base") + is_in_pose() + else: + robot.linear_move_extend([0, 0, max_z_pos - (current_layer_index_oneline * 130), 0, 0, 0], 1, False, speed, acc, 0.1) + write_log(f"BE: oneLineButton / linear_move_extend : [0, 0, {max_z_pos - (current_layer_index_oneline * 130)}, 0, 0, 0] successfully completed - get_distance_to_base") + is_in_pose() + + + robot.program_load("pallet_test") + robot.get_loaded_program() + print(robot.get_loaded_program()) + robot.program_run() + while True: + default_program_status = robot.get_program_state() + jks_status = default_program_status[1] + print(f"jks_statusL {jks_status}") + if jks_status == 0: + print("jsk 실행 여부") + print(jks_status) + joint_pos = robot.get_joint_position() + cartesian_pos = robot.kine_forward(joint_pos[1]) + z_pos = -(cartesian_pos[1][2]) + write_log(f"BE: z_pos : {z_pos} successfully completed - get_distance_to_base") + break + + +def EMO(dio_number, status): + if (emergency_stop == 1 or protected_stop_stat == 1) and (power_on_stat == 0 and enabled_stat == 0): # 긴급 정지 버튼 눌림 + robot.set_digital_output(IO_CABINET, dio_number, status) + robot.set_digital_output(IO_CABINET, 3, 0) # 경광등 초록색 off + return True + + return False + +robot_get_status_realtime() \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000..0532a1a --- /dev/null +++ b/app.py @@ -0,0 +1,113 @@ +from flask import Flask, render_template, request, jsonify +import sys +import os +from api_routes import api_routes +import webview +from waitress import serve + +if getattr(sys, 'frozen', False): + template_folder = os.path.join(sys._MEIPASS, 'templates') + app = Flask(__name__, template_folder=template_folder, static_url_path='/static') +else: + app = Flask(__name__, static_url_path='/static') + + +#app = Flask(__name__, static_url_path='/static') +app.register_blueprint(api_routes) # 분리된 API 라우트 등록 + +@app.route('/') +def index(): + return render_template('layer.html') + +@app.route('/progress') +def progess(): + return render_template('progress.html') + +@app.route('/oneLineProgress') +def oneLineProgess(): + return render_template('oneLineProgress.html') + +# 종료 함수 +def shutdown_waitress_server(): + print("Shutting down the server...") + os._exit(0) + +def destroy(window): + print('Destroying window..') + window.destroy() + print('Destroyed!') + +@app.route('/shutdown', methods=['POST']) +def shutdown(): + destroy(test) + shutdown_waitress_server() + return 'Server shutting down' + +port=5000 + +# if __name__ == "__main__": +# app.run(port=port, debug=True) + +test = webview.create_window('Palletizing', app) +if __name__ == "__main__": + webview.start() + serve(app, host="0.0.0.0", port=port) + + +# from flask import Flask, render_template, request +# import sys +# import os +# from api_routes import api_routes +# import webview +# from waitress import serve +# import threading + +# # Flask 애플리케이션 설정 +# if getattr(sys, 'frozen', False): +# template_folder = os.path.join(sys._MEIPASS, 'templates') +# app = Flask(__name__, template_folder=template_folder, static_url_path='/static') +# else: +# app = Flask(__name__, static_url_path='/static') + +# app.register_blueprint(api_routes) + +# @app.route('/') +# def index(): +# return render_template('layer.html') + +# @app.route('/progress') +# def progress(): +# return render_template('progress.html') + +# @app.route('/oneLineProgress') +# def oneLineProgress(): +# return render_template('oneLineProgress.html') + +# # 종료 함수 +# def shutdown_server(): +# print("Shutting down the server...") +# os._exit(0) + +# # 종료 라우트 설정 +# @app.route('/shutdown', methods=['POST']) +# def shutdown(): +# print("Shutdown request received.") +# destroy(test) # Webview 윈도우 종료 +# shutdown_server() # Waitress 서버와 프로그램 종료 +# return 'Server shutting down...' + +# # Webview 윈도우 종료 함수 +# def destroy(window): +# print('Destroying window..') +# window.destroy() +# print('Destroyed!') + +# # 서버 실행 +# port = 5000 +# test = webview.create_window('Palletizing', app) + +# if __name__ == "__main__": +# # Webview와 Waitress 서버를 별도 스레드로 실행 +# server_thread = threading.Thread(target=lambda: serve(app, host="0.0.0.0", port=port)) +# server_thread.start() +# webview.start() diff --git a/socket_test.py b/socket_test.py new file mode 100644 index 0000000..4d7ad8c --- /dev/null +++ b/socket_test.py @@ -0,0 +1,133 @@ +# import socket +# import time + +# def handle_client(client_socket, client_address): +# print(f"Connected by {client_address}") + +# with client_socket: +# while True: +# try: +# recv_data = client_socket.recv(1024).decode() + +# if not recv_data: +# print(f"Connection closed by {client_address}") +# break + +# print(f"Received from {client_address}: {recv_data}") + +# if recv_data == 'get ': +# send_data = '<2>' +# client_socket.send(send_data.encode()) + +# if recv_data == 'get ': +# send_data = '<"b">' +# client_socket.send(send_data.encode()) + +# if recv_data == 'get ': +# send_data = '<[1,1,1,1,1,1]>' +# client_socket.send(send_data.encode()) + +# if recv_data == 'get #real#6#': +# send_data = '[2,2,2,2,2,2]' +# client_socket.send(send_data.encode()) + +# if recv_data == 'palletType': +# send_data = '<1>' +# client_socket.send(send_data.encode()) + +# except ConnectionResetError as e: +# print(f"Connection closed by {client_address}") +# break + +# def start_server(host='0.0.0.0', port=12345): +# server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +# server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +# server_socket.bind((host, port)) +# server_socket.listen() +# server_socket.settimeout(1) +# print(f"Server listening on {host}:{port}") + +# try: +# while True: +# try: +# client_socket, client_address = server_socket.accept() +# handle_client(client_socket, client_address) + +# except socket.timeout: +# continue +# except KeyboardInterrupt: +# print("Server shutting down...") +# finally: +# server_socket.close() + +# if __name__ == "__main__": +# start_server() +import socket +import time + +def handle_client(client_socket, client_address): + print(f"Connected by {client_address}") + + with client_socket: + while True: + try: + recv_data = client_socket.recv(1024).decode() + + if not recv_data: + print(f"Connection closed by {client_address}") + return False # 클라이언트 종료 신호 반환 + + print(f"Received from {client_address}: {recv_data}") + + if recv_data == 'get ': + send_data = '<2>' + client_socket.send(send_data.encode()) + + if recv_data == 'get ': + send_data = '<"b">' + client_socket.send(send_data.encode()) + + if recv_data == 'get ': + send_data = '<[1,1,1,1,1,1]>' + client_socket.send(send_data.encode()) + + if recv_data == 'get #real#6#': + send_data = '[2,2,2,2,2,2]' + client_socket.send(send_data.encode()) + + if recv_data == 'palletType': + send_data = '<1>' + client_socket.send(send_data.encode()) + + except ConnectionResetError: + print(f"Connection closed by {client_address}") + return False # 클라이언트 종료 신호 반환 + return True # 클라이언트 정상 처리 완료 신호 반환 + + +def start_server(host='0.0.0.0', port=12345): + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + server_socket.bind((host, port)) + server_socket.listen() + server_socket.settimeout(1) + print(f"Server listening on {host}:{port}") + + try: + while True: + try: + client_socket, client_address = server_socket.accept() + connection_active = handle_client(client_socket, client_address) + if not connection_active: + print("Client disconnected. Shutting down server...") + break # 루프 종료 + except socket.timeout: + continue + except KeyboardInterrupt: + print("Server shutting down...") + finally: + server_socket.close() + print("Server socket closed.") + +if __name__ == "__main__": + start_server() diff --git a/static/css/layer.css b/static/css/layer.css new file mode 100644 index 0000000..316f4dc --- /dev/null +++ b/static/css/layer.css @@ -0,0 +1,258 @@ +.container { + margin: 20px; + border: solid 1px black; +} + +main { + display: grid; + grid-template-columns: 1fr 1.5fr 1fr; +} + +.leftContainer { + display: flex; + flex-direction: column; + align-items: center; + border: solid 1px black; +} + +.leftbuttonBox { + margin-top: 20px; + display: flex; + flex-direction: column; + align-items: center; +} + +.leftContainer button { + margin-top: 20px; + width: 200px; + height: 72px; +} + +.leftContainer button.selected { + color: rgb(54, 54, 54); + background-color: rgb(61, 230, 69); +} + +.middleContainer { + display: grid; + grid-template-rows: auto; + border: solid 1px black; +} + +.middleBoxContainer { + margin-bottom: 20px; +} + +.buttonBox { + display: flex; + flex-direction: column; + margin-top: 30px; +} + +.buttonBox button { + padding: 15px 20px; + font-size: 32px; +} + +.buttonWithImage { + display: flex; + align-items: center; + margin-bottom: 10px; +} + +.buttonWithImage img { + width: 140px; + height: 140px; + margin-right: 10px; + margin-left: 17px; +} + +.buttonBox button.selected { + color: rgb(54, 54, 54); + background-color: rgb(61, 230, 69); +} + +.rightContainer { + display: grid; + grid-template-rows: 60px 60px 238px 60px 60px; + border: solid 1px black; +} + +button { + margin: 0 20px; + margin-bottom: 10px; + padding: 10px 20px; + font-size: 32px; + font-weight: bold; + color: rgb(54, 54, 54); + background-color: #3396ff; + border: solid 2px black; + cursor: pointer; + transition: background-color 0.3s ease; +} + +button:hover { + background-color: #0056b3; +} + +#sendPaletteInfo { + margin: 0; + width: 100%; + height: 72px; + margin-bottom: 20px; + background-color: #3396ff; +} + +#startRobotButton { + margin: 0; + width: 100%; + height: 72px; + margin-bottom: 55px; + margin-top: 10px; + padding: 10px 15px; + background-color: #3396ff; +} + +#startRobotButton:disabled { + background-color: gray; + color: white; + cursor: not-allowed; +} + +#woodenFlatPallet:disabled { + background-color: gray; + color: white; + cursor: not-allowed; +} + +#exitAppButton { + margin: 0; + width: 100%; + color: rgb(54, 54, 54); + background-color: rgb(252, 101, 101); + padding: 10px; + cursor: pointer; + font-size: 22px; +} + +#resetButton { + margin: 0; + width: 100%; + color: rgb(54, 54, 54); + background-color: rgb(252, 169, 101); + padding: 10px; + cursor: pointer; + font-size: 22px; +} + +#bookHeight { + width: 100px; + height: 40px; + margin-top: 10px; + padding: 10px; + font-size: 19px; + border: 1px solid #ccc; + border-radius: 5px; +} + +#palletHeight { + width: 180px; + height: 40px; + margin-top: 10px; + padding: 10px; + font-size: 19px; + border: 1px solid #ccc; + border-radius: 5px; +} + +.inputContainer { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.inputBox { + display: flex; +} + +p { + display: flex; + justify-content: center; + align-items: center; + width: 60px; + height: 40px; + margin-top: 10px; + padding: 10px; + font-size: 19px; + border: 1px solid #ccc; + border-radius: 5px; +} + +#bookHeight::placeholder, +#palletHeight::placeholder { + color: #999; +} + +#bookHeightTitle, +#palletHeightTitle { + margin-top: 20px; + font-size: 19px; + font-weight: 600; +} + + +html, body { + margin: 0; + padding: 0; + height: 100%; + width: 100%; + justify-content: center; + align-items: center; + position: relative; + overflow: hidden; +} + +#alert { + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.3); + position: absolute; + justify-content: center; + display: none; +} + +#alertBox{ + width: 80%; + height: 50%; + background-color: white; + display: flex; + align-self: center; + border-radius: 10px; + border:2px solid black; + justify-content: center; + align-items: center; + flex-direction: column; +} + +#loader { + border: 16px solid #f3f3f3; /* Light gray */ + border-top: 16px solid #3498db; /* Blue */ + border-radius: 50%; + width: 100px; + height: 100px; + animation: spin 1s linear infinite; + margin: 10px auto; /* Center the loader */ +} + +#alert_msg { + font-size: 32px; + font-weight: bold; + color: rgb(54, 54, 54); + +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} \ No newline at end of file diff --git a/static/css/oneLineProgress.css b/static/css/oneLineProgress.css new file mode 100644 index 0000000..b98fb17 --- /dev/null +++ b/static/css/oneLineProgress.css @@ -0,0 +1,249 @@ +.container { + margin: 20px; + border: solid 1px black; +} + +main { + display: grid; + grid-template-columns: 2fr 1.5fr; +} + +.leftContainer { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + border: solid 1px black; + min-height: 90vh; +} + +.gridContainer { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 10px; + width: 100%; + max-width: 380px; + margin: 0 auto; + margin-top: 0px; +} +.gridItem { + width: 180px; + height: 120px; + background-color: #f0f0f0; + display: flex; + align-items: center; + justify-content: center; + border: 1px solid #ccc; + cursor: pointer; + font-size: 45px; + font-weight: 600; +} +.gridItem.selected { + background-color: #34b800; + color: #fff; +} +.gridItem.disabled { + pointer-events: none; + opacity: 0.5; /* 비활성화 상태를 시각적으로 나타내기 위해 투명도를 줄입니다 */ +} + +.buttonContainer { + margin-top: 10px; + display: flex; + flex-direction: column; + align-items: center; +} + +.buttonContainer button { + width: 330px; + height: 72px; + margin-top: 10px; +} + +.buttonContainer button:disabled { + background-color: gray; + color: white; + cursor: not-allowed; +} + +.rightContainer { + border: solid 1px black; + display: grid; + grid-template-rows: repeat(4, 60px); +} + +#finishAction { + margin: 0; + width: 100%; + height: 70px; +} + +#terminateAction { + margin: 0; + width: 100%; + height: 70px; + background-color: #ff3c00; +} + +#currentLayerIndexDisplay { + font-weight: 600; + font-size: 23px; +} + +button { + margin: 0 20px; + margin-bottom: 10px; + padding: 10px 20px; + font-size: 37px; + font-weight: 700; + color: rgb(54, 54, 54); + background-color: #3396ff; + border: solid 20x black; + cursor: pointer; + transition: background-color 0.3s ease; +} + +#exitAppButton { + width: 100%; + margin: 0; + height: 60px; + border-radius: 0px; + color: rgb(54, 54, 54); + background-color: rgb(252, 101, 101); + font-size: 22px; + border: solid 1px black; +} +.buttonBox { + display: flex; + flex-wrap: wrap; + width: 100%; +} + +.buttonBox button { + margin: 0; + height: 60px; + width: 50%; + border-radius: 0px; + font-size: 22px; + border: solid 1px black; +} + +#stackerStartButton, +#upDownOnButton, +#leftRightOnButton { + color: rgb(54, 54, 54); + background-color: rgb(61, 230, 69); +} + +#stackerStopButton, +#upDownOffButton, +#leftRightOffButton { + color: rgb(54, 54, 54); + background-color: rgb(252, 169, 101); +} + +.inputContainer { + display: flex; + flex-direction: column; + justify-content: end; + align-items: center; +} + +.inputBox { + display: flex; +} + +p { + display: flex; + justify-content: center; + align-items: center; + width: 60px; + height: 35px; + margin-top: 10px; + padding: 10px; + font-size: 19px; + border: 1px solid #ccc; + border-radius: 5px; +} + +span { + font-size: 21px; + font-weight: 600; +} + +#bookHeight { + width: 100px; + height: 35px; + margin-top: 10px; + padding: 10px; + font-size: 19px; + border: 1px solid #ccc; + border-radius: 5px; +} + +#bookHeight::placeholder { + color: #999; +} + +#bookHeightTitle { + margin-top: 10px; + font-size: 19px; + font-weight: 600; +} + + + + + + +/* 팝업을 화면 중앙에 표시하기 위한 스타일 */ +#bookCountPopup { + display: none; /* 기본적으로 보이지 않음 */ + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); /* 창을 중앙에 위치하게 함 */ + width: 300px; + padding: 20px; + background-color: white; + box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2); + border-radius: 8px; + z-index: 1001; + text-align: center; +} + +/* 배경을 어둡게 처리 */ +#popupOverlay { + display: none; /* 기본적으로 보이지 않음 */ + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: 1000; +} + +/* 제출 버튼 스타일 */ +#submitBookCount { + margin-top: 15px; + padding: 10px 20px; + background-color: #4CAF50; + color: white; + border: none; + border-radius: 5px; + cursor: pointer; +} + +#submitBookCount:hover { + background-color: #45a049; +} + +/* 입력 필드 스타일 */ +#bookCountInput { + margin-top: 10px; + padding: 8px; + width: 80%; + border: 1px solid #ccc; + border-radius: 5px; +} diff --git a/static/css/progress.css b/static/css/progress.css new file mode 100644 index 0000000..3093299 --- /dev/null +++ b/static/css/progress.css @@ -0,0 +1,109 @@ +.container { + margin: 0; + margin: 20px; + border: solid 1px black; +} + +main { + display: grid; + grid-template-columns: 2fr 1fr; +} + +.leftContainer { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + min-height: 90vh; + border: solid 1px black; +} + +.rightContainer { + border: solid 1px black; +} + +.msg { + margin-top: 70px; + font-size: 45px; + font-weight: 700; +} + +#finishAction { + margin-top: 20px; + width: 343px; + height: 74px; +} + +#terminateAction { + margin-top: 25px; + width: 343px; + height: 74px; + background-color: rgb(252, 101, 101); +} + +button { + margin: 0 20px; + margin-bottom: 10px; + padding: 10px 20px; + font-size: 38px; + font-weight: 700; + color: rgb(54, 54, 54); + background-color: #3396ff; + border: solid 2px black; + cursor: pointer; + transition: background-color 0.3s ease; +} + +p { + font-size: 30px; + font-weight: 600; +} + +span { + font-size: 30px; + font-weight: 600; +} + +.rightContainer { + display: grid; + grid-template-rows: repeat(4, 60px); +} + +.buttonBox { + display: flex; + height: 70px; +} + +#exitAppButton { + width: 100%; + margin: 0; + height: 60px; + border-radius: 0px; + color: rgb(54, 54, 54); + background-color: rgb(252, 101, 101); + font-size: 22px; + border: solid 1px black; +} + +.buttonBox button { + margin: 0; + height: 60px; + width: 16vw; + border-radius: 0px; + font-size: 22px; + border: solid 1px black; +} + +#stackerStartButton, +#upDownOnButton, +#leftRightOnButton { + color: rgb(54, 54, 54); + background-color: rgb(61, 230, 69); +} + +#stackerStopButton, +#upDownOffButton, +#leftRightOffButton { + color: rgb(54, 54, 54); + background-color: rgb(252, 169, 101); +} diff --git a/static/img/iron_wheel_pallet.png b/static/img/iron_wheel_pallet.png new file mode 100644 index 0000000..d9be7ce Binary files /dev/null and b/static/img/iron_wheel_pallet.png differ diff --git a/static/img/wooden_flat_pallet.png b/static/img/wooden_flat_pallet.png new file mode 100644 index 0000000..59388a2 Binary files /dev/null and b/static/img/wooden_flat_pallet.png differ diff --git a/static/img/wooden_wheel_pallet.png b/static/img/wooden_wheel_pallet.png new file mode 100644 index 0000000..6951dfd Binary files /dev/null and b/static/img/wooden_wheel_pallet.png differ diff --git a/static/js/layer.js b/static/js/layer.js new file mode 100644 index 0000000..d22d928 --- /dev/null +++ b/static/js/layer.js @@ -0,0 +1,275 @@ +const bookCenterPosition_Wheel = [ + { x: 450.5, y: 105 }, + { x: 450.5, y: 320 }, + { x: 148.5, y: 105 }, + { x: 148.5, y: 320 }, +]; +const bookCenterPosition_Flat = [ + { x: 750, y: 148.5 }, + { x: 535, y: 148.5 }, + { x: 320, y: 148.5 }, + { x: 105, y: 148.5 }, + { x: 750, y: 450.5 }, + { x: 535, y: 450.5 }, + { x: 320, y: 450.5 }, + { x: 105, y: 450.5 }, +]; + +const woodenWheelPallet = { + palletWidth: 620, + palletLength: 442, + palletHeight: 653, + bookCenterPosition_Wheel, +}; +const ironWheelPallet = { + palletWidth: 620, + palletLength: 442, + palletHeight: 633, + bookCenterPosition_Wheel, +}; +const woodenFlatPallet = { + palletWidth: 878, + palletLength: 638, + palletHeight: 148, + bookCenterPosition_Flat, +}; + +const pallets = { + woodenWheelPallet, + ironWheelPallet, + woodenFlatPallet, +}; + +document.addEventListener('DOMContentLoaded', function () { + const sendPaletteInfoButton = document.getElementById('sendPaletteInfo'); + const startRobotMove = document.getElementById('startRobotButton'); + const resetButton = document.getElementById('resetButton'); + const exitAppButton = document.getElementById('exitAppButton'); + const palletHeightInput = document.getElementById('palletHeight'); + const palletHeightTitle = document.getElementById('palletHeightTitle'); + + const stackingButtons = document.querySelectorAll('.leftbuttonBox button'); + let stackingSelected = false; + + const palletButtons = document.querySelectorAll('.buttonBox button'); + let selectedPalletId = null; + + const woodenFlatPalletButton = document.getElementById('woodenFlatPallet'); + + let isStartclicked = false; + + function customAlert(msg) { + const alert = document.getElementById('alert'); + const text = document.getElementById('alert_msg'); + if (msg) { + alert.style.display = 'flex'; + text.innerText = msg; + } else { + alert.style.display = 'none'; + text.innerText = ''; + } + } + + function logAction(message) { + fetch('/writelog', { + method: 'POST', + headers: { + 'Content-Type': 'text/plain', + }, + body: message, + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to write log.'); + } + return response.text(); + }) + .then((data) => { + console.log(`Log result: ${data}`); + }) + .catch((error) => console.error('Error writing log:', error)); + } + + stackingButtons.forEach((button) => { + button.addEventListener('click', () => { + stackingButtons.forEach((btn) => btn.classList.remove('selected')); + button.classList.add('selected'); + stackingSelected = true; + stackingButtons.forEach((btn) => btn.classList.remove('disabled')); + + // pallet 버튼의 선택 상태를 해제 + palletButtons.forEach((btn) => { + btn.classList.remove('selected'); + btn.disabled = false; // pallet 버튼을 활성화 상태로 되돌림 + }); + selectedPalletId = null; + sendPaletteInfoButton.disabled = true; + + if (button.id === 'oneLineButton') { + woodenFlatPalletButton.classList.add('disabled'); + woodenFlatPalletButton.disabled = true; + palletHeightInput.style.display = 'none'; + palletHeightTitle.style.display = 'none'; + } else if (button.id === 'normalButton') { + woodenFlatPalletButton.classList.remove('disabled'); + woodenFlatPalletButton.disabled = false; + } + + logAction(`FE : Stacking button ${button.id} clicked - layer.js`); + }); + }); + + palletButtons.forEach((button) => { + button.addEventListener('click', () => { + if (!stackingSelected) { + alert('⛔ 쌓기 버튼을 먼저 선택해주세요!'); + return; + } + palletButtons.forEach((btn) => btn.classList.remove('selected')); + button.classList.add('selected'); + selectedPalletId = button.id; + sendPaletteInfoButton.disabled = false; + + if (selectedPalletId === 'woodenFlatPallet') { + palletHeightInput.style.display = 'block'; + palletHeightTitle.style.display = 'block'; + } else { + palletHeightInput.style.display = 'none'; + palletHeightTitle.style.display = 'none'; + } + + logAction(`FE : Pallet button ${button.id} clicked - layer.js`); + }); + }); + + sendPaletteInfoButton.addEventListener('click', function () { + let palletHeight = pallets[selectedPalletId].palletHeight; // 기본 높이를 사용 + if (selectedPalletId === 'woodenFlatPallet') { + palletHeight = parseFloat(palletHeightInput.value); + if (isNaN(palletHeight) || palletHeight <= 0) { + alert('⛔ 유효한 팔레트 높이를 입력해주세요!'); + return; + } + } + + if (selectedPalletId) { + const selectedPallet = pallets[selectedPalletId]; + selectedPallet.palletHeight = palletHeight; // update the pallet height + + fetch('/update_pallet', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(selectedPallet), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send palette info.'); + } + return response.text(); + }) + .then((data) => { + if (data == 'Success') { + startRobotMove.disabled = false; + sendPaletteInfoButton.style.backgroundColor = '#34b800'; + isStartclicked = false; + logAction('FE : update_pallet api sent successfully - layer.js'); + } + }) + .catch((error) => console.error('Error sending palette info:', error)); + } else { + alert('⛔ 팔레트를 선택해주세요!'); + } + }); + + startRobotMove.addEventListener('click', function () { + logAction('FE : startRobotMove button clicked - layer.js'); + + if (selectedPalletId) { + let confirmResult = confirm('로봇 동작을 시작하시겠습니까?'); + if (confirmResult && isStartclicked == false) { + isStartclicked = true; + + const selectedPallet = pallets[selectedPalletId]; + + const selectedStackingButton = document.querySelector( + '.leftbuttonBox .selected' + ); + + let btnId = ''; + + if (selectedStackingButton.id === 'normalButton') { + btnId = 'normalButton'; + window.location.href = '/progress'; + } else if (selectedStackingButton.id === 'oneLineButton') { + btnId = 'oneLineButton'; + window.location.href = '/oneLineProgress'; + } + + const data = { selectedPallet, btnId, selectedPalletId }; + customAlert('로봇 동작을 시작합니다...'); + + fetch('/robot_start', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }) + // 지금 현재 상황 (2024.10.10 문제점 : .then아래로 안내려옴 문제 해결 필요 시급) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send palette info.'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction( + 'FE : robot_start function(server) finish successfully - layer.js' + ); + }) + .catch((error) => + console.error('Error sending palette info:', error) + ); + } + } else { + alert('⛔ 팔레트를 선택해주세요!'); + } + }); + + resetButton.addEventListener('click', function () { + fetch('/reset_data', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ message: 'Reset button clicked' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send reset data.'); + } + return response.text(); + }) + .then((data) => { + if (data == 'Success') { + logAction('FE : reset_data api sent successfully - layer.js'); + } + }) + .catch((error) => console.error('Error sending reset data:', error)); + }); + + exitAppButton.addEventListener('click', function () { + fetch('/shutdown', { + method: 'POST', + }) + .then((response) => response.text()) + .then((data) => { + console.log(data); + logAction('FE : shutdown api sent successfully - layer.js'); + }) + .catch((error) => console.error('Error shutting down:', error)); + }); +}); diff --git a/static/js/oneLineProgress.js b/static/js/oneLineProgress.js new file mode 100644 index 0000000..80da035 --- /dev/null +++ b/static/js/oneLineProgress.js @@ -0,0 +1,418 @@ +document.addEventListener('DOMContentLoaded', function () { + const terminateAction = document.getElementById('terminateAction'); + const finishAction = document.getElementById('finishAction'); + + const gridItems = document.querySelectorAll('.gridItem'); + const runButton = document.getElementById('run'); + const stopButton = document.getElementById('stop'); + + const exitAppButton = document.getElementById('exitAppButton'); + + const stackerStartButton = document.getElementById('stackerStartButton'); + const stackerStopButton = document.getElementById('stackerStopButton'); + + const upDownOnButton = document.getElementById('upDownOnButton'); + const upDownOffButton = document.getElementById('upDownOffButton'); + + const leftRightOnButton = document.getElementById('leftRightOnButton'); + const leftRightOffButton = document.getElementById('leftRightOffButton'); + + let selectedGridId = null; // 선택된 그리드 ID + let intervalId = null; // setInterval ID + let isRunning = false; // 한줄쌓기 실행 상태 + + // 초기 상태 설정 + stopButton.disabled = true; + runButton.disabled = true; + + function logAction(message) { + fetch('/writelog', { + method: 'POST', + headers: { + 'Content-Type': 'text/plain', + }, + body: message, + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to write log.'); + } + return response.text(); + }) + .then((data) => { + console.log(`Log result: ${data}`); + }) + .catch((error) => console.error('Error writing log:', error)); + } + + // JSON 파일에서 데이터 로드 + function fetchJsonData() { + fetch('/static/json/oneLine.json') + .then((response) => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then((data) => { + updateGridStatus(data); + }) + .catch((error) => console.error('Error loading JSON:', error)); + } + + // 초기 데이터 로드 + fetchJsonData(); + + // 그리드 상태 업데이트 함수 + function updateGridStatus(data) { + const grids = ['grid1', 'grid2', 'grid3', 'grid4']; + + // 그리드 비활성화 초기화 + gridItems.forEach((item) => item.classList.remove('disabled')); + + grids.forEach((grid) => { + if (data[grid].currentLayerHeight > 720) { + document.getElementById(grid).classList.add('disabled'); + } + }); + + if (data.grid4.currentLayerHeight > data.grid2.currentLayerHeight) { + document.getElementById('grid2').classList.add('disabled'); + } + + if (data.grid3.currentLayerHeight > data.grid1.currentLayerHeight) { + document.getElementById('grid1').classList.add('disabled'); + } + + // 선택된 그리드의 currentLayerIndex 출력 + if (selectedGridId) { + const selectedGridData = data[selectedGridId]; + document.getElementById( + 'currentLayerIndexDisplay' + ).textContent = `현재 쌓고 있는 단 : ${ + selectedGridData.currentLayerIndex + 1 + }`; + } + + // 한줄쌓기 실행 중인 경우 그리드 비활성화 유지 + if (isRunning) { + toggleGridItems(true); + } + } + + // 그리드 아이템 클릭 핸들러 + function handleGridItemClick(event) { + const item = event.currentTarget; + if (item.classList.contains('disabled')) { + return; // 클릭 이벤트 무시 + } + gridItems.forEach((btn) => btn.classList.remove('selected')); + item.classList.add('selected'); + selectedGridId = item.id; + checkRunButtonState(); + } + + gridItems.forEach((item) => { + item.addEventListener('click', handleGridItemClick); + }); + + // 한줄쌓기 실행 버튼 클릭 핸들러 + runButton.addEventListener('click', function () { + runButton.disabled = true; + stopButton.disabled = false; + isRunning = true; + toggleGridItems(true); + + intervalId = setInterval(fetchJsonData, 5000); + + fetch('/one_line_run', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + message: 'one_line_run', + gridId: selectedGridId, // 선택된 그리드 아이템의 ID 전송 + }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('one_line_run failed.'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction( + 'FE : one_line_run api sent successfully - oneLineProgress.js' + ); + }) + .catch((error) => + console.error('Error sending one_line_run action:', error) + ); + }); + + // 한줄쌓기 멈춤 버튼 클릭 핸들러 + stopButton.addEventListener('click', function () { + runButton.disabled = false; + stopButton.disabled = true; + isRunning = false; + toggleGridItems(false); + clearGridSelection(); + + // JSON 데이터 주기적으로 가져오기 중지 + clearInterval(intervalId); + + // 멈춤 버튼 클릭 시 JSON 데이터 다시 로드 + fetchJsonData(); + + fetch('/one_line_stop', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ message: 'one_line_stop' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('one_line_stop failed.'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction( + 'FE : one_line_stop api sent successfully - oneLineProgress.js' + ); + }) + .catch((error) => + console.error('Error sending one_line_stop action:', error) + ); + }); + + // 한줄쌓기 실행 버튼 활성화 여부 확인 함수 + function checkRunButtonState() { + const anyGridSelected = Array.from(gridItems).some((item) => + item.classList.contains('selected') + ); + + runButton.disabled = !anyGridSelected; + } + + // 그리드 아이템 활성화/비활성화 함수 + function toggleGridItems(disable) { + gridItems.forEach((item) => item.classList.toggle('disabled', disable)); + } + + // 그리드 아이템 선택 해제 함수 + function clearGridSelection() { + gridItems.forEach((item) => item.classList.remove('selected')); + checkRunButtonState(); // 선택 해제 후 버튼 상태 재확인 + } + + finishAction.addEventListener('click', function () { + finishAction.disabled = true; + fetch('/robot_immediately_take_book', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + immediately_take_book: 'robot_immediately_take_book', + }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('immediately_take_book failed.'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction( + 'FE : robot_immediately_take_book api sent successfully - oneLineProgress.js' + ); + }) + .catch((error) => + console.error('Error Sending robot finish action:', error) + ) + .finally(() => { + setTimeout(() => { + finishAction.disabled = false; + }, 10000); + }); + }); + + terminateAction.addEventListener('click', function () { + fetch('/robot_finish_action', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ action: 'robot_finish_action' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send robot finish action.'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction( + 'FE : terminateAction api sent successfully - oneLineProgress.js' + ); + + window.location.href = '/'; + }) + .catch((error) => + console.error('Error sending robot finish action:', error) + ); + }); + + exitAppButton.addEventListener('click', function () { + fetch('/shutdown', { + method: 'POST', + }) + .then((response) => response.text()) + .then((data) => { + console.log(data); + logAction('FE : shutdown api sent successfully - oneLineProgress.js'); + }) + .catch((error) => console.error('Error shutting down:', error)); + }); + + stackerStartButton.addEventListener('click', function () { + fetch('/stacker_start', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ action: 'stacker_start' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send stacker start.'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction( + 'FE : stacker_start api sent successfully - oneLineProgress.js' + ); + }) + .catch((error) => console.error('Error sending stacker start:', error)); + }); + + stackerStopButton.addEventListener('click', function () { + fetch('/stacker_stop', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ action: 'stacker_stop' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send stacker stop.'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction( + 'FE : stacker_stop api sent successfully - oneLineProgress.js' + ); + }) + .catch((error) => console.error('Error sending stacker stop:', error)); + }); + + upDownOnButton.addEventListener('click', function () { + fetch('/updown_on', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ action: 'updown_on' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send updown on'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction('FE : updown_on api sent successfully - oneLineProgress.js'); + }) + .catch((error) => console.error('Error sending updown on:', error)); + }); + + upDownOffButton.addEventListener('click', function () { + fetch('/updown_off', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ action: 'updown_off' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send updown off'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction('FE : updown_off api sent successfully - oneLineProgress.js'); + }) + .catch((error) => console.error('Error sending updown off:', error)); + }); + + leftRightOnButton.addEventListener('click', function () { + fetch('/leftright_on', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ action: 'leftright_on' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send leftright on'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction( + 'FE : leftright_on api sent successfully - oneLineProgress.js' + ); + }) + .catch((error) => console.error('Error sending leftright on:', error)); + }); + + leftRightOffButton.addEventListener('click', function () { + fetch('/leftright_off', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ action: 'leftright_off' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send leftright off'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction( + 'FE : leftright_off api sent successfully - oneLineProgress.js' + ); + }) + .catch((error) => console.error('Error sending leftright off:', error)); + }); +}); diff --git a/static/js/progress.js b/static/js/progress.js new file mode 100644 index 0000000..5138676 --- /dev/null +++ b/static/js/progress.js @@ -0,0 +1,255 @@ +document.addEventListener('DOMContentLoaded', function () { + const terminateAction = document.getElementById('terminateAction'); + const finishAction = document.getElementById('finishAction'); + const exitAppButton = document.getElementById('exitAppButton'); + + const stackerStartButton = document.getElementById('stackerStartButton'); + const stackerStopButton = document.getElementById('stackerStopButton'); + const upDownOnButton = document.getElementById('upDownOnButton'); + const upDownOffButton = document.getElementById('upDownOffButton'); + const leftRightOnButton = document.getElementById('leftRightOnButton'); + const leftRightOffButton = document.getElementById('leftRightOffButton'); + + function logAction(message) { + fetch('/writelog', { + method: 'POST', + headers: { + 'Content-Type': 'text/plain', + }, + body: message, + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to write log.'); + } + return response.text(); + }) + .then((data) => { + console.log(`Log result: ${data}`); + }) + .catch((error) => console.error('Error writing log:', error)); + } + + // 인덱스 표시 업데이트 함수 + function updateIndexDisplay() { + fetch('/static/json/cache.json') + .then((response) => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then((data) => { + document.getElementById('currentDataIndex').textContent = + data.currentDataIndex + 1; + document.getElementById('currentLayerIndex').textContent = + data.currentLayerIndex + 1; + console.log(data.currentDataIndex, data.currentLayerIndex); + }) + .catch((error) => console.error('Error loading cache.json:', error)); + } + + // 페이지 로드 시 초기 인덱스 표시 업데이트 + updateIndexDisplay(); + + // 일정 시간마다 인덱스 표시 업데이트 + intervalId = setInterval(updateIndexDisplay, 5000); // 5초마다 업데이트 + + finishAction.addEventListener('click', function () { + finishAction.disabled = true; + fetch('/robot_immediately_take_book', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + immediately_take_book: 'robot_immediately_take_book', + }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('immediately_take_book failed.'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction( + 'FE : robot_immediately_take_book api sent successfully - progress.js' + ); + }) + .catch((error) => + console.error('Error Sending robot finish action:', error) + ).finally(() => { + setTimeout(() => { + finishAction.disabled = false; + }, 10000); + }) + }); + + terminateAction.addEventListener('click', function () { + fetch('/robot_finish_action', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ action: 'robot_finish_action' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send robot finish action.'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + clearInterval(intervalId); + logAction( + 'FE : robot_finish_action api sent successfully - progress.js' + ); + + window.location.href = '/'; + }) + .catch((error) => + console.error('Error sending robot finish action:', error) + ); + }); + + exitAppButton.addEventListener('click', function () { + fetch('/shutdown', { + method: 'POST', + }) + .then((response) => response.text()) + .then((data) => { + console.log(data); + logAction('FE : shutdown api sent successfully - progress.js'); + }) + .catch((error) => console.error('Error shutting down:', error)); + }); + + stackerStartButton.addEventListener('click', function () { + fetch('/stacker_start', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ action: 'stacker_start' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send stacker start.'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction('FE : stacker_start api sent successfully - progress.js'); + }) + .catch((error) => console.error('Error sending stacker start:', error)); + }); + + stackerStopButton.addEventListener('click', function () { + fetch('/stacker_stop', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ action: 'stacker_stop' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send stacker stop.'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction('FE : stacker_stop api sent successfully - progress.js'); + }) + .catch((error) => console.error('Error sending stacker stop:', error)); + }); + + upDownOnButton.addEventListener('click', function () { + fetch('/updown_on', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ action: 'updown_on' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send updown on'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction('FE : updown_on api sent successfully - progress.js'); + }) + .catch((error) => console.error('Error sending updown on:', error)); + }); + + upDownOffButton.addEventListener('click', function () { + fetch('/updown_off', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ action: 'updown_off' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send updown off'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction('FE : updown_off api sent successfully - progress.js'); + }) + .catch((error) => console.error('Error sending updown off:', error)); + }); + + leftRightOnButton.addEventListener('click', function () { + fetch('/leftright_on', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ action: 'leftright_on' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send leftright on'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction('FE : leftright_on api sent successfully - progress.js'); + }) + .catch((error) => console.error('Error sending leftright on:', error)); + }); + + leftRightOffButton.addEventListener('click', function () { + fetch('/leftright_off', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ action: 'leftright_off' }), + }) + .then((response) => { + if (!response.ok) { + throw new Error('Failed to send leftright off'); + } + return response.text(); + }) + .then((data) => { + console.log(data); + logAction('FE : leftright_off api sent successfully - progress.js'); + }) + .catch((error) => console.error('Error sending leftright off:', error)); + }); +}); diff --git a/static/json/cache.json b/static/json/cache.json new file mode 100644 index 0000000..e70d7de --- /dev/null +++ b/static/json/cache.json @@ -0,0 +1,5 @@ +{ + "currentDataIndex": 0, + "currentLayerIndex": 0, + "currentLayerHeight": 0 +} \ No newline at end of file diff --git a/static/json/height.json b/static/json/height.json new file mode 100644 index 0000000..1ba6531 --- /dev/null +++ b/static/json/height.json @@ -0,0 +1,3 @@ +{ + "measuredHeight": 0 +} \ No newline at end of file diff --git a/static/json/oneLine.json b/static/json/oneLine.json new file mode 100644 index 0000000..d5e10a4 --- /dev/null +++ b/static/json/oneLine.json @@ -0,0 +1,22 @@ +{ + "grid1": { + "currentDataIndex": 0, + "currentLayerIndex": 0, + "currentLayerHeight": 0 + }, + "grid2": { + "currentDataIndex": 1, + "currentLayerIndex": 0, + "currentLayerHeight": 0 + }, + "grid3": { + "currentDataIndex": 2, + "currentLayerIndex": 0, + "currentLayerHeight": 0 + }, + "grid4": { + "currentDataIndex": 3, + "currentLayerIndex": 0, + "currentLayerHeight": 0 + } +} \ No newline at end of file diff --git a/templates/layer.html b/templates/layer.html new file mode 100644 index 0000000..f964b26 --- /dev/null +++ b/templates/layer.html @@ -0,0 +1,86 @@ + + + + + + 레이어 관리 + + + +
+
+
+ +
+
+
+
+
+
+ + +
+ + + + + +
+
+
+ +
+
+
+
+ 나무 바퀴 팔레트 + +
+
+ 철제 바퀴 팔레트 + +
+
+ 나무 납작 팔레트 + +
+
+
+
+ +
+ + +
+ + +
+
+
+ + + + diff --git a/templates/oneLineProgress.html b/templates/oneLineProgress.html new file mode 100644 index 0000000..c701d3f --- /dev/null +++ b/templates/oneLineProgress.html @@ -0,0 +1,55 @@ + + + + + + 로봇 동작 중 + + + +
+
+
+
+
2
+
4
+
1
+
3
+
+ +
+
현재 쌓고 있는 단 :
+ + +
+
+ +
+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ + +
+
+
+
+ + + + diff --git a/templates/progress.html b/templates/progress.html new file mode 100644 index 0000000..d6798b7 --- /dev/null +++ b/templates/progress.html @@ -0,0 +1,51 @@ + + + + + + 로봇 동작 중 + + + +
+
+
+
로봇이 움직이는 중입니다.
+ +
+

+ 현재 0단 + 0위치 +

+ +
+ + + +
+ +
+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+ + + +