Example #1
0
def smart_square(distance, ignore_sonar=False):
    ignore = Obstacle.IS_VISION
    if ignore_sonar:
        ignore |= Obstacle.IS_SONAR

    # Compute a square based on the current heading.
    start_pose = swarmie.get_odom_location().get_pose()
    start = Point()
    start.x = start_pose.x
    start.y = start_pose.y
    print('Start point: ({:.2f}, {:.2f})'.format(start.x, start.y))

    sq1 = Point()
    sq1.x = start.x + distance * math.cos(start_pose.theta)
    sq1.y = start.y + distance * math.sin(start_pose.theta)

    sq2 = Point()
    sq2.x = sq1.x + distance * math.cos(start_pose.theta + math.pi / 2)
    sq2.y = sq1.y + distance * math.sin(start_pose.theta + math.pi / 2)

    sq3 = Point()
    sq3.x = sq2.x + distance * math.cos(start_pose.theta + math.pi)
    sq3.y = sq2.y + distance * math.sin(start_pose.theta + math.pi)

    swarmie.drive_to(sq1, ignore=ignore)
    swarmie.drive_to(sq2, ignore=ignore)
    swarmie.drive_to(sq3, ignore=ignore)
    swarmie.drive_to(start, ignore=ignore)

    swarmie.set_heading(start_pose.theta)

    end_pose = swarmie.get_odom_location().get_pose()
    print('Start point: ({:.2f}, {:.2f})'.format(end_pose.x, end_pose.y))
def main(**kwargs):
    global planner, found_tag
    found_tag = False
    planner = Planner()
    swarmie.fingers_open()
    swarmie.wrist_middle()
    locations_gone_to = 0
    # Return to the best pile if possible, if nothing found there go to the
    #next 2 piles
    while swarmie.has_resource_pile_locations() and locations_gone_to < 3:
        locations_gone_to += 1
        cur_pose = swarmie.get_odom_location().get_pose()
        cube_location = swarmie.get_best_resource_pile_location()
        dist = math.sqrt((cube_location.x - cur_pose.x)**2 +
                         (cube_location.y - cur_pose.y)**2)
        if dist > .5:  # only bother if it was reasonably far away
            return_to_last_exit_position(cube_location)
            #if we are here then no cubes where found near the location
            swarmie.remove_resource_pile_location(cube_location)
        else:  # must be right next to it
            return_to_last_exit_position(cube_location, skip_drive_to=True)
            swarmie.remove_resource_pile_location(cube_location)

    random_walk(num_moves=30)

    print("I'm homesick!")
    search_exit(1)
Example #3
0
def recover():
    """Recover from difficult situations:
        - No home tags are in view anymore
        - The tag to drive to is too close (we might be inside of home)

    Raises:
        InsideHomeException: if we're stuck inside of home.
    """
    # TODO: should sonar be ignored when recovering?
    # TODO: is simply backing up a little bit a reliable recovery move?
    ignore = (Obstacle.TAG_TARGET | Obstacle.TAG_HOME |
              Obstacle.INSIDE_HOME | Obstacle.IS_SONAR)

    check_inside_home()

    if swarmie.has_home_odom_location():
        home_odom = swarmie.get_home_odom_location()
        loc = swarmie.get_odom_location().get_pose()
        angle = angles.shortest_angular_distance(loc.theta,
                                                 math.atan2(home_odom.y - loc.y,
                                                            home_odom.x - loc.x))
        # If the rover is facing away from home's center, turn toward it
        if abs(angle) > math.pi / 3:
            swarmie.turn(angle, ignore=ignore)
            return

    swarmie.drive(-.1, ignore=ignore)
