机器人学习模拟框架 robosuite (3) 机器人控制代码示例

news2025/3/5 10:41:12

Robosuite框架是一个用于机器人模拟和控制的强大工具,支持多种类型的机器人。

官方文档:Overview — robosuite 1.5 documentation

开源地址:https://github.com/ARISE-Initiative/robosuite

目录

1、通过键盘或SpaceMouse远程控制机器人

2、选择机器人夹抓

3、夹抓控制

4、记录轨迹数据并回放

5、多种机器人任务执行


1、通过键盘或SpaceMouse远程控制机器人

主要功能包括:

  • 远程控制:通过键盘或 SpaceMouse 远程控制机器人的末端执行器。

  • 多臂支持:支持单臂和双臂环境,适应不同的任务需求。

  • 控制器选择:支持多种控制器,适应不同的控制策略。

  • 设备灵敏度调整:通过参数调整输入设备的灵敏度,适应不同的操作需求。

运行效果:

控制机械臂移动的键盘按键:H、Y、P、O、; 、.

示例代码


import argparse
import time

import numpy as np

import robosuite as suite
from robosuite import load_composite_controller_config
from robosuite.controllers.composite.composite_controller import WholeBody
from robosuite.wrappers import VisualizationWrapper

if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    parser.add_argument("--environment", type=str, default="Lift")  # 环境名称
    parser.add_argument("--robots", nargs="+", type=str, default="Panda", help="使用的机器人")  # 机器人名称
    parser.add_argument(
        "--config", type=str, default="default", help="指定环境配置(如果需要)"
    )  # 环境配置
    parser.add_argument("--arm", type=str, default="right", help="控制的臂(例如双臂)'right' 或 'left'")  # 控制的臂
    parser.add_argument("--switch-on-grasp", action="store_true", help="在抓手动作时切换抓手控制")  # 抓手切换
    parser.add_argument("--toggle-camera-on-grasp", action="store_true", help="在抓手动作时切换相机角度")  # 相机切换
    parser.add_argument(
        "--controller",
        type=str,
        default=None,
        help="选择控制器。可以是通用名称(例如 'BASIC' 或 'WHOLE_BODY_MINK_IK')或 json 文件(参见 robosuite/controllers/config 示例)或 None(使用机器人的默认控制器(如果存在))",
    )  # 控制器选择
    parser.add_argument("--device", type=str, default="keyboard")  # 输入设备
    parser.add_argument("--pos-sensitivity", type=float, default=1.0, help="位置输入的缩放比例")  # 位置灵敏度
    parser.add_argument("--rot-sensitivity", type=float, default=1.0, help="旋转输入的缩放比例")  # 旋转灵敏度
    parser.add_argument(
        "--max_fr",
        default=20,
        type=int,
        help="当模拟运行速度超过指定帧率时暂停;20 fps 为实时。",
    )  # 最大帧率

    args = parser.parse_args()

    # 加载控制器配置
    controller_config = load_composite_controller_config(
        controller=args.controller,
        robot=args.robots[0],
    )

    # 创建参数配置
    config = {
        "env_name": args.environment,
        "robots": args.robots,
        "controller_configs": controller_config,
    }

    # 检查是否使用多臂环境,并设置环境配置
    if "TwoArm" in args.environment:
        config["env_configuration"] = args.config
    else:
        args.config = None

    # 创建环境
    env = suite.make(
        **config,
        has_renderer=True,
        has_offscreen_renderer=False,
        render_camera="agentview",
        ignore_done=True,
        use_camera_obs=False,
        reward_shaping=True,
        control_freq=20,
        hard_reset=False,
    )

    # 使用可视化包装器包装环境
    env = VisualizationWrapper(env, indicator_configs=None)

    # 设置数字打印选项
    np.set_printoptions(formatter={"float": lambda x: "{0:0.3f}".format(x)})

    # 初始化设备
    if args.device == "keyboard":
        from robosuite.devices import Keyboard

        device = Keyboard(env=env, pos_sensitivity=args.pos_sensitivity, rot_sensitivity=args.rot_sensitivity)
        env.viewer.add_keypress_callback(device.on_press)
    elif args.device == "spacemouse":
        from robosuite.devices import SpaceMouse

        device = SpaceMouse(env=env, pos_sensitivity=args.pos_sensitivity, rot_sensitivity=args.rot_sensitivity)
    elif args.device == "mjgui":
        from robosuite.devices.mjgui import MJGUI

        device = MJGUI(env=env)
    else:
        raise Exception("无效的设备选择:请选择 'keyboard' 或 'spacemouse'。")

    while True:
        # 重置环境
        obs = env.reset()

        # 设置渲染
        cam_id = 0
        num_cam = len(env.sim.model.camera_names)
        env.render()

        # 初始化在重置之间需要维护的变量
        last_grasp = 0

        # 初始化设备控制
        device.start_control()
        all_prev_gripper_actions = [
            {
                f"{robot_arm}_gripper": np.repeat([0], robot.gripper[robot_arm].dof)
                for robot_arm in robot.arms
                if robot.gripper[robot_arm].dof > 0
            }
            for robot in env.robots
        ]

        # 循环直到从输入中获得重置或任务完成
        while True:
            start = time.time()

            # 设置活动机器人
            active_robot = env.robots[device.active_robot]

            # 获取最新的动作
            input_ac_dict = device.input2action()

            # 如果动作为空,则这是一个重置,应该退出
            if input_ac_dict is None:
                break

            from copy import deepcopy

            action_dict = deepcopy(input_ac_dict)  # {}
            # 设置臂动作
            for arm in active_robot.arms:
                if isinstance(active_robot.composite_controller, WholeBody):  # 输入类型传递给关节动作策略
                    controller_input_type = active_robot.composite_controller.joint_action_policy.input_type
                else:
                    controller_input_type = active_robot.part_controllers[arm].input_type

                if controller_input_type == "delta":
                    action_dict[arm] = input_ac_dict[f"{arm}_delta"]
                elif controller_input_type == "absolute":
                    action_dict[arm] = input_ac_dict[f"{arm}_abs"]
                else:
                    raise ValueError

            # 维护每个机器人的抓手状态,但只更新活动机器人的动作
            env_action = [robot.create_action_vector(all_prev_gripper_actions[i]) for i, robot in enumerate(env.robots)]
            env_action[device.active_robot] = active_robot.create_action_vector(action_dict)
            env_action = np.concatenate(env_action)
            for gripper_ac in all_prev_gripper_actions[device.active_robot]:
                all_prev_gripper_actions[device.active_robot][gripper_ac] = action_dict[gripper_ac]

            env.step(env_action)
            env.render()

            # 如果必要,限制帧率
            if args.max_fr is not None:
                elapsed = time.time() - start
                diff = 1 / args.max_fr - elapsed
                if diff > 0:
                    time.sleep(diff)

