示例#1
0
 def test(arm1, conf1, arm2, conf2):
     # TODO: don't let the arms get too close
     if not collisions or (arm1 == arm2):
         return False
     arm1_joints = get_arm_joints(robot, arm1)
     set_joint_positions(robot, arm1_joints, conf1)
     arm2_joints = get_arm_joints(robot, arm2)
     set_joint_positions(robot, arm2_joints, conf2)
     return link_pairs_collision(robot,
                                 get_moving_links(robot,
                                                  arm1_joints), robot,
                                 get_moving_links(robot, arm2_joints))
示例#2
0
def plan_workspace_motion(robot,
                          arm,
                          tool_path,
                          collision_buffer=COLLISION_BUFFER,
                          **kwargs):
    _, resolutions = get_weights_resolutions(robot, arm)
    tool_link = link_from_name(robot, TOOL_FRAMES[arm])
    arm_joints = get_arm_joints(robot, arm)
    arm_waypoints = plan_cartesian_motion(robot,
                                          arm_joints[0],
                                          tool_link,
                                          tool_path,
                                          pos_tolerance=5e-3)
    if arm_waypoints is None:
        return None
    arm_waypoints = [[conf[j] for j in movable_from_joints(robot, arm_joints)]
                     for conf in arm_waypoints]
    set_joint_positions(robot, arm_joints, arm_waypoints[0])
    return plan_waypoints_joint_motion(
        robot,
        arm_joints,
        arm_waypoints[1:],
        resolutions=resolutions,
        max_distance=collision_buffer,
        custom_limits=get_pr2_safety_limits(robot),
        **kwargs)
示例#3
0
文件: common.py 项目: lyltc1/LTAMP
def get_weights_resolutions(robot,
                            arm,
                            weights_regularize=0.005,
                            resolution_scale=0.001):
    arm_joints = get_arm_joints(robot, arm)
    weights = np.array(
        [JOINT_WEIGHTS[i] for i in movable_from_joints(robot, arm_joints)])
    weights += weights_regularize * np.ones(weights.shape)
    resolutions = np.divide(resolution_scale * np.ones(weights.shape), weights)
    return weights, resolutions
示例#4
0
def get_pairwise_arm_links(robot, arms):
    disabled_collisions = set()
    arm_links = {}
    for arm in arms:
        arm_links[arm] = sorted(
            get_moving_links(robot, get_arm_joints(robot, arm)))
        #print(arm, [get_link_name(world.robot, link) for link in arm_links[arm]])
    for arm1, arm2 in combinations(arm_links, 2):
        disabled_collisions.update(product(arm_links[arm1], arm_links[arm2]))
    return disabled_collisions
示例#5
0
    def test(arm1, control, arm2, conf2):
        if not collisions or (arm1 == arm2):
            return False
        attachments = control['context'].assign()
        arm1_links = get_moving_links(robot, get_arm_joints(robot, arm1))

        arm2_joints = get_arm_joints(robot, arm2)
        arm2_links = get_moving_links(robot, arm2_joints)
        set_joint_positions(robot, arm2_joints, conf2)
        for command in control['commands']:
            for _ in command.iterate(world,
                                     attachments):  # TODO: randomize sequence
                for attachment in attachments.values():
                    attachment.assign()
                    if link_pairs_collision(robot, arm2_links,
                                            attachment.child):
                        return True
                if link_pairs_collision(robot, arm1_links, robot, arm2_links):
                    return True
        return False
示例#6
0
    def test(arm, control, obj, pose):
        if not collisions or (obj in control['objects']):
            return False
        attachments = control['context'].assign()
        body = world.bodies[obj]
        set_pose(body, pose)

        arm_links = get_moving_links(robot, get_arm_joints(robot, arm))
        for command in control['commands']:
            for _ in command.iterate(world,
                                     attachments):  # TODO: randomize sequence
                for attachment in attachments.values():
                    attachment.assign()
                    if body_pair_collision(attachment.child,
                                           body,
                                           collision_buffer=collision_buffer):
                        return True
                if link_pairs_collision(robot, arm_links, body):
                    return True
        return False