def setup_approach(save_loc=False):
    """Drive a little closer to the nearest block if it's far enough away."""
    global claw_offset_distance
    if swarmie.simulator_running():
        extra_offset = 0.20
    else:
        extra_offset = 0.15

    swarmie.fingers_open()
    swarmie.set_wrist_angle(1.15)
    rospy.sleep(1)

    block = swarmie.get_nearest_block_location(targets_buffer_age=5.0)

    if block is not None:
        print("Making the setup approach.")
        cur_loc = swarmie.get_odom_location().get_pose()
        dist = math.hypot(cur_loc.x - block.x, cur_loc.y - block.y)

        if dist > (claw_offset_distance + extra_offset):
            swarmie.drive_to(block,
                             claw_offset=claw_offset_distance + extra_offset,
                             ignore=Obstacle.VISION_SAFE | Obstacle.IS_SONAR,
                             timeout=20,
                             **swarmie.speed_slow)

    if save_loc:
        swarmie.print_infoLog('Setting resource pile location.')
        swarmie.add_resource_pile_location()
Example #5
0
def main(**kwargs):
    global planner, use_waypoints

    has_block = False
    if 'has_block' in kwargs : 
        has_block = kwargs['has_block']
    
    # Whether to use waypoints from searching the map. Can be set to False if
    # the map service fails.
    use_waypoints = True

    if not has_block:
        swarmie.print_infoLog("I don't have a block. Not avoiding targets.")

    planner = Planner()

    swarmie.fingers_close()  # make sure we keep a firm grip
    swarmie.wrist_middle()  # get block mostly out of camera view
    home = get_best_home_location()

    drive_result = drive_home(has_block, home)
    if drive_result == MoveResult.OBSTACLE_HOME:
        sys.exit(0)
    elif drive_result == MoveResult.OBSTACLE_TAG:
        sys.exit(GOHOME_FOUND_TAG)

    # Look to the right and left before starting spiral search, which goes
    # left:
    ignore = Obstacle.PATH_IS_CLEAR
    if has_block:
        ignore |= Obstacle.TAG_TARGET
    try:
        cur_loc = swarmie.get_odom_location()
        if not cur_loc.at_goal(home, 0.3):
            print('Getting a little closer to home position.')
            swarmie.drive_to(home, ignore=ignore, **swarmie.speed_fast)

        planner.clear(2 * math.pi / 5, ignore=ignore, throw=True)
    except HomeException:
        face_home_tag()
        sys.exit(0)
    except TagException:
        sys.exit(GOHOME_FOUND_TAG)
    except ObstacleException:
        pass # do spiral search

    swarmie.print_infoLog(swarmie.rover_name + " Starting spiral search")

    print('Starting spiral search with location')
    try:
        drive_result = spiral_search(has_block)
        if drive_result == MoveResult.OBSTACLE_HOME:
            sys.exit(0)
        elif drive_result == MoveResult.OBSTACLE_TAG:
            sys.exit(GOHOME_FOUND_TAG)
    except PathException:
        sys.exit(GOHOME_FAIL)

    # didn't find anything
    return GOHOME_FAIL
def drive_to(pose, use_waypoints):
    planner.drive_to(pose,
                     tolerance=0.5,
                     tolerance_step=0.5,
                     avoid_targets=False,
                     avoid_home=True,
                     use_waypoints=use_waypoints,
                     **swarmie.speed_fast)

    cur_loc = swarmie.get_odom_location()
    if not cur_loc.at_goal(pose, 0.3):
        print('Getting a little closer to last exit position.')
        swarmie.drive_to(pose, throw=False)
Example #7
0
def abs_square(distance):

    start_pose = swarmie.get_odom_location().get_pose()

    swarmie.drive(distance, ignore=Obstacle.IS_VISION)
    swarmie.set_heading(start_pose.theta + math.pi / 2, ignore=-1)

    swarmie.drive(distance, ignore=Obstacle.IS_VISION)
    swarmie.set_heading(start_pose.theta + math.pi, ignore=-1)

    swarmie.drive(distance, ignore=Obstacle.IS_VISION)
    swarmie.set_heading(start_pose.theta + (3 * math.pi) / 2, ignore=-1)

    swarmie.drive(distance, ignore=Obstacle.IS_VISION)
    swarmie.set_heading(start_pose.theta, ignore=-1)
