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


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