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 import optparse
00023 import yaml
00024 import operator
00025 import thread
00026 import re
00027 import time
00028 from importlib import import_module
00029
00030
00031 import bridge_library
00032
00033
00034 path, file = os.path.split(__file__)
00035 sys.path.append(os.path.realpath(path) + '/src')
00036 from data_item import Event, SimpleCondition, Sample, ThreeDSample
00037 from mtconnect_adapter import Adapter
00038
00039
00040 import roslib
00041 import rospy
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 class BridgeSubscriber():
00063
00064 def __init__(self):
00065
00066 rospy.init_node('bridge_subscriber')
00067
00068
00069 self.config = bridge_library.obtain_dataMap()
00070 self.msg_parameters = ['url', 'adapter_port']
00071 self.url = self.config[self.msg_parameters[0]]
00072 self.adapter_port = self.config[self.msg_parameters[1]]
00073
00074
00075 self.adapter = Adapter((self.url, self.adapter_port))
00076 self.di_dict = {}
00077
00078
00079 self.topic_name_list = []
00080 self.subscribed_list = []
00081 self.lib_manifests = []
00082
00083
00084 self.topic_type_list = {}
00085 self.member_types = {}
00086 self.member_names = {}
00087
00088
00089 self.msg_text = {}
00090
00091
00092 self.setup_topic_data()
00093
00094
00095 rospy.loginfo('Start the Robot Link adapter')
00096 self.adapter.start()
00097
00098
00099 self.lock = thread.allocate_lock()
00100
00101
00102 topic_list = self.topic_name_list
00103 dwell = 10
00104 while topic_list:
00105 published_topics = dict(rospy.get_published_topics())
00106 for topic_name in topic_list:
00107 if topic_name in published_topics.keys():
00108
00109 idx = topic_list.index(topic_name)
00110 del topic_list[idx]
00111 self.topic_listener((topic_name, self.topic_type_list[topic_name], self.member_names[topic_name], self.msg_text[topic_name]))
00112 else:
00113 rospy.loginfo('ROS Topic %s not available, will try to subscribe in %d seconds' % (topic_name, dwell))
00114 time.sleep(dwell)
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 def setup_topic_data(self):
00126 for topic, topic_type in self.config.items():
00127 if topic not in self.msg_parameters:
00128 self.topic_name_list.append(topic)
00129
00130
00131 type_key = topic_type.keys()[0]
00132 self.subscribed_list.append(type_key)
00133
00134
00135 self.data_items = [data_item for data_item in topic_type[type_key].keys()]
00136
00137
00138 bridge_library.add_event((self.adapter, self.data_items, self.di_dict, False))
00139
00140
00141 tokens = topic_type.keys()[0].split('/')
00142 package = tokens[0]
00143 type_name = tokens[1]
00144
00145
00146 if package not in self.lib_manifests:
00147 roslib.load_manifest(package)
00148 self.lib_manifests.append(package)
00149
00150
00151
00152 rospy.loginfo('Class Instance --> ' + package + '.msg.' + type_name)
00153 type_handle = getattr(import_module(package + '.msg'), type_name)
00154
00155 self.topic_type_list[topic] = type_handle
00156 self.msg_text[topic] = type_handle._full_text
00157 self.member_types[topic] = type_handle._slot_types
00158 self.member_names[topic] = type_handle.__slots__
00159 return
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 def topic_callback(self, data, cb_data):
00176 self.lock.acquire()
00177 try:
00178 (topic_name, type_handle, member_set, msg_text) = cb_data
00179 type_name = type_handle._type
00180
00181
00182 dout = {val:val for val in member_set}
00183
00184
00185 msg_data = []
00186 msg_constants = {}
00187 for dataitem in member_set:
00188
00189 attrib_handle = getattr(type_handle(), dataitem)
00190
00191 if 'header' not in dataitem:
00192
00193 val_key = attrib_handle.__slots__[0]
00194
00195
00196 token = getattr(data, dataitem)
00197
00198
00199 item_value = getattr(token, val_key)
00200
00201
00202 msg_data.append((dataitem, item_value))
00203
00204
00205 msg_constants[dataitem] = []
00206 for attrib in dir(attrib_handle):
00207 if attrib.isupper():
00208 if getattr(attrib_handle, attrib) == item_value:
00209 msg_constants[dataitem].append(attrib)
00210
00211
00212 self.data_item_conversion(topic_name, type_name, msg_data, msg_text, msg_constants)
00213
00214 except Exception as e:
00215 rospy.logerr('Topic callback failed: %s, releasing lock' % e)
00216 finally:
00217 self.lock.release()
00218 return
00219
00220
00221
00222
00223
00224
00225
00226
00227 def data_item_conversion(self, topic_name, type_name, msg_data, msg_text, constants):
00228
00229 for member_data in msg_data:
00230
00231
00232 for const_val in constants[member_data[0]]:
00233 if const_val in self.config[topic_name][type_name][member_data[0]].keys():
00234
00235 adapter_val = self.config[topic_name][type_name][member_data[0]][const_val]
00236 break
00237 else:
00238 adapter_val = None
00239
00240 if adapter_val is None:
00241 rospy.logerr('ROS to MTConnect Mapping failed')
00242
00243
00244 bridge_library.action_cb((self.adapter, self.di_dict, member_data[0], adapter_val))
00245 return
00246
00247
00248
00249
00250
00251
00252
00253 def topic_listener(self, data):
00254
00255 topic_name, type_handle, member_set, msg_text = data
00256
00257
00258 rospy.Subscriber(topic_name, type_handle, self.topic_callback, data)
00259 return
00260
00261
00262
00263 if __name__ == '__main__':
00264 try:
00265 rospy.loginfo('Executing robot topic subscriber')
00266 robot_topic = BridgeSubscriber()
00267 rospy.spin()
00268 except rospy.ROSInterruptException:
00269 pass