Exemplo n.º 1
0
def test_semantic_map(node):
    p00 = create_2d_pose(0, 0, 0, 'map')
    p11 = create_2d_pose(1, 1, 0, 'map')
    p22 = create_2d_pose(2, 2, 0, 'map')
    p33 = create_2d_pose(3, 3, 0, 'map')
    p16 = create_2d_pose(1.6, 1.6, 0, 'map')

    sm = SemanticMap()

    # add_object
    sm.add_object('obj1', 'dummy', p11, (1, 1))

    Visualization().add_box_marker(p00, (1, 1, 0.0001), Visualization.rand_color(0.2))
    Visualization().publish_markers()
    assert len(sm.objects_at(p00, (1, 1))) == 1
    assert len(sm.objects_at(p00, (0.9, 0.9))) == 0

    Visualization().add_box_marker(p22, (1, 1, 0.0001), Visualization.rand_color(0.2))
    Visualization().publish_markers()
    assert len(sm.objects_at(p22, (1, 1))) == 1

    Visualization().add_box_marker(p33, (1, 1, 0.0001), Visualization.rand_color(0.2))
    Visualization().publish_markers()
    assert len(sm.objects_at(p33, (1, 1))) == 0

    sm.add_object('obj2', 'dummy', p22, (0.5, 0.5))

    Visualization().add_box_marker(p16, (1, 1, 0.0001), Visualization.rand_color(0.2))
    Visualization().publish_markers()
    assert len(sm.objects_at(p16, (1, 1))) == 2

    # remove_object
    sm.remove_object('obj1')
    assert len(sm.objects_at(p16, (1, 1))) == 1

    sm.remove_object('obj2')
    assert len(sm.objects_at(p16, (1, 1))) == 0

    # objects count
    sm.add_object('obj1', 'dummy', p11, (1, 1))
    sm.add_object('obj2', 'dummy', p22, (0.5, 0.5))
    sm.add_object('obj3', 'dummy', p33, (0.5, 0.5))
    assert sm.objects_count() == 3
    assert sm.objects() == {'obj1', 'obj2', 'obj3'}
    sm.remove_object('obj1')
    sm.remove_object('obj2')
    sm.remove_object('obj3')
    assert sm.objects_count() == 0
    assert sm.objects() == set()
Exemplo n.º 2
0
    def __init__(self):
        smach.State.__init__(self,
                             outcomes=['succeeded', 'tray_full'],
                             input_keys=['object'],
                             output_keys=['pose_on_tray'])
        self.tray_link = rospy.get_param('tray_link', 'tray_link')
        self.tray_full = False
        self.slots_x = int(cfg.TRAY_SIDE_X / cfg.TRAY_SLOT +
                           0.1)  # avoid float division pitfall
        self.slots_y = int(cfg.TRAY_SIDE_Y / cfg.TRAY_SLOT +
                           0.1)  # until I switch to Python3
        self.offset_x = 0.0 if self.slots_x % 2 else cfg.TRAY_SLOT / 2.0
        self.offset_y = 0.0 if self.slots_y % 2 else cfg.TRAY_SLOT / 2.0
        self.next_x = 0
        self.next_y = 0

        # add a collision object for the tray surface, right above the mesh
        PlanningScene().add_tray(
            create_3d_pose(0, 0, 0.0015, 0, 0, 0, self.tray_link),
            (cfg.TRAY_SIDE_X + 0.01, cfg.TRAY_SIDE_Y + 0.01, 0.002))

        # visualize place poses (for debugging)
        points = []
        for _ in range(self.slots_x * self.slots_y):
            points.append(self._next_pose(0.01).pose.position)
        Visualization().add_markers(Visualization().create_point_list(
            create_2d_pose(0, 0, 0, self.tray_link), points,
            [1, 0, 0, 1]))  # solid red points
        Visualization().publish_markers()
        self.tray_full = False
Exemplo n.º 3
0
def close_to_obstacle(x, y, theta, clearance):
    # check if the location is away from any non-zero cost in the global costmap by at least the given clearance
    # (we need to subtract robot radius because check pose service assumes we want to check the footprint cost)
    resp = check_pose_srv(pose=create_2d_pose(x, y, theta, 'map'), safety_dist=clearance - robot_radius,
                          costmap=CheckPoseRequest.GLOBAL_COSTMAP)
    if resp.state > 0 or resp.cost > 0:
        return True
    return False
