Exemplo n.º 1
0
class BaseVehicle(WheeledVehicle):
    """
    Base class for all vehicles.

    Other vehicles inherit from this class and can use/overwrite its
    functions.  It provides the following basic services:
        - /set_state: Set the vehicle state.
        - /set_speed_kph: Set the vehicles speed in kilometers per hour.
        - /set_loop: Set a closed loop trajectory from a certain node.
        - /set_destination: Set a trajectory to a certain destination node.
        - /toggle_simulation: Toggle the simulation of the vehicle on/off.

    The launch_sensor function can be called from child classes to launch
    the sensor nodes that are listed in their class variable self.sensors.
    """
    def __init__(self,
                 namespace,
                 vehicle_id,
                 simulation_rate,
                 x=0.,
                 y=0.,
                 yaw=0.,
                 v=0.):
        """
        Initialize class BaseVehicle.

        @param namespace: I{(string)} Namespace in which the vehicle node is
                          started.
        @param vehicle_id: I{(int)} ID of the vehicle that is created.
        @param simulation_rate: I{(int)} Rate at which the vehicle is
                                simulated (hz)
        @param x: I{(float)} x-coordinate at which the vehicle starts.
        @param y: I{(float)} y-coordinate at which the vehicle starts.
        @param yaw: I{(float)} Initial yaw of the vehicle.
        @param v: I{(float)} Initial velocity of the vehicle.
        """
        self.launcher = ROSLaunch()
        self.launcher.start()

        self.namespace = namespace

        self.vehicle_id = int(vehicle_id)
        self.class_name = self.__class__.__name__
        self.simulation_rate = simulation_rate

        # Set parameters of base vehicle to default values.
        self.simulate = False
        self.sensors = []
        self.coms = []
        self.x = x
        self.y = y
        self.yaw = yaw
        self.v = v
        self.cruising_speed = v
        self.axles_distance = 1.9
        self.np_trajectory = []
        self.commands = {}

        self.loop = False
        self.at_dest = False

        # Start the simulation loop in a separate thread.
        sim_thread = threading.Thread(target=self.simulation_loop)
        sim_thread.daemon = True
        sim_thread.start()

        # Register all services, pubs and subs last to prevent attempts to use
        # the services before the initialization of the vehicle is finished.
        self.pub_state = rospy.Publisher('/current_vehicle_state',
                                         VehicleState,
                                         queue_size=10)

        rospy.Service(self.namespace + 'set_state', SetVehicleState,
                      self.handle_set_state)
        rospy.Service(self.namespace + 'set_speed_kph', SetSpeed,
                      self.handle_set_speed_kph)
        rospy.Service(self.namespace + 'set_loop', SetLoop,
                      self.handle_set_loop)
        rospy.Service(self.namespace + 'set_destination', SetDestination,
                      self.handle_set_destination)
        rospy.Service(self.namespace + 'toggle_simulation', SetBool,
                      self.handle_toggle_simulation)
        # rospy.wait_for_service(self.namespace + '/publish_com')
        # self.publish_com = rospy.ServiceProxy(self.namespace + 'publish_com',
        #                                       PublishCom)

    def simulation_loop(self):
        """The simulation loop of the car."""
        rate = rospy.Rate(self.simulation_rate)
        while not rospy.is_shutdown():
            # print self.x, self.y, self.yaw, self.v
            # Simulate only if the simulate flat is set.
            if self.simulate:
                self.simulation_step()
            # Check if simulatio rate could be achieved or not.
            if rate.remaining() < rospy.Duration(0):
                rospy.logwarn("Simulation rate of vehicle " +
                              "#%i " % self.vehicle_id +
                              "could not be achieved.")
                rate.last_time = rospy.get_rostime()
            else:
                rate.sleep()

    def simulation_step(self):
        """Simulate one timestep of the car."""
        # Find closest trajectory point, then set reference point some indices
        # ahead of the closest trajecctory point to imporove lateral controller
        # performance.  Use this trajectory pose as reference pose.
        closest_ind = self.find_closest_trajectory_pose()
        ref_ind = closest_ind + numpy.round(self.v / 4)
        traj_len = len(self.np_trajectory[0])
        print traj_len - 1, closest_ind
        if self.loop is True:
            ref_ind = ref_ind % traj_len
        else:
            if ref_ind > traj_len - 1:
                ref_ind = traj_len - 1
                if closest_ind == traj_len - 1:
                    self.at_dest = True
            else:
                ref_ind = closest_ind
        ref_state = self.np_trajectory[:, ref_ind]
        # set controll commands.
        self.set_control_commands(ref_state)
        # update vehicle state.
        self.update_vehicle_state()
        # publish vehicle state.
        vehicle_state = VehicleState(self.vehicle_id, self.class_name, self.x,
                                     self.y, self.yaw, self.v)
        self.pub_state.publish(vehicle_state)

    def find_closest_trajectory_pose(self):
        """
        Find closest point to the current vehicle position in the trajectory.

        @return: The index of the closest trajectory point to the current
                 vehicle position.
        """
        np_state = numpy.array([[self.x], [self.y]])
        temp_distance = numpy.sum((self.np_trajectory[0:2, :] - np_state)**2,
                                  axis=0)
        best_idx = numpy.argmin(temp_distance)
        return best_idx

    def set_control_commands(self, ref_state):
        """
        Set the control commands, depending on the vehicles controler.

        @param ref_state: I{(numpy array)} Reference state [x, y, yaw] that
                          the vehicle tries to reach.
        """
        if not self.at_dest:
            self.commands['speed'] = self.cruising_speed
        else:
            self.commands['speed'] = 0.0
        dx = ref_state[0] - self.x
        dy = ref_state[1] - self.y
        dx_v = numpy.cos(self.yaw) * dx + numpy.sin(self.yaw) * dy
        dy_v = -numpy.sin(self.yaw) * dx + numpy.cos(self.yaw) * dy
        dyaw_v = ref_state[2] - self.yaw
        # Correct yaw difference. dyaw_v 0..pi
        while dyaw_v > numpy.pi:
            dyaw_v -= 2 * numpy.pi
        while dyaw_v < -numpy.pi:
            dyaw_v += 2 * numpy.pi
        # Calculate steering command from dy_v, dx_v and dyaw_v
        steering_command = dy_v + dyaw_v * 1.5 / (1 + dx_v)
        # Compare with max steering angle
        if steering_command > 0.5:
            steering_command = 0.5
        elif steering_command < -0.5:
            steering_command = -0.5
        self.commands['steering_angle'] = steering_command

    def update_vehicle_state(self):
        """Update the vehicle state."""
        sim_timestep = 1. / self.simulation_rate
        # Decompose v into x and y component.
        self.v = self.commands['speed']
        vx = numpy.cos(self.yaw) * self.v
        vy = numpy.sin(self.yaw) * self.v
        # Update vehicles position
        self.x += vx * sim_timestep
        self.y += vy * sim_timestep
        self.yaw += ((self.v / self.axles_distance) *
                     numpy.tan(self.commands['steering_angle']) * sim_timestep)
        # Make sure self.yaw is never negative.
        # self.yaw 0..2pi
        if self.yaw > 2 * numpy.pi:
            self.yaw = 0.
        elif self.yaw < 0.:
            self.yaw += 2 * numpy.pi

    def launch_sensors(self):
        """Launch and register the sensors used by the vehicle."""
        # Go through sensor list.
        for sensor in self.sensors:
            # Launch sensor node.
            sensor_name = sensor.partition(' ')[0]
            subpub_name = sensor_name.lower() + '_readings'
            args = str(self.vehicle_id) + ' ' + sensor
            node = Node('sml_world',
                        'sensor.py',
                        namespace=self.namespace,
                        args=args,
                        name=sensor_name.lower())
            self.launcher.launch(node)
            # Register subscriptions for each of them.
            rospy.Subscriber(self.namespace + subpub_name,
                             getattr(msgs, sensor_name + 'Readings'),
                             getattr(self, 'process_' + subpub_name))

    def launch_coms(self):
        """Launch and register the communications used by the vehicle."""
        # Go through list of comunication.
        for com in self.coms:
            com_name = com.partition(' ')[0]
            subpub_name = com_name.lower() + '_com'
            args = str(self.vehicle_id) + ' ' + com
            node = Node('sml_world',
                        'communication.py',
                        namespace=self.namespace,
                        args=args,
                        name=com_name.lower())
            self.launcher.launch(node)
            # Register subscriptions for each of them.
            rospy.Subscriber(self.namespace + subpub_name,
                             getattr(msgs, com_name + 'Com'),
                             getattr(self, 'process_' + subpub_name))

    def handle_set_state(self, req):
        """
        Handle the set state request.

        @param req: I{(SetState)} Request of the service that sets the vehicle
                    state.
        """
        self.x = req.x
        self.y = req.y
        self.yaw = req.yaw
        self.v = req.v
        msg = "State of vehicle #%i successfully set." % self.vehicle_id
        return SetVehicleStateResponse(True, msg)

    def handle_set_speed_kph(self, req):
        """
        Handle the set speed request.

        @param req: I{(SetSpeed)} Request of the service that sets the vehicles
                    cruising speed in kmh.
        """
        self.cruising_speed = req.speed / 3.6
        msg = "Speed of vehicle #%i successfully set." % self.vehicle_id
        return SetSpeedResponse(True, msg)

    def handle_set_loop(self, req):
        """
        Handle the set closed loop request.

        @param req: I{(SetLoop)} Request of the service that sets the vehicles
                    closed loop trajectory.
        """
        rospy.wait_for_service('/get_trajectory')
        try:
            get_traj = rospy.ServiceProxy('/get_trajectory', GetTrajectory)
            trajectory = get_traj(True, req.node_id, 0).trajectory
        except rospy.ServiceException, e:
            raise "Service call failed: %s" % e
        self.np_trajectory = to_numpy_trajectory(trajectory)
        self.loop = True
        self.at_dest = False
        msg = ("Closed loop trajectory of vehicle #%i " % self.vehicle_id +
               "successfully set.")
        return SetLoopResponse(True, msg)
