00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 import os
00018 import re
00019 import json
00020 import socket
00021 import rostopic
00022 import rosgraph
00023
00024 from include.constants import NODE_NAME
00025
00026
00027 map_regex = re.compile(ur'^.*\/(map).*$')
00028 topic_regex = re.compile(ur'^\/([\w]+)\/*([\/\-\w]*)$')
00029 substitution_regex = re.compile(ur'^([\/\-\w]*)\/([\w]+)$')
00030 robots = {}
00031 ROBO_TOPIC_REG = {}
00032
00033 CURRENT_TOPIC_REG = {}
00034
00035 mem_whitelist = None
00036
00037
00038 class RosConfigurator:
00039
00040
00041 @staticmethod
00042 def getMapTopics():
00043
00044
00045 master = rosgraph.Master('/rostopic')
00046 maps = []
00047 try:
00048 state = master.getSystemState()
00049
00050 pubs, subs, _ = state
00051
00052 for topic_name, l in pubs:
00053 if re.search(map_regex, topic_name):
00054 maps.append(topic_name)
00055 except socket.error:
00056 raise rostopic.ROSTopicIOException("Unable to communicate with master!")
00057 return maps
00058
00059 @staticmethod
00060 def topic_type(t, topic_types):
00061
00062
00063
00064 matches = [t_type for t_name, t_type in topic_types if t_name == t]
00065 if matches:
00066 text = re.search(substitution_regex, str(matches[0]))
00067 if text is not None:
00068 return str(text.group(1)) + ".msg." + str(text.group(2))
00069 else:
00070 return matches[0].replace("msgs/", "msgs.msg.").replace("/", ".msg.")
00071
00072 return 'unknown type'
00073
00074 @staticmethod
00075 def setRobot(_robots, topic, t_type, pubsub, whiteLists):
00076
00077
00078
00079
00080
00081
00082 global ROBO_TOPIC_REG
00083 global robots
00084 matching = re.search(topic_regex, topic)
00085 robot_topic = matching.group(2)
00086 if robot_topic != '':
00087 robot_name = matching.group(1)
00088 if (whiteLists[pubsub] is not None and re.search(whiteLists[pubsub], topic) is not None) or (whiteLists[pubsub] is None):
00089 if robot_name not in ROBO_TOPIC_REG:
00090 ROBO_TOPIC_REG[robot_name] = {"topics": []}
00091 if robot_name not in CURRENT_TOPIC_REG:
00092 CURRENT_TOPIC_REG[robot_name] = {"topics": []}
00093
00094 if robot_name not in _robots:
00095 _robots[robot_name] = {"topics": {}}
00096
00097 if robot_topic not in _robots[robot_name]["topics"]:
00098 CURRENT_TOPIC_REG[robot_name]["topics"].append(robot_topic)
00099 _robots[robot_name]["topics"][robot_topic] = {
00100 "msg": t_type,
00101 "type": pubsub
00102 }
00103
00104 if robot_name not in robots:
00105 robots[robot_name] = {"topics": {}}
00106 if robot_topic not in robots[robot_name]["topics"]:
00107 ROBO_TOPIC_REG[robot_name]["topics"].append(robot_topic)
00108 robots[robot_name]["topics"][robot_topic] = {
00109 "msg": t_type,
00110 "type": pubsub
00111 }
00112
00113 @staticmethod
00114 def removeRobot(robot_name):
00115
00116
00117 global robots
00118 if robot_name in robots:
00119 del robots[robot_name]
00120 del ROBO_TOPIC_REG[robot_name]
00121
00122 @staticmethod
00123 def systemTopics(refresh=False):
00124
00125
00126 global robots
00127 global CURRENT_TOPIC_REG
00128 CURRENT_TOPIC_REG = {}
00129 if refresh:
00130 existing_topics = {
00131 "publisher": {},
00132 "subscriber": {}
00133 }
00134 whiteLists = getWhiteLists()
00135 _robots = {}
00136 master = rosgraph.Master('/rostopic')
00137 try:
00138 state = master.getSystemState()
00139 topic_types = rostopic._master_get_topic_types(master)
00140
00141 pubs, subs, _ = state
00142
00143 for t, l in pubs:
00144 existing_topics["publisher"][t] = l
00145 for t, l in subs:
00146 existing_topics["subscriber"][t] = l
00147
00148
00149 for t, l in pubs:
00150 subscribing = _isInFiros(t, existing_topics["subscriber"], l)
00151 publishing = _isInFiros(t, existing_topics["publisher"], l)
00152 if not subscribing and not publishing:
00153 _type = RosConfigurator.topic_type(t, topic_types)
00154 RosConfigurator.setRobot(_robots, t, _type, "subscriber", whiteLists)
00155 RosConfigurator.setRobot(_robots, t, _type, "publisher", whiteLists)
00156
00157
00158 for t, l in subs:
00159 subscribing = _isInFiros(t, existing_topics["subscriber"], l)
00160 publishing = _isInFiros(t, existing_topics["publisher"], l)
00161 if not subscribing and not publishing:
00162 _type = RosConfigurator.topic_type(t, topic_types)
00163 RosConfigurator.setRobot(_robots, t, _type, "publisher", whiteLists)
00164 RosConfigurator.setRobot(_robots, t, _type, "subscriber", whiteLists)
00165
00166 except socket.error:
00167 raise rostopic.ROSTopicIOException("Unable to communicate with master!")
00168
00169 return _robots
00170 else:
00171 return robots
00172
00173
00174 def setWhiteList(additions, deletions, restore=False):
00175 global mem_whitelist
00176 if mem_whitelist is None:
00177 try:
00178 current_path = os.path.dirname(os.path.abspath(__file__))
00179 json_path = current_path.replace("scripts/include/ros", "config/whitelist.json")
00180 mem_whitelist = json.load(open(json_path))
00181 except:
00182 mem_whitelist = {}
00183 if additions:
00184 for robot_name in additions:
00185 mem_whitelist[robot_name] = additions[robot_name]
00186 if deletions:
00187 for robot_name in deletions:
00188 if robot_name in mem_whitelist:
00189 for topic in deletions[robot_name]["publisher"]:
00190 if topic in mem_whitelist[robot_name]["publisher"]:
00191 mem_whitelist[robot_name]["publisher"].remove(topic)
00192 for topic in deletions[robot_name]["subscriber"]:
00193 if topic in mem_whitelist[robot_name]["subscriber"]:
00194 mem_whitelist[robot_name]["subscriber"].remove(topic)
00195 if restore:
00196 mem_whitelist = None
00197
00198
00199 def _isInFiros(topic_name, list2Check, nodes):
00200 using = False
00201 if topic_name not in list2Check:
00202 return False
00203 for node in list2Check[topic_name]:
00204 if node == "/" + NODE_NAME:
00205 using = True
00206 break
00207
00208 return using
00209
00210
00211 def getWhiteLists():
00212 return {
00213 "publisher": _getWhiteList("publisher"),
00214 "subscriber": _getWhiteList("subscriber")
00215 }
00216
00217
00218 def _getWhiteList(pubsub):
00219 try:
00220 if mem_whitelist is None:
00221 current_path = os.path.dirname(os.path.abspath(__file__))
00222 json_path = current_path.replace("scripts/include/ros", "config/whitelist.json")
00223 data = json.load(open(json_path))
00224 else:
00225 data = mem_whitelist
00226
00227 whiteregex = ur''
00228 for robot_name in data:
00229 for topic in data[robot_name][pubsub]:
00230 whiteregex += '(/' + robot_name + '/' + topic + ')|'
00231 whiteregex = whiteregex[:-1]
00232 whiteregex += "$"
00233 whiteregex = ur'^' + whiteregex
00234 return whiteregex
00235 except:
00236 return None