示例#7
0
def solve_inverse_kinematics(robot,
                             arm,
                             world_pose,
                             obstacles=[],
                             collision_buffer=COLLISION_BUFFER,
                             max_attempts=25):
    arm_joints = get_arm_joints(robot, arm)
    custom_limits = get_pr2_safety_limits(robot)  # TODO: self-collisions
    collision_fn = get_collision_fn(robot,
                                    arm_joints,
                                    obstacles=obstacles,
                                    attachments=[],
                                    max_distance=collision_buffer,
                                    self_collisions=False,
                                    disabled_collisions=set(),
                                    custom_limits=custom_limits)
    base_pose = get_link_pose(robot,
                              link_from_name(robot,
                                             BASE_FRAME))  # != get_pose(robot)
    target_point, target_quat = multiply(invert(base_pose), world_pose)
    [torso_position] = get_group_conf(robot, 'torso')
    upper_joint = joint_from_name(robot, UPPER_JOINTS[arm])
    lower, upper = get_custom_limits(robot, [upper_joint],
                                     custom_limits,
                                     circular_limits=CIRCULAR_LIMITS)
    upper_limits = list(zip(lower, upper))[0]
    # TODO(caelan): just attempt one IK sample for each generator to restart quickly
    for i, arm_conf in enumerate(
            islice(
                get_arm_ik_generator(get_arm_prefix(arm),
                                     list(target_point),
                                     list(target_quat),
                                     torso_position,
                                     upper_limits=upper_limits),
                max_attempts)):
        if not collision_fn(arm_conf):
            #print('Attempts:', i)
            return Conf(arm_conf)
    return None
示例#8
0
文件: push.py 项目: lyltc1/LTAMP
    def gen_fn(arm, obj_name, pose1, region):
        # TODO: reachability test here
        if region is None:
            goals = push_goal_gen_fn(obj_name, pose1, surface)
        elif isinstance(region, str):
            goals = push_goal_gen_fn(obj_name, pose1, surface, region=region)
        else:
            goals = [(region,)]
        if repeat:
            goals = cycle(goals)

        arm_joints = get_arm_joints(world.robot, arm)
        open_width = get_max_limit(world.robot, get_gripper_joints(world.robot, arm)[0])
        body = world.bodies[obj_name]
        for goal_pos2d, in islice(goals, max_samples):
            pose2 = get_end_pose(pose1, goal_pos2d)
            body_path = list(interpolate_poses(pose1, pose2))
            if cartesian_path_collision(body, body_path, set(obstacles) - {surface_body}) or \
                    cartesian_path_unsupported(body, body_path, surface_body):
                continue
            set_pose(body, pose1)
            push_direction = np.array(point_from_pose(pose2)) - np.array(point_from_pose(pose1))
            backoff_tform = Pose(-backoff_distance * get_unit_vector(push_direction))  # World coordinates

            feature = get_push_feature(world, arm, obj_name, pose1, goal_pos2d)
            for parameter in parameter_fn(world, feature):
                push_contact = next(iter(sample_push_contact(world, feature, parameter, under=False)))
                gripper_path = [multiply(pose, invert(multiply(TOOL_POSE, push_contact))) for pose in body_path]
                set_gripper_position(world.robot, arm, open_width)
                for _ in range(max_attempts):
                    start_conf = solve_inverse_kinematics(world.robot, arm, gripper_path[0], obstacles=obstacles)
                    if start_conf is None:
                        continue
                    set_pose(body, pose1)
                    body_saver = BodySaver(body)
                    #attachment = create_attachment(world.robot, arm, body)
                    push_path = plan_waypoint_motion(world.robot, arm, gripper_path[-1],
                                                     obstacles=obstacles, #attachments=[attachment],
                                                     self_collisions=collisions, disabled_collisions=disabled_collisions)
                    if push_path is None:
                        continue
                    pre_backoff_pose = multiply(backoff_tform, gripper_path[0])
                    pre_approach_pose = multiply(pre_backoff_pose, approach_tform)
                    set_joint_positions(world.robot, arm_joints, push_path[0])
                    pre_path = plan_waypoints_motion(world.robot, arm, [pre_backoff_pose, pre_approach_pose],
                                                    obstacles=obstacles, attachments=[],
                                                    self_collisions=collisions, disabled_collisions=disabled_collisions)
                    if pre_path is None:
                        continue
                    pre_path = pre_path[::-1]
                    post_backoff_pose = multiply(backoff_tform, gripper_path[-1])
                    post_approach_pose = multiply(post_backoff_pose, approach_tform)
                    set_joint_positions(world.robot, arm_joints, push_path[-1])
                    post_path = plan_waypoints_motion(world.robot, arm, [post_backoff_pose, post_approach_pose],
                                                     obstacles=obstacles, attachments=[],
                                                     self_collisions=collisions, disabled_collisions=disabled_collisions)
                    if post_path is None:
                        continue
                    pre_conf = Conf(pre_path[0])
                    set_joint_positions(world.robot, arm_joints, pre_conf)
                    robot_saver = BodySaver(world.robot)
                    post_conf = Conf(post_path[-1])
                    control = Control({
                        'action': 'push',
                        'objects': [obj_name],
                        'feature': feature,
                        'parameter': None,
                        'context': Context(
                            savers=[robot_saver, body_saver],
                            attachments={}),
                        'commands': [
                            ArmTrajectory(arm, pre_path),
                            Push(arm, obj_name),
                            ArmTrajectory(arm, push_path),
                            Detach(arm, obj_name),
                            ArmTrajectory(arm, post_path),
                        ],
                    })
                    yield (pose2, pre_conf, post_conf, control)
                    break
