1. 代码(以微波炉为例)
python">from ai2thor.controller import Controller
import math
import random
def distance_2d(pos1, pos2):
"""计算两点之间的二维欧几里得距离(忽略Z轴)"""
return math.sqrt((pos1['x'] - pos2['x']) ** 2 + (pos1['y'] - pos2['y']) ** 2)
def get_reachable_positions(controller):
"""获取所有可达位置"""
reachable_positions = controller.step(
action="GetReachablePositions"
).metadata["actionReturn"]
return [{k: pos[k] for k in ['x', 'y']} for pos in reachable_positions]
def move_towards_target_2d(controller, target_position):
"""导航到目标位置(仅考虑X和Y坐标)"""
max_attempts = 5
attempt = 0
while attempt < max_attempts:
current_position = {k: controller.last_event.metadata["agent"]["position"][k] for k in ['x', 'y']}
if distance_2d(current_position, target_position) <= 0.5: # 目标精度为0.5米
print("到达目标附近")
return True
diff_x = target_position['x'] - current_position['x']
diff_y = target_position['y'] - current_position['y']
if abs(diff_x) > abs(diff_y):
action = "MoveRight" if diff_x > 0 else "MoveLeft"
else:
action = "MoveAhead" if diff_y > 0 else "MoveBack"
event = controller.step(action=action, moveMagnitude=0.5)
print(f"移动:{action}{event.metadata['lastActionSuccess']}")
if not event.metadata["lastActionSuccess"]:
print(f"移动失败:{event.metadata['errorMessage']}")
possible_actions = ["MoveRight", "MoveLeft", "MoveAhead", "MoveBack"]
possible_actions.remove(action) # 移除当前尝试失败的动作
random_action = random.choice(possible_actions)
event = controller.step(action=random_action, moveMagnitude=0.5)
if not event.metadata["lastActionSuccess"]:
print(f"尝试反方向移动也失败了:{event.metadata['errorMessage']}")
back_action = "MoveBack" if diff_y > 0 else "MoveAhead"
controller.step(action=back_action, moveMagnitude=0.5)
attempt += 1
continue
else:
print(f"新方向移动成功:{random_action}")
print("不知道如何抵达")
return False
def manual_movement(controller):
"""手动控制移动"""
while True:
user_input = input("请输入移动指令(WASD键分别代表上、左、下、右),输入Q退出手动模式:").upper()
if user_input == 'Q':
print("退出手动模式")
break
elif user_input in ['W', 'A', 'S', 'D']:
action_map = {'W': 'MoveAhead', 'A': 'MoveLeft', 'S': 'MoveBack', 'D': 'MoveRight'}
action = action_map[user_input]
event = controller.step(action=action, moveMagnitude=0.5)
if event.metadata["lastActionSuccess"]:
print(f"{action} 成功!")
else:
print(f"{action} 失败:{event.metadata['errorMessage']}")
else:
print("无效输入,请重新输入")
controller = Controller(
width=1280,
height=720,
fieldOfView=110,
visibilityDistance=5,
renderInstanceSegmentation=True
)
scenes = ["FloorPlan1", "FloorPlan201", "FloorPlan301", "FloorPlan401"]
scene_names = ["厨房", "客厅", "卧室", "浴室"]
while True:
scene_choice = input("请输入场景编号(1-厨房,2-客厅,3-卧室,4-浴室),输入'Q'进入手动模式:")
if scene_choice.lower() == 'q':
print("进入手动模式")
manual_movement(controller)
continue
try:
scene_number = int(scene_choice)
if scene_number < 1 or scene_number > 4:
raise ValueError()
except ValueError:
print("无效的输入,请重新输入")
continue
selected_scene = scenes[scene_number - 1]
selected_scene_name = scene_names[scene_number - 1]
controller.reset(selected_scene)
reachable_positions = get_reachable_positions(controller)
microwaves = [obj for obj in controller.last_event.metadata["objects"] if obj["objectType"] == "Microwave"]
if len(microwaves) > 0:
target = microwaves[0]
target_position = {'x': target["position"]['x'], 'y': target["position"]['y']}
print(f"{selected_scene_name}中目标微波炉位置: {target_position}")
success = move_towards_target_2d(controller, target_position)
if success:
# 抓取动作
event = controller.step(action="PickupObject", objectId=target["objectId"])
if event.metadata["lastActionSuccess"]:
print(f"{selected_scene_name}中抓取成功!")
else:
print(f"{selected_scene_name}中抓取失败:{event.metadata['errorMessage']}")
else:
print(f"{selected_scene_name}中没有微波炉")
controller.stop()
2. 效果
ITHOR场景切换、导航" />