Exemplo n.º 4
0
 def model_states_cb(self, msg):
     if self.killed_cats and not self.alive_cats:
         # all cats toppled; we can stop listening for model states
         rospy.loginfo("All cats toppled; stop listening for model states")
         self.model_states_sub.unregister()
         return
     # TODO  maybe pause/resume myself (so once)?  looks like not needed with current throttling
     for index, model_name in enumerate(msg.name):
         if model_name in self.alive_cats:
             if abs(roll(msg.pose[index])) > self.hit_roll_threshold:
                 # we consider a cat toppled after it rolls by more than hit_roll_threshold
                 # TODO: maybe better, use body/head contacts with ground_plane
                 rospy.loginfo("Cat %s toppled at %s! (|roll| > %g)",
                               model_name, pose3d2str(msg.pose[index]),
                               self.hit_roll_threshold)
                 # send toppled cats out of the house and stop tracking them
                 pose = create_2d_pose(4.0 + len(self.killed_cats), 1.0,
                                       math.pi / 2.0)
                 self.set_model_state_srv(
                     ModelState(model_name, pose, Twist(), 'map'))
                 self.killed_cats.append(model_name)
                 del self.alive_cats[model_name]
             elif rospy.get_time() - self.alive_cats[model_name][
                     'last_hit'] < self.hit_sock_duration:
                 # hit, so stop moving; admittedly, not the most realistic for a cat
                 pass
             elif self.prowling_step > 0.0:
                 # hanging around: perform small steps but changing directions whenever we touch anything
                 new_pose = copy.deepcopy(msg.pose[index])
                 contact = self.alive_cats[model_name]['contact']
                 if contact:
                     # use inv contact direction to limit the possible orientations to those away from the contact
                     contact_inv_dir = math.atan2(
                         contact.contact_normals[0].y,
                         contact.contact_normals[0].x)
                     new_yaw_bound1 = norm_angle(contact_inv_dir -
                                                 math.pi / 3.0)
                     new_yaw_bound2 = norm_angle(contact_inv_dir +
                                                 math.pi / 3.0)
                     new_yaw = random.uniform(new_yaw_bound1,
                                              new_yaw_bound2)
                     new_pose.orientation = quaternion_msg_from_yaw(new_yaw)
                     rospy.loginfo(
                         "%s: contact from %f; new direction to %f",
                         model_name, contact_inv_dir, new_yaw)
                     self.alive_cats[model_name]['contact'] = None
                 translate_pose(new_pose, self.prowling_step, 'x')
                 self.set_model_state_srv(
                     ModelState(model_name, new_pose, Twist(), 'map'))
         elif model_name not in self.killed_cats:
             # first time to see this model; keep track of it if listed under target models
             # (individual instances are numbered _0, _1 and so by the model spawner)
             if model_name in self.target_models or '_'.join(
                     model_name.split('_')[:-1]) in self.target_models:
                 self.alive_cats[model_name] = {
                     'last_hit': -1.0,
                     'contact': None
                 }
Exemplo n.º 5
0
    def make_goal(self, ud, goal):
        """ Create a goal for the action
        """
        room_number = ud['room_number']
        segmented_map = ud['segmented_map']

        # We need an image containing only the room to explore, so we create an empty image with the same
        # properties as the original map, set to white (\xFF) all pixels that correspond to the given room
        # number in the segmented map, and set as black (\x00) te rest
        goal.input_map = ud['map_image']
        goal.input_map.data = b''
        # segmented_map encoding is 32SC1, so 4 bytes, though just the first byte is enough up to 255 rooms
        for i in range(segmented_map.height):
            for j in range(segmented_map.width):
                idx = i * segmented_map.step + j * 4
                val = segmented_map.data[idx:idx + 4]
                pixel = struct.unpack('<BBBB', val)[0]
                if pixel == room_number:
                    goal.input_map.data += b'\xFF'
                else:
                    goal.input_map.data += b'\x00'

        fov_points = rospy.get_param(
            '/exploration/room_exploration_server/field_of_view_points')
        goal.field_of_view_origin = TF2().transform_pose(
            None, 'kinect_rgb_frame', 'base_footprint').pose.position
        goal.field_of_view = [geometry_msgs.Point32(*pt) for pt in fov_points]
        goal.planning_mode = 2  # plan a path for coverage with the robot's field of view
        goal.starting_position = to_pose2d(
            ud['robot_pose'])  # we need to convert to Pose2D msg

        # use room center as starting point; theta is ignored by room exploration
        room_info = ud['room_information_in_meter'][room_number - 1]
        start_point = geometry_msgs.PointStamped()
        start_point.header.frame_id = 'map'
        start_point.point = room_info.room_center
        goal.starting_position.x = room_info.room_center.x
        goal.starting_position.y = room_info.room_center.y
        goal.starting_position.theta = 0.0  # it's ignored
        self.start_pub.publish(start_point)
        # provide the starting pose so we can move there before starting exploring
        ud['start_pose'] = create_2d_pose(room_info.room_center.x,
                                          room_info.room_center.y, 0.0, 'map')
        # IDEA: can use room_info.room_min_max to avoid points colliding with the walls

        # visualize explore map and fov on RViz
        fov = geometry_msgs.PolygonStamped()
        fov.header.frame_id = 'kinect_rgb_frame'
        fov.polygon.points = goal.field_of_view
        rospy.Publisher('/exploration/img',
                        sensor_msgs.Image,
                        queue_size=1,
                        latch=True).publish(goal.input_map)
        if not self.fov_pub_timer:
            self.fov_pub_timer = rospy.Timer(
                rospy.Duration(0.1), lambda e: self.fov_pub.publish(fov))
