Пример #1
0
    def step(self, target_angle):
        """Execute one step of lateral control reach a certain target vehicle angle.
        NOTE: target and measurements are of vehicle longitudinal angle.

        Parameters
        ==========
        target_angle : float
            Target vehicle longitudinal angle in radians.

        Returns
        =======
        float
            Steering control in the range [-1, 1] where
            -1 maximum steering to left and
            +1 maximum steering to right
        """
        _, current_angle, _ = carlautil.to_rotation_ndarray(self.__vehicle)
        current_angle = util.npu.warp_radians_about_center(current_angle, target_angle)
        error = target_angle - current_angle
        self.__error_buffer.append(error)
        if len(self.__error_buffer) >= 2:
            _ie = sum(self.__error_buffer) * self.__dt
        else:
            _ie = 0.0
        if self.__should_hotfix_mpc:
            self.__should_hotfix_mpc = False
            _de = 0.0
        elif len(self.__error_buffer) >= 2:
            _de = (self.__error_buffer[-1] - self.__error_buffer[-2]) / self.__dt
        else:
            _de = 0.0
        self.__store_current(error, _ie, _de)
        ctrl_input = (self.__coeff.K_P * error) + (self.__coeff.K_D * _de) + (self.__coeff.K_I * _ie)
        ctrl_input = ctrl_input / self.__max_steering
        return self.__clip(ctrl_input)
Пример #2
0
 def add_stats():
     # save the speed, heading and control values
     speed = carlautil.actor_to_speed(ego_vehicle)
     _, heading, _ = carlautil.to_rotation_ndarray(ego_vehicle)
     speeds.append(speed)
     headings.append(heading)
     control = ego_vehicle.get_control()
     control_steers.append(control.steer)
     control_throttles.append(control.throttle)
     control_brakes.append(control.brake)
Пример #3
0
    def set_plan(self, target_speeds, target_angles, step_period):
        """Given a trajectory consisting of heading angle and
        velocities, use lateral and longitudinal PID controllers
        to actuate the vehicle.

        Parameters
        ==========
        target_speeds : iterable of float
            Target speeds in m/s for the next few consecutive steps.
        target_angles : iterable of float
            Target angles in radians for the next few consecutive steps.
            Angles should be in radians and in the Unreal Engine coordinate system.
            The iterables `target_speed` and `target_angle` should have the same length.
        step_period : int
            The fixed number of steps between two consecutive points in the trajectory.
            Each step takes `carla.WorldSettings.fixed_delta_seconds` time.
        """
        speed = carlautil.actor_to_speed(self.__vehicle)
        _, heading, _ = carlautil.to_rotation_ndarray(self.__vehicle)
        target_speeds = np.concatenate(([speed], target_speeds))
        target_angles = np.concatenate(([heading], target_angles))
        # angles are not expected to lie within (-pi, pi]. Enforce this constraint.
        target_angles = util.npu.warp_radians_neg_pi_to_pi(target_angles)
        self.step_to_speed = []
        self.step_to_angle = []
        n_steps = len(target_speeds) - 1
        for step in range(n_steps):
            nxt1 = target_angles[step+1]
            nxt2 = target_angles[step+1] + 2*np.pi
            nxt3 = target_angles[step+1] - 2*np.pi
            dif1 = abs(target_angles[step] - nxt1)
            dif2 = abs(target_angles[step] - nxt2)
            dif3 = abs(target_angles[step] - nxt3)
            if dif1 < dif2 and dif1 < dif3:
                nxt = nxt1
            elif dif2 < dif1 and dif2 < dif3:
                nxt = nxt2
            else:
                nxt = nxt3
            for substep in range(step_period):
                self.step_to_speed.append(
                    target_speeds[step] + (substep/step_period)*(target_speeds[step+1] - target_speeds[step])
                )
                self.step_to_angle.append(
                    util.npu.warp_radians_neg_pi_to_pi(
                        target_angles[step] + (substep/step_period)*(nxt - target_angles[step])
                    )
                )
        self.step_to_speed.append(target_speeds[-1])
        self.step_to_angle.append(target_angles[-1])
        self.__step_idx = 1
        self.longitudinal_controller.hotfix_mpc()
        self.lateral_controller.hotfix_mpc()
Пример #4
0
    def extract_junction_with_portals(self):
        carla_topology = self.carla_map.get_topology()
        junctions = carlautil.get_junctions_from_topology_graph(carla_topology)
        _junctions = []
        for junction in junctions:
            jx, jy, _ = carlautil.to_location_ndarray(junction, flip_y=True)
            wps = junction.get_waypoints(carla.LaneType.Driving)
            _wps = []
            for wp1, wp2 in wps:
                # wp1 is the waypoint entering into the intersection
                # wp2 is the waypoint exiting out of the intersection
                x, y, _ = carlautil.to_location_ndarray(wp1, flip_y=True)
                _, yaw, _ = carlautil.to_rotation_ndarray(wp1, flip_y=True)
                _wp1 = (x, y, yaw, wp1.lane_width)
                x, y, _ = carlautil.to_location_ndarray(wp2, flip_y=True)
                _, yaw, _ = carlautil.to_rotation_ndarray(wp2, flip_y=True)
                _wp2 = (x, y, yaw, wp2.lane_width)
                _wps.append((_wp1, _wp2))
            _junctions.append(
                util.AttrDict(pos=np.array([jx, jy]),
                              waypoints=np.array(_wps)))

        return _junctions
Пример #5
0
    def get_current(self):
        """Get reference and measurements after step has been taken step,
        and control is applied to vehicle.

        Returns
        =======
        util.AttrDict
            Contains the following at current 
            - measurement
            - reference
            - control : the last applied control.
        """
        control = self.__vehicle.get_control()
        control = util.AttrDict(
            throttle=control.throttle, brake=control.brake, steer=control.steer
        )
        error = util.AttrDict(
            speed=self.longitudinal_controller.get_current(),
            angle=self.lateral_controller.get_current()
        )
        speed = carlautil.actor_to_speed(self.__vehicle)
        _, angle, _ = carlautil.to_rotation_ndarray(self.__vehicle)
        if not self.step_to_speed \
                or self.__step_idx - 1 >= len(self.step_to_speed):
            return util.AttrDict(
                measurement=util.AttrDict(speed=speed, angle=angle),
                reference=util.AttrDict(speed=speed, angle=angle),
                error=error,
                control=control
            )
        reference_speed = self.step_to_speed[self.__step_idx - 1]
        reference_angle = self.step_to_angle[self.__step_idx - 1]
        return util.AttrDict(
            measurement=util.AttrDict(speed=speed, angle=angle),
            reference=util.AttrDict(
                speed=reference_speed,
                angle=reference_angle,
            ),
            error=error,
            control=control
        )
Пример #6
0
def get_straight_lanes(start_wp, tol=2.0):
    """Get the points corresponding to the straight parts of all
    lanes in road starting from start_wp going in the same direction.

    Parameters
    ==========
    start_wp : carla.Waypoint
        The starting point of the road lane.
    tol : float (optional)
        The tolerance to select straight part of the road in meters.

    Returns
    =======
    list of np.array
        Each item in the list are points for one lane of of shape (N_i, 2).
        Each (x, y) point is in meters in world coordinates.
    """
    _, start_yaw, _ = carlautil.to_rotation_ndarray(start_wp)
    wps = get_adjacent_waypoints(start_wp)
    f = lambda wp: get_straight_line(wp, start_yaw, tol=tol)
    return np.concatenate(util.map_to_list(f, wps))
Пример #7
0
def get_road_segment_enclosure(start_wp, tol=2.0):
    """Get rectangle that tightly inner approximates of the road segment
    containing the starting waypoint.

    Parameters
    ==========
    start_wp : carla.Waypoint
        A starting waypoint of the road.
    tol : float (optional)
        The tolerance to select straight part of the road in meters.

    Returns
    =======
    np.array
        The position and the heading angle of the starting waypoint
        of the road of form [x, y, angle] in (meters, meters, radians).
    np.array
        The 2D bounding box enclosure in world coordinates of shape (4, 2)
        enclosing the road segment.
    np.array
        The parameters of the enclosure of form
        (b_length, f_length, r_width, l_width)
        If the enclosure is in the reference frame such that the starting
        waypoint points along +x-axis, then the enclosure has these length
        and widths:
        ____________________________________
        |              l_width             |
        |               |                  |
        |               |                  |
        | b_length -- (x, y)-> -- f_length |
        |               |                  |
        |               |                  |
        |              r_width             |
        ------------------------------------
    """
    _LENGTH = -2
    _, start_yaw, _ = carlautil.to_rotation_ndarray(start_wp)
    adj_wps = get_adjacent_waypoints(start_wp)
    # mtx : np.array
    #   Rotation matrix from world coordinates, both frames in UE orientation
    mtx = util.rotation_2d(-start_yaw)
    # rev_mtx : np.array
    #   Rotation matrix to world coordinates, both frames in UE orientation
    rev_mtx = util.rotation_2d(start_yaw)
    s_x, s_y, _ = carlautil.to_location_ndarray(start_wp)

    # Get points of lanes
    f = lambda wp: get_straight_line(wp, start_yaw, tol=tol)
    pc = util.map_to_list(f, adj_wps)

    # Get length of bb for lanes
    def g(points):
        points = points - np.array([s_x, s_y])
        points = (rev_mtx @ points.T)[0]
        return np.abs(np.max(points) - np.min(points))

    lane_lengths = util.map_to_ndarray(g, pc)
    length = np.min(lane_lengths)

    # Get width of bb for lanes
    lwp, rwp = adj_wps[0], adj_wps[-1]
    l_x, l_y, _ = carlautil.to_location_ndarray(lwp)
    r_x, r_y, _ = carlautil.to_location_ndarray(rwp)
    points = np.array([[l_x, l_y], [s_x, s_y], [r_x, r_y]])
    points = points @ rev_mtx.T
    l_width = np.abs(points[0, 1] - points[1, 1]) + lwp.lane_width / 2.
    r_width = np.abs(points[1, 1] - points[2, 1]) + rwp.lane_width / 2.

    # construct bounding box of road segment
    x, y, _ = carlautil.to_location_ndarray(start_wp)
    vec = np.array([[0, 0], [_LENGTH, 0]]) @ mtx.T
    dx0, dy0 = vec[1, 0], vec[1, 1]
    vec = np.array([[0, 0], [length, 0]]) @ mtx.T
    dx1, dy1 = vec[1, 0], vec[1, 1]
    vec = np.array([[0, 0], [0, -l_width]]) @ mtx.T
    dx2, dy2 = vec[1, 0], vec[1, 1]
    vec = np.array([[0, 0], [0, r_width]]) @ mtx.T
    dx3, dy3 = vec[1, 0], vec[1, 1]
    bbox = np.array([[x + dx0 + dx3, y + dy0 + dy3],
                     [x + dx1 + dx3, y + dy1 + dy3],
                     [x + dx1 + dx2, y + dy1 + dy2],
                     [x + dx0 + dx2, y + dy0 + dy2]])
    start_wp_spec = np.array([s_x, s_y, start_yaw])
    bbox_spec = np.array([_LENGTH, length, r_width, l_width])
    return start_wp_spec, bbox, bbox_spec