00001
00002
00003 """
00004 Copyright 2013 Southwest Research Institute
00005
00006 Licensed under the Apache License, Version 2.0 (the "License");
00007 you may not use this file except in compliance with the License.
00008 You may obtain a copy of the License at
00009
00010 http://www.apache.org/licenses/LICENSE-2.0
00011
00012 Unless required by applicable law or agreed to in writing, software
00013 distributed under the License is distributed on an "AS IS" BASIS,
00014 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015 See the License for the specific language governing permissions and
00016 limitations under the License.
00017 """
00018
00019
00020 import sys
00021 import os
00022 from Queue import Queue
00023 from threading import Thread, Timer
00024 from xml.etree import ElementTree
00025 import threading
00026 import time
00027 import urllib2
00028 import httplib
00029 import socket
00030
00031
00032 import bridge_library
00033
00034
00035 path, file = os.path.split(__file__)
00036 sys.path.append(os.path.realpath(path) + '/src')
00037 from long_pull import LongPull
00038
00039
00040 import roslib
00041 roslib.load_manifest('mtconnect_msgs')
00042 import rospy
00043 import mtconnect_msgs.msg
00044
00045
00046 import closechuck
00047 import closedoor
00048 import opendoor
00049 import openchuck
00050
00051 class RobotSim():
00052 def __init__(self):
00053
00054 rospy.init_node('robot_link')
00055
00056
00057 bridge_library.check_connectivity((1, 'localhost', 5000))
00058 bridge_library.check_connectivity((1, 'localhost', 5001))
00059
00060
00061 self.XML_CNC_queue = Queue()
00062 self.XML_RBT_queue = Queue()
00063 self.cnc_capture_xml = True
00064 self.rbt_capture_xml = True
00065 self.cnc_conn = httplib.HTTPConnection('localhost', 5000)
00066 self.rbt_conn = httplib.HTTPConnection('localhost', 5001)
00067 self.ns = dict(m = 'urn:mtconnect.org:MTConnectStreams:1.2')
00068 self.data_items = {'MaterialLoad' : 'MaterialLoad', 'MaterialUnload' : 'MaterialUnload'}
00069
00070
00071 cnc_response = bridge_library.xml_get_response(('localhost', 5000, None, self.cnc_conn, "/cnc/current"))
00072 cnc_body = cnc_response.read()
00073
00074
00075 seq, elements = bridge_library.xml_components(cnc_body, self.ns, self.data_items)
00076
00077
00078 cnc_response = bridge_library.xml_get_response(('localhost', 5000, None, self.cnc_conn, "/cnc/sample?interval=1000&count=1000&from=" + seq))
00079
00080
00081 cnc_lp = LongPull(cnc_response)
00082 self.cnc_thread = threading.Thread(target = cnc_lp.long_pull, args = (self.cnc_xml_callback,))
00083 self.cnc_thread.daemon = True
00084 self.cnc_thread.start()
00085 rospy.loginfo('STARTED STREAMING CNC XML THREAD')
00086
00087
00088 rbt_response = bridge_library.xml_get_response(('localhost', 5001, None, self.rbt_conn, "/Robot/current"))
00089 rbt_body = rbt_response.read()
00090
00091
00092 seq, elements = bridge_library.xml_components(rbt_body, self.ns, self.data_items)
00093
00094
00095 rbt_response = bridge_library.xml_get_response(('localhost', 5001, None, self.rbt_conn, "/Robot/sample?interval=1000&count=1000&from=" + seq))
00096
00097
00098 rbt_lp = LongPull(rbt_response)
00099 self.rbt_thread = threading.Thread(target = rbt_lp.long_pull, args = (self.rbt_xml_callback,))
00100 self.rbt_thread.daemon = True
00101 self.rbt_thread.start()
00102 rospy.loginfo('STARTED STREAMING ROBOT XML THREAD')
00103
00104
00105 self.t1 = threading.Thread(target = self.talker)
00106 self.t1.daemon = True
00107 self.t1.start()
00108 rospy.loginfo('STARTED ROBOT INITIALIZATION THREAD')
00109
00110
00111 self.t2 = threading.Thread(target = self.run_actions)
00112 self.t2.daemon = True
00113 self.t2.start()
00114 rospy.loginfo('STARTED STATE MACHINE THREAD')
00115
00116 def stop_thread(self):
00117 self.t1.join()
00118 self.t2.join()
00119 self.cnc_thread.join()
00120 self.rbt_thread.join()
00121 return
00122
00123 def talker(self):
00124 rospy.loginfo('Starting ROS Robot State Publisher Thread')
00125 pub1 = rospy.Publisher('RobotStateTopic', mtconnect_msgs.msg.RobotStates)
00126 pub2 = rospy.Publisher('RobotSpindleTopic', mtconnect_msgs.msg.RobotSpindle)
00127
00128 msg1 = mtconnect_msgs.msg.RobotStates()
00129 msg2 = mtconnect_msgs.msg.RobotSpindle()
00130
00131 while not rospy.is_shutdown():
00132 msg1.header.stamp = rospy.Time.now()
00133 msg1.avail.val = 1
00134 msg1.mode.val = 2
00135 msg1.rexec.val = 1
00136
00137 msg2.c_unclamp.val = 1
00138 msg2.s_inter.val = 1
00139
00140 pub1.publish(msg1)
00141 pub2.publish(msg2)
00142 return
00143
00144 def run_actions(self):
00145 rospy.loginfo('Starting Robot State Machine Thread')
00146 cnc_state = None
00147 robot_state = None
00148 sequence = None
00149
00150 while True:
00151
00152 if not self.XML_CNC_queue.empty():
00153 cnc_body = self.XML_CNC_queue.get()
00154 cnc_root = ElementTree.fromstring(cnc_body)
00155 tokenML = cnc_root.findall('.//m:MaterialLoad', namespaces = self.ns)
00156 tokenMUL = cnc_root.findall('.//m:MaterialUnload', namespaces = self.ns)
00157
00158 if tokenML and tokenML[0].text == 'ACTIVE':
00159 if sequence is None:
00160 sequence = 'MaterialLoad'
00161 cnc_state = tokenML[0].text
00162 self.cnc_capture_xml = False
00163 rospy.loginfo('CNC XML %s --> %s' % (sequence, tokenML[0].text))
00164 elif tokenMUL and tokenMUL[0].text == 'ACTIVE':
00165 if sequence is None:
00166 sequence = 'MaterialUnload'
00167 cnc_state = tokenMUL[0].text
00168 self.cnc_capture_xml = False
00169 rospy.loginfo('CNC XML %s --> %s' % (sequence, tokenMUL[0].text))
00170
00171
00172 self.XML_CNC_queue.task_done()
00173
00174
00175
00176 if not self.XML_RBT_queue.empty():
00177 rbt_body = self.XML_RBT_queue.get()
00178 rbt_root = ElementTree.fromstring(rbt_body)
00179 tokenML = rbt_root.findall('.//m:MaterialLoad', namespaces = self.ns)
00180 tokenMUL = rbt_root.findall('.//m:MaterialUnload', namespaces = self.ns)
00181
00182 if tokenML and tokenML[0].text == 'ACTIVE':
00183 if sequence is None:
00184 sequence = 'MaterialLoad'
00185 robot_state = tokenML[0].text
00186 self.rbt_capture_xml = False
00187 rospy.loginfo('ROBOT XML %s --> %s' % (sequence, tokenML[0].text))
00188 elif tokenMUL and tokenMUL[0].text == 'ACTIVE':
00189 if sequence is None:
00190 sequence = 'MaterialUnload'
00191 robot_state = tokenMUL[0].text
00192 self.rbt_capture_xml = False
00193 rospy.loginfo('ROBOT XML %s --> %s' % (sequence, tokenMUL[0].text))
00194
00195 self.XML_RBT_queue.task_done()
00196
00197
00198 if cnc_state == 'ACTIVE' and robot_state == 'ACTIVE' and sequence == 'MaterialLoad':
00199 rospy.loginfo('Starting Action Clients required by Material Load')
00200
00201
00202
00203
00204 closechuck.close_chuck_client()
00205 rospy.loginfo('CloseChuck Action Completed')
00206
00207
00208 self.cnc_capture_xml = True
00209 self.rbt_capture_xml = True
00210
00211
00212 closedoor.close_door_client()
00213 rospy.loginfo('CloseDoor Action Completed')
00214
00215
00216 cnc_state = None
00217 robot_state = None
00218 sequence = None
00219
00220
00221 if cnc_state == 'ACTIVE' and robot_state == 'ACTIVE' and sequence == 'MaterialUnload':
00222 rospy.loginfo('Starting Action Clients required by Material Unload')
00223
00224
00225 opendoor.open_door_client()
00226 rospy.loginfo('OpenDoor Action Completed')
00227
00228
00229 self.cnc_capture_xml = True
00230 self.rbt_capture_xml = True
00231
00232
00233 openchuck.open_chuck_client()
00234 rospy.loginfo('OpenChuck Action Completed')
00235
00236
00237 cnc_state = None
00238 robot_state = None
00239 sequence = None
00240
00241
00242 time.sleep(5)
00243 return
00244
00245 def cnc_xml_callback(self, chunk):
00246
00247 if self.cnc_capture_xml == True:
00248 try:
00249 self.XML_CNC_queue.put(chunk)
00250 rospy.loginfo('PUTTING CNC XML INTO QUEUE. NUMBER OF QUEUED OBJECTS %s' % self.XML_CNC_queue.qsize())
00251 if self.XML_CNC_queue.qsize() > 1:
00252 rospy.loginfo('STORED CNC XML INTO QUEUE, WAITING ON ROS ACTION SERVER, QUEUE SIZE --> %s' % self.XML_CNC_queue.qsize())
00253 except Exception as e:
00254 rospy.logerr("Robot Simulation: CNC XML Queue callback failed: %s, releasing lock" % e)
00255 finally:
00256 pass
00257
00258 return
00259
00260 def rbt_xml_callback(self, chunk):
00261
00262 if self.rbt_capture_xml == True:
00263 try:
00264 self.XML_RBT_queue.put(chunk)
00265 rospy.loginfo('PUTTING ROBOT XML INTO QUEUE. NUMBER OF QUEUED OBJECTS %s' % self.XML_RBT_queue.qsize())
00266 if self.XML_RBT_queue.qsize() > 1:
00267 rospy.loginfo('STORED ROBOT XML INTO QUEUE, WAITING ON ROS ACTION SERVER, QUEUE SIZE --> %s' % self.XML_RBT_queue.qsize())
00268 except Exception as e:
00269 rospy.logerr("Robot Simulation: ROBOT XML Queue callback failed: %s, releasing lock" % e)
00270 finally:
00271 pass
00272
00273 return
00274
00275
00276 if __name__ == '__main__':
00277 try:
00278 rospy.loginfo('Launching robot_link node, CTRL-C to terminate')
00279 simulator = RobotSim()
00280 rospy.spin()
00281 except rospy.ROSInterruptException:
00282 RobotSim.stop_thread()