当前位置: 首页 > news >正文

仿真环境下实现场景切换、定位物体和导航行走

1. 代码(以微波炉为例)

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场景切换、导航

ITHOR场景切换、导航
在这里插入图片描述

相关文章:

  • RK3588--MIPI屏幕选型以及底板设计要点
  • JUC (java. util.concurrent) 的常见类及创建新线程的方法等 [Java EE 初阶]
  • Springboot快速接入豆包大模型
  • 【二分查找 图论】P8794 [蓝桥杯 2022 国 A] 环境治理|普及
  • C++中的多重继承
  • 品牌设计分析模版
  • DeepSeek的100个实用提示词模板
  • 如何让 Git 管理本地项目
  • 使用Jenkins实现Windows服务器下C#应用程序发布
  • Deepseek开源周,第二天:Deep EP
  • OkHttp、Retrofit、RxJava:一文讲清楚
  • Wasserstein 距离(Wasserstein Distance)
  • adb的安装
  • 数据如何安全“过桥”?分类分级与风险评估,守护数据流通安全
  • 软件工程(复习折磨题目版)
  • 墨刀:Axure托管插件登录/注册时出现空白页
  • 解锁状态模式:Java 编程中的行为魔法
  • 什么限制了LLM:空间复杂度限制
  • 【人工智能】数据挖掘与应用题库(1-100)
  • 初阶数据结构(C语言实现)——2算法的时间复杂度和空间复杂度
  • 中国海油总裁:低油价短期影响利润,但也催生资产并购机会
  • 游客曝九寨沟打网约车被出租车围堵,景区回应:当地无合规网约车
  • 成都世运会倒计时100天,中国代表团运动员规模将创新高
  • 新华每日电讯:从上海街区经济看账面、市面、人面、基本面
  • 幸福航空五一前三天航班取消:客服称目前是锁舱状态,无法确认何时恢复
  • 澎湃思想周报丨数字时代的育儿;凛冬已至好莱坞