Exemplo n.º 2
0
class BaseVehicle(WheeledVehicle):
    """
    Base class for all vehicles.

    Other vehicles inherit from this class and can use/overwrite its
    functions.  It provides the following basic services:
        - /set_state: Set the vehicle state.
        - /set_speed_kph: Set the vehicles speed in kilometers per hour.
        - /set_loop: Set a closed loop trajectory from a certain node.
        - /set_destination: Set a trajectory to a certain destination node.
        - /toggle_simulation: Toggle the simulation of the vehicle on/off.

    The launch_sensor function can be called from child classes to launch
    the sensor nodes that are listed in their class variable self.sensors.
    """

    def __init__(self, namespace, vehicle_id, simulation_rate,
                 x=0., y=0., yaw=0., v=0.):
        """
        Initialize class BaseVehicle.

        @param namespace: I{(string)} Namespace in which the vehicle node is
                          started.
        @param vehicle_id: I{(int)} ID of the vehicle that is created.
        @param simulation_rate: I{(int)} Rate at which the vehicle is
                                simulated (hz)
        @param x: I{(float)} x-coordinate at which the vehicle starts.
        @param y: I{(float)} y-coordinate at which the vehicle starts.
        @param yaw: I{(float)} Initial yaw of the vehicle.
        @param v: I{(float)} Initial velocity of the vehicle.
        """
        self.launcher = ROSLaunch()
        self.launcher.start()

        self.namespace = namespace

        self.vehicle_id = int(vehicle_id)
        self.class_name = self.__class__.__name__
        self.simulation_rate = simulation_rate

        # Set parameters of base vehicle to default values.
        self.simulate = False
        self.sensors = []
        self.coms = []
        self.x = x
        self.y = y
        self.yaw = yaw
        self.v = v
        self.cruising_speed = v
        self.axles_distance = 1.9
        self.np_trajectory = []
        self.commands = {}

        self.loop = False
        self.at_dest = False

        # Start the simulation loop in a separate thread.
        sim_thread = threading.Thread(target=self.simulation_loop)
        sim_thread.daemon = True
        sim_thread.start()

        # Register all services, pubs and subs last to prevent attempts to use
        # the services before the initialization of the vehicle is finished.
        self.pub_state = rospy.Publisher('/current_vehicle_state',
                                         VehicleState, queue_size=10)

        rospy.Service(self.namespace + 'set_state', SetVehicleState,
                      self.handle_set_state)
        rospy.Service(self.namespace + 'set_speed_kph', SetSpeed,
                      self.handle_set_speed_kph)
        rospy.Service(self.namespace + 'set_loop', SetLoop,
                      self.handle_set_loop)
        rospy.Service(self.namespace + 'set_destination', SetDestination,
                      self.handle_set_destination)
        rospy.Service(self.namespace + 'toggle_simulation', SetBool,
                      self.handle_toggle_simulation)
        # rospy.wait_for_service(self.namespace + '/publish_com')
        # self.publish_com = rospy.ServiceProxy(self.namespace + 'publish_com',
        #                                       PublishCom)

    def simulation_loop(self):
        """The simulation loop of the car."""
        rate = rospy.Rate(self.simulation_rate)
        while not rospy.is_shutdown():
            # print self.x, self.y, self.yaw, self.v
            # Simulate only if the simulate flat is set.
            if self.simulate:
                self.simulation_step()
            # Check if simulatio rate could be achieved or not.
            if rate.remaining() < rospy.Duration(0):
                rospy.logwarn("Simulation rate of vehicle " +
                              "#%i " % self.vehicle_id +
                              "could not be achieved.")
                rate.last_time = rospy.get_rostime()
            else:
                rate.sleep()

    def simulation_step(self):
        """Simulate one timestep of the car."""
        # Find closest trajectory point, then set reference point some indices
        # ahead of the closest trajecctory point to imporove lateral controller
        # performance.  Use this trajectory pose as reference pose.
        closest_ind = self.find_closest_trajectory_pose()
        ref_ind = closest_ind + numpy.round(self.v / 4)
        traj_len = len(self.np_trajectory[0])
        print traj_len-1, closest_ind
        if self.loop is True:
            ref_ind = ref_ind % traj_len
        else:
            if ref_ind > traj_len-1:
                ref_ind = traj_len-1
                if closest_ind == traj_len-1:
                    self.at_dest = True
            else:
                ref_ind = closest_ind
        ref_state = self.np_trajectory[:, ref_ind]
        # set controll commands.
        self.set_control_commands(ref_state)
        # update vehicle state.
        self.update_vehicle_state()
        # publish vehicle state.
        vehicle_state = VehicleState(self.vehicle_id, self.class_name,
                                     self.x, self.y, self.yaw, self.v)
        self.pub_state.publish(vehicle_state)

    def find_closest_trajectory_pose(self):
        """
        Find closest point to the current vehicle position in the trajectory.

        @return: The index of the closest trajectory point to the current
                 vehicle position.
        """
        np_state = numpy.array([[self.x], [self.y]])
        temp_distance = numpy.sum(
                          (self.np_trajectory[0:2, :] - np_state) ** 2,
                          axis=0)
        best_idx = numpy.argmin(temp_distance)
        return best_idx

    def set_control_commands(self, ref_state):
        """
        Set the control commands, depending on the vehicles controler.

        @param ref_state: I{(numpy array)} Reference state [x, y, yaw] that
                          the vehicle tries to reach.
        """
        if not self.at_dest:
            self.commands['speed'] = self.cruising_speed
        else:
            self.commands['speed'] = 0.0
        dx = ref_state[0] - self.x
        dy = ref_state[1] - self.y
        dx_v = numpy.cos(self.yaw) * dx + numpy.sin(self.yaw) * dy
        dy_v = -numpy.sin(self.yaw) * dx + numpy.cos(self.yaw) * dy
        dyaw_v = ref_state[2] - self.yaw
        # Correct yaw difference. dyaw_v 0..pi
        while dyaw_v > numpy.pi:
            dyaw_v -= 2*numpy.pi
        while dyaw_v < -numpy.pi:
            dyaw_v += 2*numpy.pi
        # Calculate steering command from dy_v, dx_v and dyaw_v
        steering_command = dy_v + dyaw_v * 1.5 / (1 + dx_v)
        # Compare with max steering angle
        if steering_command > 0.5:
            steering_command = 0.5
        elif steering_command < -0.5:
            steering_command = -0.5
        self.commands['steering_angle'] = steering_command

    def update_vehicle_state(self):
        """Update the vehicle state."""
        sim_timestep = 1. / self.simulation_rate
        # Decompose v into x and y component.
        self.v = self.commands['speed']
        vx = numpy.cos(self.yaw) * self.v
        vy = numpy.sin(self.yaw) * self.v
        # Update vehicles position
        self.x += vx * sim_timestep
        self.y += vy * sim_timestep
        self.yaw += ((self.v / self.axles_distance) *
                     numpy.tan(self.commands['steering_angle']) *
                     sim_timestep)
        # Make sure self.yaw is never negative.
        # self.yaw 0..2pi
        if self.yaw > 2*numpy.pi:
            self.yaw = 0.
        elif self.yaw < 0.:
            self.yaw += 2*numpy.pi

    def launch_sensors(self):
        """Launch and register the sensors used by the vehicle."""
        # Go through sensor list.
        for sensor in self.sensors:
            # Launch sensor node.
            sensor_name = sensor.partition(' ')[0]
            subpub_name = sensor_name.lower()+'_readings'
            args = str(self.vehicle_id)+' '+sensor
            node = Node('sml_world', 'sensor.py', namespace=self.namespace,
                        args=args, name=sensor_name.lower())
            self.launcher.launch(node)
            # Register subscriptions for each of them.
            rospy.Subscriber(self.namespace + subpub_name,
                             getattr(msgs, sensor_name+'Readings'),
                             getattr(self, 'process_'+subpub_name))

    def launch_coms(self):
        """Launch and register the communications used by the vehicle."""
        # Go through list of comunication.
        for com in self.coms:
            com_name = com.partition(' ')[0]
            subpub_name = com_name.lower()+'_com'
            args = str(self.vehicle_id)+' '+com
            node = Node('sml_world', 'communication.py',
                        namespace=self.namespace, args=args,
                        name=com_name.lower())
            self.launcher.launch(node)
            # Register subscriptions for each of them.
            rospy.Subscriber(self.namespace + subpub_name,
                             getattr(msgs, com_name+'Com'),
                             getattr(self, 'process_'+subpub_name))

    def handle_set_state(self, req):
        """
        Handle the set state request.

        @param req: I{(SetState)} Request of the service that sets the vehicle
                    state.
        """
        self.x = req.x
        self.y = req.y
        self.yaw = req.yaw
        self.v = req.v
        msg = "State of vehicle #%i successfully set." % self.vehicle_id
        return SetVehicleStateResponse(True, msg)

    def handle_set_speed_kph(self, req):
        """
        Handle the set speed request.

        @param req: I{(SetSpeed)} Request of the service that sets the vehicles
                    cruising speed in kmh.
        """
        self.cruising_speed = req.speed / 3.6
        msg = "Speed of vehicle #%i successfully set." % self.vehicle_id
        return SetSpeedResponse(True, msg)

    def handle_set_loop(self, req):
        """
        Handle the set closed loop request.

        @param req: I{(SetLoop)} Request of the service that sets the vehicles
                    closed loop trajectory.
        """
        rospy.wait_for_service('/get_trajectory')
        try:
            get_traj = rospy.ServiceProxy('/get_trajectory', GetTrajectory)
            trajectory = get_traj(True, req.node_id, 0).trajectory
        except rospy.ServiceException, e:
            raise "Service call failed: %s" % e
        self.np_trajectory = to_numpy_trajectory(trajectory)
        self.loop = True
        self.at_dest = False
        msg = ("Closed loop trajectory of vehicle #%i " % self.vehicle_id +
               "successfully set.")
        return SetLoopResponse(True, msg)