代码关键要点: 

  1. 输入设备

    • 支持键盘和 SpaceMouse 两种输入设备。

    • 键盘提供 6 自由度(6-DoF)控制命令,通过按键实现。

    • SpaceMouse 提供 6 自由度(6-DoF)控制命令,通过鼠标移动实现。

  2. 控制器选择

    • 可以选择逆运动学控制器(ik)或操作空间控制器(osc)。

    • ik 的旋转输入相对于末端执行器坐标系,osc 的旋转输入相对于全局坐标系(即:静态/相机坐标系)。

  3. 环境配置

    • 支持单臂和双臂环境。

    • 双臂环境可以配置为平行(parallel)或相对(opposed)。

    • 可以选择控制的臂(right 或 left)。

  4. 设备灵敏度:通过 --pos_sensitivity--rot_sensitivity 参数调整位置和旋转输入的灵敏度。

  5. 主循环

    • 通过设备获取用户输入,转换为机器人动作。

    • 使用 env.step 执行动作并渲染环境。

    • 限制帧率以确保实时运行。

备注信息:

***使用以下参数选择环境特定设置***

    --environment:要执行的任务,例如:"Lift"、"TwoArmPegInHole"、"NutAssembly" 等。

    --robots:执行任务的机器人。可以是以下之一:
        {"Panda", "Sawyer", "IIWA", "Jaco", "Kinova3", "UR5e", "Baxter"}。
        注意,环境包含合理性检查,"TwoArm..." 环境只接受两个机器人名称的元组或一个双臂机器人名称,
        其他环境只接受一个单臂机器人名称。

    --config:仅适用于 "TwoArm..." 环境。指定任务所需的机器人配置。选项有 {"parallel" 和 "opposed"}

        - "parallel":设置环境,使两个机器人并排站立,面向同一方向。
            需要在 --robots 参数中指定两个机器人名称的元组。

        - "opposed":设置环境,使两个机器人相对站立,面向彼此。
            需要在 --robots 参数中指定两个机器人名称的元组。

    --arm:仅适用于 "TwoArm..." 环境。指定要控制的多个臂中的哪一个。
        其他(被动)臂将保持静止。选项有 {"right", "left"}(从机器人面向观众的方向看)

    --switch-on-grasp:仅适用于 "TwoArm..." 环境。如果启用,每次按下抓手输入时将切换当前控制的臂。

    --toggle-camera-on-grasp:如果启用,抓手输入将切换可用的相机角度。

