# -*- coding: UTF-8 -*- # Copyright 2015-2022 - RoboDK Inc. - https://robodk.com/ # # This file loads the compiled version of the RoboDK post processor for: # Universal Robots 3D Printing robot controllers # # More information about RoboDK Post Processors and Offline Programming: # https://robodk.com/help#PostProcessor # https://robodk.com/doc/en/PythonAPI/postprocessor.html # ---------------------------------------------------- import sys import os #Needed to make the robodk generated code work import math from robodk import * # Detect Python version and post processor print("Using Python version: " + str(sys.version_info)) path_app = os.path.dirname(__file__).replace(os.sep,"/") print("RoboDK Post Processor: " + path_app) # Check if the post is compatible with the Python version version_str = str(sys.version_info[0]) + str(sys.version_info[1]) path_library = path_app + '/v' + version_str if not os.path.isdir(path_library): msg = "Invalid Python version or post processor not found. Make sure you are using a supported Python version: " + path_library msg += "\nSelect Tools-Options-Python and select a supported Python version" print(msg) raise Exception(msg) # Load the post processor exec("from v" + version_str + ".Universal_Robots_3D_Printing import RobotPost as BasePost") class RobotPost(BasePost): """Robot post object""" MAX_LINES_X_PROG = 250 # Maximum number of lines per program. If the number of lines is exceeded, the program will be executed step by step by RoboDK PROG_EXT = "script" # set the program extension SPEED_MS = 0.3 # default speed for linear moves in m/s SPEED_RADS = 0.75 # default speed for joint moves in rad/s ACCEL_MSS = 3 # default acceleration for lineaer moves in m/ss ACCEL_RADSS = 1.2 # default acceleration for joint moves in rad/ss BLEND_RADIUS_M = 0.001 # default blend radius in meters (corners smoothing) MOVEC_MIN_RADIUS = 1 # minimum circle radius to output (in mm). It does not take into account the Blend radius MOVEC_MAX_RADIUS = 10000 # maximum circle radius to output (in mm). It does not take into account the Blend radius USE_MOVEP = False # 3D Printing Extruder Setup Parameters: PRINT_E_AO = 0 # Analog Output ID to command the extruder flow PRINT_SPEED_2_SIGNAL = 0.10 # Ratio to convert the speed/flow to an analog output signal PRINT_FLOW_MAX_SIGNAL = 24 # Maximum signal to provide to the Extruder PRINT_ACCEL_MMSS = -1 # Acceleration, -1 assumes constant speed if we use rounding/blending # Internal 3D Printing Parameters PRINT_POSE_LAST = None # Last pose printed PRINT_E_LAST = 0 # Last Extruder length PRINT_E_NEW = None # New Extruder Length PRINT_LAST_SIGNAL = None # Last extruder signal pass if __name__== "__main__": exec("from v" + version_str + ".Universal_Robots_3D_Printing import test_post") test_post() # Pierwszym krokiem jest przechwycenie wywołań Extrudera i odczytanie nowych wartości Extrudera (wartości E) w sekcji RunCode w postprocesorze. # Poniższa sekcja przetwarza wszystkie wywołania programów wygenerowane dla programu: def RunCode(self, code, is_function_call = False): if is_function_call: if code.startswith("Extruder("): # Intercept the extruder command. # if the program call is Extruder(123.56) # we extract the number as a string # and convert it to a number self.PRINT_E_NEW = float(code[9:-1]) # Skip the program call generation return else: self.addline(code + "()") else: # Output program code self.addline(code) def MoveL(self, pose, joints, conf_RLF=None): """Add a linear movement""" """Dodaj ruch liniowy""" # Handle 3D printing Extruder integration self.new_move(pose) def calculate_time(self, distance, Vmax, Amax=-1): """Calculate the time to move a distance with Amax acceleration and Vmax speed""" if Amax < 0: # Assume constant speed (appropriate smoothing/rounding parameter must be set) Ttot = distance/Vmax else: # Assume we accelerate and decelerate tacc = Vmax/Amax; Xacc = 0.5*Amax*tacc*tacc; if distance <= 2*Xacc: # Vmax is not reached tacc = sqrt(distance/Amax) Ttot = tacc*2 else: # Vmax is reached Xvmax = distance - 2*Xacc Tvmax = Xvmax/Vmax Ttot = 2*tacc + Tvmax return Ttot def new_move(self, new_pose): """Implement the action on the extruder for 3D printing, if applicable""" if self.PRINT_E_NEW is None or new_pose is None: return # Skip the first move and remember the pose if self.PRINT_POSE_LAST is None: self.PRINT_POSE_LAST = new_pose return # Calculate the increase of material for the next movement add_material = self.PRINT_E_NEW - self.PRINT_E_LAST self.PRINT_E_LAST = self.PRINT_E_NEW # Calculate the robot speed and Extruder signal extruder_signal = 0 if add_material > 0: distance_mm = norm(subs3(self.PRINT_POSE_LAST.Pos(), new_pose.Pos())) # Calculate movement time in seconds time_s = self.calculate_time(distance_mm, self.SPEED_MMS, self.PRINT_ACCEL_MMSS) # Avoid division by 0 if time_s > 0: # This may look redundant but it allows you to account for accelerations and we can apply small speed adjustments speed_mms = distance_mm / time_s # Calculate the extruder speed in RPM*Ratio (PRINT_SPEED_2_SIGNAL) extruder_signal = speed_mms * self.PRINT_SPEED_2_SIGNAL # Make sure the signal is within the accepted values extruder_signal = max(0,min(self.PRINT_FLOW_MAX_SIGNAL, extruder_signal)) # Update the extruder speed when required if self.PRINT_LAST_SIGNAL is None or abs(extruder_signal - self.PRINT_LAST_SIGNAL) > 1e-6: self.PRINT_LAST_SIGNAL = extruder_signal # Use the built-in setDO function to set an analog output self.setDO(self.PRINT_E_AO, "%.3f"% extruder_signal) # Alternatively, provoke a program call and handle the integration with the robot controller #self.addline('ExtruderSpeed(%.3f)' % extruder_signal) # Remember the last pose self.PRINT_POSE_LAST = new_pose