Exemplo n.º 6
0
def spawn_rockets():
    # spawn 10 x 10 rockets
    rocket_index = 1
    for i, j in product(range(-10, 0), range(10)):
        spawn_model(
            name='rocket' + str(rocket_index),
            model=models['rocket'],
            pose=create_2d_pose(i, j, 0),
            frame='ground_plane::link'
        )
        rocket_index += 1
Exemplo n.º 7
0
def test_semantic_layer(node):
    p00 = create_2d_pose(0, 0, 1, 'map')
    p11 = create_2d_pose(1, 2, 1, 'map')
    p22 = create_2d_pose(2, 2, 1, 'map')
    p33 = create_2d_pose(3, 3, 1, 'map')
    p16 = create_2d_pose(1.6, 1.6, 0, 'map')
    sz1 = (2.0, 2.0)
    sz2 = (1.2, 0.8)
    sz3 = (0.5, 0.5)
    sz4 = (0.75, 0.75)

    sl = SemanticLayer()

    # add some obstacles
    assert sl.add_object('obs0', 'blocked_area', p11, sz1, costmap='global')
    assert sl.remove_object('obs0', 'blocked_area', costmap='global')
    assert sl.add_object('obs1', 'obstacle', p11, sz1, costmap='local')
    assert sl.add_object('obs2', 'obstacle', p11, sz2, costmap='local')
    assert sl.add_object('obs3', 'obstacle', p11, sz3, costmap='local')
    assert sl.add_object('obs4', 'obstacle', p11, sz4, costmap='local')

    # add some free space
    assert sl.add_object('fs1', 'free_space', p11, (2.5, 2.9), costmap='local')
    assert sl.add_object('fs2', 'free_space', p11, sz2, costmap='local')

    # move the first one
    assert sl.add_object('obs1', 'obstacle', p33, sz1, costmap='local')

    # resize the second one
    assert sl.add_object('obs2', 'obstacle', p11, sz1, costmap='local')

    # remove un-existing object
    assert not sl.remove_object('xxx', 'obstacle', costmap='local')

    # remove all objects
    assert sl.remove_object('fs2', 'free_space', costmap='local')
    assert sl.remove_object('fs1', 'free_space', costmap='local')
    assert sl.remove_object('obs4', 'obstacle', costmap='local')
    assert sl.remove_object('obs3', 'obstacle', costmap='local')
    assert sl.remove_object('obs2', 'obstacle', costmap='local')
    assert sl.remove_object('obs1', 'obstacle', costmap='local')
Exemplo n.º 8
0
 def execute(self, ud):
     table = ud['table']
     table_pose = ud['table_pose']  # expected on map frame, as robot_pose
     if not table or not table_pose:
         rospy.logerr("Detected table contains None!")
         return 'no_table'
     p_x = self.distance + table.depth / 2.0
     n_x = -p_x
     p_y = self.distance + table.width / 2.0
     n_y = -p_y
     table_tf = to_transform(table_pose, 'table_frame')
     TF2().publish_transform(table_tf)
     table_tf.transform.translation.z = 0.0
     closest_pose = None
     closest_dist = float('inf')
     from math import pi
     poses = [('p_x', create_2d_pose(p_x, 0.0, -pi, 'table_frame')),
              ('n_x', create_2d_pose(n_x, 0.0, 0.0, 'table_frame')),
              ('p_y', create_2d_pose(0.0, p_y, -pi / 2.0, 'table_frame')),
              ('n_y', create_2d_pose(0.0, n_y, +pi / 2.0, 'table_frame'))]
     pose_array = geometry_msgs.PoseArray()  # for visualization
     sides_poses = {}
     for name, pose in poses:
         pose = transform_pose(pose, table_tf)
         pose_array.poses.append(deepcopy(pose.pose))
         pose_array.poses[
             -1].position.z += 0.025  # raise over costmap to make it visible
         sides_poses[name] = pose
         dist = distance_2d(pose, ud['robot_pose'])
         if dist < closest_dist:
             closest_pose = pose
             closest_dist = dist
     ud['poses'] = sides_poses
     ud['closest_pose'] = closest_pose
     pose_array.header = deepcopy(closest_pose.header)
     pose_array.poses.append(deepcopy(closest_pose.pose))
     pose_array.poses[
         -1].position.z += 0.05  # remark the closest pose with a double arrow
     self.poses_viz.publish(pose_array)
     return 'succeeded'
