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


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