示例:

    对于普通单臂环境:
        $ python demo_device_control.py --environment PickPlaceCan --robots Sawyer --controller osc

    对于双臂双臂环境:
        $ python demo_device_control.py --environment TwoArmLift --robots Baxter --config bimanual --arm left --controller osc

    对于双臂多单臂机器人环境:
        $ python demo_device_control.py --environment TwoArmLift --robots Sawyer Sawyer --config parallel --controller osc

2、选择机器人夹抓

涉及的关键点概括

  1. 整体流程

    • 遍历所有可用的抓手类型,并通过 gripper_types 参数将它们应用到环境中。

    • 在每个环境中运行一个随机策略,模拟抓手的操作。

  2. 主要功能

    • suite.make:用于创建模拟环境,配置环境参数(如机器人型号、抓手类型、渲染选项等)。

    • 动作空间:通过 env.action_spec 获取动作的上下界,并生成随机动作。

    • 渲染:通过 env.render() 将模拟动画显示在窗口中。

    • 帧率限制:通过时间计算确保模拟的帧率保持在指定范围内,防止运行过于流畅或迟钝。

  3. 技术细节

    • robosuite.ALL_GRIPPERS 包含了所有可用的抓手类型,程序会逐个测试这些抓手。

    • control_freq=50 参数定义了控制频率,确保模拟的帧率足够高。

    • done 标志用于检测任务是否完成(例如:物体被成功抬起)。

示例代码


import time
import numpy as np
import robosuite as suite
from robosuite import ALL_GRIPPERS

MAX_FR = 25  # 模拟中运行的最大帧率

if __name__ == "__main__":

    for gripper in ALL_GRIPPERS:

        # 通知用户正在使用哪种抓手
        print(f"使用抓手 {gripper}...")

        # 创建环境并使用选定的抓手类型
        env = suite.make(
            "Lift",
            robots="Panda",
            gripper_types=gripper,
            has_renderer=True,  # 确保我们可以在屏幕上渲染
            has_offscreen_renderer=False,  # 不需要离屏渲染,因为我们没有使用像素观察
            use_camera_obs=False,  # 不使用像素观察
            control_freq=50,  # 控制应该足够快,这样模拟看起来会更流畅
            camera_names="frontview",
        )

        # 重置环境
        env.reset()

        # 获取动作范围
        low, high = env.action_spec

        # 运行随机策略
        for t in range(300):
            start = time.time()
            env.render()  # 渲染环境
            action = np.random.uniform(low, high)  # 随机动作
            observation, reward, done, info = env.step(action)  # 执行动作
            if done:
                print("Episode 在 {} 个时间步后结束".format(t + 1))
                break

            # 如果需要,限制帧率
            elapsed = time.time() - start
            diff = 1 / MAX_FR - elapsed
            if diff > 0:
                time.sleep(diff)

        # 关闭窗口
        env.close()

3、夹抓控制

  • 抓手控制: 抓手可以在设定的高度范围内移动,并通过开合手指抓取物体。

  • 物体交互: 模拟物体与抓手的接触,监测接触的物理信息(如摩擦力、法向量等)。

  • 地面检测: 避免物体与地面的重复检测。

  • 视觉呈现: 使用 OpenCV 渲染模拟动画,展示抓手和物体的交互过程。

 运行效果:

自动切换不同夹抓:

通过上面的演示,最终我们选择合适抓取当前物体的夹抓~

 

示例代码:



import xml.etree.ElementTree as ET

from robosuite.models import MujocoWorldBase
from robosuite.models.arenas.table_arena import TableArena
from robosuite.models.grippers import PandaGripper, RethinkGripper
from robosuite.models.objects import BoxObject
from robosuite.utils import OpenCVRenderer
from robosuite.utils.binding_utils import MjRenderContextOffscreen, MjSim
from robosuite.utils.mjcf_utils import new_actuator, new_joint

