Bootstrap

不同AI2-THOR仿真场景下的位置传送

1. 目标

  1. 随意指定场景
  2. 场景里找物品(微波炉为例)
  3. 找到后传送到物品前面

2. 代码

import math
from ai2thor.controller import Controller

# 将值四舍五入到最近的网格点
def round_to_grid(value, grid_size=0.25):
    return max(grid_size,round(value / grid_size) * grid_size)

#验证场景编号是否有效
def check_scene_number(scene_number):
    return scene_number in range(1, 31) or scene_number in range(201, 231) or \
       scene_number in range(301, 331) or scene_number in range(401, 431);

# 在当前场景中搜索指定类型的物体
def search_for_object(controller, object_type="Microwave"):
    objects = [obj for obj in controller.last_event.metadata["objects"] if obj["objectType"] == object_type]
    if len(objects) > 0:
        print(f"找到{len(objects)}{object_type}(s)")
        for obj in objects:
            print(f"{object_type}位置: {obj['position']}")
        return objects[0]  # 返回第一个找到的物体
    else:
        print(f"没有找到{object_type}")
        return None

# 计算目标位置并传送到目标物体面前
def teleport_to_object(controller, target_object):
    agent_position = controller.last_event.metadata['agent']['position']
    target_rotation = (target_object['rotation']['y'] + 180) % 360  # 面向目标物体
    new_position = {
        'x': round_to_grid(target_object['position']['x'] - 1),
        'y': round_to_grid(target_object['position']['y'] - 1),
        'z': agent_position['z']
    }
    # 使用Teleport动作传送
    event = controller.step(
        action="Teleport",
        position=new_position,
        rotation=dict(x=0,y=target_rotation,z=0),
        horizon=0,  # 直视前方
        standing=True
    )

    if event.metadata["lastActionSuccess"]:
        print(f"成功传送到{new_position},面朝{rotation_y}度")
    else:
        tmpIdx = event.metadata['errorMessage'].find("trace:")
        print(f"传送失败:{event.metadata['errorMessage'][:tmpIdx]}")

# 初始化控制器
controller = Controller(
    width=1280,
    height=720,
    fieldOfView=110,
    visibilityDistance=5,
    renderInstanceSegmentation=True
)

while True:
    try:
        scene_choice = input("请输入场景编号(1-30, 201-230, 301-330, 401-430):")
        scene_number = int(scene_choice)
        if not check_scene_number(scene_number):
            raise ValueError("无效的场景编号,请重新输入。")
        selected_scene = f"FloorPlan{scene_number}"
        # 重置到选定的场景
        controller.reset(selected_scene)
        print(f"加载场景: {selected_scene}")

        # 搜索物体
        found_object = search_for_object(controller)
        if found_object is not None:
            teleport_to_object(controller, found_object)

    except ValueError as e:
        print(e)
controller.stop()

3. 最终成果

场景切换,传送

在这里插入图片描述

;