Exemplo n.º 3
0
class ScenarioLauncher:
    def __init__(self):
        print "I am ScenarioLauncher in python !!"

    def start_launcher(self):
        self.launcher = ROSLaunch()
        self.launcher.start()

    def stop_launcher(self):
        self.launcher.stop()
        time.sleep(60)

    def runGazeboServer(self, Scenarin_folder):
        arguments = "-u " + Scenarin_folder + "/scenarioEnv.world"  # -u starts the simulation in pause mode
        node = ROSNode(
            "gazebo_ros",
            "gzserver",
            name="gazebo",
            args=arguments,
            output="screen",
            respawn="false"
        )  # name="gazebo" in order for replay and grader to work (name space)
        self.launcher.launch(node)
        time.sleep(3)
        return True

    def runGazeboClient(self):
        node = ROSNode("gazebo_ros",
                       "gzclient",
                       name="gazebo_client",
                       output="screen",
                       respawn="false")
        self.launcher.launch(node)
        time.sleep(3)
        return True

    def setScenarioEnv(self, Scenarin_folder):
        rospy.set_param('/use_sim_time', True)  #synchronizing ros to gazebo

        rospack = rospkg.RosPack()
        srvss_pkg_path = rospack.get_path('smartest')
        os.environ[
            "GAZEBO_MODEL_PATH"] = srvss_pkg_path + "/world_components_models/:" + Scenarin_folder + "/scenarioSystemModels/"
        return True

    def launch_platform_controls_spawner(self):  #used by the srvss_dummy
        return True

    def launch_platform_controls_unspawner(self):  #used by the srvss_dummy
        return True

    def launch_WPdriver(self, Scenarin_folder):
        def run_node(package_name, node_type, node_nickname, params_file,
                     remap_file, arguments):
            def read_remaps_from_file(filename):
                from ast import literal_eval
                with open(filename) as f:
                    mainlist = [list(literal_eval(line)) for line in f]
                return mainlist

            def read_params_from_file(filename, namespace):
                paramlist = rosparam.load_file(filename,
                                               default_namespace=namespace,
                                               verbose=True)
                for params, ns in paramlist:
                    rosparam.upload_params(ns, params)

            if params_file != None:
                read_params_from_file(params_file, node_nickname)

            remaps_list = None
            if remap_file != None:
                remaps_list = read_remaps_from_file(remap_file)

            node = ROSNode(package_name,
                           node_type,
                           name=node_nickname,
                           remap_args=remaps_list,
                           args=arguments,
                           respawn=True,
                           output="screen")
            self.launcher.launch(node)

        #rospack = rospkg.RosPack()
        #robil2conf_pkg_path = rospack.get_path('robil2conf')
        #robil2conf_yaml = robil2conf_pkg_path +"/configuration.yaml"
        #paramlist=rosparam.load_file(robil2conf_yaml, default_namespace='' ,verbose=True)
        #for params, ns in paramlist:
        #        rosparam.upload_params(ns,params)

        #<!-- == GENERAL ===== -->
        print "Loading GENERAL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        arguments = "ODOM        GPS                        0.000  0.000  0.000        0.000  0.000  0.000 \
                     ODOM        INS                        0.266  0.155 -1.683        0.000  0.000  0.000 \
                     ODOM        IBEO                        0.310  0.170 -0.230        0.000  0.215  0.149 \
                     ODOM        TRACKS_BOTTOM                0.000  0.000 -2.260        0.000  0.000  0.000 \
                     ODOM        ROBOT_CENTER               -0.380  0.155 -1.683        0.000  0.000  0.000"

        node = ROSNode("robil2tf",
                       "robil2TF_node",
                       name="robil2TF_publisher",
                       args=arguments,
                       output="screen",
                       respawn="true")
        self.launcher.launch(node)

        node = ROSNode("robil2tf",
                       "world_gazebo_to_WORLD_TF_pub.py",
                       name="world_gazebo_to_WORLD_TF_pub",
                       output="screen",
                       respawn="true")
        self.launcher.launch(node)
        # ================ -->

        #<!-- == SENSORS INTERFACEs == -->
        node = ROSNode("shiffon2ros",
                       "shiffon2ros_node",
                       name="ipon2ros",
                       args="127.0.0.1",
                       output="screen")
        self.launcher.launch(node)
        node = ROSNode("sick_ldmrs",
                       "sickldmrs.py",
                       name="ibeo2ros",
                       args="127.0.0.1",
                       output="screen")
        self.launcher.launch(node)
        time.sleep(3)
        # ================ -->

        #<!-- == PLATFORM INTERFACE == -->
        node = ROSNode("lli",
                       "lli_node",
                       name="ros2qinetiq",
                       args="127.0.0.1",
                       output="screen",
                       respawn="true")
        self.launcher.launch(node)
        # ================ -->

        # == MONITORING == -->
        print "Loading MONITORING !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        node = ROSNode("ssm",
                       "ssm_fsm_states_tracker_node",
                       name="ssm_fsm_states_tracker_node",
                       output="screen")
        self.launcher.launch(node)
        node = ROSNode("ssm",
                       "ssm_heartbeat_monitor_node",
                       name="ssm_heartbeat_monitor_node",
                       output="screen")
        self.launcher.launch(node)
        node = ROSNode("ssm", "ssm_node", name="ssm_node", output="screen")
        self.launcher.launch(node)
        # ================ -->

        #<!-- == LOCALIZATION == -->
        print "Loading LOCALIZATION node  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        node = ROSNode("loc",
                       "loc_node",
                       name="loc_node",
                       output="screen",
                       respawn="true")
        self.launcher.launch(node)
        time.sleep(1)
        # ================ -->

        # == PERCEPTION == -->
        print "Loading PERCEPTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        node = ROSNode("per",
                       "per_node",
                       name="per_node",
                       output="screen",
                       respawn="true")
        self.launcher.launch(node)

        #<!-- == OPERATOR CONTROL UNIT == -->
        node = ROSNode("ocu", "ocu_node", name="ocu_node", output="screen")
        self.launcher.launch(node)
        # ================ -->

        # -- MISSION CONTROL  -->
        print "Loading MISSION CONTRO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        node = ROSNode("smme",
                       "smme_node",
                       name="smme_node",
                       output="screen",
                       respawn="true")
        self.launcher.launch(node)
        node = ROSNode("wsm",
                       "wsm_node",
                       name="wsm_node",
                       output="screen",
                       respawn="true")
        self.launcher.launch(node)
        # ================ -->

        #<!-- == LOW LEVEL CONTROL == -->
        print "Loading LOW LEVEL CONTROL node  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        node = ROSNode("llc",
                       "llc_node",
                       name="llc_node",
                       output="screen",
                       respawn="true")
        self.launcher.launch(node)
        time.sleep(3)

        #<!-- == PATH PLANING  +   WAY POINT DRIVER == -->
        print "Loading PATH PLANING  +   WAY POINT DRIVER !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        rospack = rospkg.RosPack()
        pp_pkg_path = rospack.get_path('pp')

        run_node("navex_navigation", "navex_navigation_node",
                 "navex_navigation", pp_pkg_path + "/launch/navex.yaml",
                 pp_pkg_path + "/launch/navex.remap", '')
        run_node("pp", "pp_node", "pp_node",
                 pp_pkg_path + "/launch/pp_node.yaml",
                 pp_pkg_path + "/launch/pp_node.remap", '')
        run_node("wpd", "wpd_node", "wpd_node", None, None, '')

        # ================ -->

        #<!-- == Navigation Mission Load  == -->
        arguments = "-d 20 " + Scenarin_folder + "/scenarioMission.bag"
        node = ROSNode("rosbag",
                       "play",
                       name="rosbag_Mission_node",
                       output="screen",
                       respawn="true",
                       args=arguments)
        self.launcher.launch(node)
        # ================ -->

    def launch_robot_tf_broadcaster(self):
        node = ROSNode("bobcat_model",
                       "world_to_body_TF_pub.py",
                       name="world_to_body_TF_pub",
                       output="screen",
                       respawn="true")
        self.launcher.launch(node)
        time.sleep(3)

        rospack = rospkg.RosPack()
        bobcat_pkg_path = rospack.get_path('bobcat_model')
        urdf_file = bobcat_pkg_path + "/urdf_models/bobcat_tracked_urdf_for_dynamic_arm.URDF"

        robot_urdf_file = open(urdf_file)
        robot_urdf = robot_urdf_file.read()
        rospy.set_param("/robot_description", robot_urdf)

        remaping = [("/joint_states", "/Sahar/joint_states")]
        node = ROSNode("robot_state_publisher",
                       "robot_state_publisher",
                       name="robot_state_broadcaster_node",
                       remap_args=remaping,
                       output="screen",
                       respawn="false")
        self.launcher.launch(node)
        time.sleep(3)

    def launch_recorder(self, Scenarin_folder):
        arguments = "-O " + Scenarin_folder + "/scen_rec.bag --all --exclude /SENSORS/CAM/(.*)|/SENSORS/IBEO/(.*)|/Sahar/(.*)|/PER/Map|/WSM/(.*)|/flea3/(.*)|/right_sick/(.*)|/left_sick/(.*)|/gazebo/model_states|/clock"
        #       arguments = "-O " + Scenarin_folder + "/scen_rec.bag --all --exclude /SENSORS/(.*)|/LOC/Velocity|/Sahar/(.*)|/OCU/(.*)|/LLC/(.*)|/PER/(.*)|/WPD/(.*)|/WSM/(.*)|/flea3/(.*)|/right_sick/(.*)|/left_sick/(.*)|/heartbeat|/gazebo/model_states|/clock"
        #        arguments = "-O " + Scenarin_folder + "/scen_rec.bag --all --exclude /SENSORS/(.*)|/LOC/Pose|/LOC/Velocity|/Sahar/(.*)|/OCU/(.*)|/LLC/(.*)|/PER/(.*)|/WPD/(.*)|/WSM/(.*)|/flea3/(.*)|/right_sick/(.*)|/left_sick/(.*)|/heartbeat|/gazebo/model_states|/clock"
        node = ROSNode("rosbag",
                       "record",
                       name="rosbag_recorde_node",
                       args=arguments)
        self.launcher.launch(node)
        time.sleep(3)

    def launch_grader(self, Scenarin_folder):
        arguments = Scenarin_folder + " " + Scenarin_folder + "/scen.SFV"
        node = ROSNode("smartest",
                       "grader_node",
                       name="grader_node",
                       output="screen",
                       args=arguments)
        self.launcher.launch(node)
        time.sleep(3)

    def Gazebo_UnPause(self):
        print " i am inside Gazebo_UnPause !!!!!!!!! "
        name = '/gazebo/unpause_physics'
        msg_class = std_srvs.srv.Empty()
        rospy.wait_for_service(name)
        try:
            service = rospy.ServiceProxy(name, msg_class)
            resp1 = service()
            return True
        except rospy.ServiceException, e:
            print "Service call failed: %s" % e
        return True
