Esempio n. 1
0
    def _init_controller(self, opt_dict):
        """
        Controller initialization.

        :param opt_dict: dictionary of arguments.
        :return:
        """
        # default params
        self._current_speed = 0.0  # Km/h
        self._current_pose = Pose()
        args_lateral_dict = {'K_P': 1.95, 'K_D': 0.01, 'K_I': 1.4}
        args_longitudinal_dict = {'K_P': 0.2, 'K_D': 0.05, 'K_I': 0.1}

        # parameters overload
        if opt_dict:
            if 'lateral_control_dict' in opt_dict:
                args_lateral_dict = opt_dict['lateral_control_dict']
            if 'longitudinal_control_dict' in opt_dict:
                args_longitudinal_dict = opt_dict['longitudinal_control_dict']

        self._current_waypoint = self.get_waypoint(self._current_pose.position)
        self._vehicle_controller = VehiclePIDController(
            args_lateral=args_lateral_dict,
            args_longitudinal=args_longitudinal_dict)

        self._global_plan = False
Esempio n. 2
0
    def __init__(self):
        super(LocalPlanner, self).__init__('local_planner')

        # ros parameters
        role_name = self.get_param("role_name", "ego_vehicle")
        self.control_time_step = self.get_param("control_time_step", 0.05)
        args_lateral_dict = {}
        args_lateral_dict['K_P'] = self.get_param("Kp_lateral", 0.9)
        args_lateral_dict['K_I'] = self.get_param("Ki_lateral", 0.0)
        args_lateral_dict['K_D'] = self.get_param("Kd_lateral", 0.0)
        args_longitudinal_dict = {}
        args_longitudinal_dict['K_P'] = self.get_param("Kp_longitudinal",
                                                       0.206)
        args_longitudinal_dict['K_I'] = self.get_param("Ki_longitudinal",
                                                       0.0206)
        args_longitudinal_dict['K_D'] = self.get_param("Kd_longitudinal",
                                                       0.515)

        self.target_route_point = None
        self._vehicle_controller = None
        self._waypoints_queue = deque(maxlen=20000)
        self._buffer_size = 5
        self._waypoint_buffer = deque(maxlen=self._buffer_size)
        self.path_received = False
        self._current_speed = None
        self._current_pose = None
        self._target_speed = 0.0

        # subscribers
        self._odometry_subscriber = self.create_subscriber(
            Odometry, "/carla/{}/odometry".format(role_name),
            self.odometry_updated)
        self._path_subscriber = self.create_subscriber(
            Path, "/carla/{}/waypoints".format(role_name), self.path_updated,
            QoSProfile(depth=1, durability=True))
        self._target_speed_subscriber = self.create_subscriber(
            Float64, "/carla/{}/speed_command".format(role_name),
            self.target_speed_updated, QoSProfile(depth=1, durability=True))

        # publishers
        self._target_point_publisher = self.new_publisher(
            Marker, "/carla/{}/next_target".format(role_name),
            QoSProfile(depth=10, durability=False))
        self._control_cmd_publisher = self.new_publisher(
            CarlaEgoVehicleControl,
            "/carla/{}/vehicle_control_cmd".format(role_name),
            QoSProfile(depth=1, durability=False))

        # initializing controller
        self._vehicle_controller = VehiclePIDController(
            self,
            args_lateral=args_lateral_dict,
            args_longitudinal=args_longitudinal_dict)

        # wait for required messages
        self.loginfo('Local planner waiting for a path and target speed...')
        while self._current_pose is None or self._target_speed is None or self.path_received is False:
            time.sleep(0.05)
            if ROS_VERSION == 2:
                rclpy.spin_once(self, timeout_sec=0)
Esempio n. 3
0
    def _init_controller(self, opt_dict):
        """
        Controller initialization.

        :param opt_dict: dictionary of arguments.
        :return:
        """
        # default params
        args_lateral_dict = {
            'K_P': 1.95,
            'K_D': 0.01,
            'K_I': 1.4}
        args_longitudinal_dict = {
            'K_P': 0.2,
            'K_D': 0.05,
            'K_I': 0.1}

        # parameters overload
        if opt_dict:
            if 'lateral_control_dict' in opt_dict:
                args_lateral_dict = opt_dict['lateral_control_dict']
            if 'longitudinal_control_dict' in opt_dict:
                args_longitudinal_dict = opt_dict['longitudinal_control_dict']

        self._vehicle_controller = VehiclePIDController(args_lateral=args_lateral_dict,
                                                        args_longitudinal=args_longitudinal_dict)