示例#9
0
文件: move.py 项目: lyltc1/LTAMP
    def gen_fn(arm, conf1, conf2, fluents=[]):
        arm_confs, object_grasps, object_poses, contains_liquid = parse_fluents(
            world, fluents)
        for a, q in arm_confs.items():
            #print(a, q) # TODO: some optimistic values are getting through
            set_joint_positions(world.robot, get_arm_joints(world.robot, a), q)
        for name, pose in object_poses.items():
            set_pose(world.bodies[name], pose)
        obstacle_names = list(world.get_fixed()) + list(object_poses)
        obstacles = [world.bodies[name] for name in obstacle_names]

        attachments = {}
        holding_water = None
        water_attachment = None
        for arm2, (obj, grasp) in object_grasps.items():
            set_gripper_position(world.robot, arm, grasp.grasp_width)
            attachment = get_grasp_attachment(world, arm2, grasp)
            attachment.assign()
            if arm == arm2:  # The moving arm
                if obj in contains_liquid:
                    holding_water = obj
                    water_attachment = attachment
                attachments[obj] = attachment
            else:  # The stationary arm
                obstacles.append(world.get_body(obj))
        if not collisions:
            obstacles = []
        # TODO: dynamically adjust step size to be more conservative near longer movements

        arm_joints = get_arm_joints(world.robot, arm)
        set_joint_positions(world.robot, arm_joints, conf1)
        weights, resolutions = get_weights_resolutions(world.robot, arm)
        #print(holding_water, attachments, [get_body_name(body) for body in obstacles])
        if teleport:
            path = [conf1, conf2]
        elif holding_water is None:
            # TODO(caelan): unify these two methods
            path = plan_joint_motion(world.robot,
                                     arm_joints,
                                     conf2,
                                     resolutions=resolutions,
                                     weights=weights,
                                     obstacles=obstacles,
                                     attachments=attachments.values(),
                                     self_collisions=collisions,
                                     disabled_collisions=disabled_collisions,
                                     max_distance=COLLISION_BUFFER,
                                     custom_limits=custom_limits,
                                     restarts=5,
                                     iterations=50,
                                     smooth=smooth)
        else:
            reference_pose = (unit_point(), get_liquid_quat(holding_water))
            path = plan_water_motion(world.robot,
                                     arm_joints,
                                     conf2,
                                     water_attachment,
                                     resolutions=resolutions,
                                     weights=weights,
                                     obstacles=obstacles,
                                     attachments=attachments.values(),
                                     self_collisions=collisions,
                                     disabled_collisions=disabled_collisions,
                                     max_distance=COLLISION_BUFFER,
                                     custom_limits=custom_limits,
                                     reference_pose=reference_pose,
                                     restarts=7,
                                     iterations=75,
                                     smooth=smooth)

        if path is None:
            return None
        control = Control({
            'action':
            'move-arm',
            #'objects': [],
            'context':
            Context(
                savers=[BodySaver(world.robot)
                        ],  # TODO: robot might be at the wrong conf
                attachments=attachments),
            'commands': [
                ArmTrajectory(arm, path),
            ],
        })
        return (control, )
