45     """Get a safe program name"""    47     for c 
in r'-[]/\;,><&*:%=+@!#^()|?^':
    48         progname = progname.replace(c,
'')
    50     if len(progname) <= 0:
    53     if progname[0].isdigit():
    54         progname = 
'P' + progname
    56     if len(progname) > max_chars:
    57         progname = progname[:max_chars]
    69     """Robot post object defined for Fanuc robots"""    71     MAX_LINES_X_PROG = 9999    
    72     INCLUDE_SUB_PROGRAMS = 
True     95     PROG_NAME_CURRENT = 
'unknown'    105     AXES_TYPE = [
'R','R','R','R','R','R']  # Important: This is usually set up by RoboDK automatically. Otherwise, override the __init__ procedure.   111     HAS_TURNTABLE = 
False   117     def __init__(self, robotpost=None, robotname=None, robot_axes = 6, **kwargs):
   124         for k,v 
in kwargs.items():
   125             if k == 
'lines_x_prog':
   140         progname_i = progname
   145                     print(
"Can't split %s: Two or more programs are split into smaller programs" % progname)
   147                     raise Exception(
"Only one program at a time can be split into smaller programs")
   176         header = header + 
'/ATTR' + 
'\n'   177         header = header + 
'OWNER\t\t= MNEDITOR;' + 
'\n'   178         header = header + 
'COMMENT\t\t= "RoboDK sequence";' + 
'\n'   179         header = header + 
'PROG_SIZE\t= 0;' + 
'\n'   180         header = header + 
'CREATE\t\t= DATE 31-12-14  TIME 12:00:00;' + 
'\n'   181         header = header + 
'MODIFIED\t= DATE 31-12-14  TIME 12:00:00;' + 
'\n'   182         header = header + 
'FILE_NAME\t= ;' + 
'\n'   183         header = header + 
'VERSION\t\t= 0;' + 
'\n'   184         header = header + (
'LINE_COUNT\t= %i;' % (self.
LINE_COUNT)) + 
'\n'   185         header = header + 
'MEMORY_SIZE\t= 0;' + 
'\n'   186         header = header + 
'PROTECT\t\t= READ_WRITE;' + 
'\n'   187         header = header + 
'TCD:  STACK_SIZE\t= 0,' + 
'\n'   188         header = header + 
'      TASK_PRIORITY\t= 50,' + 
'\n'   189         header = header + 
'      TIME_SLICE\t= 0,' + 
'\n'   190         header = header + 
'      BUSY_LAMP_OFF\t= 0,' + 
'\n'   191         header = header + 
'      ABORT_REQUEST\t= 0,' + 
'\n'   192         header = header + 
'      PAUSE_REQUEST\t= 0;' + 
'\n'   193         header = header + 
'DEFAULT_GROUP\t= 1,*,*,*,*;' + 
'\n'     195         header = header + 
'CONTROL_CODE\t= 00000000 00000000;' + 
'\n'   197             header = header + 
'/APPL' + 
'\n'   198             header = header + 
'' + 
'\n'   199             header = header + 
'LINE_TRACK;' + 
'\n'   200             header = header + 
'LINE_TRACK_SCHEDULE_NUMBER      : 0;' + 
'\n'   201             header = header + 
'LINE_TRACK_BOUNDARY_NUMBER      : 0;' + 
'\n'   202             header = header + 
'CONTINUE_TRACK_AT_PROG_END      : FALSE;' + 
'\n'   203             header = header + 
'' + 
'\n'   204         header = header + 
'/MN'   207         self.
PROG.insert(0, header)
   208         self.
PROG.append(
'/POS')
   210         self.
PROG.append(
'/END')
   221     def progsave(self, folder, progname, ask_user = False, show_result = False):
   223         if not folder.endswith(
'/'):
   224             folder = folder + 
'/'   225         progname = progname + 
'.' + self.
PROG_EXT   227             filesave = 
getSaveFile(folder, progname, 
'Save program as...')
   228             if filesave 
is not None:
   229                 filesave = filesave.name
   233             filesave = folder + progname
   234         fid = open(filesave, 
"w")
   236         for line 
in self.
PROG:
   240         print(
'SAVED: %s\n' % filesave) 
   245             if type(show_result) 
is str:
   248                 p = subprocess.Popen([show_result, filesave])
   249             elif type(show_result) 
