Example #1
0
def update():
    """
    After start() is run, this function is run every frame until the back button
    is pressed
    """
    # Use the triggers to control the car's speed
    rt = rc.controller.get_trigger(rc.controller.Trigger.RIGHT)
    lt = rc.controller.get_trigger(rc.controller.Trigger.LEFT)
    speed = rt - lt

    # Calculate the distance in front of and behind the car
    scan = rc.lidar.get_samples()
    _, forward_dist = rc_utils.get_lidar_closest_point(scan, FRONT_WINDOW)
    _, back_dist = rc_utils.get_lidar_closest_point(scan, REAR_WINDOW)

    # TODO (warmup): Prevent the car from hitting things in front or behind it.
    # Allow the user to override safety stop by holding the left or right bumper.

    # Use the left joystick to control the angle of the front wheels
    angle = rc.controller.get_joystick(rc.controller.Joystick.LEFT)[0]

    rc.drive.set_speed_angle(speed, angle)

    # Print the current speed and angle when the A button is held down
    if rc.controller.is_down(rc.controller.Button.A):
        print("Speed:", speed, "Angle:", angle)

    # Print the distance of the closest object in front of and behind the car
    if rc.controller.is_down(rc.controller.Button.B):
        print("Forward distance:", forward_dist, "Back distance:", back_dist)

    # Display the current LIDAR scan
    rc.display.show_lidar(scan)
Example #2
0
def start():
    """
    This function is run once every time the start button is pressed
    """
    global cur_speed
    global prev_forward_dist
    global prev_back_dist

    # Have the car begin at a stop
    rc.drive.stop()

    # Initialize variables
    cur_speed = 0
    scan = rc.lidar.get_samples()
    _, forward_dist = rc_utils.get_lidar_closest_point(scan, FRONT_WINDOW)
    _, back_dist = rc_utils.get_lidar_closest_point(scan, REAR_WINDOW)

    # Print start message
    print(">> Lab 5A - LIDAR Safety Stop\n"
          "\n"
          "Controls:\n"
          "   Right trigger = accelerate forward\n"
          "   Right bumper = override forward safety stop\n"
          "   Left trigger = accelerate backward\n"
          "   Left bumper = override rear safety stop\n"
          "   Left joystick = turn front wheels\n"
          "   A button = print current speed and angle\n"
          "   B button = print forward and back distances")
Example #3
0
def update():
    """
    After start() is run, this function is run every frame until the back button
    is pressed
    """
    scan = rc.lidar.get_samples()
    highlighted_samples = [
    ]  # Samples we will highlight in the LIDAR visualization

    # Choose speed based on forward distance
    _, front_dist = rc_utils.get_lidar_closest_point(
        scan, (-FRONT_DIST_ANGLE, FRONT_DIST_ANGLE))
    speed = rc_utils.remap_range(front_dist, 0, BRAKE_DISTANCE, 0, MAX_SPEED,
                                 True)

    # Measure distance to the left and right walls ahead of the car
    left_ahead = rc_utils.get_lidar_average_distance(scan, -SIDE_ANGLE)
    right_ahead = rc_utils.get_lidar_average_distance(scan, SIDE_ANGLE)
    ratio = left_ahead / right_ahead if left_ahead > 0 and right_ahead > 0 else 1.0

    # If there is a wall ahead and the left wall is significantly father, assume that
    # the hallway has turned left
    if front_dist < BRAKE_DISTANCE and ratio > LEFT_TURN_RATIO:
        angle = -1
        print("HARD LEFT: ratio", ratio, "front dist", front_dist)

    # Otherwise, try to stay GOAL_DIST away from the right wall
    else:
        right_wall_angle, right_wall_dist = rc_utils.get_lidar_closest_point(
            scan, WINDOW_ANGLES)
        angle = rc_utils.remap_range(right_wall_dist, GOAL_DIST / 2, GOAL_DIST,
                                     -1, 0)
        angle = rc_utils.clamp(angle, -1, 1)

        # Display the closest point on the right wall
        highlighted_samples = [(right_wall_angle, right_wall_dist)]

    rc.drive.set_speed_angle(speed, angle)
    rc.display.show_lidar(scan, highlighted_samples=highlighted_samples)