Exemplo n.º 4
0
class ScenarioLauncher:
    def __init__(self):
        print "I am ScenarioLauncher in python !!"

    def start_launcher(self):
        self.launcher = ROSLaunch()
        self.launcher.start()

    def stop_launcher(self):
        self.launcher.stop()
        time.sleep(10)

    def runGazeboServer(self, Scenarin_folder):
        arguments = "-u " + Scenarin_folder + "/scenarioEnv.world"  # -u starts the simulation in pause mode
        node = ROSNode(
            "gazebo_ros",
            "gzserver",
            name="gazebo",
            args=arguments,
            output="screen",
            respawn="false"
        )  # name="gazebo" in order for replay and grader to work (name space)
        self.launcher.launch(node)
        time.sleep(3)
        return True

    def runGazeboClient(self):
        node = ROSNode("gazebo_ros",
                       "gzclient",
                       name="gazebo_client",
                       output="screen",
                       respawn="false")
        self.launcher.launch(node)
        time.sleep(3)
        return True

    def setScenarioEnv(self, Scenarin_folder):
        rospy.set_param('/use_sim_time', True)  #synchronizing ros to gazebo

        rospack = rospkg.RosPack()
        smartest_pkg_path = rospack.get_path('smartest')
        os.environ[
            "GAZEBO_MODEL_PATH"] = smartest_pkg_path + "/world_components_models/:" + Scenarin_folder + "/scenarioSystemModels/"

        srvss_bobcat_pkg_path = rospack.get_path('srvss_bobcat')
        urdf_file = srvss_bobcat_pkg_path + "/urdf/BOBCAT.URDF"
        robot_urdf_file = open(urdf_file)
        robot_urdf = robot_urdf_file.read()
        rospy.set_param("/robot_description", robot_urdf)
        return True

    def launch_platform_controls_spawner(self):
        rospack = rospkg.RosPack()
        srvss_bobcat_pkg_path = rospack.get_path('srvss_bobcat')
        srvss_bobcat_controllers_yaml = srvss_bobcat_pkg_path + "/controllers/srvss_bobcat_controllers.yaml"
        paramlist = rosparam.load_file(srvss_bobcat_controllers_yaml,
                                       default_namespace='',
                                       verbose=True)
        for params, ns in paramlist:
            rosparam.upload_params(ns, params)

        # if the controllers do not load it possible to increase the time of waiting for the server in the spawner
        # it located in /home/userws3/gz_ros_cws/src/ros_control/controller_manager/scripts
        node = ROSNode("controller_manager",
                       "spawner",
                       name="platform_controllers_spawner",
                       namespace="/srvss_bobcat",
                       output="screen",
                       respawn="false",
                       args="joint_state_controller \
					front_right_wheel_velocity_controller \
					front_left_wheel_velocity_controller \
					back_right_wheel_velocity_controller \
					back_left_wheel_velocity_controller")
        self.launcher.launch(node)
        time.sleep(10)

        node = ROSNode("srvss_bobcat",
                       "srvss_bobcat_rate2effort_node",
                       name="srvss_bobcat_RateToEffort_node",
                       cwd="node",
                       output="screen")
        self.launcher.launch(node)
        time.sleep(3)

    def launch_platform_controls_unspawner(self):
        node = ROSNode("controller_manager",
                       "unspawner",
                       name="platform_controllers_unspawner",
                       namespace="/srvss_bobcat",
                       output="screen",
                       respawn="false",
                       args="joint_state_controller \
					front_right_wheel_velocity_controller \
					front_left_wheel_velocity_controller \
					back_right_wheel_velocity_controller \
					back_left_wheel_velocity_controller")
        self.launcher.launch(node)
        time.sleep(10)

    def launch_WPdriver(self, Scenarin_folder):
        arguments = "-file " + Scenarin_folder + "/scenarioMission.txt"
        node = ROSNode("srvss_wp_driver",
                       "srvss_wp_driver_node",
                       name="srvss_wp_driver_node",
                       args=arguments,
                       respawn="false")  # output="screen"
        self.launcher.launch(node)
        time.sleep(3)

    def launch_robot_tf_broadcaster(self):
        remaping = [("/joint_states", "/srvss_bobcat/joint_states")]
        node = ROSNode("robot_state_publisher",
                       "robot_state_publisher",
                       name="robot_state_broadcaster_node",
                       remap_args=remaping,
                       output="screen",
                       respawn="false")
        self.launcher.launch(node)
        time.sleep(3)

        node = ROSNode("srvss_bobcat",
                       "world_to_bobcat_tf_broadcaster_node",
                       name="worltd_to_bobcat_tf_broadcaster_node",
                       output="screen",
                       respawn="false")
        self.launcher.launch(node)
        time.sleep(3)

        node = ROSNode("tf",
                       "static_transform_publisher",
                       name="sick_link_tf_broadcaster_node",
                       args="1 0 0.2 0 0 0 body front_sick 100",
                       output="screen",
                       respawn="false")
        self.launcher.launch(node)
        time.sleep(3)

    def launch_recorder(self, Scenarin_folder):
        arguments = "-a -O " + Scenarin_folder + "/scen_rec.bag"
        node = ROSNode("rosbag",
                       "record",
                       name="rosbag_recorde_node",
                       args=arguments)
        self.launcher.launch(node)
        time.sleep(3)

    def launch_grader(self, Scenarin_folder):
        arguments = Scenarin_folder + " " + Scenarin_folder + "/scen.SFV"
        print "I am hear arguments = " + arguments
        node = ROSNode("smartest",
                       "grader_node",
                       name="grader_node",
                       output="screen",
                       args=arguments)
        self.launcher.launch(node)
        time.sleep(3)

    def Gazebo_UnPause(self):
        name = '/gazebo/unpause_physics'
        msg_class = std_srvs.srv.Empty()
        print "wait for service " + name
        rospy.wait_for_service(name)
        print "done wating"
        try:
            service = rospy.ServiceProxy(name, msg_class)
            resp1 = service()
            return True
        except rospy.ServiceException, e:
            print "Service call failed: %s" % e
        return True
