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


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