示例#10
0
文件: scoop.py 项目: lyltc1/LTAMP
 def gen_fn(arm, bowl_name, bowl_pose, spoon_name, grasp):
     if bowl_name == spoon_name:
         return
     bowl_body = world.get_body(bowl_name)
     attachment = get_grasp_attachment(world, arm, grasp)
     feature = get_scoop_feature(world, bowl_name, spoon_name)
     for parameter in parameter_generator(feature):
         spoon_path_bowl = sample_scoop_trajectory(world,
                                                   feature,
                                                   parameter,
                                                   collisions=collisions)
         if spoon_path_bowl is None:
             continue
         for _ in range(max_attempts):
             set_gripper_position(world.robot, arm, grasp.grasp_width)
             set_pose(bowl_body, bowl_pose)
             rotate_bowl = Pose(euler=Euler(
                 yaw=random.uniform(-np.pi, np.pi)))
             spoon_path = [
                 multiply(bowl_pose, invert(rotate_bowl), spoon_pose_bowl)
                 for spoon_pose_bowl in spoon_path_bowl
             ]
             #visualize_cartesian_path(world.get_body(spoon_name), spoon_path)
             # TODO: pass in tool collision pairs here
             arm_path = plan_attachment_motion(
                 world.robot,
                 arm,
                 attachment,
                 spoon_path,
                 obstacles=set(obstacles) - {bowl_body},
                 self_collisions=collisions,
                 disabled_collisions=disabled_collisions,
                 collision_buffer=collision_buffer,
                 attachment_collisions=False)
             if arm_path is None:
                 continue
             pre_conf = Conf(arm_path[0])
             set_joint_positions(world.robot,
                                 get_arm_joints(world.robot, arm), pre_conf)
             attachment.assign()
             if pairwise_collision(world.robot, bowl_body):
                 # TODO: ensure no robot/bowl collisions for the full path
                 continue
             robot_saver = BodySaver(world.robot)
             post_conf = Conf(arm_path[-1])
             control = Control({
                 'action':
                 'scoop',
                 'objects': [bowl_name, spoon_name],
                 'feature':
                 feature,
                 'parameter':
                 parameter,
                 'context':
                 Context(savers=[robot_saver],
                         attachments={spoon_name: attachment}),
                 'commands': [
                     ArmTrajectory(arm, arm_path, dialation=4.0),
                 ],
             })
             yield (pre_conf, post_conf, control)
             break
         else:
             yield None
示例#11
0
 def iterate(self, world, attachments):
     joints = get_arm_joints(world.robot, self.arm)
     # gripper_joints = get_gripper_joints(robot, arm)
     for positions in self.path:
         set_joint_positions(world.robot, joints, positions)
         yield positions