if __name__ == "__main__":

    # 创建空的世界
    world = MujocoWorldBase()

    # 添加桌子
    arena = TableArena(table_full_size=(0.4, 0.4, 0.05), table_offset=(0, 0, 1.1), has_legs=False)
    world.merge(arena)

    # 添加抓手
    gripper = RethinkGripper()
    # 创建一个新的身体,用滑动关节连接抓手
    gripper_body = ET.Element("body", name="gripper_base")
    gripper_body.set("pos", "0 0 1.3")  # 设置抓手位置
    gripper_body.set("quat", "0 0 1 0")  # 翻转 z 轴
    gripper_body.append(new_joint(name="gripper_z_joint", type="slide", axis="0 0 1", damping="50"))  # 添加滑动关节
    # 将抓手基座添加到世界中
    world.worldbody.append(gripper_body)
    # 将抓手合并进抓手基座
    world.merge(gripper, merge_body="gripper_base")
    # 添加执行器以控制滑动关节
    world.actuator.append(new_actuator(joint="gripper_z_joint", act_type="position", name="gripper_z", kp="500"))

    # 添加一个可抓取的物体
    mujoco_object = BoxObject(
        name="box", size=[0.02, 0.02, 0.02], rgba=[1, 0, 0, 1], friction=[1, 0.005, 0.0001]
    ).get_obj()
    # 设置物体位置
    mujoco_object.set("pos", "0 0 1.11")
    # 将物体添加到世界
    world.worldbody.append(mujoco_object)

    # 添加 x 轴和 y 轴的参考物(视觉辅助)
    x_ref = BoxObject(
        name="x_ref", size=[0.01, 0.01, 0.01], rgba=[0, 1, 0, 1], obj_type="visual", joints=None
    ).get_obj()
    x_ref.set("pos", "0.2 0 1.105")
    world.worldbody.append(x_ref)
    y_ref = BoxObject(
        name="y_ref", size=[0.01, 0.01, 0.01], rgba=[0, 0, 1, 1], obj_type="visual", joints=None
    ).get_obj()
    y_ref.set("pos", "0 0.2 1.105")
    world.worldbody.append(y_ref)

    # 启动模拟
    model = world.get_model(mode="mujoco")

    sim = MjSim(model)
    viewer = OpenCVRenderer(sim)
    render_context = MjRenderContextOffscreen(sim, device_id=-1)
    sim.add_render_context(render_context)

    sim_state = sim.get_state()

    # 用于重力补偿
    gravity_corrected = ["gripper_z_joint"]
    _ref_joint_vel_indexes = [sim.model.get_joint_qvel_addr(x) for x in gravity_corrected]

    # 设置抓手参数
    gripper_z_id = sim.model.actuator_name2id("gripper_z")
    gripper_z_low = 0.07  # 抓手低位置
    gripper_z_high = -0.02  # 抓手高位置
    gripper_z_is_low = False  # 抓手是否处于低位置

    gripper_jaw_ids = [sim.model.actuator_name2id(x) for x in gripper.actuators]
    gripper_open = [-0.0115, 0.0115]  # 抓手打开时的关节角度
    gripper_closed = [0.020833, -0.020833]  # 抓手关闭时的关节角度
    gripper_is_closed = True  # 抓手是否关闭

    # 硬编码的抓手轨迹序列
    seq = [(False, False), (True, False), (True, True), (False, True)]

    sim.set_state(sim_state)
    step = 0
    T = 500  # 每隔 T 步循环轨迹序列
    while True:
        if step % 100 == 0:
            print("step: {}".format(step))

            # 获取接触信息
            for contact in sim.data.contact[0 : sim.data.ncon]:
                geom_name1 = sim.model.geom_id2name(contact.geom1)
                geom_name2 = sim.model.geom_id2name(contact.geom2)
                if geom_name1 == "floor" and geom_name2 == "floor":
                    continue

                print("geom1: {}, geom2: {}".format(geom_name1, geom_name2))
                print("contact id {}".format(id(contact)))
                print("friction: {}".format(contact.friction))
                print("normal: {}".format(contact.frame[0:3]))

        # 循环抓手轨迹序列
        if step % T == 0:
            plan = seq[int(step / T) % len(seq)]
            gripper_z_is_low, gripper_is_closed = plan
            print("changing plan: gripper low: {}, gripper closed {}".format(gripper_z_is_low, gripper_is_closed))

        # 控制抓手
        if gripper_z_is_low:
            sim.data.ctrl[gripper_z_id] = gripper_z_low  # 设置抓手到低位置
        else:
            sim.data.ctrl[gripper_z_id] = gripper_z_high  # 设置抓手到高位置
        if gripper_is_closed:
            sim.data.ctrl[gripper_jaw_ids] = gripper_closed  # 关闭抓手
        else:
            sim.data.ctrl[gripper_jaw_ids] = gripper_open  # 打开抓手

        # 更新模拟
        sim.step()
        sim.data.qfrc_applied[_ref_joint_vel_indexes] = sim.data.qfrc_bias[_ref_joint_vel_indexes]
        viewer.render()  # 渲染模拟动画
        step += 1