Exemplo n.º 5
0
class ScenarioLauncher:

    def __init__(self):
	print "I am ScenarioLauncher in Python_robil2_bobtank !!"

    def start_launcher(self):
	self.launcher = ROSLaunch()
	self.launcher.start()

    def stop_launcher(self):
	self.launcher.stop()
        time.sleep(60)


    def runGazeboServer(self, Scenarin_folder):
 	arguments = "-u " + Scenarin_folder + "/scenarioEnv.world"     # -u starts the simulation in pause mode
	node = ROSNode("gazebo_ros","gzserver",name="gazebo" ,args=arguments ,output="screen" , respawn="false")      	   # name="gazebo" in order for replay and grader to work (name space)
	self.launcher.launch(node)	
        time.sleep(3)
	return True
	
    def runGazeboClient(self):
	node = ROSNode("gazebo_ros", "gzclient",name="gazebo_client" ,output="screen", respawn="false")
	self.launcher.launch(node)	
        time.sleep(3)
	return True	

    def setScenarioEnv(self,Scenarin_folder):
	rospy.set_param('/use_sim_time',True)	#synchronizing ros to gazebo

	rospack = rospkg.RosPack()
	srvss_pkg_path = rospack.get_path('SRVSS')
	os.environ["GAZEBO_MODEL_PATH"] = srvss_pkg_path+"/world_components_models/:" + Scenarin_folder + "/scenarioSystemModels/"

	bobcat_pkg_path = rospack.get_path('bobtank')
	urdf_file = bobcat_pkg_path +"/urdf/BOBCAT_sdf_model_new.URDF"
        robot_urdf_file = open(urdf_file)
	robot_urdf = robot_urdf_file.read()
	rospy.set_param("/robot_description", robot_urdf )
	return True


    def launch_platform_controls_spawner(self):
	rospack = rospkg.RosPack()
	bobcat_pkg_path = rospack.get_path('bobtank')
	bobcat_controllers_yaml = bobcat_pkg_path +"/config/bobcat_with_trucks_gazebo_control.yaml"
	paramlist=rosparam.load_file(bobcat_controllers_yaml, default_namespace='' ,verbose=True)
	for params, ns in paramlist:
    		rosparam.upload_params(ns,params)

	# if the controllers do not load it possible to increase the time of waiting for the server in the spawner
	# it located in /home/userws3/gz_ros_cws/src/ros_control/controller_manager/scripts			
	node = ROSNode("controller_manager", "spawner", name="platform_controllers_spawner" ,namespace="/Sahar", output="screen", respawn="false" ,
				args="joint_state_controller \
					  right_wheel_velocity_controller \
					  left_wheel_velocity_controller \
					  loader_position_controller \
					  supporter_position_controller \
                                          brackets_position_controller")	
	self.launcher.launch(node)	
        time.sleep(10)
	
	node = ROSNode("rate2effort", "rate2effort_for_tracks", name="rate2effort_for_tracks_node", cwd="node", output="screen") 
	self.launcher.launch(node)	
        time.sleep(3)

    
    def launch_platform_controls_unspawner(self):
	node = ROSNode("controller_manager", "unspawner" ,name="platform_controllers_unspawner" ,namespace="/Sahar", output="screen", respawn="false" ,
				args="joint_state_controller \
					  right_wheel_velocity_controller \
					  left_wheel_velocity_controller \
					  loader_position_controller \
					  supporter_position_controller \
                                          brackets_position_controller")	
	self.launcher.launch(node)	
        time.sleep(10)
    

    def launch_WPdriver(self,Scenarin_folder):
	

	# ==  GENERAL == -->
	rospack = rospkg.RosPack()
	robil2conf_pkg_path = rospack.get_path('robil2conf')
	robil2conf_yaml = robil2conf_pkg_path +"/configuration.yaml"
	paramlist=rosparam.load_file(robil2conf_yaml, default_namespace='' ,verbose=True)
	for params, ns in paramlist:
    		rosparam.upload_params(ns,params)
	
	node = ROSNode("robil2TF", "robil2TF_node",name="robil2TF_publishe",output="screen"
				  args="ODOM	GPS		0.000  0.000  0.000	0.000  0.000  0.000 \
	      				ODOM	INS		0.266  0.155 -1.683	0.000  0.000  0.000 \
      	      				ODOM	IBEO		0.256  0.169 -0.231	0.005  0.201  0.107 \
	      				ODOM	TRACKS_BOTTOM	0.000  0.000 -2.323	0.000  0.000  0.000 \
	      				ODOM	ROBOT_CENTER   -0.380  0.155 -1.683	0.000  0.000  0.000 \	
	      				ODOM	body		0.616  0.155 -2.133	0.000  0.000  0.000")
	self.launcher.launch(node)	
        time.sleep(3)


	

	# == MONITORING == -->
	print "Loading MONITORING !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
	node = ROSNode("ssm", "ssm_fsm_states_tracker_node",name="ssm_fsm_states_tracker_node",output="screen")
	self.launcher.launch(node)
	node = ROSNode("ssm", "ssm_heartbeat_monitor_node",name="ssm_heartbeat_monitor_node",output="screen")
	self.launcher.launch(node)
	node = ROSNode("ssm", "ssm_node",name="ssm_node",output="screen")
	self.launcher.launch(node)
        #time.sleep(3)	
	# ================ -->

	# == PERCEPTION == -->
	#print "Loading PERCEPTION-sensors_node  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"  --  Not Working therefore stuck the loading process, not critical for robil2
	#node = ROSNode("sensors", "sensors_node",name="sensors_node",output="screen",respawn="true")
	#self.launcher.launch(node)
	print "Loading PERCEPTION-iedsim_node  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
	node = ROSNode("iedsim", "iedsim_node",name="iedsim_node",output="screen",respawn="true")
	self.launcher.launch(node)
	print "Loading PERCEPTION-per_node  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
	node = ROSNode("per", "per_node",name="per_node",output="screen",respawn="true")
	self.launcher.launch(node)
	print "Loading PERCEPTION-loc_node  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
	node = ROSNode("loc", "loc_node",name="loc_node",output="screen",respawn="true")
	self.launcher.launch(node)
        time.sleep(3)
	# ================ -->


	# -- MISSION CONTROL  -->
	print "Loading MISSION CONTRO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
	node = ROSNode("smme", "smme_node",name="smme_node",output="screen",respawn="true")
	self.launcher.launch(node)
	node = ROSNode("wsm", "wsm_node",name="wsm_node",output="screen",respawn="true")
	self.launcher.launch(node)
	node = ROSNode("ocu", "ocu_node",name="ocu_node",output="screen")
	self.launcher.launch(node)
	# ================ -->


	#-- == NAVIGATION == -->
	print "Loading NAVIGATION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
	rospack = rospkg.RosPack()
	pp_pkg_path = rospack.get_path('pp')
	costmap_common_params = pp_pkg_path +"/params/costmap_common_params.yaml"
	paramlist=rosparam.load_file(costmap_common_params, default_namespace='move_base/global_costmap' ,verbose=True)
	for params, ns in paramlist:
    		rosparam.upload_params(ns,params)

	paramlist=rosparam.load_file(costmap_common_params, default_namespace='move_base/local_costmap' ,verbose=True)
	for params, ns in paramlist:
    		rosparam.upload_params(ns,params)

	local_costmap_params = pp_pkg_path +"/params/local_costmap_params.yaml"
	paramlist=rosparam.load_file(local_costmap_params, default_namespace='move_base' ,verbose=True)
	for params, ns in paramlist:
    		rosparam.upload_params(ns,params)


	global_costmap_params = pp_pkg_path +"/params/global_costmap_params.yaml"
	paramlist=rosparam.load_file(global_costmap_params, default_namespace='move_base' ,verbose=True)
	for params, ns in paramlist:
    		rosparam.upload_params(ns,params)


	base_local_planner_params = pp_pkg_path +"/params/base_local_planner_params.yaml"
	paramlist=rosparam.load_file(base_local_planner_params, default_namespace='move_base' ,verbose=True)
	for params, ns in paramlist:
    		rosparam.upload_params(ns,params)


	node = ROSNode("move_base", "move_base",name="move_base",output="screen")
	self.launcher.launch(node)

	node = ROSNode("pp", "pp_node",name="pp_node",output="screen")
	self.launcher.launch(node)

	node = ROSNode("wpd", "wpd_node",name="wpd_node",output="screen")
	self.launcher.launch(node)

	node = ROSNode("llc", "llc_node",name="llc_node",output="screen",respawn="true")
	self.launcher.launch(node)
        time.sleep(3)

	arguments = "-d 40 "+ Scenarin_folder + "/scenarioMission.bag"
	node = ROSNode("rosbag", "play",name="rosbag_Mission_node",output="screen",respawn="true", args=arguments)
	self.launcher.launch(node)
        # ================ -->


    def launch_robot_tf_broadcaster(self):
	remaping = [ ("/joint_states" , "/Sahar/joint_states") ] 
	node = ROSNode("robot_state_publisher", "robot_state_publisher",name="robot_state_broadcaster_node", remap_args=remaping ,output="screen", respawn="false")
	self.launcher.launch(node)
        time.sleep(3)	


    def launch_recorder(self, Scenarin_folder):
	arguments = "-O " + Scenarin_folder + "/scen_rec.bag --all --exclude /SENSORS/CAM/(.*)|/SENSORS/IBEO/(.*)|/Sahar/(.*)|/PER/Map|/WSM/(.*)|/flea3/(.*)|/right_sick/(.*)|/left_sick/(.*)|/gazebo/model_states|/clock"
#       arguments = "-O " + Scenarin_folder + "/scen_rec.bag --all --exclude /SENSORS/(.*)|/LOC/Velocity|/Sahar/(.*)|/OCU/(.*)|/LLC/(.*)|/PER/(.*)|/WPD/(.*)|/WSM/(.*)|/flea3/(.*)|/right_sick/(.*)|/left_sick/(.*)|/heartbeat|/gazebo/model_states|/clock"
#	arguments = "-O " + Scenarin_folder + "/scen_rec.bag --all --exclude /SENSORS/(.*)|/LOC/Pose|/LOC/Velocity|/Sahar/(.*)|/OCU/(.*)|/LLC/(.*)|/PER/(.*)|/WPD/(.*)|/WSM/(.*)|/flea3/(.*)|/right_sick/(.*)|/left_sick/(.*)|/heartbeat|/gazebo/model_states|/clock"
	node = ROSNode("rosbag", "record", name="rosbag_recorde_node", args=arguments)
	self.launcher.launch(node)
        time.sleep(3)	


    def launch_grader(self, Scenarin_folder):
	arguments = Scenarin_folder + " " + Scenarin_folder+"/scen.SFV"
	node = ROSNode("SRVSS", "grader_node", name="grader_node", output="screen", args=arguments)
	self.launcher.launch(node)
        time.sleep(3)	




    def Gazebo_UnPause(self):
	name = '/gazebo/unpause_physics'
	msg_class = std_srvs.srv.Empty()
	print "wait for service " + name
     	rospy.wait_for_service(name)
        print "done wating"
        try:
            service = rospy.ServiceProxy(name, msg_class)
            resp1 = service()
            return True
        except rospy.ServiceException, e:
            print "Service call failed: %s"%e
        return True
Exemplo n.º 6
0
class BITE:
    def __init__(self, robotName, plan, team, packageName):
        self.robotName = robotName
        self.plan = plan
        self.team = team
        self.packageName = packageName
        self.runningBehaviorsStack = []
        self.behaviorsRunning = []
        self.nodesToTerminate = []
        self.readyTeam = []
    	self.roslauncher = ROSLaunch()
    	self.roslauncher.start()
        
        # Initiate publishers
        # broadcast is the topic used for broadcast messages
        self.broadcastPublisher = rospy.Publisher('/bite/broadcast', InformMsg)
        self.terminateBehaviorPublisher = rospy.Publisher(str.format('/bite/{0}/terminate',self.robotName), String)

        # Initiate subscribers
        # broadcast is the topic used for broadcast messages
        rospy.Subscriber('/bite/broadcast', InformMsg, self.receiveCallback)

        print 'Waiting for knowledgebase...'
        knowledgeServiceName = str.format('/bite/{0}/get_knowledge', self.robotName)
        rospy.wait_for_service(knowledgeServiceName)
        self.getKnowledgeClient = rospy.ServiceProxy(knowledgeServiceName, GetKnowledge)
        print 'Ready'

        rospy.sleep(0.5)

    #######################################################
    # Expands the running behaviors stack hierarchichally #
    #######################################################
    def expandStackHierarchically(self):
        # Initiates the current node
        currentNode = self.plan.nodes[0]
        currentTeam = self.team

        if self.runningBehaviorsStack == []:
            # Adds the first node of the plan
            print str.format('Adding node "{0}" to the stack', currentNode.nodeName)
            self.runningBehaviorsStack.append((currentNode, currentTeam, ''))
        else:
            # If the stack is not empty starting from the last behavior in the stack
            currentNode, currentTeam = self.runningBehaviorsStack[-1][0:2]
            print str.format('Starting from node "{0}"', currentNode.nodeName)

        print str.format('Hierarchical children of node "{0}" are: {1}', currentNode.nodeName, [node.nodeName for node in currentNode.hierarchicalChildren])
        while not currentNode.hierarchicalChildren == []:
            # Allocating next level of hierarchy
            result = self.allocateNextNode(currentNode, currentTeam)

            if result.node == '':
                break

            currentNode = self.plan.getNode(result.node)
            currentTeam = result.newTeam

            # Adds the node to the stack
            print str.format('Adding node "{0}" to the stack', currentNode.nodeName)
            self.runningBehaviorsStack.append((currentNode, currentTeam, result.params))

            print str.format('Hierarchical children of node "{0}" are: {1}', currentNode.nodeName, [node.nodeName for node in currentNode.hierarchicalChildren])

        self.terminateBehaviorsNotInStack()
        rospy.sleep(1)
        print 'Starting behaviors in stack'
        for (node, team, params) in self.runningBehaviorsStack:
            if not node in self.behaviorsRunning:
                print str.format('Starting behavior: {0}', node.behaviorName)
                self.startBehavior(node, params)
                # Notify other robots what behavior its starting
                self.broadcastPublisher.publish(self.robotName, self.team,  str.format('STRATING {0}', node.behaviorName))

        self.nodesToTerminate = []

    ####################################################################
    # Allocate procedure for next node. Including team synchronization #
    ####################################################################
    def allocateNextNode(self, currentNode, currentTeam):
        filteredChildren = self.filterByPreConds(currentNode.hierarchicalChildren)
        print str.format('Next behaviors that their preconditions are true: {0}', [node.nodeName for node in filteredChildren])

        # Set the right allocate method for the current node
        print str.format('Node\'s allocate method is: "{0}"', currentNode.allocateMethod)
        allocateServiceName = str.format('/bite/{0}/{1}', self.robotName, currentNode.allocateMethod)
        rospy.wait_for_service(allocateServiceName)
        allocateClient = rospy.ServiceProxy(allocateServiceName, Allocate)

        if len(currentTeam) > 1:
            # Inform the rest of the team that preconditions of these behaviors are true
            print str.format('Informing the rest of the team: {0}', currentTeam)
            for node in filteredChildren:
                for preCond in node.preConds:
                    self.broadcastPublisher.publish(self.robotName, currentTeam, str.format('INFORM {0} {1}', preCond, True))

            # Sync with team
            print str.format('Waiting for team: {0}', currentTeam)
            self.waitForTeam(currentTeam)

            # Checks again after received information from other robots
            filteredChildren = self.filterByPreConds(currentNode.hierarchicalChildren)

            # Sleeps to make sure all the team gets here
            rospy.sleep(1)

        if (filteredChildren == []):
            # None of the nodes fit their preconditions
            return AllocateResponse('', [], '')
        # Calls allocate
        return allocateClient([child.nodeName for child in filteredChildren], currentTeam)

    ##############################################
    # Filters given nodes by their preconditions #
    ##############################################
    def filterByPreConds(self, nodes):
        filteredNodes = []
        
        # Iterates over all the given nodes
        for node in nodes:
            shouldAddNode = True
            for preCond in node.preConds:
                if not self.getKnowledgeClient(preCond).value == 'True':
                    # One of the preconds isn't true - not adding the node
                    shouldAddNode = False
                    break
            if shouldAddNode:
                filteredNodes.append(node)

        return filteredNodes

    ##############################
    # Waits for rest of the team #
    ##############################
    def waitForTeam(self, currentTeam):
        allTeamReady = False
        self.readyTeam = []
        while not allTeamReady:
            allTeamReady = True
            self.broadcastPublisher.publish(self.robotName, currentTeam, 'READY')
            rospy.sleep(1)
            for robot in currentTeam:
                if not robot in self.readyTeam:
                    allTeamReady = False
                    break
        self.broadcastPublisher.publish(self.robotName, currentTeam, 'READY')
        print 'All team is ready'

    ##############################################
    # Terminates behaviors not in current branch #
    ##############################################
    def terminateBehaviorsNotInStack(self):
        print 'Terminating behaviors not in current branch'
        for (node, team, params) in self.nodesToTerminate:
            if not (node, team, params) in self.runningBehaviorsStack:
                print str.format('Terminating behavior: {0}', node.behaviorName)
                self.terminateBehavior(node, team)

    ############################################################
    # Terminates a behavior and informing the rest of the team #
    ############################################################
    def terminateBehavior(self, node, team):
        # Inform the rest of the robots 
        self.broadcastPublisher.publish(self.robotName, team, str.format('TERMINATING {0}', node.behaviorName))
        # Terminate the behavior
        self.terminateBehaviorPublisher.publish(node.behaviorName)
        self.behaviorsRunning.remove(node)

    #####################
    # Starts a behavior #
    #####################
    def startBehavior(self, node, params):
        # Node name with the robot name appended for namespace reasons
        fullNodeName = str.format('bite_{0}_{1}', self.robotName.lower(), node.behaviorName.lower())
        # args var is for command line input, and by default is given the robot name, each argument is
        # is seperetd by space char
        args = str.format('{0} {1} {2}', self.robotName, node.behaviorName, params)
        # Creates a node, name argument is adding robotName and _ for namespace reasons
        runNode = Node(package = self.packageName, node_type = "BehaviorLauncher.py", name = fullNodeName, args = args, output = "screen")
        # Launch node
        self.roslauncher.launch(runNode)
        self.behaviorsRunning.append(node)

    ###################################################
    # Receives information from the broadcast channel #
    ###################################################
    def receiveCallback(self, msg):
        if self.robotName in msg.to:
            if msg.data == 'READY' and not msg.from_ in self.readyTeam:
                print str.format('Received that {0} is ready', msg.from_)
                self.readyTeam.append(msg.from_)

    ###########################################
    # Monitors running behaviors in the stack #
    ###########################################
    def monitorBehaviors(self):
        behaviorsEnded = []
        # Monitors behaviors in running stack
        while behaviorsEnded == []:
            rospy.sleep(1)
            # Test all nodes in the running stack for their termination conditions
            for (node, team, params) in self.runningBehaviorsStack:
                for termCond in node.termConds:
                    if self.getKnowledgeClient(termCond).value == 'True':
                        print str.format('I think that node {0} has to be terminated', node.nodeName)
                        behaviorsEnded.append(node)
                        # Informs the rest of the team
                        print str.format('Informing: {0}', team)
                        self.broadcastPublisher.publish(self.robotName, team, str.format('INFORM {0} {1}', termCond, True))
                        break

        # Adds nodes pending for termination
        while not behaviorsEnded == []:
            (node, team, params) = self.runningBehaviorsStack.pop()
            self.nodesToTerminate.append((node, team, params))
            if node in behaviorsEnded:
                behaviorsEnded.remove(node)

        # Returns the last node terminated
        return (node, team)

    #######################################################
    # Expands the stack sequentially                      #
    # Returns whether the stack was expanded sequentially #
    #######################################################
    def expandStackSequentially(self, currentNode, currentTeam):
        if currentNode.sequentialChildren == []:
            return False

        # Get all sequential children of current node and filter them by preconditions
        print str.format('Sequential children of node "{0}" are: {1}', currentNode.nodeName, [node.nodeName for node in currentNode.sequentialChildren])
        filteredChildren = self.filterByPreConds(currentNode.sequentialChildren)
        print str.format('Next behaviors that their preconditions are true: {0}', [node.nodeName for node in filteredChildren])

        # Set the right vote method for the last node went out of the stack
        print str.format('Node\'s vote method is: "{0}"', currentNode.voteMethod)
        voteServiceName = str.format('/bite/{0}/{1}', self.robotName, currentNode.voteMethod)
        rospy.wait_for_service(voteServiceName)
        voteClient = rospy.ServiceProxy(voteServiceName, Vote)

        if len(currentTeam) > 1:
            # Inform the rest of the team that preconditions of these behaviors are true
            print str.format('Informing the rest of the team: {0}', currentTeam)
            for node in filteredChildren:
                for preCond in node.preConds:
                    self.broadcastPublisher.publish(self.robotName, currentTeam, str.format('INFORM {0} {1}', preCond, True))

            # Sync with team
            print str.format('Waiting for team: {0}', currentTeam)
            self.waitForTeam(currentTeam)

            # Checks again after received information from other robots
            filteredChildren = self.filterByPreConds(currentNode.sequentialChildren)

            if filteredChildren == []:
                # None of the nodes fit their preconditions
                return False

            # Sleeps to make sure all the team gets here
            rospy.sleep(1)

        # Calls Vote
        result = voteClient([child.nodeName for child in filteredChildren], currentTeam)

        # Adds the node to the stack
        nextNode = self.plan.getNode(result.node)
        print str.format('Adding node "{0}" to the stack', nextNode.nodeName)
        self.runningBehaviorsStack.append((nextNode, currentTeam, result.params))
        return True