Esempio n. 4
0
class LocalPlanner(object):
    """
    LocalPlanner implements the basic behavior of following a trajectory of waypoints that is
    generated on-the-fly. The low-level motion of the vehicle is computed by using two PID
    controllers, one is used for the lateral control and the other for the longitudinal
    control (cruise speed).

    When multiple paths are available (intersections) this local planner makes a random choice.
    """

    # minimum distance to target waypoint as a percentage (e.g. within 90% of
    # total distance)
    MIN_DISTANCE_PERCENTAGE = 0.9

    def __init__(self, role_name, opt_dict=None):
        """
        :param vehicle: actor to apply to local planner logic onto
        :param opt_dict: dictionary of arguments with the following semantics:

            target_speed -- desired cruise speed in Km/h

            sampling_radius -- search radius for next waypoints in seconds: e.g. 0.5 seconds ahead

            lateral_control_dict -- dictionary of arguments to setup the lateral PID controller
                                    {'K_P':, 'K_D':, 'K_I'}

            longitudinal_control_dict -- dictionary of arguments to setup the longitudinal
                                         PID controller
                                         {'K_P':, 'K_D':, 'K_I'}
        """
        self._current_waypoint = None
        self.target_waypoint = None
        self._vehicle_controller = None
        self._global_plan = None
        self._waypoints_queue = deque(maxlen=20000)
        self._buffer_size = 5
        self._waypoint_buffer = deque(maxlen=self._buffer_size)
        self._vehicle_yaw = None
        self._current_speed = None
        self._current_pose = None

        self._target_point_publisher = rospy.Publisher("/next_target",
                                                       PointStamped,
                                                       queue_size=1)
        rospy.wait_for_service(
            '/carla_waypoint_publisher/{}/get_waypoint'.format(role_name))

        self._get_waypoint_client = rospy.ServiceProxy(
            '/carla_waypoint_publisher/{}/get_waypoint'.format(role_name),
            GetWaypoint)

        # initializing controller
        self._init_controller(opt_dict)

    def get_waypoint(self, location):
        """
        Helper to get waypoint from a ros service
        """
        try:
            response = self._get_waypoint_client(location)
            return response.waypoint
        except (rospy.ServiceException, rospy.ROSInterruptException) as e:
            if not rospy.is_shutdown:
                rospy.logwarn("Service call failed: {}".format(e))

    def odometry_updated(self, odo):
        """
        Callback on new odometry
        """
        self._current_speed = math.sqrt(odo.twist.twist.linear.x**2 +
                                        odo.twist.twist.linear.y**2 +
                                        odo.twist.twist.linear.z**2) * 3.6

        self._current_pose = odo.pose.pose
        quaternion = (odo.pose.pose.orientation.x, odo.pose.pose.orientation.y,
                      odo.pose.pose.orientation.z, odo.pose.pose.orientation.w)
        _, _, self._vehicle_yaw = euler_from_quaternion(quaternion)

    def _init_controller(self, opt_dict):
        """
        Controller initialization.

        :param opt_dict: dictionary of arguments.
        :return:
        """
        # default params
        self._current_speed = 0.0  # Km/h
        self._current_pose = Pose()
        args_lateral_dict = {'K_P': 1.95, 'K_D': 0.01, 'K_I': 1.4}
        args_longitudinal_dict = {'K_P': 0.2, 'K_D': 0.05, 'K_I': 0.1}

        # parameters overload
        if opt_dict:
            if 'lateral_control_dict' in opt_dict:
                args_lateral_dict = opt_dict['lateral_control_dict']
            if 'longitudinal_control_dict' in opt_dict:
                args_longitudinal_dict = opt_dict['longitudinal_control_dict']

        self._current_waypoint = self.get_waypoint(self._current_pose.position)
        self._vehicle_controller = VehiclePIDController(
            args_lateral=args_lateral_dict,
            args_longitudinal=args_longitudinal_dict)

        self._global_plan = False

    def set_global_plan(self, current_plan):
        """
        set a global plan to follow
        """
        self._waypoints_queue.clear()
        self._waypoint_buffer.clear()
        for elem in current_plan:
            self._waypoints_queue.append(elem.pose)
        self._global_plan = True

    def run_step(self, target_speed):
        """
        Execute one step of local planning which involves running the longitudinal
        and lateral PID controllers to follow the waypoints trajectory.
        """
        if not self._waypoints_queue:
            control = CarlaEgoVehicleControl()
            control.steer = 0.0
            control.throttle = 0.0
            control.brake = 1.0
            control.hand_brake = False
            control.manual_gear_shift = False

            return control

        #   Buffering the waypoints
        if not self._waypoint_buffer:
            for i in range(self._buffer_size):
                if self._waypoints_queue:
                    self._waypoint_buffer.append(
                        self._waypoints_queue.popleft())
                else:
                    break

        # current vehicle waypoint
        self._current_waypoint = self.get_waypoint(self._current_pose.position)

        # target waypoint
        target_route_point = self._waypoint_buffer[0]

        # for us redlight-detection
        self.target_waypoint = self.get_waypoint(target_route_point.position)

        target_point = PointStamped()
        target_point.header.frame_id = "map"
        target_point.point.x = target_route_point.position.x
        target_point.point.y = target_route_point.position.y
        target_point.point.z = target_route_point.position.z
        self._target_point_publisher.publish(target_point)
        # move using PID controllers
        control = self._vehicle_controller.run_step(target_speed,
                                                    self._current_speed,
                                                    self._current_pose,
                                                    target_route_point)

        # purge the queue of obsolete waypoints
        max_index = -1

        sampling_radius = target_speed * 1 / 3.6  # 1 seconds horizon
        min_distance = sampling_radius * self.MIN_DISTANCE_PERCENTAGE

        for i, route_point in enumerate(self._waypoint_buffer):
            if distance_vehicle(route_point,
                                self._current_pose.position) < min_distance:
                max_index = i
        if max_index >= 0:
            for i in range(max_index + 1):
                self._waypoint_buffer.popleft()

        return control