示例#12
0
def ss_from_problem(problem,
                    bound='shared',
                    remote=False,
                    teleport=False,
                    movable_collisions=False):
    robot = problem.robot

    #initial_bq = Pose(robot, get_pose(robot))
    initial_bq = Conf(robot, get_group_joints(robot, 'base'),
                      get_group_conf(robot, 'base'))
    initial_atoms = [
        CanMove(),
        IsBConf(initial_bq),
        AtBConf(initial_bq),
        initialize(TotalCost(), 0),
    ]
    for name in problem.arms:
        joints = get_arm_joints(robot, name)
        conf = Conf(robot, joints, get_joint_positions(robot, joints))
        initial_atoms += [
            IsArm(name),
            HandEmpty(name),
            IsAConf(name, conf),
            AtAConf(name, conf)
        ]
    for body in problem.movable:
        pose = Pose(body, get_pose(body))
        initial_atoms += [
            IsMovable(body),
            IsPose(body, pose),
            AtPose(body, pose),
            POSE(pose)
        ]
        for surface in problem.surfaces:
            initial_atoms += [Stackable(body, surface)]
            if is_placement(body, surface):
                initial_atoms += [IsSupported(pose, surface)]

    initial_atoms += map(Washer, problem.sinks)
    initial_atoms += map(Stove, problem.stoves)
    initial_atoms += [IsConnected(*pair) for pair in problem.buttons]
    initial_atoms += [IsButton(body) for body, _ in problem.buttons]

    goal_literals = []
    if problem.goal_conf is not None:
        goal_conf = Pose(robot, problem.goal_conf)
        initial_atoms += [IsBConf(goal_conf)]
        goal_literals += [AtBConf(goal_conf)]
    goal_literals += [Holding(*pair) for pair in problem.goal_holding]
    goal_literals += [On(*pair) for pair in problem.goal_on]
    goal_literals += map(Cleaned, problem.goal_cleaned)
    goal_literals += map(Cooked, problem.goal_cooked)

    #GraspedCollision = Predicate([A, G, AT], domain=[IsArm(A), POSE(G), IsArmTraj(AT)],
    #                             fn=lambda a, p, at: False, bound=False)

    PlacedCollision = Predicate([AT, P],
                                domain=[IsArmTraj(AT), POSE(P)],
                                fn=lambda at, p: False,
                                bound=False)

    actions = [
        Action(name='pick',
               param=[A, O, P, G, BQ, AT],
               pre=[
                   IsKin(A, O, P, G, BQ, AT),
                   HandEmpty(A),
                   AtPose(O, P),
                   AtBConf(BQ), ~Unsafe(AT)
               ],
               eff=[
                   HasGrasp(A, O, G),
                   CanMove(), ~HandEmpty(A), ~AtPose(O, P),
                   Increase(TotalCost(), 1)
               ]),
        Action(name='place',
               param=[A, O, P, G, BQ, AT],
               pre=[
                   IsKin(A, O, P, G, BQ, AT),
                   HasGrasp(A, O, G),
                   AtBConf(BQ), ~Unsafe(AT)
               ],
               eff=[
                   HandEmpty(A),
                   CanMove(),
                   AtPose(O, P), ~HasGrasp(A, O, G),
                   Increase(TotalCost(), 1)
               ]),
        Action(
            name='move',
            param=[BQ, BQ2, BT],
            pre=[IsMotion(BQ, BQ2, BT),
                 CanMove(),
                 AtBConf(BQ), ~Unsafe(BT)],
            eff=[
                AtBConf(BQ2), ~CanMove(), ~AtBConf(BQ),
                Increase(TotalCost(), 1)
            ]),

        # TODO: should the robot be allowed to have different carry configs or a defined one?
        #Action(name='move_arm', param=[A, BQ, BQ2],
        #       pre=[IsAConf(A, BQ), IsAConf(A, BQ),
        #            CanMove(), AtBConf(BQ)],
        #       eff=[AtAConf(BQ2), ~AtAConf(BQ),
        #            Increase(TotalCost(), 1)]),

        # Why would one want to move to the pick configuration for something anywhere but the goal?
        # Stream that generates arm motions as long as one is a shared configuration
        # Maybe I should make a base
    ]

    if remote:
        actions += [
            Action(
                name='clean',
                param=[O, O2],  # Wirelessly communicates to clean
                pre=[Stackable(O, O2),
                     Washer(O2), ~Cooked(O),
                     On(O, O2)],
                eff=[Cleaned(O)]),
            Action(
                name='cook',
                param=[O, O2],  # Wirelessly communicates to cook
                pre=[Stackable(O, O2),
                     Stove(O2),
                     Cleaned(O),
                     On(O, O2)],
                eff=[Cooked(O), ~Cleaned(O)]),
        ]
    else:
        actions += [
            Action(name='press_clean',
                   param=[O, O2, A, B, BQ, AT],
                   pre=[
                       Stackable(O, O2),
                       Washer(O2),
                       IsConnected(B, O2),
                       IsPress(A, B, BQ, AT), ~Cooked(O),
                       On(O, O2),
                       HandEmpty(A),
                       AtBConf(BQ)
                   ],
                   eff=[Cleaned(O), CanMove()]),
            Action(name='press_cook',
                   param=[O, O2, A, B, BQ, AT],
                   pre=[
                       Stackable(O, O2),
                       Stove(O2),
                       IsConnected(B, O2),
                       IsPress(A, B, BQ, AT),
                       Cleaned(O),
                       On(O, O2),
                       HandEmpty(A),
                       AtBConf(BQ)
                   ],
                   eff=[Cooked(O), ~Cleaned(O),
                        CanMove()]),
        ]

    axioms = [
        Axiom(param=[A, O, G],
              pre=[IsArm(A), IsGrasp(O, G),
                   HasGrasp(A, O, G)],
              eff=Holding(A, O)),
        Axiom(param=[O, P, O2],
              pre=[IsPose(O, P),
                   IsSupported(P, O2),
                   AtPose(O, P)],
              eff=On(O, O2)),
    ]
    if movable_collisions:
        axioms += [
            Axiom(param=[O, P, AT],
                  pre=[IsPose(O, P),
                       PlacedCollision(AT, P),
                       AtPose(O, P)],
                  eff=Unsafe(AT)),
        ]

    streams = [
        FnStream(name='motion',
                 inp=[BQ, BQ2],
                 domain=[IsBConf(BQ), IsBConf(BQ2)],
                 fn=get_motion_gen(problem, teleport=teleport),
                 out=[BT],
                 graph=[IsMotion(BQ, BQ2, BT),
                        IsBaseTraj(BT)],
                 bound=bound),
        ListStream(name='grasp',
                   inp=[O],
                   domain=[IsMovable(O)],
                   fn=get_grasp_gen(problem),
                   out=[G],
                   graph=[IsGrasp(O, G), GRASP(G)],
                   bound=bound),

        # TODO: test_support
        Stream(name='support',
               inp=[O, O2],
               domain=[Stackable(O, O2)],
               fn=get_stable_gen(problem),
               out=[P],
               graph=[IsPose(O, P), IsSupported(P, O2),
                      POSE(P)],
               bound=bound),
        GenStream(
            name='ik_ir',
            inp=[A, O, P, G],
            domain=[IsArm(A), IsPose(O, P),
                    IsGrasp(O, G)],
            fn=get_ik_ir_gen(problem, teleport=teleport),
            out=[BQ, AT],
            graph=[IsKin(A, O, P, G, BQ, AT),
                   IsBConf(BQ),
                   IsArmTraj(AT)],
            bound=bound),
        GenStream(name='press',
                  inp=[A, B],
                  domain=[IsArm(A), IsButton(B)],
                  fn=get_press_gen(problem, teleport=teleport),
                  out=[BQ, AT],
                  graph=[IsPress(A, B, BQ, AT),
                         IsBConf(BQ),
                         IsArmTraj(AT)],
                  bound=bound),
    ]

    return Problem(initial_atoms,
                   goal_literals,
                   actions,
                   axioms,
                   streams,
                   objective=TotalCost())
