rosConfigurator.py
Go to the documentation of this file.
00001 # MIT License
00002 #
00003 # Copyright (c) <2015> <Ikergune, Etxetar>
00004 #
00005 # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
00006 # (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge,
00007 # publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
00008 # subject to the following conditions:
00009 #
00010 # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
00011 #
00012 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00013 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
00014 # FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00015 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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 # map_regex = re.compile(ur'^.*\/(map)[\/]*$')
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     ## \brief Tool to get Ros data from system
00040 
00041     @staticmethod
00042     def getMapTopics():
00043         ## \brief Get topics that are maps
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         ## \brief Get topic's data type
00062         # \param topic
00063         # \param topic types
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         ## \brief Set robot in robot container based on whitelist and topic lifecycle
00077         # \param local robot dictionary
00078         # \param topic name
00079         # \param topic type
00080         # \param publisher/subscriber action
00081         # \param whitelist regular expresions
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         ## \brief Remove robot from list
00116         # \param robot name
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         ## \brief Get existing topics and return in a map grouped by namespace
00125         # \param refresh list
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                 # ROS publisher --> firos subscribes to listen data published
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                 # ROS subscriber --> firos publishes data to them
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


firos
Author(s): IƱigo Gonzalez, igonzalez@ikergune.com
autogenerated on Thu Jun 6 2019 17:51:04