代码解析:

  1. MujocoWorldBaseMujocoSim:

    • MujocoWorldBase 用于创建一个Mujoco模拟世界的基础。

    • MujocoSim 则是负责运行穆乔科模拟的核心类。

  2. 抓手的添加和控制:

    • 使用 RethinkGripper 创建抓手模型。

    • 通过定义 gripper_z_joint 和对应的执行器 new_actuator,实现抓手的高度控制。

  3. 物体的添加:

    • 使用 BoxObject 定义了一个红色的立方体小物体,用于抓取演示。

    • 物体的物理属性(如摩擦力)通过 friction 参数设置。

  4. 视觉辅助: 通过添加绿色和蓝色的方块作为参考,方便观察物体的位置和方向。

  5. 模拟控制: 使用 sim.step() 更新模拟状态。使用 viewer.render() 渲染模拟图像到窗口。

  6. 接触信息: 通过 sim.data.contact 获取接触信息,可用于调试和分析抓手与物体的交互情况。

运行效果:

抓起物体:

4、记录轨迹数据并回放

  • 数据收集:通过随机策略生成轨迹数据并保存。

  • 数据回放:从保存的数据中加载轨迹并回放。

  • 环境包装:使用 DataCollectionWrapper 包装环境,支持数据收集功能。

  • 实时渲染:在数据收集和回放过程中实时渲染环境动画。

示例代码:


import argparse
import os
import time
from glob import glob

import numpy as np

import robosuite as suite
from robosuite.wrappers import DataCollectionWrapper


def collect_random_trajectory(env, timesteps=1000, max_fr=None):
    """运行随机策略以收集轨迹数据。

    轨迹数据以 npz 格式保存到文件中。
    修改 DataCollectionWrapper 包装器以添加新字段或更改数据格式。

    参数:
        env (MujocoEnv): 用于收集轨迹的环境实例
        timesteps (int): 每个轨迹运行的环境时间步数
        max_fr (int): 如果指定,当模拟运行速度超过最大帧率时暂停
    """
    env.reset()  # 重置环境
    dof = env.action_dim  # 获取动作维度

    for t in range(timesteps):
        start = time.time()
        action = np.random.randn(dof)  # 生成随机动作
        env.step(action)  # 执行动作
        env.render()  # 渲染环境
        if t % 100 == 0:
            print(t)  # 每 100 步打印一次进度

        # 如果指定了最大帧率,则限制帧率
        if max_fr is not None:
            elapsed = time.time() - start
            diff = 1 / max_fr - elapsed
            if diff > 0:
                time.sleep(diff)


def playback_trajectory(env, ep_dir, max_fr=None):
    """回放某一集的数据。

    参数:
        env (MujocoEnv): 用于回放轨迹的环境实例
        ep_dir (str): 包含某一集数据的目录路径
    """
    # 从 XML 文件重新加载模型
    xml_path = os.path.join(ep_dir, "model.xml")
    with open(xml_path, "r") as f:
        env.reset_from_xml_string(f.read())  # 从 XML 字符串重置环境

    state_paths = os.path.join(ep_dir, "state_*.npz")  # 获取状态文件路径

    # 逐个加载状态文件并回放
    t = 0
    for state_file in sorted(glob(state_paths)):
        print(state_file)
        dic = np.load(state_file)  # 加载状态文件
        states = dic["states"]  # 获取状态数据
        for state in states:
            start = time.time()
            env.sim.set_state_from_flattened(state)  # 设置模拟状态
            env.sim.forward()  # 更新模拟
            env.viewer.update()  # 更新视图
            env.render()  # 渲染环境
            t += 1
            if t % 100 == 0:
                print(t)  # 每 100 步打印一次进度

            # 如果指定了最大帧率,则限制帧率
            if max_fr is not None:
                elapsed = time.time() - start
                diff = 1 / max_fr - elapsed
                if diff > 0:
                    time.sleep(diff)
    env.close()  # 关闭环境


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--environment", type=str, default="Door")  # 环境名称
    parser.add_argument("--robots", nargs="+", type=str, default="Panda", help="使用的机器人")  # 机器人名称
    parser.add_argument("--directory", type=str, default="/tmp/")  # 数据保存目录
    parser.add_argument("--timesteps", type=int, default=1000)  # 时间步数
    parser.add_argument(
        "--max_fr",
        default=20,
        type=int,
        help="当模拟运行速度超过指定帧率时暂停;20 fps 为实时。",
    )  # 最大帧率
    args = parser.parse_args()

    # 创建原始环境
    env = suite.make(
        args.environment,
        robots=args.robots,
        ignore_done=True,
        use_camera_obs=False,
        has_renderer=True,
        has_offscreen_renderer=False,
        control_freq=20,
    )
    data_directory = args.directory  # 数据保存目录

    # 使用数据收集包装器包装环境
    env = DataCollectionWrapper(env, data_directory)

    # 测试多次调用 env.reset 是否会创建多个目录
    env.reset()
    env.reset()
    env.reset()

    # 收集一些数据
    print("正在收集随机数据...")
    collect_random_trajectory(env, timesteps=args.timesteps, max_fr=args.max_fr)

    # 回放数据
    _ = input("按下任意键开始回放...")
    print("正在回放数据...")
    data_directory = env.ep_directory  # 获取当前集的目录
    playback_trajectory(env, data_directory, args.max_fr)