Exemplo n.º 9
0
def test_progress_tracker(node):
    wp = [
        create_2d_pose(-1, -1, 0, 'map'),
        create_2d_pose(+1, -1, 0, 'map'),
        create_2d_pose(+1, +1, 0, 'map'),
        create_2d_pose(-1, +1, 0, 'map')
    ]
    origin = create_2d_pose(0, 0, 0, 'map')
    Visualization().add_point_markers(wp, 0.1)
    pt = ProgressTracker(wp, np.sqrt(2) - 0.99)
    for theta in np.arange(-np.pi, np.pi, np.pi / 100.0):
        rpose = create_2d_pose(np.cos(theta), np.sin(theta), 0, 'map')
        Visualization().add_line_marker([origin, rpose])
        Visualization().publish_markers()
        pt.update_pose(rpose)
        if theta > (3 * np.pi) / 4.0:
            assert pt.reached_waypoint() == 3
            assert pt.next_waypoint() is None
        elif theta > np.pi / 4.0:
            assert pt.reached_waypoint() == 2
            assert pt.next_waypoint() == 3
        elif theta > -np.pi / 4.0:
            assert pt.reached_waypoint() == 1
            assert pt.next_waypoint() == 2
        elif theta > -(3.0 * np.pi) / 4.0:
            assert pt.reached_waypoint() == 0
            assert pt.next_waypoint() == 1
        else:
            assert pt.reached_waypoint() is None
            assert pt.next_waypoint() == 0
Exemplo n.º 10
0
def spawn_surfaces(use_preferred_locs=False):
    added_poses = []  # to check that tables are at least SURFS_MIN_DIST apart from each other
    for surf in surfaces:
        surf_index = 0
        # clearance = surface diagonal / 2 + some extra margin
        clearance = sqrt((surf['size'][0] / 2.0) ** 2 + (surf['size'][1] / 2.0) ** 2) + 0.1
        while surf_index < surf['count'] and not rospy.is_shutdown():
            if use_preferred_locs:
                x, y = random.choice(PREFERRED_LOCATIONS)
            else:
                x = random.uniform(min_x, max_x)
                y = random.uniform(min_y, max_y)
            theta = random.uniform(-pi, +pi)
            pose = create_2d_pose(x, y, theta)
            # we check that the distance to all previously added surfaces is below a threshold to space the surfaces
            if close_to_prev_pose(pose, added_poses, SURFS_MIN_DIST):
                continue

            # check also that the surface is not too close to the robot
            if close_to_robot(pose, robot_pose, SURFS_MIN_DIST):
                continue

            # and in open space
            if close_to_obstacle(x, y, theta, clearance):
                continue

            added_poses.append(pose)
            model = surf['name']
            model_name = model + '_' + str(surf_index + 10)   # allow for some objects added by hand
            success = spawn_model(
                name=model_name,
                model=models[model],
                pose=pose,
                frame='ground_plane::link'
            )
            if success:
                # populate this surface with some objects
                spawn_objects(surf, surf_index + 10)
            surf_index += 1
Exemplo n.º 11
0
def spawn_cats(use_preferred_locs=False):
    added_poses = []  # to check that cats are at least CATS_MIN_DIST apart from each other
    for cat in cats:
        cat_index = 0
        while cat_index < cat['count'] and not rospy.is_shutdown():
            if use_preferred_locs:
                x, y = random.choice(PREFERRED_LOCATIONS)
            else:
                x = random.uniform(min_x, max_x)
                y = random.uniform(min_y, max_y)
            theta = random.uniform(-pi, +pi)
            pose = create_2d_pose(x, y, theta)
            # we check that the distance to all previously added surfaces is below a threshold to space the surfaces
            if close_to_prev_pose(pose, added_poses, CATS_MIN_DIST):
                continue

            # check also that the surface is not too close to the robot
            if close_to_robot(pose, robot_pose, CATS_MIN_DIST):
                continue

            # and not within an obstacle
            if close_to_obstacle(x, y, theta, 0.0):
                continue

            added_poses.append(pose)
            model = cat['name']
            model_name = model + '_' + str(cat_index)
            success = spawn_model(
                name=model_name,
                model=models[model].format(name=model_name),
                pose=pose,
                frame='ground_plane::link'
            )
            if success:
                rospy.loginfo("Spawn %s at %s", model_name, pose2d2str(pose))
            cat_index += 1
