Fanuc_RJ3.py
Go to the documentation of this file.
1 # Copyright 2017 - RoboDK Software S.L. - http://www.robodk.com/
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at
5 # http://www.apache.org/licenses/LICENSE-2.0
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11 
12 # ----------------------------------------------------
13 # This file is a POST PROCESSOR for Robot Offline Programming to generate programs
14 # for a generic Fanuc robot with RoboDK
15 #
16 # To edit/test this POST PROCESSOR script file:
17 # Select "Program"->"Add/Edit Post Processor", then select your post or create a new one.
18 # You can edit this file using any text editor or Python editor. Using a Python editor allows to quickly evaluate a sample program at the end of this file.
19 # Python should be automatically installed with RoboDK
20 #
21 # You can also edit the POST PROCESSOR manually:
22 # 1- Open the *.py file with Python IDLE (right click -> Edit with IDLE)
23 # 2- Make the necessary changes
24 # 3- Run the file to open Python Shell: Run -> Run module (F5 by default)
25 # 4- The "test_post()" function is called automatically
26 # Alternatively, you can edit this file using a text editor and run it with Python
27 #
28 # To use a POST PROCESSOR file you must place the *.py file in "C:/RoboDK/Posts/"
29 # To select one POST PROCESSOR for your robot in RoboDK you must follow these steps:
30 # 1- Open the robot panel (double click a robot)
31 # 2- Select "Parameters"
32 # 3- Select "Unlock advanced options"
33 # 4- Select your post as the file name in the "Robot brand" box
34 #
35 # To delete an existing POST PROCESSOR script, simply delete this file (.py file)
36 #
37 # ----------------------------------------------------
38 # More information about RoboDK Post Processors and Offline Programming here:
39 # http://www.robodk.com/help#PostProcessor
40 # http://www.robodk.com/doc/en/PythonAPI/postprocessor.html
41 # ----------------------------------------------------
42 
43 
44 def get_safe_name(progname, max_chars = 10):
45  """Get a safe program name"""
46  # Remove special characters
47  for c in r'-[]/\;,><&*:%=+@!#^()|?^':
48  progname = progname.replace(c,'')
49  # Set a program name by default:
50  if len(progname) <= 0:
51  progname = 'Program'
52  # Force the program to start with a letter (not a number)
53  if progname[0].isdigit():
54  progname = 'P' + progname
55  # Set the maximum size of a program (number of characters)
56  if len(progname) > max_chars:
57  progname = progname[:max_chars]
58  return progname
59 
60 
61 # ----------------------------------------------------
62 # Import RoboDK tools
63 from robodk import *
64 import sys
65 
66 # ----------------------------------------------------
67 # Object class that handles the robot instructions/syntax
68 class RobotPost(object):
69  """Robot post object defined for Fanuc robots"""
70  PROG_EXT = 'LS' # set the program extension
71  MAX_LINES_X_PROG = 9999 # maximum number of lines per program. It will then generate multiple "pages (files)". This can be overriden by RoboDK settings.
72  INCLUDE_SUB_PROGRAMS = True # Generate sub programs
73  JOINT_SPEED = '20%' # set default joint speed motion
74  SPEED = '500mm/sec' # set default cartesian speed motion
75  CNT_VALUE = 'FINE' # set default CNT value (all motion until smooth value is changed)
76  ACTIVE_UF = 9 # Active UFrame Id (register)
77  ACTIVE_UT = 9 # Active UTool Id (register)
78  SPARE_PR = 9 # Spare Position register for calculations
79 
80  # PROG specific variables:
81  LINE_COUNT = 0 # Count the number of instructions (limited by MAX_LINES_X_PROG)
82  P_COUNT = 0 # Count the number of P targets in one file
83  nProgs = 0 # Count the number of programs and sub programs
84  LBL_ID_COUNT = 0 # Number of labels used
85 
86  # other variables
87  ROBOT_POST = ''
88  ROBOT_NAME = ''
89  PROG_FILES = [] # List of Program files to be uploaded through FTP
90 
91  PROG_NAMES = [] # List of PROG NAMES
92  PROG_LIST = [] # List of PROG
93 
94  PROG_NAME = 'unknown' # Original name of the current program (example: ProgA)
95  PROG_NAME_CURRENT = 'unknown' # Auto generated name (different from PROG_NAME if we have more than 1 page per program. Example: ProgA2)
96 
97  nPages = 0 # Count the number of pages
98  PROG_NAMES_MAIN = [] # List of programs called by a main program due to splitting
99 
100  PROG = [] # Save the program lines
101  PROG_TARGETS = [] # Save the program lines (targets section)
102  LOG = '' # Save a log
103 
104  nAxes = 6 # Important: This is usually provided by RoboDK automatically. Otherwise, override the __init__ procedure.
105  AXES_TYPE = ['R','R','R','R','R','R'] # Important: This is usually set up by RoboDK automatically. Otherwise, override the __init__ procedure.
106  # 'R' for rotative axis, 'L' for linear axis, 'T' for external linear axis (linear track), 'J' for external rotative axis (turntable)
107  #AXES_TYPE = ['R','R','R','R','R','R','T','J','J'] #example of a robot with one external linear track axis and a turntable with 2 rotary axes
108  AXES_TRACK = []
109  AXES_TURNTABLE = []
110  HAS_TRACK = False
111  HAS_TURNTABLE = False
112 
113  # Specific to ARC welding applications
114  SPEED_BACKUP = None
115  LAST_POSE = None
116 
117  def __init__(self, robotpost=None, robotname=None, robot_axes = 6, **kwargs):
118  self.ROBOT_POST = robotpost
119  self.ROBOT_NAME = robotname
120  self.nAxes = robot_axes
121  self.PROG = []
122  self.LOG = ''
123  #for k,v in kwargs.iteritems(): # python2
124  for k,v in kwargs.items():
125  if k == 'lines_x_prog':
127  if k == 'axes_type':
128  self.AXES_TYPE = v
129 
130  for i in range(len(self.AXES_TYPE)):
131  if self.AXES_TYPE[i] == 'T':
132  self.AXES_TRACK.append(i)
133  self.HAS_TRACK = True
134  elif self.AXES_TYPE[i] == 'J':
135  self.AXES_TURNTABLE.append(i)
136  self.HAS_TURNTABLE = True
137 
138  def ProgStart(self, progname, new_page = False):
139  progname = get_safe_name(progname)
140  progname_i = progname
141  if new_page:
142  #nPages = len(self.PROG_LIST)
143  if self.nPages == 0:
144  if len(self.PROG_NAMES_MAIN) > 0:
145  print("Can't split %s: Two or more programs are split into smaller programs" % progname)
146  print(self.PROG_NAMES_MAIN)
147  raise Exception("Only one program at a time can be split into smaller programs")
148  self.PROG_NAMES_MAIN.append(self.PROG_NAME) # add the first program in the list to be genrated as a subprogram call
149  self.nPages = self.nPages + 1
150 
151  self.nPages = self.nPages + 1
152  progname_i = "%s%i" % (self.PROG_NAME, self.nPages)
153  self.PROG_NAMES_MAIN.append(progname_i)
154 
155  else:
156  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
157  return
158  self.PROG_NAME = progname
159  self.nProgs = self.nProgs + 1
160  #self.PROG_NAMES = []
161 
162  self.PROG_NAME_CURRENT = progname_i
163  self.PROG_NAMES.append(progname_i)
164 
165  def ProgFinish(self, progname, new_page = False):
166  progname = get_safe_name(progname)
167  if not new_page:
168  # Reset page count
169  self.nPages = 0
170 
171  #if self.nPROGS > 1:
172  # # Fanuc does not support defining multiple programs in the same file, so one program per file
173  # return
174  header = ''
175  header = header + ('/PROG %s' % self.PROG_NAME_CURRENT) + '\n' # Use the latest name set at ProgStart
176  header = header + '/ATTR' + '\n'
177  header = header + 'OWNER\t\t= MNEDITOR;' + '\n'
178  header = header + 'COMMENT\t\t= "RoboDK sequence";' + '\n'
179  header = header + 'PROG_SIZE\t= 0;' + '\n'
180  header = header + 'CREATE\t\t= DATE 31-12-14 TIME 12:00:00;' + '\n'
181  header = header + 'MODIFIED\t= DATE 31-12-14 TIME 12:00:00;' + '\n'
182  header = header + 'FILE_NAME\t= ;' + '\n'
183  header = header + 'VERSION\t\t= 0;' + '\n'
184  header = header + ('LINE_COUNT\t= %i;' % (self.LINE_COUNT)) + '\n'
185  header = header + 'MEMORY_SIZE\t= 0;' + '\n'
186  header = header + 'PROTECT\t\t= READ_WRITE;' + '\n'
187  header = header + 'TCD: STACK_SIZE\t= 0,' + '\n'
188  header = header + ' TASK_PRIORITY\t= 50,' + '\n'
189  header = header + ' TIME_SLICE\t= 0,' + '\n'
190  header = header + ' BUSY_LAMP_OFF\t= 0,' + '\n'
191  header = header + ' ABORT_REQUEST\t= 0,' + '\n'
192  header = header + ' PAUSE_REQUEST\t= 0;' + '\n'
193  header = header + 'DEFAULT_GROUP\t= 1,*,*,*,*;' + '\n' #old controllers
194  #header = header + 'DEFAULT_GROUP\t= 1,*,*,*,*,*,*;' + '\n'
195  header = header + 'CONTROL_CODE\t= 00000000 00000000;' + '\n'
196  if self.HAS_TURNTABLE:
197  header = header + '/APPL' + '\n'
198  header = header + '' + '\n'
199  header = header + 'LINE_TRACK;' + '\n'
200  header = header + 'LINE_TRACK_SCHEDULE_NUMBER : 0;' + '\n'
201  header = header + 'LINE_TRACK_BOUNDARY_NUMBER : 0;' + '\n'
202  header = header + 'CONTINUE_TRACK_AT_PROG_END : FALSE;' + '\n'
203  header = header + '' + '\n'
204  header = header + '/MN'
205  #header = header + '/MN' + '\n' # Important! Last line should not have \n
206 
207  self.PROG.insert(0, header)
208  self.PROG.append('/POS')
209  self.PROG += self.PROG_TARGETS
210  self.PROG.append('/END')
211 
212  # Save PROG in PROG_LIST
213  self.PROG_LIST.append(self.PROG)
214  self.PROG = []
215  self.PROG_TARGETS = []
216  #self.nLines = 0
217  self.LINE_COUNT = 0
218  self.P_COUNT = 0
219  self.LBL_ID_COUNT = 0
220 
221  def progsave(self, folder, progname, ask_user = False, show_result = False):
222  print(folder)
223  if not folder.endswith('/'):
224  folder = folder + '/'
225  progname = progname + '.' + self.PROG_EXT
226  if ask_user or not DirExists(folder):
227  filesave = getSaveFile(folder, progname, 'Save program as...')
228  if filesave is not None:
229  filesave = filesave.name
230  else:
231  return
232  else:
233  filesave = folder + progname
234  fid = open(filesave, "w")
235  #fid.write(self.PROG)
236  for line in self.PROG:
237  fid.write(line)
238  fid.write('\n')
239  fid.close()
240  print('SAVED: %s\n' % filesave) # tell RoboDK the path of the saved file
241  self.PROG_FILES.append(filesave)
242 
243  # open file with default application
244  if show_result:
245  if type(show_result) is str:
246  # Open file with provided application
247  import subprocess
248  p = subprocess.Popen([show_result, filesave])
249  elif type(show_result) is list:
250  import subprocess
251  p = subprocess.Popen(show_result + [filesave])
252  else:
253  # open file with default application
254  import os
255  os.startfile(filesave)
256  #if len(self.LOG) > 0:
257  # mbox('Program generation LOG:\n\n' + self.LOG)
258  # -------- build with MakeTP ---------
259  # set robot first with setrobot.exe (delete robot.ini file)
260  PATH_MAKE_TP = 'C:/Program Files (x86)/FANUC/WinOLPC/bin/'
261  if FileExists(PATH_MAKE_TP + 'MakeTP.exe'):
262  filesave_TP = filesave[:-3] + '.TP'
263  print("POPUP: Compiling LS file with MakeTP.exe: %s..." % progname)
264  sys.stdout.flush()
265  import subprocess
266  command = [PATH_MAKE_TP + 'MakeTP.exe', filesave.replace('/','\\'), filesave_TP.replace('/','\\'), '/config', PATH_MAKE_TP + 'robot.ini']
267  #output = subprocess.check_output(command)
268  #self.LOG = output.decode('utf-8')
269  self.LOG += 'Program generation for: ' + progname + '\n'
270  with subprocess.Popen(command, stdout=subprocess.PIPE, bufsize=1, universal_newlines=True) as p:
271  for line in p.stdout:
272  line_ok = line.strip()
273  self.LOG += line_ok + '\n'
274  print("POPUP: " + line_ok)
275  sys.stdout.flush()
276  self.LOG += '\n'
277 
278 
279  def ProgSave(self, folder, progname, ask_user = False, show_result = False):
280  progname = get_safe_name(progname)
281  nfiles = len(self.PROG_LIST)
282  if nfiles >= 1:
283  if self.LINE_COUNT > 0:
284  # Progfinish was not called!
285  print("Warning: ProgFinish was not called properly")
286  self.PROG_LIST.append(self.PROG)
287  self.PROG_NAMES.append("Unknown")
288  self.PROG = []
289  self.LINE_COUNT = 0
290 
291  if len(self.PROG_NAMES_MAIN) > 1:
292  # Warning: the program might be cut to a maximum number of chars
293  progname_main = "M_" + self.PROG_NAMES_MAIN[0]
294  self.INCLUDE_SUB_PROGRAMS = True # Force generation of main program
295  self.ProgStart(progname_main)
296  for prog_call in self.PROG_NAMES_MAIN:
297  self.RunCode(prog_call, True)
298 
299  self.ProgFinish(progname_main)
300 
301  # Save the last program added to the PROG_LIST
302  self.PROG = self.PROG_LIST.pop()
303  progname_last = self.PROG_NAMES.pop()
304  self.progsave(folder, progname_last, ask_user, show_result)
305  #-------------------------
306  #self.LOG = ''
307  if len(self.PROG_FILES) == 0:
308  # cancelled by user
309  return
310 
311  first_file = self.PROG_FILES[0]
312  folder_user = getFileDir(first_file)
313  # progname_user = getFileName(self.FILE_SAVED)
314 
315  # Generate each program
316  for i in range(len(self.PROG_LIST)):
317  self.PROG = self.PROG_LIST[i]
318  self.progsave(folder_user, self.PROG_NAMES[i], False, show_result)
319 
320  elif nfiles == 1:
321  self.PROG = self.PROG_NAMES[0]
322  self.progsave(folder, progname, ask_user, show_result)
323 
324  else:
325  print("Warning! Program has not been properly finished")
326  self.progsave(folder, progname, ask_user, show_result)
327 
328  if show_result and len(self.LOG) > 0:
329  mbox('Program generation LOG:\n\n' + self.LOG)
330 
331  def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass):
332  """Send a program to the robot using the provided parameters. This method is executed right after ProgSave if we selected the option "Send Program to Robot".
333  The connection parameters must be provided in the robot connection menu of RoboDK"""
334  UploadFTP(self.PROG_FILES, robot_ip, remote_path, ftp_user, ftp_pass)
335 
336  def MoveJ(self, pose, joints, conf_RLF=None):
337  """Add a joint movement"""
338  self.page_size_control() # Important to control the maximum lines per program and not save last target on new program
339 
340  target_id = self.add_target_joints(pose, joints)
341  move_ins = 'P[%i] %s %s ;' % (target_id, self.JOINT_SPEED, self.CNT_VALUE)
342  self.addline(move_ins, 'J')
343  self.LAST_POSE = pose
344 
345  def MoveL(self, pose, joints, conf_RLF=None):
346  """Add a linear movement"""
347 
348  #if self.LAST_POSE is not None and pose is not None:
349  # # Skip adding a new movement if the new position is the same as the last one
350  # if distance(pose.Pos(), self.LAST_POSE.Pos()) < 0.1 and pose_angle_between(pose, self.LAST_POSE) < 0.1:
351  # return
352 
353  self.page_size_control() # Important to control the maximum lines per program and not save last target on new program
354 
355  if pose is None:
356  target_id = self.add_target_joints(pose, joints)
357  move_ins = 'P[%i] %s %s ;' % (target_id, self.SPEED, self.CNT_VALUE)
358  else:
359  target_id = self.add_target_cartesian(pose, joints, conf_RLF)
360  move_ins = 'P[%i] %s %s ;' % (target_id, self.SPEED, self.CNT_VALUE)
361 
362  self.addline(move_ins, 'L')
363  self.LAST_POSE = pose
364 
365  def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None):
366  """Add a circular movement"""
367  self.page_size_control() # Important to control the maximum lines per program and not save last target on new program
368 
369  target_id1 = self.add_target_cartesian(pose1, joints1, conf_RLF_1)
370  target_id2 = self.add_target_cartesian(pose2, joints2, conf_RLF_2)
371  move_ins = 'P[%i] \n P[%i] %s %s ;' % (target_id1, target_id2, self.SPEED, self.CNT_VALUE)
372  self.addline(move_ins, 'C')
373  self.LAST_POSE = pose2
374 
375  def setFrame(self, pose, frame_id=None, frame_name=None):
376  """Change the robot reference frame"""
377  xyzwpr = Pose_2_Fanuc(pose)
378  if frame_id is None or frame_id < 0:
379  for i in range(6):
380  self.addline('PR[%i,%i]=%.3f ;' % (self.SPARE_PR, i+1, xyzwpr[i]))
381  for i in range(6,self.nAxes):
382  self.addline('PR[%i,%i]=%.3f ;' % (self.SPARE_PR, i+1, 0))
383  self.addline('UFRAME[%i]=PR[%i] ;' % (self.ACTIVE_UF, self.SPARE_PR))
384  self.addline('UFRAME_NUM=%i ;' % (self.ACTIVE_UF))
385  else:
386  self.ACTIVE_UF = frame_id
387  self.addline('UFRAME_NUM=%i ;' % (self.ACTIVE_UF))
388  self.RunMessage('UF%i:%.1f,%.1f,%.1f,%.1f,%.1f,%.1f' % (frame_id, xyzwpr[0], xyzwpr[1], xyzwpr[2], xyzwpr[3], xyzwpr[4], xyzwpr[5]), True)
389 
390  def setTool(self, pose, tool_id=None, tool_name=None):
391  """Change the robot TCP"""
392  xyzwpr = Pose_2_Fanuc(pose)
393  if tool_id is None or tool_id < 0:
394  for i in range(6):
395  self.addline('PR[%i,%i]=%.3f ;' % (self.SPARE_PR, i+1, xyzwpr[i]))
396  for i in range(6,self.nAxes):
397  self.addline('PR[%i,%i]=%.3f ;' % (self.SPARE_PR, i+1, 0))
398  self.addline('UTOOL[%i]=PR[%i] ;' % (self.ACTIVE_UT, self.SPARE_PR))
399  self.addline('UTOOL_NUM=%i ;' % (self.ACTIVE_UT))
400  else:
401  self.ACTIVE_UT = tool_id
402  self.addline('UTOOL_NUM=%i ;' % (self.ACTIVE_UT))
403  self.RunMessage('UT%i:%.1f,%.1f,%.1f,%.1f,%.1f,%.1f' % (tool_id, xyzwpr[0], xyzwpr[1], xyzwpr[2], xyzwpr[3], xyzwpr[4], xyzwpr[5]), True)
404 
405  def Pause(self, time_ms):
406  """Pause the robot program"""
407  if time_ms <= 0:
408  self.addline('PAUSE ;')
409  else:
410  self.addline('WAIT %.2f(sec) ;' % (time_ms*0.001))
411 
412  def setSpeed(self, speed_mms):
413  """Changes the robot speed (in mm/s)"""
414  if self.SPEED_BACKUP is None:
415  # Set the normal speed
416  self.SPEED = '%.0fmm/sec' % max(speed_mms, 0.01)
417  # assume 5000 mm/s as 100%
418  self.JOINT_SPEED = '%.0f%%' % max(min(100.0*speed_mms/5000.0, 100.0), 1) # Saturate percentage speed between 1 and 100
419 
420  else:
421  # Do not alter the speed as we are in ARC movement mode
422  # skip speed settings if it has been overriden
423  self.SPEED_BACKUP = '%.0fmm/sec' % max(speed_mms, 0.01)
424  # assume 5000 mm/s as 100%
425  self.JOINT_SPEED = '%.0f%%' % max(min(100.0*speed_mms/5000.0, 100.0), 1) # Saturate percentage speed between 1 and 100
426 
427  def setAcceleration(self, accel_mmss):
428  """Changes the robot acceleration (in mm/s2)"""
429  self.addlog('setAcceleration not defined')
430 
431  def setSpeedJoints(self, speed_degs):
432  """Changes the robot joint speed (in deg/s)"""
433  self.addlog('setSpeedJoints not defined')
434 
435  def setAccelerationJoints(self, accel_degss):
436  """Changes the robot joint acceleration (in deg/s2)"""
437  self.addlog('setAccelerationJoints not defined')
438 
439  def setZoneData(self, zone_mm):
440  """Changes the zone data approach (makes the movement more smooth)"""
441  if zone_mm < 0:
442  self.CNT_VALUE = 'FINE'
443  else:
444  self.CNT_VALUE = 'CNT%i' % round(min(zone_mm, 100.0))
445 
446  def setDO(self, io_var, io_value):
447  """Sets a variable (output) to a given value"""
448  if type(io_var) != str: # set default variable name if io_var is a number
449  io_var = 'DO[%s]' % str(io_var)
450  if type(io_value) != str: # set default variable value if io_value is a number
451  if io_value > 0:
452  io_value = 'ON'
453  else:
454  io_value = 'OFF'
455 
456  # at this point, io_var and io_value must be string values
457  self.addline('%s=%s ;' % (io_var, io_value))
458 
459  def waitDI(self, io_var, io_value, timeout_ms=-1):
460  """Waits for an input io_var to attain a given value io_value. Optionally, a timeout can be provided."""
461  if type(io_var) != str: # set default variable name if io_var is a number
462  io_var = 'DI[%s]' % str(io_var)
463  if type(io_value) != str: # set default variable value if io_value is a number
464  if io_value > 0:
465  io_value = 'ON'
466  else:
467  io_value = 'OFF'
468 
469  # at this point, io_var and io_value must be string values
470  if timeout_ms < 0:
471  self.addline('WAIT %s=%s ;' % (io_var, io_value))
472  else:
473  self.LBL_ID_COUNT = self.LBL_ID_COUNT + 1
474  self.addline('$WAITTMOUT=%i ;' % round(timeout_ms))
475  self.addline('WAIT %s=%s TIMEOUT, LBL[%i] ;' % (io_var, io_value, self.LBL_ID_COUNT))
476  self.addline('MESSAGE[Timed out for LBL %i] ;' % self.LBL_ID_COUNT)
477  self.addline('PAUSE ;')
478  self.addline('LBL[%i] ;' % self.LBL_ID_COUNT)
479 
480  def addlastline(self, add_params):
481  """Add parameters to the last command"""
482  if len(self.PROG) > 0 and self.PROG[-1].endswith(';\n'):
483  self.PROG[-1] = self.PROG[-1][:-2] + add_params + ';' # remove last 2 characters
484 
485  def RunCode(self, code, is_function_call = False):
486  """Adds code or a function call"""
487  if is_function_call:
488  code = get_safe_name(code, 12)
489  if code.startswith("ArcStart"):
490  if not code.endswith(')'):
491  code = code + '()'
492 
493  self.ARC_PARAMS = code[9:-1]
494  if len(self.ARC_PARAMS) < 1:
495  # Use default sine wave parameters
496  self.ARC_PARAMS = '2.0Hz,8.0mm,0.075s,0.075'
497 
498  # use desired weld speed:
499  self.SPEED_BACKUP = self.SPEED
500  self.SPEED = 'WELD_SPEED'
501 
502  # Provoke ARC START:
503  self.addlastline('Arc Start[11]')
504 
505  # Tune weave with parameters
506  self.addline('Weave Sine[%s] ;' % self.ARC_PARAMS)
507  return # Do not generate default program call
508  elif code.startswith("ArcEnd"):
509  # Provoke ARC END:
510  self.addlastline('Arc End[11]')
511 
512  # Revert to desired speed
513  self.SPEED = self.SPEED_BACKUP
514  self.SPEED_BACKUP = None
515 
516  self.ARC_PARAMS = None
517  return # Do not generate default program call
518 
519  # default program call
520  code.replace(' ','_')
521  self.addline('CALL %s ;' % (code))
522  else:
523  if not code.endswith(';'):
524  code = code + ';'
525  self.addline(code)
526 
527  def RunMessage(self, message, iscomment = False):
528  """Add a joint movement"""
529  if iscomment:
530  #pass
531  for i in range(0,len(message), 20):
532  i2 = min(i + 20, len(message))
533  self.addline('! %s ;' % message[i:i2])
534 
535  else:
536  for i in range(0,len(message), 20):
537  i2 = min(i + 20, len(message))
538  self.addline('MESSAGE[%s] ;' % message[i:i2])
539 
540 # ------------------ private ----------------------
541  def page_size_control(self):
542  if self.LINE_COUNT >= self.MAX_LINES_X_PROG:
543  #self.nLines = 0
544  self.ProgFinish(self.PROG_NAME, True)
545  self.ProgStart(self.PROG_NAME, True)
546 
547 
548  def addline(self, newline, movetype = ' '):
549  """Add a program line"""
550  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
551  return
552 
553  self.page_size_control()
554 
555  self.LINE_COUNT = self.LINE_COUNT + 1
556  newline_ok = ('%4i:%s ' % (self.LINE_COUNT, movetype)) + newline
557  self.PROG.append(newline_ok)
558 
559  def addline_targets(self, newline):
560  """Add a line at the end of the program (used for targets)"""
561  self.PROG_TARGETS.append(newline)
562 
563  def addlog(self, newline):
564  """Add a log message"""
565  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
566  return
567  self.LOG = self.LOG + newline + '\n'
568 
569 # ------------------ targets ----------------------
570  def add_target_joints(self, pose, joints):
571  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
572  return
573  self.P_COUNT = self.P_COUNT + 1
574  add_comma = ""
575  if self.HAS_TRACK:
576  add_comma = ","
577  self.addline_targets('P[%i]{' % self.P_COUNT)
578  self.addline_targets(' GP1:')
579  self.addline_targets(' UF : %i, UT : %i, ' % (self.ACTIVE_UF, self.ACTIVE_UT))
580  self.addline_targets('\tJ1= %.3f deg,\tJ2= %.3f deg,\tJ3= %.3f deg,' % (joints[0], joints[1], joints[2]))
581  self.addline_targets('\tJ4= %.3f deg,\tJ5= %.3f deg,\tJ6= %.3f deg%s' % (joints[3], joints[4], joints[5], add_comma))
582  if self.HAS_TRACK:
583  # adding external axes (linear track):
584  track_str = ''
585  for i in range(len(self.AXES_TRACK)):
586  track_str = track_str + '\tE%i=%10.3f mm,' % (i+1, joints[self.AXES_TRACK[i]])
587  track_str = track_str[:-1]
588  self.addline_targets(track_str)
589  if self.HAS_TURNTABLE:
590  # adding rotative axes (turntable):
591  self.addline_targets(' GP2:')
592  self.addline_targets(' UF : %i, UT : %i,' % (self.ACTIVE_UF, self.ACTIVE_UT))
593  turntable_str = ''
594  for i in range(len(self.AXES_TURNTABLE)):
595  turntable_str = turntable_str + '\tJ%i=%10.3f deg,' % (i+1, joints[self.AXES_TURNTABLE[i]])
596  turntable_str = turntable_str[:-1]
597  self.addline_targets(turntable_str)
598  self.addline_targets('};')
599  return self.P_COUNT
600 
601  def add_target_cartesian(self, pose, joints, conf_RLF=None):
602  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
603  return
604  def angle_2_turn(angle):
605  if angle >= 0.0:
606  return +math.floor((+angle+180.0)/360.0)
607  else:
608  return -math.floor((-angle+180.0)/360.0)
609  #return add_target_joints(pose, joints) # using joints as targets is safer to avoid problems setting up the reference frame and configurations
610  xyzwpr = Pose_2_Fanuc(pose)
611  config = ['N','U','T'] #normal
612  #config= ['F','D','B'] #alternative
613  if conf_RLF is not None:
614  if conf_RLF[2] > 0:
615  config[0] = 'F' # F means axis 5 >= 0, N means axis 5 < 0
616  if conf_RLF[1] > 0:
617  config[1] = 'D'
618  if conf_RLF[0] > 0:
619  config[2] = 'B'
620 
621  turnJ1 = angle_2_turn(joints[0])
622  turnJ4 = angle_2_turn(joints[3])
623  turnJ6 = angle_2_turn(joints[5])
624 
625  self.P_COUNT = self.P_COUNT + 1
626  add_comma = ""
627  if self.HAS_TRACK:
628  add_comma = ","
629  self.addline_targets('P[%i]{' % self.P_COUNT)
630  self.addline_targets(' GP1:')
631  self.addline_targets(' UF : %i, UT : %i, CONFIG : \'%c %c %c, %i, %i, %i\',' % (self.ACTIVE_UF, self.ACTIVE_UT, config[0], config[1], config[2], turnJ1, turnJ4, turnJ6))
632  self.addline_targets('\tX =%10.3f mm,\tY =%10.3f mm,\tZ =%10.3f mm,' % (xyzwpr[0], xyzwpr[1], xyzwpr[2]))
633  self.addline_targets('\tW =%10.3f deg,\tP =%10.3f deg,\tR =%10.3f deg%s' % (xyzwpr[3], xyzwpr[4], xyzwpr[5], add_comma))
634  if self.HAS_TRACK:
635  # adding external axes (linear track):
636  track_str = ''
637  for i in range(len(self.AXES_TRACK)):
638  track_str = track_str + '\tE%i=%10.3f mm,' % (i+1, joints[self.AXES_TRACK[i]])
639  track_str = track_str[:-1]
640  self.addline_targets(track_str)
641  if self.HAS_TURNTABLE:
642  # adding rotative axes (turntable):
643  self.addline_targets(' GP2:')
644  self.addline_targets(' UF : %i, UT : %i,' % (self.ACTIVE_UF, self.ACTIVE_UT))
645  turntable_str = ''
646  for i in range(len(self.AXES_TURNTABLE)):
647  turntable_str = turntable_str + '\tJ%i=%10.3f deg,' % (i+1, joints[self.AXES_TURNTABLE[i]])
648  turntable_str = turntable_str[:-1]
649  self.addline_targets(turntable_str)
650  self.addline_targets('};')
651  return self.P_COUNT
652 
653 # syntax examples for joint-defined targets:
654 #P[1]{
655 # GP1:
656 # UF : 1, UT : 1,
657 # J1= 0.000 deg, J2= -40.966 deg, J3= 43.328 deg,
658 # J4= 0.000 deg, J5= -84.792 deg, J6= 180.000 deg
659 #};
660 #P[258]{
661 # GP1:
662 # UF : 6, UT : 4,
663 # J1= -41.180 deg, J2= -26.810 deg, J3= 11.060 deg,
664 # J4= -217.400 deg, J5= 71.740 deg, J6= 85.790 deg,
665 # E1= 0.000 deg
666 #};
667 
668 # syntax examples for cartesian targets:
669 #P[2]{
670 # GP1:
671 # UF : 1, UT : 1, CONFIG : 'F U T, 0, 0, 0',
672 # X = 564.871 mm, Y = 0.000 mm, Z = 571.832 mm,
673 # W = -180.000 deg, P = 0.000 deg, R = -180.000 deg
674 #};
675 #P[8:]{
676 # GP1:
677 # UF : 9, UT : 8, CONFIG : 'N D B, 0, 0, 0',
678 # X = 0.000 mm, Y = -10.000 mm, Z = 0.000 mm,
679 # W = 0.000 deg, P = 0.000 deg, R = 0.000 deg
680 # GP2:
681 # UF : 9, UT : 2,
682 # J1= 0.000 deg, J2= 0.000 deg
683 #};
684 
685 
686 
687 # -------------------------------------------------
688 # ------------ For testing purposes ---------------
689 def Pose(xyzrpw):
690  [x,y,z,r,p,w] = xyzrpw
691  a = r*math.pi/180
692  b = p*math.pi/180
693  c = w*math.pi/180
694  ca = math.cos(a)
695  sa = math.sin(a)
696  cb = math.cos(b)
697  sb = math.sin(b)
698  cc = math.cos(c)
699  sc = math.sin(c)
700  return Mat([[cb*ca, ca*sc*sb - cc*sa, sc*sa + cc*ca*sb, x],[cb*sa, cc*ca + sc*sb*sa, cc*sb*sa - ca*sc, y],[-sb, cb*sc, cc*cb, z],[0,0,0,1]])
701 
702 def test_post():
703  """Test the post with a basic program"""
704 
705  robot = RobotPost('Fanuc_custom', 'Fanuc robot', 6)
706 
707  robot.ProgStart("Program")
708  robot.RunMessage("Program generated by RoboDK", True)
709  robot.setFrame(Pose([807.766544, -963.699898, 41.478944, 0, 0, 0]))
710  robot.setTool(Pose([62.5, -108.253175, 100, -60, 90, 0]))
711  robot.MoveJ(Pose([200, 200, 500, 180, 0, 180]), [-46.18419, -6.77518, -20.54925, 71.38674, 49.58727, -302.54752] )
712  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
713  robot.MoveL(Pose([200, 200, 262.132034, 180, 0, -150]), [-43.73892, -3.91728, -35.77935, 58.57566, 54.11615, -253.81122] )
714  robot.RunMessage("Setting air valve 1 on")
715  robot.RunCode("TCP_On", True)
716  robot.Pause(1000)
717  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
718  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
719  robot.MoveL(Pose([250, 250, 191.421356, 180, 0, -150]), [-39.75778, -1.04537, -40.37883, 52.09118, 54.15317, -246.94403] )
720  robot.RunMessage("Setting air valve off")
721  robot.RunCode("TCP_Off", True)
722  robot.Pause(1000)
723  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
724  robot.MoveL(Pose([250, 200, 278.023897, 180, 0, -150]), [-41.85389, -1.95619, -34.89154, 57.43912, 52.34162, -253.73403] )
725  robot.MoveL(Pose([250, 150, 191.421356, 180, 0, -150]), [-43.82111, 3.29703, -40.29493, 56.02402, 56.61169, -249.23532] )
726  robot.ProgFinish("Program")
727  # robot.ProgSave(".","Program",True)
728 
729  robot.PROG = robot.PROG_LIST.pop()
730  for line in robot.PROG:
731  print(line)
732 
733  if len(robot.LOG) > 0:
734  mbox('Program generation LOG:\n\n' + robot.LOG)
735 
736  input("Press Enter to close...")
737 
738 if __name__ == "__main__":
739  """Function to call when the module is executed by itself: test"""
740  test_post()
def setFrame(self, pose, frame_id=None, frame_name=None)
Definition: Fanuc_RJ3.py:375
def setTool(self, pose, tool_id=None, tool_name=None)
Definition: Fanuc_RJ3.py:390
def MoveL(self, pose, joints, conf_RLF=None)
Definition: Fanuc_RJ3.py:345
def ProgStart(self, progname, new_page=False)
Definition: Fanuc_RJ3.py:138
def get_safe_name(progname, max_chars=10)
Definition: Fanuc_RJ3.py:44
def ProgFinish(self, progname, new_page=False)
Definition: Fanuc_RJ3.py:165
def ProgSave(self, folder, progname, ask_user=False, show_result=False)
Definition: Fanuc_RJ3.py:279
def UploadFTP(program, robot_ip, remote_path, ftp_user, ftp_pass)
Definition: robodk.py:1312
def addline(self, newline, movetype=' ')
Definition: Fanuc_RJ3.py:548
def __init__(self, robotpost=None, robotname=None, robot_axes=6, kwargs)
Definition: Fanuc_RJ3.py:117
def mbox(msg, b1='OK', b2='Cancel', frame=True, t=False, entry=None)
Definition: robodk.py:1458
def add_target_cartesian(self, pose, joints, conf_RLF=None)
Definition: Fanuc_RJ3.py:601
def progsave(self, folder, progname, ask_user=False, show_result=False)
Definition: Fanuc_RJ3.py:221
def RunMessage(self, message, iscomment=False)
Definition: Fanuc_RJ3.py:527
def waitDI(self, io_var, io_value, timeout_ms=-1)
Definition: Fanuc_RJ3.py:459
def RunCode(self, code, is_function_call=False)
Definition: Fanuc_RJ3.py:485
def MoveJ(self, pose, joints, conf_RLF=None)
Definition: Fanuc_RJ3.py:336
def getSaveFile(strdir='C:\\', strfile='file.txt', strtitle='Save file as ...')
Definition: robodk.py:1354
def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None)
Definition: Fanuc_RJ3.py:365
def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass)
Definition: Fanuc_RJ3.py:331


ros_robodk_post_processors
Author(s): Victor Lamoine - Institut Maupertuis
autogenerated on Sun Jun 7 2020 03:50:22