代码分析:

  1. DataCollectionWrapper 包装器:用于包装环境,以便在运行过程中收集数据。收集的数据以 npz 格式保存到指定目录中。

  2. 数据收集:使用随机策略生成动作,运行环境并收集轨迹数据。数据包括环境状态、动作、观察值等。

  3. 数据回放:从保存的数据中加载状态,并逐帧回放。通过 env.sim.set_state_from_flattened(state) 设置模拟状态。

  4. 帧率控制:如果指定了最大帧率 (max_fr),则通过 time.sleep 控制模拟速度,避免运行过快。

  5. 数据保存和加载:数据保存在指定目录中,包括 XML 模型文件和状态文件。回放时从这些文件中加载数据并恢复环境状态。

运行效果:

打印信息:

DataCollectionWrapper: making folder at /tmp/ep_1740881381_0772326
0
100
200
300
400
500
600
700
800
900
按下任意键开始回放...
正在回放数据...
/tmp/ep_1740881381_0772326/state_1740881386_010901.npz
100
/tmp/ep_1740881381_0772326/state_1740881391_0270681.npz
200
/tmp/ep_1740881381_0772326/state_1740881396_0425832.npz
300
/tmp/ep_1740881381_0772326/state_1740881401_0576134.npz
400
/tmp/ep_1740881381_0772326/state_1740881406_0732286.npz
500
/tmp/ep_1740881381_0772326/state_1740881411_0889266.npz
600
/tmp/ep_1740881381_0772326/state_1740881416_1048322.npz
700
/tmp/ep_1740881381_0772326/state_1740881421_1204755.npz
800
/tmp/ep_1740881381_0772326/state_1740881426_135585.npz
900
/tmp/ep_1740881381_0772326/state_1740881431_1502776.npz
1000
Xlib:  extension "NV-GLX" missing on display ":1".

5、多种机器人任务执行

  • 环境自定义:支持选择不同的环境和机器人组合,适应多种模拟场景。

  • 领域随机化:通过随机化环境参数,提高机器人在不同条件下的适应能力。

  • 可视化:实时渲染模拟过程,方便观察机器人的行为和环境交互。

示例代码:

# 导入移动机器人模块
from robosuite.robots import MobileRobot

# 导入 RoboSuite 的输入工具
from robosuite.utils.input_utils import *
import time

# 定义最大帧率,用于控制模拟的运行速度
MAX_FR = 25

# 主程序入口
if __name__ == "__main__":
    options = {}  # 保存创建环境的选项

    # 欢迎信息
    print("欢迎使用 RoboSuite v{}!".format(suite.__version__))
    print(suite.__logo__)  # 打印 RoboSuite 的标志

    # 用户选择环境
    options["env_name"] = choose_environment()

    # 如果是多臂环境,默认选择机器人
    if "TwoArm" in options["env_name"]:
        options["env_configuration"] = choose_multi_arm_config()

        if options["env_configuration"] == "single-robot":
            options["robots"] = choose_robots(
                exclude_bimanual=False,  # 不排除双臂机器人
                use_humanoids=True,      # 允许使用人形机器人
                exclude_single_arm=True  # 排除单臂机器人
            )
        else:
            options["robots"] = []
            # 循环选择两个机器人
            for i in range(2):
                print("请选择机器人 {}...\n".format(i + 1))
                options["robots"].append(
                    choose_robots(exclude_bimanual=False, use_humanoids=True)
                )
    # 如果是人形机器人环境,选择人形机器人
    elif "Humanoid" in options["env_name"]:
        options["robots"] = choose_robots(use_humanoids=True)
    else:
        options["robots"] = choose_robots(
            exclude_bimanual=False,  # 不排除双臂机器人
            use_humanoids=True       # 允许使用人形机器人
        )

    # 初始化环境
    env = suite.make(
        **options,            # 使用用户选择的选项
        has_renderer=True,    # 启用视觉渲染
        has_offscreen_renderer=False,  # 不启用离屏渲染
        ignore_done=True,     # 忽略任务完成信号
        use_camera_obs=False, # 不使用相机观测
        control_freq=20,      # 控制频率为 20Hz
    )
    env.reset()  # 重置环境

    env.viewer.set_camera(camera_id=0)  # 设置摄像头

    # 禁用移动机器人的腿部和底座控制
    for robot in env.robots:
        if isinstance(robot, MobileRobot):
            robot.enable_parts(legs=False, base=False)

    # 开始渲染环境
    for i in range(10000):
        start = time.time()  # 记录当前时间

        # 随机生成动作并执行
        action = np.random.randn(*env.action_spec[0].shape)
        obs, reward, done, _ = env.step(action)
        env.render()  # 渲染环境

        # 控制帧率
        elapsed = time.time() - start
        diff = 1 / MAX_FR - elapsed
        if diff > 0:
            time.sleep(diff)  # 确保帧率在限制范围内