Exemplo n.º 12
0
#!/usr/bin/env python

import rospy

from smach.user_data import UserData

from thorp_toolkit.geometry import TF2, create_2d_pose
from thorp_smach.states.navigation import LookToPose
from thorp_smach.utils import wait_for_mbf

if __name__ == '__main__':
    rospy.init_node('run_look_to_pose_state')

    # MBF is the last component to start, so wait for it before running the sm
    wait_for_mbf()

    ud = UserData()
    ud['robot_pose'] = TF2().transform_pose(None, 'base_footprint', 'map')
    ud['target_pose'] = create_2d_pose(0.0, 0.0, 0.0, 'map')
    state = LookToPose()
    t0 = rospy.get_time()
    outcome = state.execute(ud)
    rospy.loginfo("LookToPose completed in %.2fs with outcome '%s'",
                  rospy.get_time() - t0, outcome)

    # Wait for ctrl-c to stop the application
    rospy.spin()

    rospy.signal_shutdown('All done.')
Exemplo n.º 13
0
    load_models()

    robot_pose = TF2().transform_pose(None, 'base_footprint', 'map')
    robot_radius = rospy.get_param('move_base_flex/local_costmap/robot_radius')

    random.seed()
    use_preferred_locs = len(sys.argv) > 2 and '-l' in sys.argv
    rospy.loginfo("Spawning %s in %s locations", sys.argv[1], 'preferred' if use_preferred_locs else 'random')
    if sys.argv[1] == 'objects':
        spawn_surfaces(use_preferred_locs)
        rospy.loginfo("Spawned objects:\n  " + '\n  '.join('{}: {}'.format(k, v) for k, v in spawned.items()))
    elif sys.argv[1] == 'cats':
        spawn_cats(use_preferred_locs)
        spawn_rockets()
    elif sys.argv[1] == 'playground_random':  # random objects over a random table
        surface = random.choice(surfaces)
        spawn_model(surface['name'] + '_0', models[surface['name']], create_2d_pose(0.44, 0, pi / 2.0),
                    'ground_plane::link')
        spawn_objects(surface, 0, sys.argv[2] if len(sys.argv) > 2 and not use_preferred_locs else None)
    elif sys.argv[1] == 'playground_objs':  # a sample of objects mostly at reachable locations
        spawn_model('lack_table', models['lack_table'], create_2d_pose(0.45, 0, 0.0), 'ground_plane::link')
        for obj in PLAYGROUND_OBJS:
            spawn_model(obj[0], models[obj[1]], create_3d_pose(*obj[2]), 'ground_plane::link')
    elif sys.argv[1] == 'playground_cubes':  # cubes at reachable locations, ready to stack
        spawn_model('doll_table', models['doll_table'], create_2d_pose(0.38, 0, 0.0), 'ground_plane::link')
        for obj in PLAYGROUND_CUBES:
            spawn_model(obj[0], models[obj[1]], create_3d_pose(*obj[2]), 'doll_table::link')

    sys.exit(0)
Exemplo n.º 14
0
    state_pub = rospy.Publisher("gazebo/set_model_state", ModelState, queue_size=1)
    pose_pub = rospy.Publisher("target_object_pose", PoseStamped, queue_size=1)

    target_models = sys.argv[1:]
    if not target_models:
        rospy.logwarn("No target models provided; nothing to do")
        print("Usage: model_markers.py <list of interactive models>")
        sys.exit(0)
    try:
        model_states = rospy.wait_for_message("gazebo/model_states", ModelStates, 10.0)
    except rospy.ROSInterruptException:
        sys.exit(0)
    except rospy.ROSException as err:
        rospy.logwarn(err)
        rospy.logwarn("Creating markers for models %s on random poses", str(target_models))
        model_states = ModelStates()
        for model_name in target_models:
            model_states.name.append(model_name)
            model_states.pose.append(create_2d_pose(randint(1, 10), randint(1, 10), uniform(-pi, pi)))

    for index, model_name in enumerate(model_states.name):
        if model_name in target_models:
            make_interactive_marker(model_states.pose[index], model_name)
            rospy.loginfo("Interactive marker added at %s for model %s",
                          pose3d2str(model_states.pose[index]), model_name)

    server.applyChanges()

    rospy.spin()