Esempio n. 5
0
class LocalPlanner(object):
    """
    LocalPlanner implements the basic behavior of following a trajectory of waypoints that is
    generated on-the-fly. The low-level motion of the vehicle is computed by using two PID
    controllers, one is used for the lateral control and the other for the longitudinal
    control (cruise speed).

    When multiple paths are available (intersections) this local planner makes a random choice.
    """

    # minimum distance to target waypoint as a percentage (e.g. within 90% of
    # total distance)
    MIN_DISTANCE_PERCENTAGE = 0.9

    def __init__(self, opt_dict=None):
        """
        :param vehicle: actor to apply to local planner logic onto
        :param opt_dict: dictionary of arguments with the following semantics:

            target_speed -- desired cruise speed in Km/h

            sampling_radius -- search radius for next waypoints in seconds: e.g. 0.5 seconds ahead

            lateral_control_dict -- dictionary of arguments to setup the lateral PID controller
                                    {'K_P':, 'K_D':, 'K_I'}

            longitudinal_control_dict -- dictionary of arguments to setup the longitudinal
                                         PID controller
                                         {'K_P':, 'K_D':, 'K_I'}
        """
        self.target_route_point = None
        self._vehicle_controller = None
        self._waypoints_queue = deque(maxlen=20000)
        self._buffer_size = 5
        self._waypoint_buffer = deque(maxlen=self._buffer_size)

        self._target_point_publisher = rospy.Publisher("/next_target",
                                                       PointStamped,
                                                       queue_size=1)

        # initializing controller
        self._init_controller(opt_dict)

    def _init_controller(self, opt_dict):
        """
        Controller initialization.

        :param opt_dict: dictionary of arguments.
        :return:
        """
        # default params
        args_lateral_dict = {'K_P': 1.95, 'K_D': 0.01, 'K_I': 1.4}
        args_longitudinal_dict = {'K_P': 0.2, 'K_D': 0.05, 'K_I': 0.1}

        # parameters overload
        if opt_dict:
            if 'lateral_control_dict' in opt_dict:
                args_lateral_dict = opt_dict['lateral_control_dict']
            if 'longitudinal_control_dict' in opt_dict:
                args_longitudinal_dict = opt_dict['longitudinal_control_dict']

        self._vehicle_controller = VehiclePIDController(
            args_lateral=args_lateral_dict,
            args_longitudinal=args_longitudinal_dict)

    def set_global_plan(self, current_plan):
        """
        set a global plan to follow
        """
        self.target_route_point = None
        self._waypoint_buffer.clear()
        self._waypoints_queue.clear()
        for elem in current_plan:
            self._waypoints_queue.append(elem.pose)

    def run_step(self, target_speed, current_speed, current_pose):
        """
        Execute one step of local planning which involves running the longitudinal
        and lateral PID controllers to follow the waypoints trajectory.
        """
        if not self._waypoint_buffer and not self._waypoints_queue:
            control = CarlaEgoVehicleControl()
            control.steer = 0.0
            control.throttle = 0.0
            control.brake = 1.0
            control.hand_brake = False
            control.manual_gear_shift = False

            rospy.loginfo("Route finished.")
            return control, True

        #   Buffering the waypoints
        if not self._waypoint_buffer:
            for i in range(self._buffer_size):
                if self._waypoints_queue:
                    self._waypoint_buffer.append(
                        self._waypoints_queue.popleft())
                else:
                    break

        # target waypoint
        self.target_route_point = self._waypoint_buffer[0]

        target_point = PointStamped()
        target_point.header.frame_id = "map"
        target_point.point.x = self.target_route_point.position.x
        target_point.point.y = self.target_route_point.position.y
        target_point.point.z = self.target_route_point.position.z
        self._target_point_publisher.publish(target_point)
        # move using PID controllers
        control = self._vehicle_controller.run_step(target_speed,
                                                    current_speed,
                                                    current_pose,
                                                    self.target_route_point)

        # purge the queue of obsolete waypoints
        max_index = -1

        sampling_radius = target_speed * 1 / 3.6  # 1 seconds horizon
        min_distance = sampling_radius * self.MIN_DISTANCE_PERCENTAGE

        for i, route_point in enumerate(self._waypoint_buffer):
            if distance_vehicle(route_point,
                                current_pose.position) < min_distance:
                max_index = i
        if max_index >= 0:
            for i in range(max_index + 1):
                self._waypoint_buffer.popleft()

        return control, False