Example #8
0
def main():
    rospy.sleep(5)
    swarmie.pump_backward(True)
    rospy.sleep(5)
    swarmie.pump_backward(False)
    prev_heading = swarmie.get_odom_location().get_pose().theta
    for _ in range(0, 3):
        swarmie.drive(-.4, ignore=Obstacle.IS_SONAR)
        swarmie.turn(-math.pi / 2, ignore=Obstacle.IS_SONAR)
        swarmie.drive(.2, ignore=Obstacle.IS_SONAR)
        swarmie.set_heading(prev_heading, ignore=Obstacle.IS_SONAR)
        swarmie.drive(.4, ignore=Obstacle.IS_SONAR)
        swarmie.pump_forward(True)
        rospy.sleep(5)
        swarmie.pump_forward(False)
    swarmie.drive(-.4, ignore=Obstacle.IS_SONAR)
Example #9
0
def loc_in_home_frame(transform_timeout=1.0):
    # type: (float) -> PoseStamped
    """Return the rover's current location in the home coordinate frame."""
    cur_odom = swarmie.get_odom_location().Odometry

    cur_loc = PoseStamped()
    cur_loc.header = cur_odom.header
    cur_loc.pose = cur_odom.pose.pose

    swarmie.xform.waitForTransform(
        'home',
        cur_loc.header.frame_id,
        cur_loc.header.stamp,
        rospy.Duration(transform_timeout)
    )

    return swarmie.xform.transformPose('home', cur_loc)
Example #10
0
def setup_approach():
    """Drive a little closer to the nearest tag if it's far enough away."""
    global claw_offset_distance
    if swarmie.simulator_running():
        extra_offset = 0.20
    else:
        extra_offset = 0.15

    block = swarmie.get_nearest_block_location(targets_buffer_age=5.0)

    if block is not None:
        print("Making the setup approach.")
        cur_loc = swarmie.get_odom_location().get_pose()
        dist = math.hypot(cur_loc.x - block.x, cur_loc.y - block.y)

        if dist > (claw_offset_distance + extra_offset):
            swarmie.drive_to(block,
                             claw_offset=claw_offset_distance + extra_offset,
                             ignore=Obstacle.VISION_SAFE | Obstacle.IS_SONAR,
                             timeout=20,
                             **swarmie.speed_slow)
def wander():
    try:
        rospy.loginfo("Wandering...")
        swarmie.drive(random.gauss(2.5, 1), **swarmie.speed_fast)
        prev_heading = swarmie.get_odom_location().get_pose().theta

        rospy.loginfo("Circling...")
        swarmie.circle()
        swarmie.set_heading(prev_heading + random.gauss(0, math.pi / 6),
                            **swarmie.speed_fast)

    except HomeException:
        print("I saw home!")
        # TODO: We used to set the home odom location here, while we had
        #  the chance. If finding home during gohome becomes difficult,
        #  it may be useful to have home_transform publish a less
        #  accurate, but easier to update, home position estimate.
        turnaround()

    except ObstacleException:
        print("I saw an obstacle!")
        turnaround(ignore=Obstacle.IS_SONAR | Obstacle.VISION_HOME)
Example #12
0
def plant_walk(num_moves):
    """Do a plant walk `num_moves` times."""
    for move in range(num_moves):
        if rospy.is_shutdown():
            water_plants_exit(-1)
        rospy.sleep(1)
        # get thirstiest plant also weigh in distance
        plant_ids = [
            plant_id for plant_id in range(len(swarmie.plants))
            if swarmie.plants[plant_id]['pot_imp'] > moisture_msg.DRY_SOIL
            or swarmie.plants[plant_id]['plant_imp'] > moisture_msg.DRY_PLANT
        ]
        while not plant_ids:
            rospy.loginfo("Waiting for plants to water")
            rospy.sleep(5)
            plant_ids = [
                plant_id for plant_id in range(len(swarmie.plants)) if
                swarmie.plants[plant_id]['pot_imp'] > moisture_msg.DRY_SOIL or
                swarmie.plants[plant_id]['plant_imp'] > moisture_msg.DRY_PLANT
            ]

        cur_pose = swarmie.get_odom_location().get_pose()
        # get the closest plant
        plant_id = min(plant_ids,
                       key=lambda k: math.sqrt(
                           (swarmie.plants[k]['point'].x - cur_pose.x)**2 +
                           (swarmie.plants[k]['point'].y - cur_pose.y)**2))
        try:
            drive_to_plant(plant_id)
            rospy.loginfo("Watering plant #" + str(plant_id))
            rospy.sleep(2)
            swarmie.plants[plant_id]['pot_imp'] = 10
            swarmie.plants[plant_id]['plant_imp'] = 10
            swarmie.delete_light("plant_light_" + str(plant_id))
            swarmie.plants[plant_id]['light'] = False
        except rospy.ServiceException, e:
            rospy.loginfo("plant_walk: ServiceException%s" % e)
        except PathException:
            rospy.loginfo("plant_walk: PathException")