示例#13
0
def get_initial_and_goal(world):
    # TODO: add an object representing the world
    task = world.task
    constant_map = {
        '@{}'.format(material): material
        for material in SIM_MATERIALS
    }
    initial_atoms = list(task.init) + [
        ('IsPose', world.world_name, world.world_pose),
        ('AtPose', world.world_name, world.world_pose),
    ] + [('Material', material) for material in SIM_MATERIALS]
    goal_literals = list(task.goal)
    for arm in ARMS:
        arm_joints = get_arm_joints(world.robot, arm)
        arm_conf = Conf(get_joint_positions(world.robot, arm_joints))
        constant_map['@{}'.format(arm)] = arm
        constant_map['@{}-conf'.format(arm)] = arm_conf
        initial_atoms.extend([
            ('IsConf', arm, arm_conf),
            ('AtConf', arm, arm_conf),
        ])
        if arm not in world.arms:
            continue
        initial_atoms.extend([
            ('IsArm', arm),
            ('CanMove', arm),  # Prevents double moves
        ])
        if arm not in world.initial_grasps:
            initial_atoms.append(('Empty', arm))
        if task.reset_arms:
            goal_literals.append(
                ('AtConf', arm,
                 arm_conf))  # Be careful of end orientation constraints
        if arm in task.empty_arms:
            goal_literals.append(('Empty', arm))
    for name, pose in world.initial_poses.items():
        initial_atoms.extend([
            ('IsPose', name, pose),
            ('AtPose', name, pose),
            # TODO: detect which frame is supporting
            ('IsSupported', name, pose, world.world_name, world.world_pose, TOP
             ),
        ])
        if in_type_group(name, task.reset_items):
            goal_literals.append(('AtPose', name, pose))
    for arm, grasp in world.initial_grasps.items():
        name = grasp.obj_name
        initial_atoms.extend([
            ('IsGrasp', name, grasp),
            ('AtGrasp', arm, name, grasp),
        ])

    for name in world.bodies:
        initial_atoms.append(('IsType', name, get_type(name)))
    for item in world.items:
        initial_atoms.extend(get_item_facts(world, item))
    for surface in world.bodies:  # world.surfaces
        if in_type_group(surface, task.pressable):
            initial_atoms.append(('Pressable', surface))
        if is_obj_type(surface, 'stove'):
            initial_atoms.append(('Stove', surface, TOP))

    print('Constants:', constant_map)
    print('Initial:', initial_atoms)
    print('Goal:', goal_literals)
    return constant_map, initial_atoms, And(*goal_literals)