KUKA_KRC2.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 Kuka 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 # ----------------------------------------------------
45 # Import RoboDK tools
46 from robodk import *
47 
48 
49 HEADER = '''
50 EXT BAS (BAS_COMMAND :IN,REAL :IN )
51 
52 ;FOLD INI
53 BAS (#INITMOV,0 )
54 ;ENDFOLD (INI)
55 
56 ;FOLD STARTPOS
57 $BWDSTART = FALSE
58 PDAT_ACT = PDEFAULT
59 BAS(#PTP_DAT)
60 FDAT_ACT = {TOOL_NO 0,BASE_NO 0,IPO_FRAME #BASE}
61 BAS(#FRAMES)
62 ;ENDFOLD
63 
64 ;FOLD SET DEFAULT SPEED
65 $VEL.CP=0.2
66 BAS(#VEL_PTP,100)
67 BAS(#TOOL,0)
68 BAS(#BASE,0)
69 ;ENDFOLD
70 
71 $ADVANCE = 5
72 
73 PTP $AXIS_ACT ; skip BCO quickly
74 '''
75 
76 # ----------------------------------------------------
77 def pose_2_str(pose):
78  """Converts a pose target to a string"""
79  #[x,y,z,w,p,r] = Pose_2_KUKA(pose)
80  #return ('X %.3f, Y %.3f, Z %.3f, A %.3f, B %.3f, C %.3f' % (x,y,z,r,p,w)) # old version had to be switched
81  [x,y,z,r,p,w] = pose_2_xyzrpw(pose)
82  return ('X %.3f,Y %.3f,Z %.3f,A %.3f,B %.3f,C %.3f' % (x,y,z,w,p,r))
83 
84 def pose_2_str_ext(pose,joints):
85  njoints = len(joints)
86  if njoints <= 6:
87  return pose_2_str(pose)
88  else:
89  extaxes = ''
90  for i in range(njoints-6):
91  extaxes = extaxes + (',E%i %.5f' % (i+1, joints[i+6]))
92  return pose_2_str(pose) + extaxes
93 
94 def angles_2_str(angles):
95  """Prints a joint target"""
96  str = ''
97  data = ['A1','A2','A3','A4','A5','A6','E1','E2','E3','E4','E5','E6']
98  for i in range(len(angles)):
99  str = str + ('%s %.5f,' % (data[i], angles[i]))
100  str = str[:-1]
101  return str
102 
103 # ----------------------------------------------------
104 # Object class that handles the robot instructions/syntax
105 class RobotPost(object):
106  """Robot post object"""
107  PROG_EXT = 'src' # set the program extension
108  MAX_LINES_X_PROG = 2500 # maximum number of lines per program. It will then generate multiple "pages (files)"
109  INCLUDE_SUB_PROGRAMS = False
110 
111  # other variables
112  ROBOT_POST = ''
113  ROBOT_NAME = ''
114 
115  # Multiple program files variables
116  PROG_NAME = 'unknown' # single program name
117  PROG_NAMES = []
118  PROG_FILES = []
119  PROG_LIST = []
120  nLines = 0
121  nProgs = 0
122 
123  PROG = []
124  LOG = ''
125  nAxes = 6
126  APO_VALUE = 1
127  C_DIS = ''#' C_DIS'
128  C_PTP = ''#' C_PTP'
129 
130  PROG_CALLS = []
131  PROG_CALLS_LIST = []
132 
133  def __init__(self, robotpost=None, robotname=None, robot_axes = 6, **kwargs):
134  self.ROBOT_POST = robotpost
135  self.ROBOT_NAME = robotname
136  self.PROG = []
137  self.LOG = ''
138  self.nAxes = robot_axes
139  for k,v in kwargs.items():
140  if k == 'lines_x_prog':
142 
143  def ProgStart(self, progname, new_page = False):
144  progname_i = progname
145  if new_page:
146  nPages = len(self.PROG_LIST)
147  if nPages == 0:
148  progname_i = progname
149  else:
150  progname_i = "%s%i" % (self.PROG_NAME, nPages)
151 
152  else:
153  self.PROG_NAME = progname
154  self.nProgs = self.nProgs + 1
155  self.PROG_NAMES = []
156  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
157  return
158 
159  self.PROG_NAMES.append(progname_i)
160 
161  self.addline('DEF %s ( )' % progname_i)
162  if not new_page:
163  self.PROG.append(HEADER)
164  #if self.nAxes > 6:
165  # self.addline('$ACT_EX_AX = %i' % (self.nAxes-6))
166  #else:
167  # self.PROG += '*PROGDEFS*\n'
168 
169  def ProgFinish(self, progname, new_page = False):
170  if new_page:
171  self.PROG.append("END")
172  self.PROG_LIST.append(self.PROG)
173  self.PROG_CALLS_LIST.append(self.PROG_CALLS)
174  self.PROG = []
175  self.PROG_CALLS = []
176  self.nLines = 0
177 
178  def progsave(self, folder, progname, ask_user = False, show_result = False):
179  progname = progname + '.' + self.PROG_EXT
180  if ask_user or not DirExists(folder):
181  filesave = getSaveFile(folder, progname, 'Save program as...')
182  if filesave is not None:
183  filesave = filesave.name
184  else:
185  return
186  else:
187  filesave = folder + '/' + progname
188 
189  ext_defs = ''
190  for prog_nm in self.PROG_CALLS:
191  ext_defs += "EXT %s()\n" % prog_nm
192 
193  if len(ext_defs) > 0 and len(self.PROG) > 1:
194  self.PROG.insert(1, ext_defs)
195  self.PROG.insert(1, "\n; External program calls:")
196 
197 
198  fid = open(filesave, "w")
199  #fid.write("&ACCESS RVP\n")
200  #fid.write("&REL 1\n")
201  #fid.write("&COMMENT Generated by RoboDK\n")
202  fid.write("&ACCESS RVP\n")
203  fid.write("&REL 1\n") #fid.write("&REL 29\n")
204  fid.write("&PARAM TEMPLATE = C:\\KRC\\Roboter\\Template\\vorgabe\n")
205  fid.write("&PARAM EDITMASK = *\n")
206  for line in self.PROG:
207  fid.write(line)
208  fid.write("\n")
209  fid.close()
210  print('SAVED: %s\n' % filesave) # tell RoboDK the path of the saved file
211  self.PROG_FILES.append(filesave)
212 
213  # open file with default application
214  if show_result:
215  if type(show_result) is str:
216  # Open file with provided application
217  import subprocess
218  p = subprocess.Popen([show_result, filesave])
219  elif type(show_result) is list:
220  import subprocess
221  p = subprocess.Popen(show_result + [filesave])
222  else:
223  # open file with default application
224  import os
225 
226  os.startfile(filesave)
227  if len(self.LOG) > 0:
228  mbox('Program generation LOG:\n\n' + self.LOG)
229 
230  def ProgSave(self, folder, progname, ask_user = False, show_result = False):
231  if len(self.PROG_LIST) >= 1:
232  if self.nLines > 0:
233  self.ProgFinish(progname, True)
234 
235  npages = len(self.PROG_LIST)
236  for i in range(npages-1):
237  prog_call_next = self.PROG_NAMES[i+1]
238  self.PROG_CALLS_LIST[i].append(prog_call_next)
239  self.PROG_LIST[i].insert(-1, "\n; Continue running program as cascaded execution")
240  self.PROG_LIST[i].insert(-1, prog_call_next+"()\n")
241 
242  folder_user = folder
243 
244  for i in range(npages):
245  self.PROG = self.PROG_LIST[i]
246  self.PROG_CALLS = self.PROG_CALLS_LIST[i]
247  self.progsave(folder_user, self.PROG_NAMES[i], ask_user, show_result)
248  if i == 0:
249  if len(self.PROG_FILES) == 0:
250  # cancelled by user
251  return
252  first_file = self.PROG_FILES[0]
253  folder_user = getFileDir(first_file)
254  self.LOG = ''
255  ask_user = False # ask only for the first program
256  show_result = False # only show the first program, if required
257 
258  else:
259  self.PROG.append("END")
260  self.progsave(folder, progname, ask_user, show_result)
261 
262  def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass):
263  """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".
264  The connection parameters must be provided in the robot connection menu of RoboDK"""
265  UploadFTP(self.PROG_FILES, robot_ip, remote_path, ftp_user, ftp_pass)
266 
267  def MoveJ(self, pose, joints, conf_RLF=None):
268  """Add a joint movement"""
269  self.addline('PTP {' + angles_2_str(joints) + '}' + self.C_PTP)
270 
271  def MoveL(self, pose, joints, conf_RLF=None):
272  """Add a linear movement"""
273  self.addline('LIN {' + pose_2_str_ext(pose,joints) + '}' + self.C_DIS)
274 
275  def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None):
276  """Add a circular movement"""
277  self.addline('CIRC {' + pose_2_str_ext(pose1,joints1) + '},{' + pose_2_str_ext(pose2,joints2) + '}' + self.C_DIS)
278 
279  def setFrame(self, pose, frame_id=None, frame_name=None):
280  """Change the robot reference frame"""
281  if self.nAxes <= 6:
282  self.addline('$BASE = {FRAME: ' + pose_2_str(pose) + '}')
283  else:
284  # option 1:
285  #self.addline('$BASE = EK (MACHINE_DEF[2].ROOT, MACHINE_DEF[2].MECH_TYPE, { %s })' % pose_2_str(pose))
286 
287  # option 2:
288  #self.addline('$BASE=EK(EX_AX_DATA[1].ROOT,EX_AX_DATA[1].EX_KIN, { %s })' % pose_2_str(pose))
289 
290  # Option 3:
291  self.addline('$BASE=EK(EX_AX_DATA[1].ROOT,EX_AX_DATA[1].EX_KIN,EX_AX_DATA[1].OFFSET)')
292  self.addline('$ACT_EX_AX= %i' % (self.nAxes - 6))
293 
294  def setTool(self, pose, tool_id=None, tool_name=None):
295  """Change the robot TCP"""
296  self.addline('$TOOL = {FRAME: ' + pose_2_str(pose) + '}')
297 
298  def Pause(self, time_ms):
299  """Pause the robot program"""
300  if time_ms <= 0:
301  self.addline('HALT')
302  else:
303  self.addline('WAIT SEC %.3f' % (time_ms*0.001))
304 
305  def setSpeed(self, speed_mms):
306  """Changes the robot speed (in mm/s)"""
307  self.addline('$VEL.CP = %.5f' % (speed_mms/1000.0))
308 
309  def setAcceleration(self, accel_mmss):
310  """Changes the current robot acceleration"""
311  self.addline('$ACC.CP = %.5f' % (accel_mmss/1000.0))
312 
313  def setSpeedJoints(self, speed_degs):
314  """Changes the robot joint speed (in deg/s)"""
315  self.addline('$VEL.ORI1 = %.5f' % speed_degs)
316  self.addline('$VEL.ORI2 = %.5f' % speed_degs)
317 
318  def setAccelerationJoints(self, accel_degss):
319  """Changes the robot joint acceleration (in deg/s2)"""
320  self.addline('$ACC.ORI1 = %.5f' % accel_degss)
321  self.addline('$ACC.ORI2 = %.5f' % accel_degss)
322 
323  def setZoneData(self, zone_mm):
324  """Changes the zone data approach (makes the movement more smooth)"""
325  self.APO_VALUE = zone_mm
326  if zone_mm >= 0:
327  self.addline('$APO.CPTP = %.3f' % zone_mm)
328  self.addline('$APO.CDIS = %.3f' % zone_mm)
329  self.C_DIS = ' C_DIS'
330  self.C_PTP = ' C_PTP'
331  else:
332  self.C_DIS = ''
333  self.C_PTP = ''
334 
335  def setDO(self, io_var, io_value):
336  """Sets a variable (output) to a given value"""
337  if type(io_var) != str: # set default variable name if io_var is a number
338  io_var = '$OUT[%s]' % str(io_var)
339  if type(io_value) != str: # set default variable value if io_value is a number
340  if io_value > 0:
341  io_value = 'TRUE'
342  else:
343  io_value = 'FALSE'
344 
345  # at this point, io_var and io_value must be string values
346  self.addline('%s=%s' % (io_var, io_value))
347 
348  def waitDI(self, io_var, io_value, timeout_ms=-1):
349  """Waits for an input io_var to attain a given value io_value. Optionally, a timeout can be provided."""
350  if type(io_var) != str: # set default variable name if io_var is a number
351  io_var = '$IN[%s]' % str(io_var)
352  if type(io_value) != str: # set default variable value if io_value is a number
353  if io_value > 0:
354  io_value = 'TRUE'
355  else:
356  io_value = 'FALSE'
357 
358  # at this point, io_var and io_value must be string values
359  if timeout_ms < 0:
360  self.addline('WAIT FOR (%s==%s)' % (io_var, io_value))
361  else:
362  self.addline('START_TIMER:')
363  self.addline('$TIMER_STOP[1]=TRUE')
364  self.addline('$TIMER_FLAG[1]=FALSE')
365  self.addline('$TIMER[1]=%.3f' % (float(timeout_ms)*0.001))
366  self.addline('$TIMER_STOP[1]=FALSE')
367  self.addline('WAIT FOR (%s==%s OR $TIMER_FLAG[1])' % (io_var, io_value))
368  self.addline('$TIMER_STOP[1]=TRUE')
369  self.addline('IF $TIMER_FLAG[1]== TRUE THEN')
370  self.addline(' HALT ; Timed out!')
371  self.addline(' GOTO START_TIMER')
372  self.addline('ENDIF')
373 
374  def RunCode(self, code, is_function_call = False):
375  """Adds code or a function call"""
376  if is_function_call:
377  code.replace(' ','_')
378  if not code.endswith(')'):
379  code = code + '()'
380 
381  fcn_def = code
382  if '(' in fcn_def:
383  fcn_def = fcn_def.split('(')[0]
384  if not (fcn_def in self.PROG_CALLS):
385  self.PROG_CALLS.append(fcn_def)
386 
387  self.addline(code)
388  else:
389  self.addline(code)
390 
391  def RunMessage(self, message, iscomment = False):
392  """Add a joint movement"""
393  if iscomment:
394  self.addline('; ' + message)
395  else:
396  self.addline('Wait for StrClear($LOOP_MSG[])')
397  self.addline('$LOOP_CONT = TRUE')
398  self.addline('$LOOP_MSG[] = "%s"' % message)
399 
400 # ------------------ private ----------------------
401  def addline(self, newline):
402  """Add a program line"""
403  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
404  return
405 
406  if self.nLines > self.MAX_LINES_X_PROG:
407  self.nLines = 0
408  self.ProgFinish(self.PROG_NAME, True)
409  self.ProgStart(self.PROG_NAME, True)
410 
411  self.PROG.append(newline)
412  self.nLines = self.nLines + 1
413 
414  def addlog(self, newline):
415  """Add a log message"""
416  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
417  return
418 
419  self.LOG = self.LOG + newline + '\n'
420 
421 # -------------------------------------------------
422 # ------------ For testing purposes ---------------
423 def Pose(xyzrpw):
424  [x,y,z,r,p,w] = xyzrpw
425  a = r*math.pi/180
426  b = p*math.pi/180
427  c = w*math.pi/180
428  ca = math.cos(a)
429  sa = math.sin(a)
430  cb = math.cos(b)
431  sb = math.sin(b)
432  cc = math.cos(c)
433  sc = math.sin(c)
434  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]])
435 
436 def test_post():
437  """Test the post with a basic program"""
438 
439  robot = RobotPost('Kuka_custom', 'Generic Kuka')
440 
441  robot.ProgStart("Program")
442  robot.RunMessage("Program generated by RoboDK", True)
443  robot.setFrame(Pose([807.766544, -963.699898, 41.478944, 0, 0, 0]))
444  robot.setTool(Pose([62.5, -108.253175, 100, -60, 90, 0]))
445  robot.MoveJ(Pose([200, 200, 500, 180, 0, 180]), [-46.18419, -6.77518, -20.54925, 71.38674, 49.58727, -302.54752] )
446  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
447  robot.MoveL(Pose([200, 200, 262.132034, 180, 0, -150]), [-43.73892, -3.91728, -35.77935, 58.57566, 54.11615, -253.81122] )
448  robot.RunMessage("Setting air valve 1 on")
449  robot.RunCode("TCP_On", True)
450  robot.Pause(1000)
451  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
452  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
453  robot.MoveL(Pose([250, 250, 191.421356, 180, 0, -150]), [-39.75778, -1.04537, -40.37883, 52.09118, 54.15317, -246.94403] )
454  robot.RunMessage("Setting air valve off")
455  robot.RunCode("TCP_Off", True)
456  robot.Pause(1000)
457  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
458  robot.MoveL(Pose([250, 200, 278.023897, 180, 0, -150]), [-41.85389, -1.95619, -34.89154, 57.43912, 52.34162, -253.73403] )
459  robot.MoveL(Pose([250, 150, 191.421356, 180, 0, -150]), [-43.82111, 3.29703, -40.29493, 56.02402, 56.61169, -249.23532] )
460  robot.ProgFinish("Program")
461  # robot.ProgSave(".","Program",True)
462  for line in robot.PROG:
463  print(line)
464 
465  if len(robot.LOG) > 0:
466  mbox('Program generation LOG:\n\n' + robot.LOG)
467 
468  input("Press Enter to close...")
469 
470 if __name__ == "__main__":
471  """Function to call when the module is executed by itself: test"""
472  test_post()
def RunMessage(self, message, iscomment=False)
Definition: KUKA_KRC2.py:391
def MoveJ(self, pose, joints, conf_RLF=None)
Definition: KUKA_KRC2.py:267
def __init__(self, robotpost=None, robotname=None, robot_axes=6, kwargs)
Definition: KUKA_KRC2.py:133
def progsave(self, folder, progname, ask_user=False, show_result=False)
Definition: KUKA_KRC2.py:178
def waitDI(self, io_var, io_value, timeout_ms=-1)
Definition: KUKA_KRC2.py:348
def ProgSave(self, folder, progname, ask_user=False, show_result=False)
Definition: KUKA_KRC2.py:230
def UploadFTP(program, robot_ip, remote_path, ftp_user, ftp_pass)
Definition: robodk.py:1312
def RunCode(self, code, is_function_call=False)
Definition: KUKA_KRC2.py:374
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: KUKA_KRC2.py:294
def setFrame(self, pose, frame_id=None, frame_name=None)
Definition: KUKA_KRC2.py:279
def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass)
Definition: KUKA_KRC2.py:262
def ProgFinish(self, progname, new_page=False)
Definition: KUKA_KRC2.py:169
def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None)
Definition: KUKA_KRC2.py:275
def MoveL(self, pose, joints, conf_RLF=None)
Definition: KUKA_KRC2.py:271
def getSaveFile(strdir='C:\\', strfile='file.txt', strtitle='Save file as ...')
Definition: robodk.py:1354
def ProgStart(self, progname, new_page=False)
Definition: KUKA_KRC2.py:143


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