is list:
   251                 p = subprocess.Popen(show_result + [filesave])   
   255                 os.startfile(filesave)
   260         PATH_MAKE_TP = 
'C:/Program Files (x86)/FANUC/WinOLPC/bin/'   262             filesave_TP = filesave[:-3] + 
'.TP'   263             print(
"POPUP: Compiling LS file with MakeTP.exe: %s..." % progname)
   266             command = [PATH_MAKE_TP + 
'MakeTP.exe', filesave.replace(
'/',
'\\'), filesave_TP.replace(
'/',
'\\'), 
'/config', PATH_MAKE_TP + 
'robot.ini']
   269             self.
LOG += 
'Program generation for: ' + progname + 
'\n'   270             with subprocess.Popen(command, stdout=subprocess.PIPE, bufsize=1, universal_newlines=
True) 
as p:
   271                 for line 
in p.stdout:
   272                     line_ok = line.strip()
   273                     self.
LOG += line_ok + 
'\n'   274                     print(
"POPUP: " + line_ok)
   279     def ProgSave(self, folder, progname, ask_user = False, show_result = False):
   285                 print(
"Warning: ProgFinish was not called properly")
   304             self.
progsave(folder, progname_last, ask_user, show_result)
   322             self.
progsave(folder, progname, ask_user, show_result)
   325             print(
"Warning! Program has not been properly finished")
   326             self.
progsave(folder, progname, ask_user, show_result)
   328         if show_result 
and len(self.
LOG) > 0:
   329             mbox(
'Program generation LOG:\n\n' + self.
LOG)
   332         """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".   333         The connection parameters must be provided in the robot connection menu of RoboDK"""   336     def MoveJ(self, pose, joints, conf_RLF=None):
   337         """Add a joint movement"""   345     def MoveL(self, pose, joints, conf_RLF=None):
   346         """Add a linear movement"""   357             move_ins = 
'P[%i] %s %s ;' % (target_id, self.
SPEED, self.
CNT_VALUE)
   360             move_ins = 
'P[%i] %s %s ;' % (target_id, self.
SPEED, self.
CNT_VALUE)
   365     def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None):
   366         """Add a circular movement"""   371         move_ins = 
'P[%i] \n       P[%i] %s %s ;' % (target_id1, target_id2, self.
SPEED, self.
CNT_VALUE)
   375     def setFrame(self, pose, frame_id=None, frame_name=None):
   376         """Change the robot reference frame"""   378         if frame_id 
is None or frame_id < 0:            
   381             for i 
in range(6,self.
nAxes):
   388             self.
RunMessage(
'UF%i:%.1f,%.1f,%.1f,%.1f,%.1f,%.1f' % (frame_id, xyzwpr[0], xyzwpr[1], xyzwpr[2], xyzwpr[3], xyzwpr[4], xyzwpr[5]), 
True)
   390     def setTool(self, pose, tool_id=None, tool_name=None):
   391         """Change the robot TCP"""   393         if tool_id 
is None or tool_id < 0:
   396             for i 
in range(6,self.
nAxes):
   403             self.
RunMessage(
'UT%i:%.1f,%.1f,%.1f,%.1f,%.1f,%.1f' % (tool_id, xyzwpr[0], xyzwpr[1], xyzwpr[2], xyzwpr[3], xyzwpr[4], xyzwpr[5]), 
True)
   406         """Pause the robot program"""   410             self.
addline(
'WAIT  %.2f(sec) ;' % (time_ms*0.001))
   413         """Changes the robot speed (in mm/s)"""   416             self.
SPEED = 
'%.0fmm/sec' % max(speed_mms, 0.01)
   418             self.
JOINT_SPEED = 
'%.0f%%' % max(min(100.0*speed_mms/5000.0, 100.0), 1) 
   425             self.
JOINT_SPEED = 
'%.0f%%' % max(min(100.0*speed_mms/5000.0, 100.0), 1) 
   428         """Changes the robot acceleration (in mm/s2)"""   429         self.
addlog(
'setAcceleration not defined')
   432         """Changes the robot joint speed (in deg/s)"""   433         self.
addlog(
'setSpeedJoints not defined')
   436         """Changes the robot joint acceleration (in deg/s2)"""   437         self.
addlog(
'setAccelerationJoints not defined')
   440         """Changes the zone data approach (makes the movement more smooth)"""   444             self.