Esempio n. 6
0
class LocalPlanner(CompatibleNode):
    """
    LocalPlanner implements the basic behavior of following a trajectory of waypoints that is
    generated on-the-fly. The low-level motion of the vehicle is computed by using two PID
    controllers, one is used for the lateral control and the other for the longitudinal
    control (cruise speed).

    When multiple paths are available (intersections) this local planner makes a random choice.
    """

    # minimum distance to target waypoint as a percentage (e.g. within 90% of
    # total distance)
    MIN_DISTANCE_PERCENTAGE = 0.9

    def __init__(self):
        super(LocalPlanner, self).__init__('local_planner')

        # ros parameters
        role_name = self.get_param("role_name", "ego_vehicle")
        self.control_time_step = self.get_param("control_time_step", 0.05)
        args_lateral_dict = {}
        args_lateral_dict['K_P'] = self.get_param("Kp_lateral", 0.9)
        args_lateral_dict['K_I'] = self.get_param("Ki_lateral", 0.0)
        args_lateral_dict['K_D'] = self.get_param("Kd_lateral", 0.0)
        args_longitudinal_dict = {}
        args_longitudinal_dict['K_P'] = self.get_param("Kp_longitudinal",
                                                       0.206)
        args_longitudinal_dict['K_I'] = self.get_param("Ki_longitudinal",
                                                       0.0206)
        args_longitudinal_dict['K_D'] = self.get_param("Kd_longitudinal",
                                                       0.515)

        self.target_route_point = None
        self._vehicle_controller = None
        self._waypoints_queue = deque(maxlen=20000)
        self._buffer_size = 5
        self._waypoint_buffer = deque(maxlen=self._buffer_size)
        self.path_received = False
        self._current_speed = None
        self._current_pose = None
        self._target_speed = 0.0

        # subscribers
        self._odometry_subscriber = self.create_subscriber(
            Odometry, "/carla/{}/odometry".format(role_name),
            self.odometry_updated)
        self._path_subscriber = self.create_subscriber(
            Path, "/carla/{}/waypoints".format(role_name), self.path_updated,
            QoSProfile(depth=1, durability=True))
        self._target_speed_subscriber = self.create_subscriber(
            Float64, "/carla/{}/speed_command".format(role_name),
            self.target_speed_updated, QoSProfile(depth=1, durability=True))

        # publishers
        self._target_point_publisher = self.new_publisher(
            Marker, "/carla/{}/next_target".format(role_name),
            QoSProfile(depth=10, durability=False))
        self._control_cmd_publisher = self.new_publisher(
            CarlaEgoVehicleControl,
            "/carla/{}/vehicle_control_cmd".format(role_name),
            QoSProfile(depth=1, durability=False))

        # initializing controller
        self._vehicle_controller = VehiclePIDController(
            self,
            args_lateral=args_lateral_dict,
            args_longitudinal=args_longitudinal_dict)

        # wait for required messages
        self.loginfo('Local planner waiting for a path and target speed...')
        while self._current_pose is None or self._target_speed is None or self.path_received is False:
            time.sleep(0.05)
            if ROS_VERSION == 2:
                rclpy.spin_once(self, timeout_sec=0)

    def odometry_updated(self, new_pose):
        """
        callback on new odometry
        """
        self._current_speed = math.sqrt(new_pose.twist.twist.linear.x**2 +
                                        new_pose.twist.twist.linear.y**2 +
                                        new_pose.twist.twist.linear.z**2) * 3.6
        self._current_pose = new_pose.pose.pose

    def target_speed_updated(self, new_target_speed):
        self._target_speed = new_target_speed.data

    def path_updated(self, new_path):
        """
        set a global plan to follow
        """
        self.loginfo('New path to follow received.')
        self.path_received = True
        self.target_route_point = None
        self._waypoint_buffer.clear()
        self._waypoints_queue.clear()
        for elem in new_path.poses:
            self._waypoints_queue.append(elem.pose)

    def run_step(self):
        """
        Execute one step of local planning which involves running the longitudinal
        and lateral PID controllers to follow the waypoints trajectory.
        """
        if self.path_received is False:
            return

        if not self._waypoint_buffer and not self._waypoints_queue:
            self.emergency_stop()
            self.loginfo("Route finished. Waiting for a new one.")
            self.path_received = False
            return

        # When target speed is 0, brake
        if self._target_speed == 0.0:
            self.emergency_stop()
            return

        #   Buffering the waypoints
        if not self._waypoint_buffer:
            for i in range(self._buffer_size):
                if self._waypoints_queue:
                    self._waypoint_buffer.append(
                        self._waypoints_queue.popleft())
                else:
                    break

        # target waypoint
        self.target_route_point = self._waypoint_buffer[0]
        target_point = Marker()
        target_point.type = 0
        target_point.header.frame_id = "map"
        target_point.pose = self.target_route_point
        target_point.scale.x = 1.0
        target_point.scale.y = 0.2
        target_point.scale.z = 0.2
        target_point.color.r = 255.0
        target_point.color.a = 1.0
        self._target_point_publisher.publish(target_point)

        # move using PID controllers
        control = self._vehicle_controller.run_step(self._target_speed,
                                                    self._current_speed,
                                                    self._current_pose,
                                                    self.target_route_point)

        # purge the queue of obsolete waypoints
        max_index = -1

        sampling_radius = self._target_speed * 1 / 3.6  # search radius for next waypoints in seconds
        min_distance = sampling_radius * self.MIN_DISTANCE_PERCENTAGE

        for i, route_point in enumerate(self._waypoint_buffer):
            if distance_vehicle(route_point,
                                self._current_pose.position) < min_distance:
                max_index = i
        if max_index >= 0:
            for i in range(max_index + 1):
                self._waypoint_buffer.popleft()

        self._control_cmd_publisher.publish(control)
        return

    def emergency_stop(self):
        control = CarlaEgoVehicleControl()
        control.steer = 0.0
        control.throttle = 0.0
        control.brake = 1.0
        control.hand_brake = False
        control.manual_gear_shift = False
        self._control_cmd_publisher.publish(control)