Example #13
0
def should_sweep(home_tag_yaw):
    """Given a rightmost home tag's orientation in the odometry frame, decide
    whether the rover should turn right to sweep for more tags.
    """
    rover_yaw = swarmie.get_odom_location().get_pose().theta

    if swarmie.has_home_odom_location():
        try:
            loc_home = loc_in_home_frame()
        except tf.Exception as e:
            rospy.logwarn('Transform exception in should_sweep(): {}'.format(e))
            loc_home = PoseStamped()
            loc_home.pose.position.x = 0.0
            loc_home.pose.position.y = 0.0
    else:
        loc_home = PoseStamped()
        loc_home.pose.position.x = 0.0
        loc_home.pose.position.y = 0.0

    return (abs(angles.shortest_angular_distance(rover_yaw, home_tag_yaw))
            > math.pi / 2
            and (abs(loc_home.pose.position.x) < 0.6
                 or abs(loc_home.pose.position.y) < 0.6))
Example #14
0
def drive_to_next_tag(rightmost_tag, prev_rightmost_tag):
    """Attempt to drive to the next rightmost home tag in view.

    Args:
        rightmost_tag: The current rightmost tag in view.
        prev_rightmost_tag: The previous rightmost tag in view. Used as a
            fallback if no home tags are currently in view.

    Returns:
        True if successful, False if we had to recover.

    Raises:
        HomeCornerException: From Swarmie.drive(), if we find a corner of home.
    """
    # The rover drives repeatedly to the rightmost home tag in view. However,
    # swarmie.drive_to() drives to a point such that the rover is on top of that
    # point. If the rover did this here, it's likely no home tags would be in
    # view anymore. The claw_offset argument allows the rover to stop short of
    # the goal point by this distance in meters.
    claw_offset = 0.3

    # TODO: should sonar be ignored all the time?
    ignore = (Obstacle.TAG_TARGET | Obstacle.TAG_HOME |
              Obstacle.INSIDE_HOME | Obstacle.IS_SONAR)

    if rightmost_tag is None:
        if prev_rightmost_tag is not None:
            rightmost_tag = prev_rightmost_tag
        else:
            return False

    # TODO: pull helpers out of home_transform.py and into utils.py
    #  so you can use yaw_from_quaternion() here.
    _r, _p, home_yaw = euler_from_quaternion(rightmost_tag.pose.orientation)

    # Using set heading before driving is useful when the rover is
    # mostly facing the corner to its left (which isn't the one we
    # want to drive to). Given the home tag's orientation on the
    # home ring, this gets the rover facing to the right, and keeps
    # it that way. Otherwise, it's possible for the rover to be
    # facing a corner to its left, and the simple "drive to the
    # rightmost tag" logic here will fail; the rover won't move at
    # all because its already where it should be according to
    # drive_to().
    if should_sweep(home_yaw):
        swarmie.set_heading(home_yaw + math.pi / 3, ignore=ignore)

    else:
        cur_loc = swarmie.get_odom_location().get_pose()
        dist = math.hypot(cur_loc.x - rightmost_tag.pose.position.x,
                          cur_loc.y - rightmost_tag.pose.position.y)

        if abs(dist - claw_offset) < 0.07:
            # If dist - claw_offset is small, drive_to() is unlikely to
            # make the rover move at all. In this case it's worth
            # recovering or raising an InsideHomeException
            # from recover()
            return False

        swarmie.drive_to(rightmost_tag.pose.position,
                         claw_offset=claw_offset, ignore=ignore)

    return True