CNT_VALUE = 
'CNT%i' % round(min(zone_mm, 100.0))        
   447         """Sets a variable (output) to a given value"""   448         if type(io_var) != str:  
   449             io_var = 
'DO[%s]' % str(io_var)        
   450         if type(io_value) != str: 
   457         self.
addline(
'%s=%s ;' % (io_var, io_value))
   459     def waitDI(self, io_var, io_value, timeout_ms=-1):
   460         """Waits for an input io_var to attain a given value io_value. Optionally, a timeout can be provided."""   461         if type(io_var) != str:  
   462             io_var = 
'DI[%s]' % str(io_var)        
   463         if type(io_value) != str: 
   471             self.
addline(
'WAIT %s=%s ;' % (io_var, io_value))
   474             self.
addline(
'$WAITTMOUT=%i ;' % round(timeout_ms))
   481         """Add parameters to the last command"""   482         if len(self.
PROG) > 0 
and self.
PROG[-1].endswith(
';\n'):
   483             self.
PROG[-1] = self.
PROG[-1][:-2] + add_params + 
';'    485     def RunCode(self, code, is_function_call = False):
   486         """Adds code or a function call"""   489             if code.startswith(
"ArcStart"):
   490                 if not code.endswith(
')'):
   500                 self.
SPEED = 
'WELD_SPEED'   508             elif code.startswith(
"ArcEnd"):
   520             code.replace(
' ',
'_')
   521             self.
addline(
'CALL %s ;' % (code))
   523             if not code.endswith(
';'):
   528         """Add a joint movement"""   531             for i 
in range(0,len(message), 20):
   532                 i2 = min(i + 20, len(message))
   533                 self.
addline(
'! %s ;' % message[i:i2])
   536             for i 
in range(0,len(message), 20):
   537                 i2 = min(i + 20, len(message))
   538                 self.
addline(
'MESSAGE[%s] ;' % message[i:i2])
   549         """Add a program line"""   556         newline_ok = (
'%4i:%s ' % (self.
LINE_COUNT, movetype)) + newline            
   557         self.
PROG.append(newline_ok)
   560         """Add a line at the end of the program (used for targets)"""   564         """Add a log message"""   567         self.
LOG = self.
LOG + newline + 
'\n'   580         self.
addline_targets(
'\tJ1=    %.3f deg,\tJ2=    %.3f deg,\tJ3=    %.3f deg,' % (joints[0], joints[1], joints[2]))
   581         self.
addline_targets(
'\tJ4=    %.3f deg,\tJ5=    %.3f deg,\tJ6=    %.3f deg%s' % (joints[3], joints[4], joints[5], add_comma))
   586                 track_str = track_str + 
'\tE%i=%10.3f  mm,' % (i+1, joints[self.
AXES_TRACK[i]])
   587             track_str = track_str[:-1]
   595                 turntable_str = turntable_str + 
'\tJ%i=%10.3f deg,' % (i+1, joints[self.
AXES_TURNTABLE[i]])
   596             turntable_str = turntable_str[:-1]
   604         def angle_2_turn(angle):
   606                 return +math.floor((+angle+180.0)/360.0)
   608                 return -math.floor((-angle+180.0)/360.0)
   611         config = [
'N',
'U','T'] #normal        
   613         if conf_RLF 
is not None:
   621         turnJ1 = angle_2_turn(joints[0])
   622         turnJ4 = angle_2_turn(joints[3])
   623         turnJ6 = angle_2_turn(joints[5])       
   631         self.
addline_targets(
'    UF : %i, UT : %i,        CONFIG : \'%c %c %c, %i, %i, %i\',' % (self.
ACTIVE_UF, self.
ACTIVE_UT, config[0], config[1], config[2], turnJ1, turnJ4, turnJ6))        
   632         self.
addline_targets(
'\tX =%10.3f  mm,\tY =%10.3f  mm,\tZ =%10.3f  mm,' % (xyzwpr[0], xyzwpr[1], xyzwpr[2]))
   633         self.
addline_targets(
'\tW =%10.3f deg,\tP =%10.3f deg,\tR =%10.3f deg%s' % (xyzwpr[3], xyzwpr[4], xyzwpr[5], add_comma))
   638                 track_str = track_str + 
