Fanuc_R30iA.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  self.JOINT_SPEED = '%.0f%%' % max(min(100.0*speed_degs/200.0, 100.0), 1) # Saturate percentage speed between 1 and 100
435 
436  def setAccelerationJoints(self, accel_degss):
437  """Changes the robot joint acceleration (in deg/s2)"""
438  self.addlog('setAccelerationJoints not defined')
439 
440  def setZoneData(self, zone_mm):
441  """Changes the zone data approach (makes the movement more smooth)"""
442  if zone_mm < 0:
443  self.CNT_VALUE = 'FINE'
444  else:
445  self.CNT_VALUE = 'CNT%i' % round(min(zone_mm, 100.0))
446 
447  def setDO(self, io_var, io_value):
448  """Sets a variable (output) to a given value"""
449  if type(io_var) != str: # set default variable name if io_var is a number
450  io_var = 'DO[%s]' % str(io_var)
451  if type(io_value) != str: # set default variable value if io_value is a number
452  if io_value > 0:
453  io_value = 'ON'
454  else:
455  io_value = 'OFF'
456 
457  # at this point, io_var and io_value must be string values
458  self.addline('%s=%s ;' % (io_var, io_value))
459 
460  def waitDI(self, io_var, io_value, timeout_ms=-1):
461  """Waits for an input io_var to attain a given value io_value. Optionally, a timeout can be provided."""
462  if type(io_var) != str: # set default variable name if io_var is a number
463  io_var = 'DI[%s]' % str(io_var)
464  if type(io_value) != str: # set default variable value if io_value is a number
465  if io_value > 0:
466  io_value = 'ON'
467  else:
468  io_value = 'OFF'
469 
470  # at this point, io_var and io_value must be string values
471  if timeout_ms < 0:
472  self.addline('WAIT %s=%s ;' % (io_var, io_value))
473  else:
474  self.LBL_ID_COUNT = self.LBL_ID_COUNT + 1
475  self.addline('$WAITTMOUT=%i ;' % round(timeout_ms))
476  self.addline('WAIT %s=%s TIMEOUT, LBL[%i] ;' % (io_var, io_value, self.LBL_ID_COUNT))
477  self.addline('MESSAGE[Timed out for LBL %i] ;' % self.LBL_ID_COUNT)
478  self.addline('PAUSE ;')
479  self.addline('LBL[%i] ;' % self.LBL_ID_COUNT)
480 
481  def addlastline(self, add_params):
482  """Add parameters to the last command"""
483  if len(self.PROG) > 0 and self.PROG[-1].endswith(';\n'):
484  self.PROG[-1] = self.PROG[-1][:-2] + add_params + ';' # remove last 2 characters
485 
486  def RunCode(self, code, is_function_call = False):
487  """Adds code or a function call"""
488  if is_function_call:
489  code = get_safe_name(code, 12)
490  if code.startswith("ArcStart"):
491  if not code.endswith(')'):
492  code = code + '()'
493 
494  self.ARC_PARAMS = code[9:-1]
495  if len(self.ARC_PARAMS) < 1:
496  # Use default sine wave parameters
497  self.ARC_PARAMS = '2.0Hz,8.0mm,0.075s,0.075'
498 
499  # use desired weld speed:
500  self.SPEED_BACKUP = self.SPEED
501  self.SPEED = 'WELD_SPEED'
502 
503  # Provoke ARC START:
504  self.addlastline('Arc Start[11]')
505 
506  # Tune weave with parameters
507  self.addline('Weave Sine[%s] ;' % self.ARC_PARAMS)
508  return # Do not generate default program call
509  elif code.startswith("ArcEnd"):
510  # Provoke ARC END:
511  self.addlastline('Arc End[11]')
512 
513  # Revert to desired speed
514  self.SPEED = self.SPEED_BACKUP
515  self.SPEED_BACKUP = None
516 
517  self.ARC_PARAMS = None
518  return # Do not generate default program call
519 
520  # default program call
521  code.replace(' ','_')
522  self.addline('CALL %s ;' % (code))
523  else:
524  if not code.endswith(';'):
525  code = code + ';'
526  self.addline(code)
527 
528  def RunMessage(self, message, iscomment = False):
529  """Add a joint movement"""
530  if iscomment:
531  #pass
532  for i in range(0,len(message), 20):
533  i2 = min(i + 20, len(message))
534  self.addline('! %s ;' % message[i:i2])
535 
536  else:
537  for i in range(0,len(message), 20):
538  i2 = min(i + 20, len(message))
539  self.addline('MESSAGE[%s] ;' % message[i:i2])
540 
541 # ------------------ private ----------------------
542  def page_size_control(self):
543  if self.LINE_COUNT >= self.MAX_LINES_X_PROG:
544  #self.nLines = 0
545  self.ProgFinish(self.PROG_NAME, True)
546  self.ProgStart(self.PROG_NAME, True)
547 
548 
549  def addline(self, newline, movetype = ' '):
550  """Add a program line"""
551  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
552  return
553 
554  self.page_size_control()
555 
556  self.LINE_COUNT = self.LINE_COUNT + 1
557  newline_ok = ('%4i:%s ' % (self.LINE_COUNT, movetype)) + newline
558  self.PROG.append(newline_ok)
559 
560  def addline_targets(self, newline):
561  """Add a line at the end of the program (used for targets)"""
562  self.PROG_TARGETS.append(newline)
563 
564  def addlog(self, newline):
565  """Add a log message"""
566  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
567  return
568  self.LOG = self.LOG + newline + '\n'
569 
570 # ------------------ targets ----------------------
571  def add_target_joints(self, pose, joints):
572  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
573  return
574  self.P_COUNT = self.P_COUNT + 1
575  add_comma = ""
576  if self.HAS_TRACK:
577  add_comma = ","
578  self.addline_targets('P[%i]{' % self.P_COUNT)
579  self.addline_targets(' GP1:')
580  self.addline_targets(' UF : %i, UT : %i, ' % (self.ACTIVE_UF, self.ACTIVE_UT))
581  self.addline_targets('\tJ1= %.3f deg,\tJ2= %.3f deg,\tJ3= %.3f deg,' % (joints[0], joints[1], joints[2]))
582  self.addline_targets('\tJ4= %.3f deg,\tJ5= %.3f deg,\tJ6= %.3f deg%s' % (joints[3], joints[4], joints[5], add_comma))
583  if self.HAS_TRACK:
584  # adding external axes (linear track):
585  track_str = ''
586  for i in range(len(self.AXES_TRACK)):
587  track_str = track_str + '\tE%i=%10.3f mm,' % (i+1, joints[self.AXES_TRACK[i]])
588  track_str = track_str[:-1]
589  self.addline_targets(track_str)
590  if self.HAS_TURNTABLE:
591  # adding rotative axes (turntable):
592  self.addline_targets(' GP2:')
593  self.addline_targets(' UF : %i, UT : %i,' % (self.ACTIVE_UF, self.ACTIVE_UT))
594  turntable_str = ''
595  for i in range(len(self.AXES_TURNTABLE)):
596  turntable_str = turntable_str + '\tJ%i=%10.3f deg,' % (i+1, joints[self.AXES_TURNTABLE[i]])
597  turntable_str = turntable_str[:-1]
598  self.addline_targets(turntable_str)
599  self.addline_targets('};')
600  return self.P_COUNT
601 
602  def add_target_cartesian(self, pose, joints, conf_RLF=None):
603  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
604  return
605  def angle_2_turn(angle):
606  if angle >= 0.0:
607  return +math.floor((+angle+180.0)/360.0)
608  else:
609  return -math.floor((-angle+180.0)/360.0)
610  #return add_target_joints(pose, joints) # using joints as targets is safer to avoid problems setting up the reference frame and configurations
611  xyzwpr = Pose_2_Fanuc(pose)
612  config = ['N','U','T'] #normal
613  #config= ['F','D','B'] #alternative
614  if conf_RLF is not None:
615  if conf_RLF[2] > 0:
616  config[0] = 'F' # F means axis 5 >= 0, N means axis 5 < 0
617  if conf_RLF[1] > 0:
618  config[1] = 'D'
619  if conf_RLF[0] > 0:
620  config[2] = 'B'
621 
622  turnJ1 = angle_2_turn(joints[0])
623  turnJ4 = angle_2_turn(joints[3])
624  turnJ6 = angle_2_turn(joints[5])
625 
626  self.P_COUNT = self.P_COUNT + 1
627  add_comma = ""
628  if self.HAS_TRACK:
629  add_comma = ","
630  self.addline_targets('P[%i]{' % self.P_COUNT)
631  self.addline_targets(' GP1:')
632  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))
633  self.addline_targets('\tX =%10.3f mm,\tY =%10.3f mm,\tZ =%10.3f mm,' % (xyzwpr[0], xyzwpr[1], xyzwpr[2]))
634  self.addline_targets('\tW =%10.3f deg,\tP =%10.3f deg,\tR =%10.3f deg%s' % (xyzwpr[3], xyzwpr[4], xyzwpr[5], add_comma))
635  if self.HAS_TRACK:
636  # adding external axes (linear track):
637  track_str = ''
638  for i in range(len(self.AXES_TRACK)):
639  track_str = track_str + '\tE%i=%10.3f mm,' % (i+1, joints[self.AXES_TRACK[i]])
640  track_str = track_str[:-1]
641  self.addline_targets(track_str)
642  if self.HAS_TURNTABLE:
643  # adding rotative axes (turntable):
644  self.addline_targets(' GP2:')
645  self.addline_targets(' UF : %i, UT : %i,' % (self.ACTIVE_UF, self.ACTIVE_UT))
646  turntable_str = ''
647  for i in range(len(self.AXES_TURNTABLE)):
648  turntable_str = turntable_str + '\tJ%i=%10.3f deg,' % (i+1, joints[self.AXES_TURNTABLE[i]])
649  turntable_str = turntable_str[:-1]
650  self.addline_targets(turntable_str)
651  self.addline_targets('};')
652  return self.P_COUNT
653 
654 # syntax examples for joint-defined targets:
655 #P[1]{
656 # GP1:
657 # UF : 1, UT : 1,
658 # J1= 0.000 deg, J2= -40.966 deg, J3= 43.328 deg,
659 # J4= 0.000 deg, J5= -84.792 deg, J6= 180.000 deg
660 #};
661 #P[258]{
662 # GP1:
663 # UF : 6, UT : 4,
664 # J1= -41.180 deg, J2= -26.810 deg, J3= 11.060 deg,
665 # J4= -217.400 deg, J5= 71.740 deg, J6= 85.790 deg,
666 # E1= 0.000 deg
667 #};
668 
669 # syntax examples for cartesian targets:
670 #P[2]{
671 # GP1:
672 # UF : 1, UT : 1, CONFIG : 'F U T, 0, 0, 0',
673 # X = 564.871 mm, Y = 0.000 mm, Z = 571.832 mm,
674 # W = -180.000 deg, P = 0.000 deg, R = -180.000 deg
675 #};
676 #P[8:]{
677 # GP1:
678 # UF : 9, UT : 8, CONFIG : 'N D B, 0, 0, 0',
679 # X = 0.000 mm, Y = -10.000 mm, Z = 0.000 mm,
680 # W = 0.000 deg, P = 0.000 deg, R = 0.000 deg
681 # GP2:
682 # UF : 9, UT : 2,
683 # J1= 0.000 deg, J2= 0.000 deg
684 #};
685 
686 
687 
688 # -------------------------------------------------
689 # ------------ For testing purposes ---------------
690 def Pose(xyzrpw):
691  [x,y,z,r,p,w] = xyzrpw
692  a = r*math.pi/180
693  b = p*math.pi/180
694  c = w*math.pi/180
695  ca = math.cos(a)
696  sa = math.sin(a)
697  cb = math.cos(b)
698  sb = math.sin(b)
699  cc = math.cos(c)
700  sc = math.sin(c)
701  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]])
702 
703 def test_post():
704  """Test the post with a basic program"""
705 
706  robot = RobotPost('Fanuc_custom', 'Fanuc robot', 6)
707 
708  robot.ProgStart("Program")
709  robot.RunMessage("Program generated by RoboDK", True)
710  robot.setFrame(Pose([807.766544, -963.699898, 41.478944, 0, 0, 0]))
711  robot.setTool(Pose([62.5, -108.253175, 100, -60, 90, 0]))
712  robot.MoveJ(Pose([200, 200, 500, 180, 0, 180]), [-46.18419, -6.77518, -20.54925, 71.38674, 49.58727, -302.54752] )
713  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
714  robot.MoveL(Pose([200, 200, 262.132034, 180, 0, -150]), [-43.73892, -3.91728, -35.77935, 58.57566, 54.11615, -253.81122] )
715  robot.RunMessage("Setting air valve 1 on")
716  robot.RunCode("TCP_On", True)
717  robot.Pause(1000)
718  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
719  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
720  robot.MoveL(Pose([250, 250, 191.421356, 180, 0, -150]), [-39.75778, -1.04537, -40.37883, 52.09118, 54.15317, -246.94403] )
721  robot.RunMessage("Setting air valve off")
722  robot.RunCode("TCP_Off", True)
723  robot.Pause(1000)
724  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
725  robot.MoveL(Pose([250, 200, 278.023897, 180, 0, -150]), [-41.85389, -1.95619, -34.89154, 57.43912, 52.34162, -253.73403] )
726  robot.MoveL(Pose([250, 150, 191.421356, 180, 0, -150]), [-43.82111, 3.29703, -40.29493, 56.02402, 56.61169, -249.23532] )
727  robot.ProgFinish("Program")
728  # robot.ProgSave(".","Program",True)
729 
730  robot.PROG = robot.PROG_LIST.pop()
731  for line in robot.PROG:
732  print(line)
733 
734  if len(robot.LOG) > 0:
735  mbox('Program generation LOG:\n\n' + robot.LOG)
736 
737  input("Press Enter to close...")
738 
739 if __name__ == "__main__":
740  """Function to call when the module is executed by itself: test"""
741  test_post()
def add_target_cartesian(self, pose, joints, conf_RLF=None)
Definition: Fanuc_R30iA.py:602
def waitDI(self, io_var, io_value, timeout_ms=-1)
Definition: Fanuc_R30iA.py:460
def UploadFTP(program, robot_ip, remote_path, ftp_user, ftp_pass)
Definition: robodk.py:1312
def get_safe_name(progname, max_chars=10)
Definition: Fanuc_R30iA.py:44
def RunMessage(self, message, iscomment=False)
Definition: Fanuc_R30iA.py:528
def MoveL(self, pose, joints, conf_RLF=None)
Definition: Fanuc_R30iA.py:345
def progsave(self, folder, progname, ask_user=False, show_result=False)
Definition: Fanuc_R30iA.py:221
def addline(self, newline, movetype=' ')
Definition: Fanuc_R30iA.py:549
def mbox(msg, b1='OK', b2='Cancel', frame=True, t=False, entry=None)
Definition: robodk.py:1458
def setTool(self, pose, tool_id=None, tool_name=None)
Definition: Fanuc_R30iA.py:390
def __init__(self, robotpost=None, robotname=None, robot_axes=6, kwargs)
Definition: Fanuc_R30iA.py:117
def ProgFinish(self, progname, new_page=False)
Definition: Fanuc_R30iA.py:165
def ProgStart(self, progname, new_page=False)
Definition: Fanuc_R30iA.py:138
def MoveJ(self, pose, joints, conf_RLF=None)
Definition: Fanuc_R30iA.py:336
def getSaveFile(strdir='C:\\', strfile='file.txt', strtitle='Save file as ...')
Definition: robodk.py:1354
def RunCode(self, code, is_function_call=False)
Definition: Fanuc_R30iA.py:486
def setFrame(self, pose, frame_id=None, frame_name=None)
Definition: Fanuc_R30iA.py:375
def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None)
Definition: Fanuc_R30iA.py:365
def ProgSave(self, folder, progname, ask_user=False, show_result=False)
Definition: Fanuc_R30iA.py:279
def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass)
Definition: Fanuc_R30iA.py:331


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