def update():
    """
    After start() is run, this function is run every frame until the back button
    is pressed
    """
    # TODO: Park the car 30 cm away from the closest orange cone.
    # Use both color and depth information to handle cones of multiple sizes.
    # You may wish to copy some of your code from lab2b.py
    image = rc.camera.get_color_image()
    contours = rc_utils.find_contours(image, ORANGE[0], ORANGE[1])
    contour = rc_utils.get_largest_contour(contours, MIN_CONTOUR_AREA)
    if contour is not None:
        contour_center = rc_utils.get_contour_center(contour)
        rc_utils.draw_contour(image, contour)
        rc_utils.draw_circle(image, contour_center)
    else:
        contour_center = 0

    scan = rc.lidar.get_samples()
    __, coneDist = rc_utils.get_lidar_closest_point(scan, (-20, 20))

    if contour is not None:
        global pastTerm
        global derivTerm
        angleTerm = contour_center[1] - rc.camera.get_width() / 2
        speedTerm = coneDist - 50
        derivTerm = (speedTerm - pastTerm) / rc.get_delta_time(
        ) if speedTerm != pastTerm else derivTerm
        speedSign = speedTerm / abs(speedTerm) if speedTerm != 0 else 0

        print(str(speedTerm) + " and " + str(derivTerm))

        angle = angleTerm * (1 / 200)  #angle P controller
        speed = speedTerm * (1 / 50) + derivTerm * (1 / 250
                                                    )  #speed P"D" controller

        angle = -1 if angle < -1 else angle
        angle = 1 if angle > 1 else angle
        speed = -1 if speed < -1 else speed
        speed = 1 if speed > 1 else speed
        #speed = 0 if abs(derivTerm) < 15 else speed

    else:
        speed = 0
        angle = 0

    pastTerm = speedTerm
    rc.drive.set_speed_angle(speed, angle)