'\tE%i=%10.3f  mm,' % (i+1, joints[self.
AXES_TRACK[i]])
   639             track_str = track_str[:-1]
   647                 turntable_str = turntable_str + 
'\tJ%i=%10.3f deg,' % (i+1, joints[self.
AXES_TURNTABLE[i]])
   648             turntable_str = turntable_str[:-1]
   690     [x,y,z,r,p,w] = xyzrpw
   700     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]])
   703     """Test the post with a basic program"""   705     robot = 
RobotPost(
'Fanuc_custom', 
'Fanuc robot', 6)
   707     robot.ProgStart(
"Program")
   708     robot.RunMessage(
"Program generated by RoboDK", 
True)
   709     robot.setFrame(
Pose([807.766544, -963.699898, 41.478944, 0, 0, 0]))
   710     robot.setTool(
Pose([62.5, -108.253175, 100, -60, 90, 0]))
   711     robot.MoveJ(
Pose([200, 200, 500, 180, 0, 180]), [-46.18419, -6.77518, -20.54925, 71.38674, 49.58727, -302.54752] )
   712     robot.MoveL(
Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
   713     robot.MoveL(
Pose([200, 200, 262.132034, 180, 0, -150]), [-43.73892, -3.91728, -35.77935, 58.57566, 54.11615, -253.81122] )
   714     robot.RunMessage(
"Setting air valve 1 on")
   715     robot.RunCode(
"TCP_On", 
True)
   717     robot.MoveL(
Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
   718     robot.MoveL(
Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
   719     robot.MoveL(
Pose([250, 250, 191.421356, 180, 0, -150]), [-39.75778, -1.04537, -40.37883, 52.09118, 54.15317, -246.94403] )
   720     robot.RunMessage(
"Setting air valve off")
   721     robot.RunCode(
"TCP_Off", 
True)
   723     robot.MoveL(
Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
   724     robot.MoveL(
Pose([250, 200, 278.023897, 180, 0, -150]), [-41.85389, -1.95619, -34.89154, 57.43912, 52.34162, -253.73403] )
   725     robot.MoveL(
Pose([250, 150, 191.421356, 180, 0, -150]), [-43.82111, 3.29703, -40.29493, 56.02402, 56.61169, -249.23532] )
   726     robot.ProgFinish(
"Program")
   729     robot.PROG = robot.PROG_LIST.pop()
   730     for line 
in robot.PROG:
   733     if len(robot.LOG) > 0:
   734         mbox(
'Program generation LOG:\n\n' + robot.LOG)
   736     input(
"Press Enter to close...")
   738 if __name__ == 
"__main__":
   739     """Function to call when the module is executed by itself: test""" 
def setAccelerationJoints(self, accel_degss)
def addlastline(self, add_params)
def setSpeedJoints(self, speed_degs)
def setFrame(self, pose, frame_id=None, frame_name=None)
def setZoneData(self, zone_mm)
def setSpeed(self, speed_mms)
def setTool(self, pose, tool_id=None, tool_name=None)
def MoveL(self, pose, joints, conf_RLF=None)
def ProgStart(self, progname, new_page=False)
def get_safe_name(progname, max_chars=10)
def addline_targets(self, newline)
def ProgFinish(self, progname, new_page=False)
def ProgSave(self, folder, progname, ask_user=False, show_result=False)
def UploadFTP(program, robot_ip, remote_path, ftp_user, ftp_pass)
def addline(self, newline, movetype=' ')
def __init__(self, robotpost=None, robotname=None, robot_axes=6, kwargs)
def add_target_joints(self, pose, joints)
def page_size_control(self)
def mbox(msg, b1='OK', b2='Cancel', frame=True, t=False, entry=None)
def add_target_cartesian(self, pose, joints, conf_RLF=None)
def progsave(self, folder, progname, ask_user=False, show_result=False)
def RunMessage(self, message, iscomment=False)
def waitDI(self, io_var, io_value, timeout_ms=-1)
def RunCode(self, code, is_function_call=False)
def MoveJ(self, pose, joints, conf_RLF=None)
def setAcceleration(self, accel_mmss)
def getSaveFile(strdir='C:\\', strfile='file.txt', strtitle='Save file as ...')
def addlog(self, newline)
def setDO(self, io_var, io_value)
def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None)
bool INCLUDE_SUB_PROGRAMS
def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass)