KUKA_CNC.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 sample POST PROCESSOR script to generate robot programs for
14 # KUKA CNC
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 JOINT_DATA = ['X','Y','Z','A','B','C','X1=','Y1=','Z1=']
49 
50 # ----------------------------------------------------
51 def pose_2_str(pose, joints = None):
52  """Prints a pose target"""
53  [x,y,z,r,p,w] = Pose_2_KUKA(pose)
54  str_xyzwpr = 'X%.4f Y%.4f Z%.4f A%.4f B%.4f C%.4f' % (x,y,z,r,p,w)
55  if joints is not None:
56  if len(joints) > 6:
57  for j in range(6,len(joints)):
58  str_xyzwpr += (' %s%.6f ' % (JOINT_DATA[j], joints[j]))
59 
60  return str_xyzwpr
61 
62 def joints_2_str(joints):
63  """Prints a joint target"""
64  str = ''
65  for i in range(len(joints)):
66  str = str + ('%s%.6f ' % (JOINT_DATA[i], joints[i]))
67  str = str[:-1]
68  return str
69 
70 # ----------------------------------------------------
71 # Object class that handles the robot instructions/syntax
72 class RobotPost(object):
73  """Robot post object"""
74  PROG_EXT = 'nc' # set the program extension
75 
76  # other variables
77  ROBOT_POST = ''
78  ROBOT_NAME = ''
79  PROG_FILES = []
80 
81  PROG = []
82  LOG = ''
83  nAxes = 6
84  nId = 0
85  SPEED_F = ' F400' # Set default speed
86  MoveType = -1
87 
88  MOVE_TYPE_NONE = -1
89  MOVE_NAMES = []
90  MOVE_TYPE_MCS = 0
91  MOVE_NAMES.append("MCS")
92  MOVE_TYPE_HSC = 1
93  MOVE_NAMES.append("HSC")
94  MOVE_TYPE_PTP = 2
95  MOVE_NAMES.append("PTP")
96 
97 
98  REF_FRAME = eye(4)
99 
100 
101  def __init__(self, robotpost=None, robotname=None, robot_axes = 6, **kwargs):
102  self.ROBOT_POST = robotpost
103  self.ROBOT_NAME = robotname
104  self.PROG = []
105  self.LOG = ''
106  self.nAxes = robot_axes
107 
108  def ProgStart(self, progname):
109  self.addline('%% program: %s()' % progname, False)
110  self.addline('', False)
111  self.addline('G90')
112  self.addline('#HSC [BSPLINE PATH_DEV 0.0000 TRACK_DEV 0.0000]', False)
113  self.addline('#CS OFF ALL')
114  self.addline('#CS DEF[1][0.0000,0.0000,0.0000,0.0000,0.0000,0.0000]')
115  self.addline('#CS ON[1]')
116  self.addline('G54')
117  self.addline('', False)
118 
119  def ProgFinish(self, progname):
120  self.set_move_type(self.MOVE_TYPE_NONE)
121  self.addline('%% End of program %s' % progname, False)
122 
123  def ProgSave(self, folder, progname, ask_user=False, show_result=False):
124  progname = progname + '.' + self.PROG_EXT
125  if ask_user or not DirExists(folder):
126  filesave = getSaveFile(folder, progname, 'Save program as...')
127  if filesave is not None:
128  filesave = filesave.name
129  else:
130  return
131  else:
132  filesave = folder + '/' + progname
133  fid = open(filesave, "w")
134  for line in self.PROG:
135  fid.write(line + '\n')
136  fid.close()
137  print('SAVED: %s\n' % filesave)
138  self.PROG_FILES = filesave
139  #---------------------- show result
140  if show_result:
141  if type(show_result) is str:
142  # Open file with provided application
143  import subprocess
144  p = subprocess.Popen([show_result, filesave])
145  elif type(show_result) is list:
146  import subprocess
147  p = subprocess.Popen(show_result + [filesave])
148  else:
149  # open file with default application
150  import os
151  os.startfile(filesave)
152 
153  if len(self.LOG) > 0:
154  mbox('Program generation LOG:\n\n' + self.LOG)
155 
156  def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass):
157  """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".
158  The connection parameters must be provided in the robot connection menu of RoboDK"""
159  UploadFTP(self.PROG_FILES, robot_ip, remote_path, ftp_user, ftp_pass)
160 
161  def set_move_type(self, move_type):
162  if self.MoveType == move_type:
163  return
164 
165  if self.MoveType >= 0:
166  self.addline("#%s OFF" % self.MOVE_NAMES[self.MoveType])
167  self.MoveType = -1
168 
169  if move_type >= 0:
170  self.addline('',False) # add empty line
171  self.addline("#%s ON" % self.MOVE_NAMES[move_type])
172  self.MoveType = move_type
173 
174  def MoveJ(self, pose, joints, conf_RLF=None):
175  """Add a joint movement"""
176  self.set_move_type(self.MOVE_TYPE_MCS)
177  self.addline('G0 ' + joints_2_str(joints))
178 
179  if pose is not None:
180  self.set_move_type(self.MOVE_TYPE_PTP)
181  self.addline('G0 ' + pose_2_str(pose, joints))
182 
183  def MoveL(self, pose, joints, conf_RLF=None):
184  """Add a linear movement"""
185  self.set_move_type(self.MOVE_TYPE_HSC)
186  self.addline('G1 ' + pose_2_str(self.REF_FRAME*pose, joints) + self.SPEED_F)
187  self.SPEED_F = ''
188 
189  def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None):
190  """Add a circular movement"""
191  xyz1 = (self.REF_FRAME*pose1).Pos()
192  xyz2 = (self.REF_FRAME*pose2).Pos()
193  self.addline('G2 X%.3f Y%.3f Z%.3f I1=%.3f J1=%.3f K1=%.3f' % (xyz2[0], xyz2[1], xyz2[2], xyz1[0], xyz1[1], xyz1[2]))
194  #self.addline('N%02i G102 X%.3f Y%.3f Z%.3f I1=%.3f J1=%.3f K1=%.3f' % (self.nId, xyz1[0], xyz1[1], xyz1[2], xyz2[0]-xyz1[0], xyz2[1]-xyz1[1], xyz2[2]-xyz1[2]))
195 
196  def setFrame(self, pose, frame_id=None, frame_name=None):
197  """Change the robot reference frame"""
198  self.REF_FRAME = pose
199  self.addline('%% Using Reference %s: %s' % (frame_name, pose_2_str(pose)), False)
200  self.addline('%% (Using absolute coordinates)', False)
201 
202  def setTool(self, pose, tool_id=None, tool_name=None):
203  """Change the robot TCP"""
204  self.addline('', False)
205  self.addline('%% Using Tool %s: %s' % (tool_name, pose_2_str(pose)), False)
206  if tool_id < 1:
207  tool_id = 99
208 
209  self.addline('M5')
210  self.addline('#TRAFO OFF')
211  self.addline('M6 T%i' % tool_id)
212  self.addline('#TRAFO ON')
213  self.addline('M3 S3501')
214  self.addline('G131 100')
215  self.addline('G133 150')
216  self.addline('G134 150')
217  self.addline('', False)
218 
219 
220  def Pause(self, time_ms):
221  """Pause the robot program"""
222  if time_ms < 0:
223  self.addline('%% PAUSE', False)
224  else:
225  self.addline('%% WAIT %.3f' % (time_ms*0.001), False)
226 
227  def setSpeed(self, speed_mms):
228  """Changes the robot speed (in mm/s)"""
229  self.SPEED_F = ' F%.3f' % (speed_mms*60)
230 
231  def setAcceleration(self, accel_mmss):
232  """Changes the robot acceleration (in mm/s2)"""
233  self.addlog('setAcceleration not defined')
234 
235  def setSpeedJoints(self, speed_degs):
236  """Changes the robot joint speed (in deg/s)"""
237  self.addlog('setSpeedJoints not defined')
238 
239  def setAccelerationJoints(self, accel_degss):
240  """Changes the robot joint acceleration (in deg/s2)"""
241  self.addlog('setAccelerationJoints not defined')
242 
243  def setZoneData(self, zone_mm):
244  """Changes the rounding radius (aka CNT, APO or zone data) to make the movement smoother"""
245  self.addlog('setZoneData not defined (%.1f mm)' % zone_mm)
246 
247  def setDO(self, io_var, io_value):
248  """Sets a variable (digital output) to a given value"""
249  if type(io_var) != str: # set default variable name if io_var is a number
250  io_var = 'OUT[%s]' % str(io_var)
251  if type(io_value) != str: # set default variable value if io_value is a number
252  if io_value > 0:
253  io_value = 'TRUE'
254  else:
255  io_value = 'FALSE'
256 
257  # at this point, io_var and io_value must be string values
258  self.addline('%s=%s' % (io_var, io_value))
259 
260  def waitDI(self, io_var, io_value, timeout_ms=-1):
261  """Waits for a variable (digital input) io_var to attain a given value io_value. Optionally, a timeout can be provided."""
262  if type(io_var) != str: # set default variable name if io_var is a number
263  io_var = 'IN[%s]' % str(io_var)
264  if type(io_value) != str: # set default variable value if io_value is a number
265  if io_value > 0:
266  io_value = 'TRUE'
267  else:
268  io_value = 'FALSE'
269 
270  # at this point, io_var and io_value must be string values
271  if timeout_ms < 0:
272  self.addline('WAIT FOR %s==%s' % (io_var, io_value))
273  else:
274  self.addline('WAIT FOR %s==%s TIMEOUT=%.1f' % (io_var, io_value, timeout_ms))
275 
276  def RunCode(self, code, is_function_call = False):
277  """Adds code or a function call"""
278  if is_function_call:
279  code.replace(' ','_')
280  if not code.endswith(')'):
281  code = code + '()'
282  self.addline(code)
283  else:
284  self.addline(code)
285 
286  def RunMessage(self, message, iscomment = False):
287  """Display a message in the robot controller screen (teach pendant)"""
288  if iscomment:
289  self.addline('%% ' + message, False)
290  else:
291  self.addline('%% Show message: %s' % message, False)
292 
293 # ------------------ private ----------------------
294  def addline(self, newline, add_N = True):
295  """Add a program line"""
296  if add_N:
297  self.nId += 1
298  newline = 'N%i ' % self.nId + newline
299 
300  self.PROG.append(newline)
301 
302  def addlog(self, newline):
303  """Add a log message"""
304  self.LOG = self.LOG + newline + '\n'
305 
306 # -------------------------------------------------
307 # ------------ For testing purposes ---------------
308 def Pose(xyzrpw):
309  [x,y,z,r,p,w] = xyzrpw
310  a = r*math.pi/180
311  b = p*math.pi/180
312  c = w*math.pi/180
313  ca = math.cos(a)
314  sa = math.sin(a)
315  cb = math.cos(b)
316  sb = math.sin(b)
317  cc = math.cos(c)
318  sc = math.sin(c)
319  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]])
320 
321 def test_post():
322  """Test the post with a basic program"""
323 
324  robot = RobotPost()
325 
326  robot.ProgStart("Program")
327  robot.RunMessage("Program generated by RoboDK using a custom post processor", True)
328  robot.setFrame(Pose([807.766544, -963.699898, 41.478944, 0, 0, 0]), 3, 'Reference 2')
329  robot.setTool(Pose([62.5, -108.253175, 100, -60, 90, 0]), 5, 'Tool 5')
330  robot.MoveJ(Pose([200, 200, 500, 180, 0, 180]), [-46.18419, -6.77518, -20.54925, 71.38674, 49.58727, -302.54752] )
331  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
332  robot.MoveL(Pose([200, 200, 262.132034, 180, 0, -150]), [-43.73892, -3.91728, -35.77935, 58.57566, 54.11615, -253.81122] )
333  robot.RunMessage("Setting air valve 1 on")
334  robot.RunCode("TCP_On", True)
335  robot.Pause(1000)
336  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
337  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
338  robot.MoveL(Pose([250, 250, 191.421356, 180, 0, -150]), [-39.75778, -1.04537, -40.37883, 52.09118, 54.15317, -246.94403] )
339  robot.RunMessage("Setting air valve off")
340  robot.RunCode("TCP_Off", True)
341  robot.Pause(1000)
342  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
343  robot.MoveL(Pose([250, 200, 278.023897, 180, 0, -150]), [-41.85389, -1.95619, -34.89154, 57.43912, 52.34162, -253.73403] )
344  robot.MoveL(Pose([250, 150, 191.421356, 180, 0, -150]), [-43.82111, 3.29703, -40.29493, 56.02402, 56.61169, -249.23532] )
345  robot.MoveJ(None, [-46.18419, -6.77518, -20.54925, 71.38674, 49.58727, -302.54752] )
346  robot.ProgFinish("Program")
347  # robot.ProgSave(".","Program",True)
348  for line in robot.PROG:
349  print(line)
350 
351  if len(robot.LOG) > 0:
352  mbox('Program generation LOG:\n\n' + robot.LOG)
353 
354  input("Press Enter to close...")
355 
356 if __name__ == "__main__":
357  """Function to call when the module is executed by itself: test"""
358  test_post()
def waitDI(self, io_var, io_value, timeout_ms=-1)
Definition: KUKA_CNC.py:260
def MoveJ(self, pose, joints, conf_RLF=None)
Definition: KUKA_CNC.py:174
def UploadFTP(program, robot_ip, remote_path, ftp_user, ftp_pass)
Definition: robodk.py:1312
def setTool(self, pose, tool_id=None, tool_name=None)
Definition: KUKA_CNC.py:202
def __init__(self, robotpost=None, robotname=None, robot_axes=6, kwargs)
Definition: KUKA_CNC.py:101
def MoveL(self, pose, joints, conf_RLF=None)
Definition: KUKA_CNC.py:183
def mbox(msg, b1='OK', b2='Cancel', frame=True, t=False, entry=None)
Definition: robodk.py:1458
def addline(self, newline, add_N=True)
Definition: KUKA_CNC.py:294
def setFrame(self, pose, frame_id=None, frame_name=None)
Definition: KUKA_CNC.py:196
def RunMessage(self, message, iscomment=False)
Definition: KUKA_CNC.py:286
def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None)
Definition: KUKA_CNC.py:189
def ProgSave(self, folder, progname, ask_user=False, show_result=False)
Definition: KUKA_CNC.py:123
def getSaveFile(strdir='C:\\', strfile='file.txt', strtitle='Save file as ...')
Definition: robodk.py:1354
def RunCode(self, code, is_function_call=False)
Definition: KUKA_CNC.py:276
def pose_2_str(pose, joints=None)
Definition: KUKA_CNC.py:51
def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass)
Definition: KUKA_CNC.py:156


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