运行代码后,首先选择“环境”,也就是执行任务的种类

Here is a list of environments in the suite:

[0] Door
[1] Lift
[2] NutAssembly
[3] NutAssemblyRound
[4] NutAssemblySingle
[5] NutAssemblySquare
[6] PickPlace
[7] PickPlaceBread
[8] PickPlaceCan
[9] PickPlaceCereal
[10] PickPlaceMilk
[11] PickPlaceSingle
[12] Stack
[13] ToolHang
[14] TwoArmHandover
[15] TwoArmLift
[16] TwoArmPegInHole
[17] TwoArmTransport
[18] Wipe

Choose an environment to run (enter a number from 0 to 18):

然后选择执行的机器人类型

Here is a list of available robots:

[0] Baxter
[1] GR1ArmsOnly
[2] IIWA
[3] Jaco
[4] Kinova3
[5] Panda
[6] Sawyer
[7] SpotWithArmFloating
[8] Tiago
[9] UR5e

Choose a robot (enter a number from 0 to 9): 

运行效果,第二个机器人选择7(SpotWithArmFloating)

相关文章推荐:

机器人学习模拟框架 robosuite 支持强化学习和模仿学习 (1) 快速入门_机械臂模仿学习入门-CSDN博客

机器人学习模拟框架 robosuite (2)支持多种机器人、夹抓和底座 工作流程-CSDN博客

 分享完成~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2309973.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

kakfa-3:ISR机制、HWLEO、生产者、消费者、核心参数负载均衡

1. kafka内核原理 1.1 ISR机制 光是依靠多副本机制能保证Kafka的高可用性,但是能保证数据不丢失吗?不行,因为如果leader宕机,但是leader的数据还没同步到follower上去,此时即使选举了follower作为新的leader&#xff…

【微知】如何查看Mellanox网卡上的光模块的信息?(ethtool -m enp1s0f0 看型号、厂商、生产日期等)

背景 服务器上插入的光模块经常被忽略,往往这里是定位问题最根本的地方。如何通过命令查看? 命令 ethtool提供了-m参数,m是module-info的意思,他是从光模块的eeprom中读取数据。(应该是用i2c协议读取的)…

yum源选要配置华为云的源,阿里云用不了的情况

curl -O /etc/yum.repos.d/CentOS-Base.repo https://repo.huaweicloud.com/repository/conf/CentOS-7-reg.repo

好数——前缀和思想(题目分享)

今天我的舍友去参加“传智杯”广东省的省赛,跟我说了这样一道题,他说他想不出来怎么去优化代码,怎么做都是套用两层for循环超时,下面我就根据题意,使用前缀和的算法去优化一下思路,题目本身是不难的&#x…

MWC 2025 | 移远通信大模型解决方案加速落地,引领服务机器人创新变革

随着人工智能、大模型等技术的蓬勃发展,生成式AI应用全面爆发。在此背景下,服务机器人作为大模型技术在端侧落地的关键场景,迎来了前所未有的发展机遇。 作为与用户直接交互的智能设备,服务机器人需要应对复杂场景下的感知、决策和…

springboot425-基于SpringBoot的BUG管理系统(源码+数据库+纯前后端分离+部署讲解等)

💕💕作者: 爱笑学姐 💕💕个人简介:十年Java,Python美女程序员一枚,精通计算机专业前后端各类框架。 💕💕各类成品Java毕设 。javaweb,ssm&#xf…

FineReport 操作注意

1.父单元格重复的时候,如何取消合并 效果如下: 只需要在单元格中,将数据设置为【列表】即可。 2.待定

3D手眼标定转换详细实施步骤及原理概述

3D手眼标定转换详细实施步骤及原理概述 一、手眼标定的核心目标二、3D手眼标定的原理概述一、基本概念与坐标系定义**二、数学建模与方程推导****1. 坐标变换的齐次矩阵表示****2. 手眼标定方程推导** **三、方程求解方法****1. 分离旋转与平移****2. 旋转矩阵求解****3. 平移向…

