Staubli_S6.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 Staubli (VAL3) 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 from robolink import *
48 
49 
50 # Program.pjx file (references data file as %s.dtx)
51 PROGRAM_PJX = '''<?xml version="1.0" encoding="utf-8" ?>
52 <project xmlns="ProjectNameSpace" >
53  <parameters version="s6.4.2" stackSize="5000" millimeterUnit="true" />
54  <programSection>
55  <program file="start.pgx" />
56  <program file="stop.pgx" />
57  </programSection>
58  <dataSection>
59  <data file="%s.dtx" />
60  </dataSection>
61  <aliasSection>
62  <alias name="io" interface="io" autoload="true" password="" />
63  </aliasSection>
64 </project>
65 '''
66 
67 PROGRAM_PJX_MAIN = '''<?xml version="1.0" encoding="utf-8" ?>
68 <project xmlns="ProjectNameSpace" >
69  <parameters version="s6.4.2" stackSize="5000" millimeterUnit="true" />
70  <programSection>
71  <program file="start.pgx" />
72  <program file="stop.pgx" />
73  </programSection>
74  <dataSection>
75  <data file="%s.dtx" />
76  </dataSection>
77  <aliasSection>
78  <alias name="io" interface="io" autoload="true" password="" />
79  <alias name="prog" interface="prog" autoload="true" password="" path="./%s.pjx" />
80  <alias name="prog_swap" interface="prog_swap" autoload="true" password="" path="./%s.pjx" />
81  <alias name="tooldata" interface="tooldata" autoload="true" password="" path="saveChangeTool" />
82 
83  </aliasSection>
84 </project>
85 '''
86 
87 DATA_DTX = '''<?xml version="1.0" encoding="utf-8" ?>
88 <dataList xmlns="DataNameSpace" >
89  <aioSection />
90  <boolSection />
91  <configRsSection />
92  <configSection />
93  <configVrbSection />
94  <dioSection />
95  <frameSection>
96  <frame name="world" public="false" privilege="0" >
97  <fFather alias="" name="" fatherIndex="0" />
98  <valueFrame index="0" >
99  <tfValue x="0" y="0" z="0" rx="0" ry="0" rz="0" />
100  </valueFrame>
101  </frame>
102  </frameSection>
103  <jointRsSection />
104  <jointSection>%s
105  </jointSection>
106  <jointVrbSection />
107  <mdescSection>
108  <mdesc name="mNomSpeed" public="true" privilege="0" >
109  <valueMdesc index="0" >
110  <mdescValue accel="100" vel="100" decel="100" tmax="99999" rmax="99999" blend="off" leave="50" reach="50" />
111  </valueMdesc>
112  </mdesc>
113  </mdescSection>
114  <numSection />
115  <pointRsSection />
116  <pointSection>%s
117  </pointSection>
118  <pointVrbSection />
119  <sioSection />
120  <stringSection />
121  <toolSection>
122  <tool name="flange" public="false" privilege="0" >
123  <tFather alias="" name="" fatherIndex="0" />
124  <valueTool index="0" >
125  <ttValue x="0" y="0" z="0" rx="0" ry="0" rz="0" />
126  <io alias="io" name="valve1" ioIndex="0" open="0" close="0" />
127  </valueTool>
128  </tool>
129  <tool name="tProg" public="false" privilege="0" >
130  <tFather alias="" name="flange" fatherIndex="0" />
131  <valueTool index="0" >
132  <ttValue %s />
133  <io alias="io" name="valve1" ioIndex="0" open="0" close="0" />
134  </valueTool>
135  </tool>
136  </toolSection>
137  <trsfSection />
138 </dataList>
139 '''
140 
141 
142 
143 # start.pjx file (references data file as %s.dtx)
144 START_PGX = '''<?xml version="1.0" encoding="utf-8" ?>
145 <programList xmlns="ProgramNameSpace" >
146  <program name="start" public="false" >
147  <description />
148  <paramSection/>
149  <localSection/>
150  <source>
151  <code>begin
152  do
153 %s
154  until (false)
155 end
156 
157  </code>
158  </source>
159  </program>
160 </programList>
161 '''
162 
163 
164 STOP_PGX = '''<?xml version="1.0" encoding="utf-8" ?>
165 <programList xmlns="ProgramNameSpace" >
166  <program name="stop" public="false" >
167  <description />
168  <paramSection/>
169  <localSection/>
170  <source>
171  <code>begin
172  popUpMsg(&quot;Pending movement commands have been canceled&quot;)
173  resetMotion()
174 end
175 
176  </code>
177  </source>
178  </program>
179 </programList>
180 '''
181 
182 LOAD_NEXT_ONE = '''<?xml version="1.0" encoding="utf-8" ?>
183 <programList xmlns="ProgramNameSpace" >
184  <program name="stop" public="false" >
185  <description />
186  <paramSection/>
187  <localSection/>
188  <source>
189  <code>begin
190  prog_swap:libLoad(x_sName)
191 end
192 
193  </code>
194  </source>
195  </program>
196 </programList>
197 '''
198 
199 LTX_FILE = '''<?xml version="1.0" encoding="utf-8" ?>
200 <externList>
201 </externList>'''
202 
203 
205  """Converts a pose to a Staubli target target"""
206  x = H[0,3]
207  y = H[1,3]
208  z = H[2,3]
209  a = H[0,0]
210  b = H[0,1]
211  c = H[0,2]
212  d = H[1,2]
213  e = H[2,2]
214  if c > (1.0 - 1e-10):
215  ry1 = pi/2
216  rx1 = 0
217  rz1 = atan2(H[1,0],H[1,1])
218  elif c < (-1.0 + 1e-10):
219  ry1 = -pi/2
220  rx1 = 0
221  rz1 = atan2(H[1,0],H[1,1])
222  else:
223  sy = c
224  cy1 = +sqrt(1-sy*sy)
225  sx1 = -d/cy1
226  cx1 = e/cy1
227  sz1 = -b/cy1
228  cz1 = a/cy1
229  rx1 = atan2(sx1,cx1)
230  ry1 = atan2(sy,cy1)
231  rz1 = atan2(sz1,cz1)
232  return [x, y, z, rx1*180.0/pi, ry1*180.0/pi, rz1*180.0/pi]
233 
234 # ----------------------------------------------------
235 def pose_2_str(pose):
236  """Prints a pose target"""
237  [x,y,z,r,p,w] = Pose_2_Staubli_v2(pose)
238  return ('x="%.3f" y="%.3f" z="%.3f" rx="%.3f" ry="%.3f" rz="%.3f"' % (x,y,z,r,p,w))
239 
240 def angles_2_str(angles):
241  """Prints a joint target for Staubli VAL3 XML"""
242  str = ''
243  for i in range(len(angles)):
244  str = str + ('j%i="%.5f" ' % ((i+1), angles[i]))
245  str = str[:-1]
246  return str
247 
248 def getSaveFolder(strdir='C:\\', strtitle='Save program folder ...'):
249  import tkinter
250  from tkinter import filedialog
251  options = {}
252  options['initialdir'] = strdir
253  options['title'] = strtitle
254  root = tkinter.Tk()
255  root.withdraw()
256  file_path = tkinter.filedialog.askdirectory(**options)
257  return file_path
258 
259 # ----------------------------------------------------
260 # Object class that handles the robot instructions/syntax
261 class RobotPost(object):
262  """Robot post object"""
263  # other variables
264  ROBOT_POST = ''
265  ROBOT_NAME = ''
266  PROG_FILES = []
267  PROG_NAME = 'unknown'
268  MAIN_FOLDER = 'ProgRoboDK'
269  PROG_PGX = ''
270  PROG_MOVE_COUNT = 0
271  PROG_MOVE_COUNT_MAX = 2000
272  PROG_PGX_LIST = []
273  PROG_DTX_LIST = []
274  PROG_PJX_LIST = []
275  PROG_NAME_LIST = []
276  LOG = ''
277  nAxes = 6
278  TAB_PGX = ' '
279  DEFAULT_SPEED = 150
280  DEFAULT_SMOOTH = 0.1
281  SPEED = DEFAULT_SPEED
282  REF = eye(4)
283  TOOL = eye(4)
284  SMOOTH = DEFAULT_SMOOTH
285  REF_NAME = 'fPartReal'
286  REF_CURRENT = 'world'
287  REF_DATA = ''
288  REF_COUNT = 0
289  TOOL_NAME = 'tCad'
290  TOOL_CURRENT = 'tProg'
291  TOOL_DATA = ''
292  TOOL_COUNT = 0
293  SPEED_NAME = 'mSpeed'
294  SPEED_CURRENT = 'mNomSpeed'
295  SPEED_DATA = ''
296  SPEED_COUNT = 0
297  JOINT_NAME = 'jJoint'
298  JOINT_DATA = ''
299  JOINT_COUNT = 0
300  POINT_NAME = 'pPoint'
301  POINT_DATA = ''
302  POINT_COUNT = 0
303 
304  def __init__(self, robotpost=None, robotname=None, robot_axes = 6, **kwargs):
305  self.ROBOT_POST = robotpost
306  self.ROBOT_NAME = robotname
307  self.PROG = ''
308  self.LOG = ''
309  self.nAxes = robot_axes
310 
311  def ProgStart(self, progname):
312  self.PROG_NAME = progname.lower()
313  self.addline('// Program %s start' % progname)
314 
315  def ProgFinish(self, progname):
316  self.addline('')
317  self.addline('waitEndMove()')
318  self.addline('// Program %s end' % progname.lower())
319 
320 
321  def RemoveDirFTP(self, ftp, path):
322  import ftplib
323  """Recursively delete a directory tree on a remote server."""
324  wd = ftp.pwd()
325  try:
326  names = ftp.nlst(path)
327  except ftplib.all_errors as e:
328  # some FTP servers complain when you try and list non-existent paths
329  print('RemoveDirFTP: Could not remove {0}: {1}'.format(path, e))
330  return
331 
332  for name in names:
333  if os.path.split(name)[1] in ('.', '..'): continue
334  print('RemoveDirFTP: Checking {0}'.format(name))
335  try:
336  ftp.cwd(name) # if we can cwd to it, it's a folder
337  ftp.cwd(wd) # don't try a nuke a folder we're in
338  self.RemoveDirFTP(ftp, name)
339  except ftplib.all_errors:
340  ftp.delete(name)
341 
342  try:
343  ftp.rmd(path)
344  except ftplib.all_errors as e:
345  print('RemoveDirFTP: Could not remove {0}: {1}'.format(path, e))
346 
347  def UploadFTP(self, localpath):
348  import ftplib
349  import os
350  robot = None
351  try:
352  RDK = Robolink()
353  robot = RDK.Item(self.ROBOT_NAME, ITEM_TYPE_ROBOT)
354  [server_ip, port, remote_path, username, password] = robot.ConnectionParams()
355  except:
356  server_ip = 'localhost' # enter URL address of the robot it may look like: '192.168.1.123'
357  username = 'username' # enter FTP user name
358  password = 'password' # enter FTP password
359  remote_path = '/usr/usrapp/session/default/saveTraj/CAD' # enter the remote path
360  import sys
361  while True:
362  print("POPUP: Uploading program through FTP. Enter server parameters...")
363  sys.stdout.flush()
364 
365  # check if connection parameters are OK
366  values_ok = mbox('Using the following FTP connection parameters to transfer the program:\nRobot IP: %s\nRemote path: %s\nFTP username: %s\nFTP password: ****\n\nContinue?' % (server_ip, remote_path, username))
367  if values_ok:
368  print("Using default connection parameters")
369  else:
370  server_ip = mbox('Enter robot IP', entry=server_ip)
371  if not server_ip:
372  print('FTP upload cancelled by user')
373  return
374  remote_path = mbox('Enter the remote path (program folder) on the Staubli robot controller', entry=remote_path)
375  if not remote_path:
376  return
377  if remote_path.endswith('/'):
378  remote_path = remote_path[:-1]
379  rob_user_pass = mbox('Enter user name and password as\nuser-password', entry=('%s-%s' % (username, password)))
380  if not rob_user_pass:
381  return
382  name_value = rob_user_pass.split('-')
383  if len(name_value) < 2:
384  password = ''
385  else:
386  password = name_value[1]
387  username = name_value[0]
388  print("POPUP: <p>Connecting to <strong>%s</strong> using user name <strong>%s</strong> and password ****</p><p>Please wait...</p>" % (server_ip, username))
389  #print("POPUP: Trying to connect. Please wait...")
390  sys.stdout.flush()
391  if robot is not None:
392  robot.setConnectionParams(server_ip, port, remote_path, username, password)
393  pause(2)
394  try:
395  myFTP = ftplib.FTP(server_ip, username, password)
396  break;
397  except:
398  error_str = sys.exc_info()[1]
399  print("POPUP: Connection to %s failed: <p>%s</p>" % (server_ip,error_str))
400  sys.stdout.flush()
401  contin = mbox("Connection to %s failed. Reason:\n%s\n\nRetry?" % (server_ip,error_str))
402  if not contin:
403  return
404 
405  remote_path_prog = remote_path + '/' + self.MAIN_FOLDER
406  myPath = r'%s' % localpath
407  print("POPUP: Connected. Deleting existing files on %s..." % remote_path_prog)
408  sys.stdout.flush()
409  self.RemoveDirFTP(myFTP, remote_path_prog)
410  print("POPUP: Connected. Uploading program to %s..." % server_ip)
411  sys.stdout.flush()
412  try:
413  myFTP.cwd(remote_path)
414  myFTP.mkd(self.MAIN_FOLDER)
415  myFTP.cwd(remote_path_prog)
416  #print('asdf')
417  except:
418  error_str = sys.exc_info()[1]
419  print("POPUP: Remote path not found or can't be created: %s" % (remote_path))
420  sys.stdout.flush()
421  contin = mbox("Remote path\n%s\nnot found or can't create folder.\n\nChange path and permissions and retry." % remote_path)
422  return
423 
424  def uploadThis(path):
425  files = os.listdir(path)
426  os.chdir(path)
427  for f in files:
428  if os.path.isfile(path + r'\{}'.format(f)):
429  print(' Sending file: %s' % f)
430  print("POPUP: Sending file: %s" % f)
431  sys.stdout.flush()
432  fh = open(f, 'rb')
433  myFTP.storbinary('STOR %s' % f, fh)
434  fh.close()
435  elif os.path.isdir(path + r'\{}'.format(f)):
436  print(' Sending folder: %s' % f)
437  myFTP.mkd(f)
438  myFTP.cwd(f)
439  uploadThis(path + r'\{}'.format(f))
440  myFTP.cwd('..')
441  os.chdir('..')
442  uploadThis(myPath) # now call the recursive function
443 
444  def ProgSave(self, folder, progname, ask_user = False, show_result = False):
445  progname = progname.lower()
446  self.close_module()
447 
448  if ask_user or not DirExists(folder):
449  foldersave = getSaveFolder(folder, 'Save program as...')
450  if foldersave is not None and len(foldersave) > 0:
451  foldersave = foldersave
452  else:
453  return
454  else:
455  foldersave = folder
456 
457  nprogs = len(self.PROG_NAME_LIST)
458  print("Saving %i programs..." % nprogs)
459 
460  main_progname = 'Main' + progname
461  if nprogs > 1: # always create a main program
462  folderprog = foldersave + '/' + main_progname
463  self.MAIN_FOLDER = main_progname
464  else:
465  folderprog = foldersave + '/' + progname
466  self.MAIN_FOLDER = progname
467 
468  if not DirExists(folderprog):
469  import os
470  os.makedirs(folderprog)
471 
472  show_file_list = []
473  if nprogs > 1: # always create a main program
474  call_sequence = ''
475  for i in range(nprogs):
476  call_sequence+=(' if prog:libLoad("./%s")!=0\n' % self.PROG_NAME_LIST[i])
477  call_sequence+=(' logMsg("Error Loading RoboDK library")\n')
478  call_sequence+=(' popUpMsg("Error Loading RoboDK library")\n')
479  call_sequence+=(' endIf\n')
480  call_sequence+=(' wait(taskStatus("loading")==-1)\n')
481  if i < nprogs-1:
482  call_sequence+=(' taskCreate "loading",10,loadNextOne("./%s")\n' % self.PROG_NAME_LIST[i+1])
483  call_sequence+=(' prog:fPartReal.trsf=fPartCad.trsf*fCadToReal.trsf\n')
484  call_sequence+=(' prog:tCad.trsf=prog:tCad.trsf*{0,0,tooldata:nLength,0,0,0}\n')
485  call_sequence+=(' call prog:start()\n')
486  call_sequence+=(' \n')
487 
488  #-----------------------------------
489  # start.pgx
490  start_file = folderprog + '/start.pgx'
491  show_file_list.append(start_file)
492  fid = open(start_file, mode="w", encoding='utf-8')
493  fid.write('\ufeff')
494  fid.write(START_PGX % call_sequence)
495  fid.close()
496  #-----------------------------------
497  # mainprog.pjx
498  project_file = folderprog + '/%s.pjx' % main_progname
499  #show_file_list.append(project_file)
500  fid = open(project_file, mode="w", encoding='utf-8')
501  dummy_folder = self.PROG_NAME_LIST[0] + '/' + self.PROG_NAME_LIST[0]
502  fid.write('\ufeff')
503  fid.write(PROGRAM_PJX_MAIN % (main_progname, dummy_folder, dummy_folder))
504  fid.close()
505  print('SAVED: %s\n' % project_file)
506  #-----------------------------------
507  # mainprog.dtx
508  program_data = folderprog + '/%s.dtx' % main_progname
509  show_file_list.append(project_file)
510  fid = open(program_data, mode="w", encoding='utf-8')
511  fid.write('\ufeff')
512  #fid.write(DATA_DTX_MAIN % (pose_2_str(self.REF_DATA), self.TOOL_DATA))
513  fid.write(DATA_DTX % (self.TOOL_DATA, ''))
514  fid.close()
515  #-----------------------------------
516  # stop.pgx
517  stop_file = folderprog + '/stop.pgx'
518  fid = open(stop_file, mode="w", encoding='utf-8')
519  fid.write('\ufeff')
520  fid.write(STOP_PGX)
521  fid.close()
522  #-----------------------------------
523  # loadNextOne.pgx
524  program_data = folderprog + '/loadNextOne.pgx'
525  fid = open(program_data, mode="w", encoding='utf-8')
526  fid.write('\ufeff')
527  fid.write(LOAD_NEXT_ONE)
528  fid.close()
529  #-----------------------------------
530  # mainprog.ltx
531  ltx_f = folderprog + '/%s.ltx' % main_progname
532  fid = open(ltx_f, mode="w", encoding='utf-8')
533  fid.write('\ufeff')
534  fid.write(LTX_FILE)
535  fid.close()
536  #-----------------------------------
537 
538 
539  for i in range(nprogs):
540  if nprogs > 1: # Always create a main program loading sub programs
541  folderprog_final = folderprog + '/' + self.PROG_NAME_LIST[i]
542  else:
543  folderprog_final = folderprog
544 
545  if not DirExists(folderprog_final):
546  import os
547  os.makedirs(folderprog_final)
548 
549  #-----------------------------------
550  # start.pgx
551  start_file = folderprog_final + '/start.pgx'
552  show_file_list.append(start_file)
553  fid = open(start_file, mode="w", encoding='utf-8')
554  fid.write('\ufeff')
555  fid.write(self.PROG_PGX_LIST[i])
556  fid.close()
557  #-----------------------------------
558  # stop.pgx
559  stop_file = folderprog_final + '/stop.pgx'
560  fid = open(stop_file, mode="w", encoding='utf-8')
561  fid.write('\ufeff')
562  fid.write(STOP_PGX)
563  fid.close()
564  #-----------------------------------
565  # program.pjx
566  project_file = folderprog_final + '/%s.pjx' % self.PROG_NAME_LIST[i]
567  #show_file_list.append(project_file)
568  fid = open(project_file, mode="w", encoding='utf-8')
569  fid.write('\ufeff')
570  fid.write(self.PROG_PJX_LIST[i])
571  fid.close()
572  print('SAVED: %s\n' % project_file)
573  #-----------------------------------
574  # program.dtx
575  program_data = folderprog_final + '/%s.dtx' % self.PROG_NAME_LIST[i]
576  show_file_list.append(project_file)
577  fid = open(program_data, mode="w", encoding='utf-8')
578  fid.write('\ufeff')
579  fid.write(self.PROG_DTX_LIST[i])
580  fid.close()
581  #-----------------------------------
582  # program.ltx
583  ltx_f = folderprog + '/%s.ltx' % self.PROG_NAME_LIST[i]
584  fid = open(ltx_f, mode="w", encoding='utf-8')
585  fid.write('\ufeff')
586  fid.write(LTX_FILE)
587  fid.close()
588  #-----------------------------------
589 
590  #self.UploadFTP(folderprog)
591  self.PROG_FILES = folderprog
592 
593  if show_result:
594  if type(show_result) is str:
595  # Open file with provided application
596  import subprocess
597  for file_i in show_file_list:
598  p = subprocess.Popen([show_result, file_i])
599  #p = subprocess.Popen([show_result, start_file])
600  #p = subprocess.Popen([show_result, program_data])
601  elif type(show_result) is list:
602  import subprocess
603  p = subprocess.Popen(show_result + [filesave])
604  else:
605  # open file with default application
606  import os
607  os.startfile(start_file)
608  os.startfile(program_data)
609  if len(self.LOG) > 0:
610  mbox('Program generation LOG:\n\n' + self.LOG)
611  # attempt FTP upload
612 
613  def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass):
614  """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".
615  The connection parameters must be provided in the robot connection menu of RoboDK"""
616  UploadFTP(self.PROG_FILES, robot_ip, remote_path, ftp_user, ftp_pass)
617 
618  def MoveJ(self, pose, joints, conf_RLF=None):
619  """Add a joint movement"""
620  self.control_ProgSize()
621  #nTraj=movej(jJoints[0],tTool[0],mSpeed[0])
622  #waitEndMove()
623  # <Value key="0" j1="0.000" j2="-10.000" j3="100.000" j4="0.000" j5="0.000" j6="-90.000" />
624  self.JOINT_COUNT = self.JOINT_COUNT + 1
625  variable = 't%i' % (self.JOINT_COUNT)
626  self.JOINT_DATA = self.JOINT_DATA + '\n <joint name="t%i" public="false" privilege="0" >\n <valueJoint index="0" >\n <jointValue %s />\n </valueJoint>\n </joint>' % (self.JOINT_COUNT, angles_2_str(joints))
627  self.addline('movej(%s,%s,%s)' % (variable, self.TOOL_CURRENT, self.SPEED_CURRENT))
628  #self.addline('waitEndMove()')
629 
630 
631  #<joint name="t2" public="false" privilege="0" >
632  # <valueJoint index="0" >
633  # <jointValue j1="153.331931" j2="66.046995" j3="31.149415" j4="-0.500557" j5="-16.297583" j6="34.988225" />
634  # </valueJoint>
635  #</joint>
636 
637  def MoveL(self, pose, joints, conf_RLF=None):
638  """Add a linear movement"""
639  self.control_ProgSize()
640  poseabs = self.REF * pose
641  #nTraj=movej(jJoints[0],tTool[0],mSpeed[0])
642  #waitEndMove()
643  # <Value key="0" x="-36.802" y="-6.159" z="500.000" rx="135.407" ry="80.416" rz="46.453" shoulder="lefty" elbow="epositive" wrist="wpositive" fatherId="fPartReal[0]" />
644  # Configuration needs to be checked for older RoboDK versions
645  self.POINT_COUNT = self.POINT_COUNT + 1
646  variable = 'p%i' % (self.POINT_COUNT)
647  self.POINT_DATA = self.POINT_DATA + '\n <point name="p%i" public="false" privilege="0" >\n <pFather alias="" name="world" fatherIndex="0" />\n <valuePoint index="0" >\n <tpValue %s />\n <cpValue shoulder="ssame" elbow="esame" wrist="wsame"/>\n </valuePoint>\n </point>' % (self.POINT_COUNT, pose_2_str(poseabs))
648  #movej(t1,flange,mNomSpeed)
649  self.addline('movel(%s,%s,%s)' % (variable, self.TOOL_CURRENT, self.SPEED_CURRENT))
650 
651  def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None):
652  """Add a circular movement"""
653  self.control_ProgSize()
654  pose1abs = self.REF * pose1
655  pose2abs = self.REF * pose2
656 
657  #nTraj=movej(jJoints[0],tTool[0],mSpeed[0])
658  #waitEndMove()
659  # <Value key="0" x="-36.802" y="-6.159" z="500.000" rx="135.407" ry="80.416" rz="46.453" shoulder="lefty" elbow="epositive" wrist="wpositive" fatherId="fPartReal[0]" />
660  # Configuration needs to be checked for older RoboDK versions
661  self.POINT_COUNT = self.POINT_COUNT + 1
662  variable1 = 'p%i' % (self.POINT_COUNT)
663  self.POINT_DATA = self.POINT_DATA + '\n <point name="p%i" public="false" privilege="0" >\n <pFather alias="" name="world" fatherIndex="0" />\n <valuePoint index="0" >\n <tpValue %s />\n <cpValue shoulder="ssame" elbow="esame" wrist="wsame"/>\n </valuePoint>\n </point>' % (self.POINT_COUNT, pose_2_str(pose1abs))
664  self.POINT_COUNT = self.POINT_COUNT + 1
665  variable2 = 'p%i' % (self.POINT_COUNT)
666  self.POINT_DATA = self.POINT_DATA + '\n <point name="p%i" public="false" privilege="0" >\n <pFather alias="" name="world" fatherIndex="0" />\n <valuePoint index="0" >\n <tpValue %s />\n <cpValue shoulder="ssame" elbow="esame" wrist="wsame"/>\n </valuePoint>\n </point>' % (self.POINT_COUNT, pose_2_str(pose2abs))
667 
668  #movej(t1,flange,mNomSpeed)
669  self.addline('movec(%s,%s,%s,%s)' % (variable1, variable2, self.TOOL_CURRENT, self.SPEED_CURRENT))
670 
671 
672  def setFrame(self, pose, frame_id=None, frame_name=None):
673  """Change the robot reference frame"""
674  if self.REF_COUNT > 1:
675  self.RunMessage('Warning: This post processor is meant to use one reference frame. Errors might follow.', True)
676  self.log('This post processor is meant to use one reference frame. Errors might follow.')
677 
678  self.control_ProgSize()
679  self.REF = pose
680  self.REF_COUNT = self.REF_COUNT + 1
681 
682  def setTool(self, pose, tool_id=None, tool_name=None):
683  """Change the robot TCP"""
684  if self.TOOL_COUNT > 1:
685  self.RunMessage('Warning: Only one tool allowed per program. Tool change skipped.', True)
686  self.log('Only one tool allowed per program')
687  return
688 
689  self.control_ProgSize()
690  self.TOOL = pose
691  self.TOOL_COUNT = self.TOOL_COUNT + 1
692 
693  def Pause(self, time_ms):
694  """Pause the robot program"""
695  self.control_ProgSize()
696  if time_ms < 0:
697  self.addline('popUpMsg("Paused. Press OK to continue")')
698  else:
699  self.addline('delay(%.3f)' % (time_ms*0.001))
700 
701  def setSpeed(self, speed_mms):
702  """Changes the robot speed (in mm/s)"""
703  if self.SPEED != speed_mms:
704  self.SPEED = speed_mms
705  self.addline('mNomSpeed.tvel = %.3f' % speed_mms)
706 
707  def setAcceleration(self, accel_mmss):
708  """Changes the robot acceleration (in mm/s2)"""
709  self.ACCEL_MMSS = accel_mmss
710 
711  def setSpeedJoints(self, speed_degs):
712  """Changes the robot joint speed (in deg/s)"""
713  self.SPEED_DEGS = speed_degs
714 
715  def setAccelerationJoints(self, accel_degss):
716  """Changes the robot joint acceleration (in deg/s2)"""
717  self.ACCEL_DEGSS = accel_degss
718 
719  def setZoneData(self, zone_mm):
720  """Changes the zone data approach (makes the movement more smooth)"""
721  self.control_ProgSize()
722  self.SMOOTH = zone_mm
723 
724  def setDO(self, io_var, io_value):
725  """Sets a variable (output) to a given value"""
726  if type(io_var) != str: # set default variable name if io_var is a number
727  io_var = 'OUT[%s]' % str(io_var)
728  if type(io_value) != str: # set default variable value if io_value is a number
729  if io_value > 0:
730  io_value = 'TRUE'
731  else:
732  io_value = 'FALSE'
733 
734  # at this point, io_var and io_value must be string values
735  self.addline('%s=%s' % (io_var, io_value))
736 
737  def waitDI(self, io_var, io_value, timeout_ms=-1):
738  """Waits for an input io_var to attain a given value io_value. Optionally, a timeout can be provided."""
739  if type(io_var) != str: # set default variable name if io_var is a number
740  io_var = 'IN[%s]' % str(io_var)
741  if type(io_value) != str: # set default variable value if io_value is a number
742  if io_value > 0:
743  io_value = 'TRUE'
744  else:
745  io_value = 'FALSE'
746 
747  # at this point, io_var and io_value must be string values
748  if timeout_ms < 0:
749  self.addline('WAIT FOR %s==%s' % (io_var, io_value))
750  else:
751  self.addline('WAIT FOR %s==%s TIMEOUT=%.1f' % (io_var, io_value, timeout_ms))
752 
753  def RunCode(self, code, is_function_call = False):
754  """Adds code or a function call"""
755  self.control_ProgSize()
756  if is_function_call:
757  code.replace(' ','_')
758  #call prog:start()
759  #self.addline('call prog:%s' % code)# add as a call
760  self.addline('//call prog:%s' % code)# add as a comment
761  self.addline('taskCreate "%sTSK",80,%s()' % (code, code))# add as a comment
762 
763  else:
764  self.addline(code)
765 
766  def RunMessage(self, message, iscomment = False):
767  """Display a message in the robot controller screen (teach pendant)"""
768  self.control_ProgSize()
769  if iscomment:
770  self.addline('// ' + message)
771  else:
772  self.addline('popUpMsg("%s")' % message)
773 
774 # ------------------ private ----------------------
775  def addline(self, newline):
776  """Add a program line"""
777  self.PROG_PGX = self.PROG_PGX + self.TAB_PGX + newline + '\n'
778 
779  def addlog(self, newline):
780  """Add a log message"""
781  self.LOG = self.LOG + newline + '\n'
782 
783  def control_ProgSize(self):
785  if self.PROG_MOVE_COUNT > self.PROG_MOVE_COUNT_MAX:
786  self.close_module()
787 
788  def close_module(self):
789  if self.PROG_MOVE_COUNT == 0:
790  return
791 
792  progname = self.PROG_NAME
793  nprogs = len(self.PROG_NAME_LIST)
794  if nprogs > 0:
795  progname = progname + ('%i' % (nprogs+1))
796 
797  self.PROG_PGX_LIST.append(START_PGX % self.PROG_PGX)
798  self.PROG_DTX_LIST.append(DATA_DTX % (self.JOINT_DATA, self.POINT_DATA, pose_2_str(self.TOOL)))
799  self.PROG_PJX_LIST.append(PROGRAM_PJX % progname)
800  self.PROG_NAME_LIST.append(progname)
801  self.PROG_PGX = ''
802  self.REF_DATA = ''
803  self.REF_COUNT = 0
804  self.TOOL_DATA = ''
805  self.TOOL_COUNT = 0
806  self.SPEED_DATA = ''
807  self.SPEED_COUNT = 0
808  self.JOINT_DATA = ''
809  self.JOINT_COUNT = 0
810  self.POINT_DATA = ''
811  self.POINT_COUNT = 0
812  self.PROG_MOVE_COUNT = 0
813  # initialise next program
814  self.setFrame(self.REF)
815  self.setTool(self.TOOL)
816  self.setSpeed(self.SPEED)
817  self.PROG_MOVE_COUNT = 0 # very important to avoid writting two programs
818 
819 
820 
821 
822 
823 
824 # -------------------------------------------------
825 # ------------ For testing purposes ---------------
826 def Pose(xyzrpw):
827  [x,y,z,r,p,w] = xyzrpw
828  a = r*math.pi/180
829  b = p*math.pi/180
830  c = w*math.pi/180
831  ca = math.cos(a)
832  sa = math.sin(a)
833  cb = math.cos(b)
834  sb = math.sin(b)
835  cc = math.cos(c)
836  sc = math.sin(c)
837  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]])
838 
839 def test_post():
840  """Test the post with a basic program"""
841 
842  robot = RobotPost()
843 
844  robot.ProgStart("Program")
845  robot.RunMessage("Program generated by RoboDK using a custom post processor", True)
846  robot.setFrame(Pose([807.766544, -963.699898, 41.478944, 0, 0, 0]))
847  robot.setTool(Pose([62.5, -108.253175, 100, -60, 90, 0]))
848  robot.MoveJ(Pose([200, 200, 500, 180, 0, 180]), [-46.18419, -6.77518, -20.54925, 71.38674, 49.58727, -302.54752] )
849  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
850  robot.MoveL(Pose([200, 200, 262.132034, 180, 0, -150]), [-43.73892, -3.91728, -35.77935, 58.57566, 54.11615, -253.81122] )
851  robot.RunMessage("Setting air valve 1 on")
852  robot.RunCode("TCP_On", True)
853  robot.Pause(1000)
854  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
855  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
856  robot.MoveL(Pose([250, 250, 191.421356, 180, 0, -150]), [-39.75778, -1.04537, -40.37883, 52.09118, 54.15317, -246.94403] )
857  robot.RunMessage("Setting air valve off")
858  robot.RunCode("TCP_Off", True)
859  robot.Pause(1000)
860  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
861  robot.MoveL(Pose([250, 200, 278.023897, 180, 0, -150]), [-41.85389, -1.95619, -34.89154, 57.43912, 52.34162, -253.73403] )
862  robot.MoveL(Pose([250, 150, 191.421356, 180, 0, -150]), [-43.82111, 3.29703, -40.29493, 56.02402, 56.61169, -249.23532] )
863  robot.ProgFinish("Program")
864  # robot.ProgSave(".","Program",True)
865  print(robot.PROG_PGX)
866  if len(robot.LOG) > 0:
867  mbox('Program generation LOG:\n\n' + robot.LOG)
868 
869  input("Press Enter to close...")
870 
871 if __name__ == "__main__":
872  """Function to call when the module is executed by itself: test"""
873  test_post()
def MoveJ(self, pose, joints, conf_RLF=None)
Definition: Staubli_S6.py:618
def setFrame(self, pose, frame_id=None, frame_name=None)
Definition: Staubli_S6.py:672
def __init__(self, robotpost=None, robotname=None, robot_axes=6, kwargs)
Definition: Staubli_S6.py:304
def RunMessage(self, message, iscomment=False)
Definition: Staubli_S6.py:766
def setTool(self, pose, tool_id=None, tool_name=None)
Definition: Staubli_S6.py:682
def MoveL(self, pose, joints, conf_RLF=None)
Definition: Staubli_S6.py:637
def mbox(msg, b1='OK', b2='Cancel', frame=True, t=False, entry=None)
Definition: robodk.py:1458
def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None)
Definition: Staubli_S6.py:651
def RunCode(self, code, is_function_call=False)
Definition: Staubli_S6.py:753
def getSaveFolder(strdir='C:\\', strtitle='Save program folder ...')
Definition: Staubli_S6.py:248
def waitDI(self, io_var, io_value, timeout_ms=-1)
Definition: Staubli_S6.py:737
def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass)
Definition: Staubli_S6.py:613
def ProgSave(self, folder, progname, ask_user=False, show_result=False)
Definition: Staubli_S6.py:444


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