00001
00002
00003 import os
00004 import rocon_python_utils
00005 import rospkg
00006 import rospy
00007 import subprocess
00008 import tempfile
00009
00010 from concert_service_gazebo import RobotManager
00011 from gateway_msgs.msg import Rule, ConnectionType
00012 from gazebo_msgs.srv import DeleteModel, DeleteModelRequest
00013
00014 def reformat_position_vector(position_vector):
00015 """
00016 Reformats position vector so that it can be used with the segbot launch script
00017 """
00018 if len(position_vector) == 2:
00019 return [position_vector[0],
00020 position_vector[1],
00021 0.0, 0.0, 0.0, 0.0]
00022 if len(position_vector) == 3:
00023 return [position_vector[0],
00024 position_vector[1],
00025 0.0, 0.0, 0.0,
00026 position_vector[2]]
00027 return [position_vector[x] if x < len(position_vector) else 0.0 for x in range(6)]
00028
00029 def generate_spawn_robot_launch_script(name, gazebo_name, location,
00030 use_full_gazebo_model=False,
00031 configuration_file=None):
00032 """
00033 Generates the roslaunch script for a single robot, wrapping the appropriate
00034 launch file in segbot_gazebo
00035 """
00036 launch_text = '<launch>\n'
00037 launch_text += ' <group ns="%s">\n' % name
00038 launch_text += ' <include file="$(find segbot_gazebo)/launch/segbot_mobile_base.launch">'
00039 launch_text += ' <arg name="world" value="%s"/>\n' % gazebo_name
00040 launch_text += ' <arg name="robotid" value="%s"/>\n' % name
00041 launch_text += ' <arg name="tf_prefix" value="/%s"/>\n' % name
00042 launch_text += ' <arg name="x" value="%s"/>\n' % location[0]
00043 launch_text += ' <arg name="y" value="%s"/>\n' % location[1]
00044 launch_text += ' <arg name="z" value="%s"/>\n' % location[2]
00045 launch_text += ' <arg name="roll" value="%s"/>\n' % location[3]
00046 launch_text += ' <arg name="pitch" value="%s"/>\n' % location[4]
00047 launch_text += ' <arg name="yaw" value="%s"/>\n' % location[5]
00048 if use_full_gazebo_model:
00049 launch_text += ' <arg name="use_full_gazebo_model" value="true"/>\n'
00050 else:
00051 launch_text += ' <arg name="use_full_gazebo_model" value="false"/>\n'
00052 if configuration_file:
00053 launch_text += ' <arg name="configuration_file" value="%s"/>\n' % configuration_file
00054 launch_text += ' </include>\n'
00055 launch_text += ' </group>\n'
00056 launch_text += '</launch>\n'
00057 return launch_text
00058
00059 def start_roslaunch_process(launch_script):
00060 """
00061 Robots are spawned using roslaunch instead of gazebo/spawn_model so that
00062 a few other scripts such as robot_state_publisher can also be launched.
00063 This convenience function helps launch a roslaunch script
00064 """
00065 temp = tempfile.NamedTemporaryFile(mode='w+t', delete=False)
00066 temp.write(launch_script)
00067 temp.close()
00068 command_args = ['roslaunch', temp.name]
00069 command_args.append('--screen')
00070 roslaunch_env = os.environ.copy()
00071 try:
00072
00073
00074 del roslaunch_env['ROS_NAMESPACE']
00075 except KeyError:
00076 pass
00077 process = subprocess.Popen(command_args, env=roslaunch_env)
00078 return process
00079
00080 class SegbotManager(RobotManager):
00081
00082 def __init__(self, namespace = '/'):
00083 rospy.wait_for_service(namespace + 'gazebo/delete_model')
00084 self.delete_model = rospy.ServiceProxy(namespace + 'gazebo/delete_model', DeleteModel)
00085 self.namespace = namespace
00086 self.use_full_gazebo_model = rospy.get_param('use_full_gazebo_model', False)
00087 self.configuration_file = rospy.get_param('configuration_file', None)
00088 if self.configuration_file != None:
00089 try:
00090 self.configuration_file = rocon_python_utils.ros.find_resource_from_string(self.configuration_file)
00091 except rospkg.ResourceNotFound:
00092 raise rospkg.ResourceNotFound("could not resolve configuration file [%s]" % self.configuration_file)
00093 self.processes = {}
00094
00095 def spawn_robot(self, name, position_vector):
00096 reformatted_position_vector = reformat_position_vector(position_vector)
00097 launch_script = generate_spawn_robot_launch_script(name, self.namespace + '/gazebo',
00098 reformatted_position_vector,
00099 self.use_full_gazebo_model,
00100 self.configuration_file)
00101 self.processes[name] = start_roslaunch_process(launch_script)
00102
00103 def delete_robot(self, name):
00104 delete_service_req = DeleteModelRequest(name)
00105 try:
00106 self.processes[name].terminate()
00107 self.delete_model(delete_service_req)
00108 except rospy.ServiceException:
00109 rospy.logerr("GazeboSegbotManager : unable to delete model %s" % name)
00110
00111 def prepare_rocon_launch_text(self, robots):
00112 port = 11
00113 launch_text = '<concert>\n'
00114 for name in robots:
00115 launch_text += ' <launch title="%s:114%s" package="concert_service_gazebo" name="robot.launch" port="114%s">\n' % (name, str(port), str(port))
00116 launch_text += ' <arg name="robot_name" value="%s"/>\n' % name
00117 launch_text += ' <arg name="robot_concert_whitelist" value="Gazebo Concert;Concert Tutorial"/>\n'
00118 launch_text += ' <arg name="robot_rapp_whitelist" value="[rocon_apps, segbot_rapps, segbot_gazebo_concert]"/>\n'
00119 launch_text += ' </launch>\n'
00120 port = port + 1
00121 launch_text += '</concert>\n'
00122 return launch_text
00123
00124 def get_flip_rule_list(self, name):
00125 return [Rule(ConnectionType.SUBSCRIBER, '/' + name + '/cmd_vel', None),
00126 Rule(ConnectionType.PUBLISHER, '/' + name + '/odom', None),
00127 Rule(ConnectionType.PUBLISHER, '/' + name + '/scan_filtered', None),
00128 Rule(ConnectionType.SERVICE, '/static_map', None),
00129 Rule(ConnectionType.PUBLISHER, '/map', None),
00130 Rule(ConnectionType.PUBLISHER, '/tf', None),
00131 Rule(ConnectionType.PUBLISHER, '/tf_static', None),
00132 Rule(ConnectionType.PUBLISHER, '/clock', None)]