Example #5
0
def update():
    """
    After start() is run, this function is run every frame until the back button
    is pressed
    """
    global cur_speed
    global prev_forward_dist
    global prev_back_dist

    # Use the triggers to control the car's speed
    rt = rc.controller.get_trigger(rc.controller.Trigger.RIGHT)
    lt = rc.controller.get_trigger(rc.controller.Trigger.LEFT)
    speed = rt - lt

    # Calculate the distance in front of and behind the car
    scan = rc.lidar.get_samples()
    _, forward_dist = rc_utils.get_lidar_closest_point(scan, FRONT_WINDOW)
    _, back_dist = rc_utils.get_lidar_closest_point(scan, REAR_WINDOW)

    frame_speed: float
    if forward_dist < back_dist:
        frame_speed = (prev_forward_dist - forward_dist) / rc.get_delta_time()
    else:
        frame_speed = -(prev_back_dist - back_dist) / rc.get_delta_time()

    cur_speed += ALPHA * (frame_speed - cur_speed)
    prev_forward_dist = forward_dist
    prev_back_dist = back_dist
    stop_distance: float

    # FORARD SAFETY STOP: We are about to hit something in front of us
    if not rc.controller.is_down(rc.controller.Button.RB) and cur_speed > 0:
        # Calculate slow and stop distances based on the current speed
        stop_distance = rc_utils.clamp(
            MIN_STOP_DISTANCE +
            cur_speed * abs(cur_speed) * STOP_DISTANCE_SCALE,
            MIN_STOP_DISTANCE,
            MAX_STOP_DISTANCE,
        )
        slow_distance = stop_distance * SLOW_DISTANCE_RATIO

        # If we are past slow_distance, reduce speed proportional to how close we are
        # to stop_distance
        if stop_distance < forward_dist < slow_distance:
            speed = min(
                speed,
                rc_utils.remap_range(forward_dist, stop_distance,
                                     slow_distance, 0, 0.5),
            )
            print("Forward safety slow: speed limited to {}".format(speed))

        # Safety stop if we are passed stop_distance by reversing at a speed
        # proportional to how far we are past stop_distance
        if 0 < forward_dist < stop_distance:
            speed = rc_utils.remap_range(forward_dist, 0, stop_distance, -4,
                                         -0.2)
            speed = rc_utils.clamp(speed, -1, -0.2)
            print("Forward safety stop: reversing at {}".format(speed))

    # REAR SAFETY STOP: We are about to hit something behind us
    if not rc.controller.is_down(rc.controller.Button.LB) and cur_speed < 0:
        stop_distance = rc_utils.clamp(
            MIN_STOP_DISTANCE -
            cur_speed * abs(cur_speed) * STOP_DISTANCE_SCALE,
            MIN_STOP_DISTANCE,
            MAX_STOP_DISTANCE,
        )
        slow_distance = stop_distance * SLOW_DISTANCE_RATIO

        if stop_distance < back_dist < slow_distance:
            speed = max(
                speed,
                rc_utils.remap_range(back_dist, stop_distance, slow_distance,
                                     0, -0.5),
            )
            print("Back safety slow: speed limited to {}".format(speed))

        if 0 < back_dist < stop_distance:
            speed = rc_utils.remap_range(back_dist, 0, stop_distance, 4, 0.2,
                                         True)
            speed = rc_utils.clamp(speed, 0.2, 1)
            print("Back safety stop: accelerating forward at {}".format(speed))

    # Use the left joystick to control the angle of the front wheels
    angle = rc.controller.get_joystick(rc.controller.Joystick.LEFT)[0]

    rc.drive.set_speed_angle(speed, angle)

    # Print the current speed and angle when the A button is held down
    if rc.controller.is_down(rc.controller.Button.A):
        print("Speed:", speed, "Angle:", angle)

    # Print the distance of the closest object in front of and behind the car
    if rc.controller.is_down(rc.controller.Button.B):
        print("Forward distance:", forward_dist, "Back distance:", back_dist)

    # Print cur_speed estimate and stop distance when the X button is held down
    if rc.controller.is_down(rc.controller.Button.X):
        print("Current speed estimate: {:.2f} cm/s, Stop distance: {:.2f}".
              format(cur_speed, stop_distance))

    # Display the current LIDAR scan
    rc.display.show_lidar(scan)
