6 from collections
import Iterable
8 from mir_driver
import rosbridge
9 from rospy_message_converter
import message_converter
11 from actionlib_msgs.msg
import GoalID, GoalStatusArray
12 from diagnostic_msgs.msg
import DiagnosticArray, DiagnosticStatus
13 from dynamic_reconfigure.msg
import Config, ConfigDescription
14 from geometry_msgs.msg
import PolygonStamped, Pose, PoseArray, PoseStamped, PoseWithCovarianceStamped, Twist
17 from move_base_msgs.msg
import MoveBaseActionFeedback, MoveBaseActionGoal, MoveBaseActionResult, MoveBaseFeedback, MoveBaseResult
18 from nav_msgs.msg
import GridCells, MapMetaData, OccupancyGrid, Odometry, Path
19 from rosgraph_msgs.msg
import Log
20 from sdc21x0.msg
import MotorCurrents
21 from sensor_msgs.msg
import Imu, LaserScan, PointCloud2, Range
22 from std_msgs.msg
import Float64, String
23 from tf.msg
import tfMessage
24 from visualization_msgs.msg
import Marker, MarkerArray
29 def __init__(self, topic, topic_type, latch=False, dict_filter=None):
39 filtered_msg_dict = copy.deepcopy(msg_dict)
40 filtered_msg_dict[
'feedback'] = {key: msg_dict[
'feedback'][key]
for key
in MoveBaseFeedback.__slots__}
41 return filtered_msg_dict
44 filtered_msg_dict = copy.deepcopy(msg_dict)
45 filtered_msg_dict[
'result'] = {key: msg_dict[
'result'][key]
for key
in MoveBaseResult.__slots__}
46 return filtered_msg_dict
49 filtered_msg_dict = copy.deepcopy(msg_dict)
50 for transform
in filtered_msg_dict[
'transforms']:
51 transform[
'child_frame_id'] = tf_prefix +
'/' + transform[
'child_frame_id'].strip(
'/')
52 return filtered_msg_dict
56 if not isinstance(msg_dict, dict):
58 for (key, value)
in msg_dict.iteritems():
62 frame_id = value[
'frame_id'].strip(
'/')
63 if (frame_id !=
'map'):
65 value[
'frame_id'] = (tf_prefix +
'/' + frame_id).strip(
'/')
67 value[
'frame_id'] = frame_id
73 elif isinstance(value, dict):
75 elif isinstance(value, Iterable):
82 if not isinstance(msg_dict, dict):
84 for (key, value)
in msg_dict.iteritems():
88 s = value[
'frame_id'].strip(
'/')
89 if s.find(tf_prefix) == 0:
90 value[
'frame_id'] = (s[len(tf_prefix):]).strip(
'/')
95 elif isinstance(value, dict):
97 elif isinstance(value, Iterable):
108 TopicConfig(
'MissionController/CheckArea/visualization_marker', Marker),
109 TopicConfig(
'SickPLC/parameter_descriptions', ConfigDescription),
111 TopicConfig(
'amcl_pose', PoseWithCovarianceStamped),
114 TopicConfig(
'camera_floor/background', PointCloud2),
115 TopicConfig(
'camera_floor/depth/parameter_descriptions', ConfigDescription),
116 TopicConfig(
'camera_floor/depth/parameter_updates', Config),
117 TopicConfig(
'camera_floor/depth/points', PointCloud2),
118 TopicConfig(
'camera_floor/filter/parameter_descriptions', ConfigDescription),
119 TopicConfig(
'camera_floor/filter/parameter_updates', Config),
121 TopicConfig(
'camera_floor/obstacles', PointCloud2),
122 TopicConfig(
'camera_floor/transform/parameter_descriptions', ConfigDescription),
123 TopicConfig(
'camera_floor/transform/parameter_updates', Config),
127 TopicConfig(
'diagnostics_toplevel_state', DiagnosticStatus),
131 TopicConfig(
'laser_back/driver/parameter_descriptions', ConfigDescription),
132 TopicConfig(
'laser_back/driver/parameter_updates', Config),
133 TopicConfig(
'laser_back/transform/parameter_descriptions', ConfigDescription),
134 TopicConfig(
'laser_back/transform/parameter_updates', Config),
135 TopicConfig(
'laser_front/driver/parameter_descriptions', ConfigDescription),
136 TopicConfig(
'laser_front/driver/parameter_updates', Config),
137 TopicConfig(
'laser_front/transform/parameter_descriptions', ConfigDescription),
138 TopicConfig(
'laser_front/transform/parameter_updates', Config),
141 TopicConfig(
'mir_amcl/parameter_descriptions', ConfigDescription),
143 TopicConfig(
'mir_amcl/selected_points', PointCloud2),
150 TopicConfig(
'mirwebapp/grid_map_metadata', LocalMapStat),
151 TopicConfig(
'mirwebapp/laser_map_metadata', LocalMapStat),
154 TopicConfig(
'move_base/feedback', MoveBaseActionFeedback, dict_filter=_move_base_feedback_dict_filter),
155 TopicConfig(
'move_base/result', MoveBaseActionResult, dict_filter=_move_base_result_dict_filter),
160 TopicConfig(
'move_base_node/MIRPlannerROS/local_plan', Path),
163 TopicConfig(
'move_base_node/SBPLLatticePlanner/plan', Path),
165 TopicConfig(
'move_base_node/current_goal', PoseStamped),
175 TopicConfig(
'move_base_node/local_costmap/inflated_obstacles', GridCells),
176 TopicConfig(
'move_base_node/local_costmap/obstacles', GridCells),
179 TopicConfig(
'move_base_node/local_costmap/robot_footprint', PolygonStamped),
187 TopicConfig(
'relative_move_action/feedback', RelativeMoveActionFeedback),
188 TopicConfig(
'relative_move_action/result', RelativeMoveActionResult),
189 TopicConfig(
'relative_move_action/status', GoalStatusArray),
190 TopicConfig(
'relative_move_node/parameter_descriptions', ConfigDescription),
191 TopicConfig(
'relative_move_node/parameter_updates', Config),
192 TopicConfig(
'relative_move_node/time_to_coll', Float64),
193 TopicConfig(
'relative_move_node/visualization_marker', Marker),
200 TopicConfig(
'scan_filter/visualization_marker', Marker),
201 TopicConfig(
'tf', tfMessage, dict_filter=_tf_dict_filter),
202 TopicConfig(
'transform_footprint/parameter_descriptions', ConfigDescription),
203 TopicConfig(
'transform_footprint/parameter_updates', Config),
204 TopicConfig(
'transform_imu/parameter_descriptions', ConfigDescription),
205 TopicConfig(
'transform_imu/parameter_updates', Config)]
209 TopicConfig(
'initialpose', PoseWithCovarianceStamped),
216 TopicConfig(
'relative_move_action/cancel', GoalID),
217 TopicConfig(
'relative_move_action/goal', RelativeMoveActionGoal)]
224 self.
pub = rospy.Publisher(name=topic_config.topic,
225 data_class=topic_config.topic_type,
226 subscriber_listener=self,
227 latch=topic_config.latch,
229 rospy.loginfo(
"[%s] publishing topic '%s' [%s]",
230 rospy.get_name(), topic_config.topic, topic_config.topic_type._type)
232 if topic_config.latch:
239 rospy.loginfo(
"[%s] starting to stream messages on topic '%s'", rospy.get_name(), self.topic_config.topic)
240 self.robot.subscribe(topic=(
'/' + self.topic_config.topic), callback=self.callback)
252 if self.topic_config.dict_filter
is not None:
253 msg_dict = self.topic_config.dict_filter(msg_dict)
254 msg = message_converter.convert_dictionary_to_ros_message(self.topic_config.topic_type._type, msg_dict)
255 self.pub.publish(msg)
261 self.
sub = rospy.Subscriber(name=topic_config.topic,
262 data_class=topic_config.topic_type,
265 rospy.loginfo(
"[%s] subscribing to topic '%s' [%s]",
266 rospy.get_name(), topic_config.topic, topic_config.topic_type._type)
269 msg_dict = message_converter.convert_ros_message_to_dictionary(msg)
271 if self.topic_config.dict_filter
is not None:
272 msg_dict = self.topic_config.dict_filter(msg_dict)
273 self.robot.publish(
'/' + self.topic_config.topic, msg_dict)
278 hostname = rospy.get_param(
'~hostname')
280 rospy.logfatal(
'[%s] parameter "hostname" is not set!', rospy.get_name())
282 port = rospy.get_param(
'~port', 9090)
285 tf_prefix = rospy.get_param(
'~tf_prefix',
'').strip(
'/')
287 rospy.loginfo(
'[%s] trying to connect to %s:%i...', rospy.get_name(), hostname, port)
288 self.
robot = rosbridge.RosbridgeSetup(hostname, port)
292 while not self.robot.is_connected():
293 if rospy.is_shutdown():
295 if self.robot.is_errored():
296 rospy.logfatal(
'[%s] connection error to %s:%i, giving up!', rospy.get_name(), hostname, port)
299 rospy.logwarn(
'[%s] still waiting for connection to %s:%i...', rospy.get_name(), hostname, port)
303 rospy.loginfo(
'[%s] ... connected.', rospy.get_name())
306 published_topics = [topic_name
for (topic_name, _, has_publishers, _)
in topics
if has_publishers]
307 subscribed_topics = [topic_name
for (topic_name, _, _, has_subscribers)
in topics
if has_subscribers]
309 for pub_topic
in PUB_TOPICS:
311 if (
'/' + pub_topic.topic)
not in published_topics:
312 rospy.logwarn(
"[%s] topic '%s' is not published by the MiR!", rospy.get_name(), pub_topic.topic)
314 for sub_topic
in SUB_TOPICS:
316 if (
'/' + sub_topic.topic)
not in subscribed_topics:
317 rospy.logwarn(
"[%s] topic '%s' is not yet subscribed to by the MiR!", rospy.get_name(), sub_topic.topic)
320 srv_response = self.robot.callService(
'/rosapi/topics', msg={})
321 topic_names = sorted(srv_response[
'topics'])
324 for topic_name
in topic_names:
325 srv_response = self.robot.callService(
"/rosapi/topic_type", msg={
'topic': topic_name})
326 topic_type = srv_response[
'type']
328 srv_response = self.robot.callService(
"/rosapi/publishers", msg={
'topic': topic_name})
329 has_publishers =
True if len(srv_response[
'publishers']) > 0
else False 331 srv_response = self.robot.callService(
"/rosapi/subscribers", msg={
'topic': topic_name})
332 has_subscribers =
True if len(srv_response[
'subscribers']) > 0
else False 334 topics.append([topic_name, topic_type, has_publishers, has_subscribers])
337 for (topic_name, topic_type, has_publishers, has_subscribers)
in topics:
339 print ' * %s [%s]' % (topic_name, topic_type)
341 print '\nSubscribers:' 342 for (topic_name, topic_type, has_publishers, has_subscribers)
in topics:
344 print ' * %s [%s]' % (topic_name, topic_type)
350 rospy.init_node(
'mir_bridge')
354 if __name__ ==
'__main__':
357 except rospy.ROSInterruptException:
def peer_subscribe(self, topic_name, topic_publish, peer_publish)
def _move_base_feedback_dict_filter(msg_dict)
def __init__(self, topic_config, robot)
def __init__(self, topic_config, robot)
def __init__(self, topic, topic_type, latch=False, dict_filter=None)
def peer_unsubscribe(self, topic_name, num_peers)
def callback(self, msg_dict)
doesn't work: once ubsubscribed, robot doesn't let us subscribe again if self.connected and self...
def _prepend_tf_prefix_dict_filter(msg_dict)
def _tf_dict_filter(msg_dict)
def _move_base_result_dict_filter(msg_dict)
def _remove_tf_prefix_dict_filter(msg_dict)