Verilog:SCCB控制器

目录 一、SCCB协议 (1)SCCB时序 (2)与I2C的区别 二、Verilog 实现 (1)设计要求 (2)设计要点 (3)模块完整代码 三、功能验证 (1)写…

与中国联通技术共建:通过obdiag分析OceanBase DDL中的报错场景

中国联通软件研究院(简称联通软研院)在全面评估与广泛调研后,在 2021年底决定采用OceanBase 作为基础,自研分布式数据库产品CUDB(即China Unicom Database,中国联通数据库)。目前,该…

大数据与网络安全讲座

🍅 点击文末小卡片 ,免费获取网络安全全套资料,资料在手,涨薪更快 大数据的价值为大家公认。业界通常以4个“V”来概括大数据的基本特征——Volume(数据体量巨大)、Variety(数据类型繁多)、Value(价值密度低)、Velocity(处理速度快…

张驰咨询:用六西格玛重构动力电池行业的BOM成本逻辑

在动力电池行业,BOM(物料清单)成本每降低1%,都可能改写企业的利润曲线。某头部企业的三元锂电池BOM成本曾较行业标杆高出11%,单电芯利润率被压缩至3%的生死线。然而,通过张驰咨询的六西格玛方法论&#xff…

pyside6学习专栏(九):在PySide6中使用PySide6.QtCharts绘制6种不同的图表的示例代码

PySide6的QtCharts类支持绘制各种型状的图表,如面积区域图、饼状图、折线图、直方图、线条曲线图、离散点图等,下面的代码是采用示例数据绘制这6种图表的示例代码,并可实现动画显示效果,实际使用时参照代码中示例数据的格式将实际数据替换即可…

《深度学习实战》第10集:联邦学习与隐私保护

第10集:联邦学习与隐私保护 2025年3月4日更新了代码,补充了实例程序运行截图 和 如何提高模型准确率的方法 系统梳理 集集精彩 代码验证 保证实战 随着数据隐私问题日益受到关注,联邦学习(Federated Learning) 作为一…

【数据结构】二叉树总结篇

遍历 递归 递归三部曲: 1.参数和返回值 2.终止条件 3.单层逻辑(遍历顺序) var preorderTraversal function(root) { // 第一种let res[];const dfsfunction(root){if(rootnull)return ;//先序遍历所以从父节点开始res.push(root.val);//递归…

软考-数据库开发工程师-3.1-数据结构-线性结构

第3章内容比较多,内容考试分数占比较大,6分左右 线性表 1、线性表的定义 一个线性表是n个元素的有限序列(n≥0),通常表示为(a1,a2, a3,…an). 2、线性表的顺序存储(顺序表) 是指用一组地址连续的存储单元依次存储线性表中的数据元…

【五.LangChain技术与应用】【2.LangChain虚拟环境搭建(下):环境优化与调试】

一、Docker化部署:别让你的环境成为薛定谔的猫 经历过"在我机器上能跑"惨案的老铁都懂,传统虚拟环境就像个黑盒子。去年我帮客户部署LangChain应用,因为glibc版本差了0.1,整个服务直接崩成烟花。从那天起,我所有项目都强制上Docker! Dockerfile生存指南: #…

deepseek+mermaid【自动生成流程图】

成果: 第一步打开deepseek官网(或百度版(更快一点)): 百度AI搜索 - 办公学习一站解决 第二步,生成对应的Mermaid流程图: 丢给deepseek代码,或题目要求 生成mermaid代码 第三步将代码复制到me…

在 Element Plus 的 <el-select> 组件中,如果需要将 <el-option> 的默认值设置为 null。 用于枚举传值

文章目录 引言轻松实现 `<el-option>` 的默认值为 `null`I 实现方式监听清空事件 【推荐】使用 v-model 绑定 null添加一个值为 null 的选项处理 null 值的显示引言 背景:接口签名规则要求空串参与,空对象不参与签名计算 // 空字符串“” 参与签名组串,null不参与签…

解码未来!安徽艾德未来智能科技有限公司荣获“GAS消费电子科创奖-产品创新奖”!

在2025年“GAS消费电子科创奖”评选中&#xff0c;安徽艾德未来智能科技有限公司提交的“讯飞AI会议耳机iFLYBUDS Pro 2”&#xff0c;在技术创新性、设计创新性、工艺创新性、智能化创新性及原创性五大维度均获得评委的高度认可&#xff0c;荣获“产品创新奖”。 这一殊荣不仅…