Example #6
0
def update():
    """
    After start() is run, this function is run every frame until the back button
    is pressed
    """
    # Display the color image cropped to the top left
    if rc.controller.was_pressed(rc.controller.Button.A):
        image = rc.camera.get_color_image()
        cropped = rc_utils.crop(
            image, (0, 0),
            (rc.camera.get_height() // 2, rc.camera.get_width() // 2))
        rc.display.show_color_image(cropped)

    # Find and display the largest red contour in the color image
    if rc.controller.was_pressed(rc.controller.Button.B):
        image = rc.camera.get_color_image()
        contours = rc_utils.find_contours(image, RED[0], RED[1])
        largest_contour = rc_utils.get_largest_contour(contours)

        if largest_contour is not None:
            center = rc_utils.get_contour_center(largest_contour)
            area = rc_utils.get_contour_area(largest_contour)
            print("Largest red contour: center={}, area={:.2f}".format(
                center, area))
            rc_utils.draw_contour(image, largest_contour,
                                  rc_utils.ColorBGR.green.value)
            rc_utils.draw_circle(image, center, rc_utils.ColorBGR.yellow.value)
            rc.display.show_color_image(image)
        else:
            print("No red contours found")

    # Print depth image statistics and show the cropped upper half
    if rc.controller.was_pressed(rc.controller.Button.X):
        depth_image = rc.camera.get_depth_image()

        # Measure average distance at several points
        left_distance = rc_utils.get_pixel_average_distance(
            depth_image,
            (rc.camera.get_height() // 2, rc.camera.get_width() // 4),
        )
        center_distance = rc_utils.get_depth_image_center_distance(depth_image)
        center_distance_raw = rc_utils.get_depth_image_center_distance(
            depth_image, 1)
        right_distance = rc_utils.get_pixel_average_distance(
            depth_image,
            (rc.camera.get_height() // 2, 3 * rc.camera.get_width() // 4),
        )
        print(f"Depth image left distance: {left_distance:.2f} cm")
        print(f"Depth image center distance: {center_distance:.2f} cm")
        print(f"Depth image raw center distance: {center_distance_raw:.2f} cm")
        print(f"Depth image right distance: {right_distance:.2f} cm")

        # Measure pixels where the kernel falls off the edge of the photo
        upper_left_distance = rc_utils.get_pixel_average_distance(
            depth_image, (2, 1), 11)
        lower_right_distance = rc_utils.get_pixel_average_distance(
            depth_image,
            (rc.camera.get_height() - 2, rc.camera.get_width() - 5), 13)
        print(f"Depth image upper left distance: {upper_left_distance:.2f} cm")
        print(
            f"Depth image lower right distance: {lower_right_distance:.2f} cm")

        # Find closest point in bottom third
        cropped = rc_utils.crop(
            depth_image,
            (0, 0),
            (rc.camera.get_height() * 2 // 3, rc.camera.get_width()),
        )
        closest_point = rc_utils.get_closest_pixel(cropped)
        closest_distance = cropped[closest_point[0]][closest_point[1]]
        print(
            f"Depth image closest point (upper half): (row={closest_point[0]}, col={closest_point[1]}), distance={closest_distance:.2f} cm"
        )
        rc.display.show_depth_image(cropped, points=[closest_point])

    # Print lidar statistics and show visualization with closest point highlighted
    if rc.controller.was_pressed(rc.controller.Button.Y):
        lidar = rc.lidar.get_samples()
        front_distance = rc_utils.get_lidar_average_distance(lidar, 0)
        right_distance = rc_utils.get_lidar_average_distance(lidar, 90)
        back_distance = rc_utils.get_lidar_average_distance(lidar, 180)
        left_distance = rc_utils.get_lidar_average_distance(lidar, 270)
        print(f"Front LIDAR distance: {front_distance:.2f} cm")
        print(f"Right LIDAR distance: {right_distance:.2f} cm")
        print(f"Back LIDAR distance: {back_distance:.2f} cm")
        print(f"Left LIDAR distance: {left_distance:.2f} cm")

        closest_sample = rc_utils.get_lidar_closest_point(lidar)
        print(
            f"Closest LIDAR point: {closest_sample[0]:.2f} degrees, {closest_sample[1]:.2f} cm"
        )
        rc.display.show_lidar(lidar, highlighted_samples=[closest_sample])

    # Print lidar distance in the direction the right joystick is pointed
    rjoy_x, rjoy_y = rc.controller.get_joystick(rc.controller.Joystick.RIGHT)
    if abs(rjoy_x) > 0 or abs(rjoy_y) > 0:
        lidar = rc.lidar.get_samples()
        angle = (math.atan2(rjoy_x, rjoy_y) * 180 / math.pi) % 360
        distance = rc_utils.get_lidar_average_distance(lidar, angle)
        print(f"LIDAR distance at angle {angle:.2f} = {distance:.2f} cm")

    # Default drive-style controls
    left_trigger = rc.controller.get_trigger(rc.controller.Trigger.LEFT)
    right_trigger = rc.controller.get_trigger(rc.controller.Trigger.RIGHT)
    left_joystick = rc.controller.get_joystick(rc.controller.Joystick.LEFT)
    rc.drive.set_speed_angle(right_trigger - left_trigger, left_joystick[0])
Example #7
0
def update():
    """
    After start() is run, this function is run every frame until the back button
    is pressed
    """
    global cur_mode

    scan = rc.lidar.get_samples()
    speed = 0
    angle = 0

    # Find the minimum distance to the front, side, and rear of the car
    front_angle, front_dist = rc_utils.get_lidar_closest_point(
        scan, (-MIN_SIDE_ANGLE, MIN_SIDE_ANGLE)
    )
    left_angle, left_dist = rc_utils.get_lidar_closest_point(
        scan, (-MAX_SIDE_ANGLE, -MIN_SIDE_ANGLE)
    )
    right_angle, right_dist = rc_utils.get_lidar_closest_point(
        scan, (MIN_SIDE_ANGLE, MAX_SIDE_ANGLE)
    )

    # Estimate the left wall angle relative to the car by comparing the distance
    # to the left-front and left-back
    left_front_dist = rc_utils.get_lidar_average_distance(
        scan, -SIDE_FRONT_ANGLE, WINDOW_ANGLE
    )
    left_back_dist = rc_utils.get_lidar_average_distance(
        scan, -SIDE_BACK_ANGLE, WINDOW_ANGLE
    )
    left_dif = left_front_dist - left_back_dist

    # Use the same process for the right wall angle
    right_front_dist = rc_utils.get_lidar_average_distance(
        scan, SIDE_FRONT_ANGLE, WINDOW_ANGLE
    )
    right_back_dist = rc_utils.get_lidar_average_distance(
        scan, SIDE_BACK_ANGLE, WINDOW_ANGLE
    )
    right_dif = right_front_dist - right_back_dist

    # If we are within PANIC_DISTANCE of either wall, enter panic mode
    if left_dist < PANIC_DISTANCE or right_dist < PANIC_DISTANCE:
        cur_mode = Mode.left_panic if left_dist < right_dist else Mode.right_panic

    # If there are no visible walls to follow, stop the car
    if left_front_dist == 0.0 and right_front_dist == 0.0:
        speed = 0
        angle = 0

    # LEFT PANIC: We are close to hitting a wall to the left, so turn hard right
    elif cur_mode == Mode.left_panic:
        angle = 1
        speed = PANIC_SPEED

        if left_dist > END_PANIC_DISTANCE:
            cur_mode = Mode.align

    # RIGHT PANIC: We are close to hitting a wall to the right, so turn hard left
    elif cur_mode == Mode.right_panic:
        angle = -1
        speed = PANIC_SPEED

        if right_dist > END_PANIC_DISTANCE:
            cur_mode = Mode.align

    # ALIGN: Try to align straight and equidistant between the left and right walls
    else:
        # If left_dif is very large, the hallway likely turns to the left
        if left_dif > TURN_THRESHOLD:
            angle = -1

        # Similarly, if right_dif is very large, the hallway likely turns to the right
        elif right_dif > TURN_THRESHOLD:
            angle = 1

        # Otherwise, determine angle by taking into account both the relative angles and
        # distances of the left and right walls
        value = (right_dif - left_dif) + (right_dist - left_dist)
        angle = rc_utils.remap_range(
            value, -TURN_THRESHOLD, TURN_THRESHOLD, -1, 1, True
        )

        # Choose speed based on the distance of the object in front of the car
        speed = rc_utils.remap_range(front_dist, 0, BRAKE_DISTANCE, 0, MAX_SPEED, True)

    rc.drive.set_speed_angle(speed, angle)

    # Show the lidar scan, highlighting the samples used as min_dist measurements
    highlighted_samples = [
        (front_angle, front_dist),
        (left_angle, left_dist),
        (right_angle, right_dist),
    ]
    rc.display.show_lidar(scan, highlighted_samples=highlighted_samples)

    # Print the current speed and angle when the A button is held down
    if rc.controller.is_down(rc.controller.Button.A):
        print("Speed:", speed, "Angle:", angle)

    # Print calculated statistics when the B button is held down
    if rc.controller.is_down(rc.controller.Button.B):
        print(
            "front_dist {:.2f}, left_dist {:.2f} cm, left_dif {:.2f} cm, right_dist {:.2f} cm, right_dif {:.2f} cm".format(
                front_dist, left_dist, left_dif, right_dist, right_dif
            )
        )

    # Print the current mode when the X button is held down
    if rc.controller.is_down(rc.controller.Button.X):
        print("Mode:", cur_mode)
Example #8
0
 def update_images(self, rc):
     self.__color_image = rc.camera.get_color_image()
     self.__depth_image = cv.GaussianBlur((rc.camera.get_depth_image() - 0.01) % 10000, (c.BLUR_KERNEL_SIZE, c.BLUR_KERNEL_SIZE), 0) 
     self.__closest_lidar_sample = rc_utils.get_lidar_closest_point((rc.lidar.get_samples() - 0.1) * 1000, (0, 360))