机器人学习模拟框架 robosuite (3) 机器人控制代码示例
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 timeimport numpy as npimport robosuite as suite
from robosuite import load_composite_controller_config
from robosuite.controllers.composite.composite_controller import WholeBody
from robosuite.wrappers import VisualizationWrapperif __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.configelse: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 Keyboarddevice = 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 SpaceMousedevice = SpaceMouse(env=env, pos_sensitivity=args.pos_sensitivity, rot_sensitivity=args.rot_sensitivity)elif args.device == "mjgui":from robosuite.devices.mjgui import MJGUIdevice = MJGUI(env=env)else:raise Exception("无效的设备选择:请选择 'keyboard' 或 'spacemouse'。")while True:# 重置环境obs = env.reset()# 设置渲染cam_id = 0num_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.armsif 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:breakfrom copy import deepcopyaction_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_typeelse:controller_input_type = active_robot.part_controllers[arm].input_typeif 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() - startdiff = 1 / args.max_fr - elapsedif diff > 0:time.sleep(diff)
代码关键要点:
-
输入设备:
-
支持键盘和 SpaceMouse 两种输入设备。
-
键盘提供 6 自由度(6-DoF)控制命令,通过按键实现。
-
SpaceMouse 提供 6 自由度(6-DoF)控制命令,通过鼠标移动实现。
-
-
控制器选择:
-
可以选择逆运动学控制器(ik)或操作空间控制器(osc)。
-
ik 的旋转输入相对于末端执行器坐标系,osc 的旋转输入相对于全局坐标系(即:静态/相机坐标系)。
-
-
环境配置:
-
支持单臂和双臂环境。
-
双臂环境可以配置为平行(parallel)或相对(opposed)。
-
可以选择控制的臂(right 或 left)。
-
-
设备灵敏度:通过
--pos_sensitivity和--rot_sensitivity参数调整位置和旋转输入的灵敏度。 -
主循环:
-
通过设备获取用户输入,转换为机器人动作。
-
使用
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、选择机器人夹抓
涉及的关键点概括
-
整体流程:
-
遍历所有可用的抓手类型,并通过
gripper_types参数将它们应用到环境中。 -
在每个环境中运行一个随机策略,模拟抓手的操作。
-
-
主要功能:
-
suite.make:用于创建模拟环境,配置环境参数(如机器人型号、抓手类型、渲染选项等)。 -
动作空间:通过
env.action_spec获取动作的上下界,并生成随机动作。 -
渲染:通过
env.render()将模拟动画显示在窗口中。 -
帧率限制:通过时间计算确保模拟的帧率保持在指定范围内,防止运行过于流畅或迟钝。
-
-
技术细节:
-
robosuite.ALL_GRIPPERS包含了所有可用的抓手类型,程序会逐个测试这些抓手。 -
control_freq=50参数定义了控制频率,确保模拟的帧率足够高。 -
done标志用于检测任务是否完成(例如:物体被成功抬起)。
-
示例代码
import time
import numpy as np
import robosuite as suite
from robosuite import ALL_GRIPPERSMAX_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() - startdiff = 1 / MAX_FR - elapsedif diff > 0:time.sleep(diff)# 关闭窗口env.close()
3、夹抓控制
-
抓手控制: 抓手可以在设定的高度范围内移动,并通过开合手指抓取物体。
-
物体交互: 模拟物体与抓手的接触,监测接触的物理信息(如摩擦力、法向量等)。
-
地面检测: 避免物体与地面的重复检测。
-
视觉呈现: 使用 OpenCV 渲染模拟动画,展示抓手和物体的交互过程。
运行效果:

自动切换不同夹抓:

通过上面的演示,最终我们选择合适抓取当前物体的夹抓~
示例代码:
import xml.etree.ElementTree as ETfrom 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_jointif __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 = 0T = 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":continueprint("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 = planprint("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
代码解析:
-
MujocoWorldBase和MujocoSim:-
MujocoWorldBase用于创建一个Mujoco模拟世界的基础。 -
MujocoSim则是负责运行穆乔科模拟的核心类。
-
-
抓手的添加和控制:
-
使用
RethinkGripper创建抓手模型。 -
通过定义
gripper_z_joint和对应的执行器new_actuator,实现抓手的高度控制。
-
-
物体的添加:
-
使用
BoxObject定义了一个红色的立方体小物体,用于抓取演示。 -
物体的物理属性(如摩擦力)通过
friction参数设置。
-
-
视觉辅助: 通过添加绿色和蓝色的方块作为参考,方便观察物体的位置和方向。
-
模拟控制: 使用
sim.step()更新模拟状态。使用viewer.render()渲染模拟图像到窗口。 -
接触信息: 通过
sim.data.contact获取接触信息,可用于调试和分析抓手与物体的交互情况。
运行效果:

抓起物体:

4、记录轨迹数据并回放
-
数据收集:通过随机策略生成轨迹数据并保存。
-
数据回放:从保存的数据中加载轨迹并回放。
-
环境包装:使用
DataCollectionWrapper包装环境,支持数据收集功能。 -
实时渲染:在数据收集和回放过程中实时渲染环境动画。
示例代码:
import argparse
import os
import time
from glob import globimport numpy as npimport robosuite as suite
from robosuite.wrappers import DataCollectionWrapperdef 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() - startdiff = 1 / max_fr - elapsedif 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 = 0for 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 += 1if t % 100 == 0:print(t) # 每 100 步打印一次进度# 如果指定了最大帧率,则限制帧率if max_fr is not None:elapsed = time.time() - startdiff = 1 / max_fr - elapsedif 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)
代码分析:
-
DataCollectionWrapper包装器:用于包装环境,以便在运行过程中收集数据。收集的数据以npz格式保存到指定目录中。 -
数据收集:使用随机策略生成动作,运行环境并收集轨迹数据。数据包括环境状态、动作、观察值等。
-
数据回放:从保存的数据中加载状态,并逐帧回放。通过
env.sim.set_state_from_flattened(state)设置模拟状态。 -
帧率控制:如果指定了最大帧率 (
max_fr),则通过time.sleep控制模拟速度,避免运行过快。 -
数据保存和加载:数据保存在指定目录中,包括 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() - startdiff = 1 / MAX_FR - elapsedif 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] WipeChoose 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] UR5eChoose a robot (enter a number from 0 to 9):
运行效果,第二个机器人选择7(SpotWithArmFloating)

相关文章推荐:
机器人学习模拟框架 robosuite 支持强化学习和模仿学习 (1) 快速入门_机械臂模仿学习入门-CSDN博客
机器人学习模拟框架 robosuite (2)支持多种机器人、夹抓和底座 工作流程-CSDN博客
分享完成~
相关文章:
机器人学习模拟框架 robosuite (3) 机器人控制代码示例
Robosuite框架是一个用于机器人模拟和控制的强大工具,支持多种类型的机器人。 官方文档:Overview — robosuite 1.5 documentation 开源地址:https://github.com/ARISE-Initiative/robosuite 目录 1、通过键盘或SpaceMouse远程控制机器人…...
kakfa-3:ISR机制、HWLEO、生产者、消费者、核心参数负载均衡
1. kafka内核原理 1.1 ISR机制 光是依靠多副本机制能保证Kafka的高可用性,但是能保证数据不丢失吗?不行,因为如果leader宕机,但是leader的数据还没同步到follower上去,此时即使选举了follower作为新的leaderÿ…...
【微知】如何查看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...
nginx accesslog 打印自定义header
比如我在请求的header中添加了一个path-match-type,那我现在nginx的accesslog 中打印出来,应该如何配置呢? rootnginx-59f5d66df6-jw5k8:/# cat /etc/nginx/nginx.conf user nginx; worker_processes auto;error_log /var/log/nginx/erro…...
好数——前缀和思想(题目分享)
今天我的舍友去参加“传智杯”广东省的省赛,跟我说了这样一道题,他说他想不出来怎么去优化代码,怎么做都是套用两层for循环超时,下面我就根据题意,使用前缀和的算法去优化一下思路,题目本身是不难的&#x…...
MWC 2025 | 移远通信大模型解决方案加速落地,引领服务机器人创新变革
随着人工智能、大模型等技术的蓬勃发展,生成式AI应用全面爆发。在此背景下,服务机器人作为大模型技术在端侧落地的关键场景,迎来了前所未有的发展机遇。 作为与用户直接交互的智能设备,服务机器人需要应对复杂场景下的感知、决策和…...
【大模型基础_毛玉仁】0.概述
更多内容:XiaoJ的知识星球 【大模型基础_毛玉仁】 系列文章参考 系列文章 【大模型基础_毛玉仁】0.概述 【大模型基础_毛玉仁】1.1 基于统计方法的语言模型 更新中。。。。。。 参考 书籍:大模型基础_完整版.pdf Github:https://github.co…...
ADB、Appium 和 大模型融合开展移动端自动化测试
将 ADB、Appium 和 大模型(如 GPT、LLM) 结合,可以显著提升移动端自动化测试的智能化水平和效率。以下是具体的实现思路和应用场景: 1. 核心组件的作用 ADB(Android Debug Bridge): 用于与 Android 设备通信,执行设备操作(如安装应用、获取日志、截图等)。Appium: 用…...
springboot425-基于SpringBoot的BUG管理系统(源码+数据库+纯前后端分离+部署讲解等)
💕💕作者: 爱笑学姐 💕💕个人简介:十年Java,Python美女程序员一枚,精通计算机专业前后端各类框架。 💕💕各类成品Java毕设 。javaweb,ssm…...
Ubuntu系统上部署Node.js项目的完整流程
以下是在Ubuntu系统上部署Node.js项目的完整流程,分为系统初始化、环境配置、项目部署三个部分: 一、系统初始化 & 环境准备 bash # 1. 更新系统软件包 sudo apt update && sudo apt upgrade -y# 2. 安装基础工具 sudo apt install -y buil…...
X Window---图形接口
摘抄自 鸟哥的linux私房菜 基础篇 第四版 有鉴于图形用户接口(Graphical User Interface, GUI) 的需求日益加重,在 1984 年由 MIT 与其他第三方首次发表了 X Window System ,并且更在 1988 年成立了非营利性质的 XFree86 这个组织。所谓的XFree86 其实是…...
数据序列化协议 Protobuf 3 介绍(Go 语言)
Protobuf 3 入门 1. 什么是序列化? 1.1 概念 序列化(Serialization 或 Marshalling) 是指将数据结构或对象的状态转换成可存储或传输的格式。反向操作称为反序列化(Deserialization 或 Unmarshalling),它…...
FineReport 操作注意
1.父单元格重复的时候,如何取消合并 效果如下: 只需要在单元格中,将数据设置为【列表】即可。 2.待定...
3D手眼标定转换详细实施步骤及原理概述
3D手眼标定转换详细实施步骤及原理概述 一、手眼标定的核心目标二、3D手眼标定的原理概述一、基本概念与坐标系定义**二、数学建模与方程推导****1. 坐标变换的齐次矩阵表示****2. 手眼标定方程推导** **三、方程求解方法****1. 分离旋转与平移****2. 旋转矩阵求解****3. 平移向…...
Verilog:SCCB控制器
目录 一、SCCB协议 (1)SCCB时序 (2)与I2C的区别 二、Verilog 实现 (1)设计要求 (2)设计要点 (3)模块完整代码 三、功能验证 (1)写…...
维度建模基础篇:从理论到核心组件解析
维度建模基础篇:从理论到核心组件解析 引言 在数据仓库与商业智能(BI)领域,维度建模(Dimensional Modeling)作为一种经典的数据组织方法论,自Kimball提出以来,已成为构建高效分析型系统的核心范式1,2,3。其以业务需求为导向,通过事实表与维度表的组合,实现对复杂…...
与中国联通技术共建:通过obdiag分析OceanBase DDL中的报错场景
中国联通软件研究院(简称联通软研院)在全面评估与广泛调研后,在 2021年底决定采用OceanBase 作为基础,自研分布式数据库产品CUDB(即China Unicom Database,中国联通数据库)。目前,该…...
大数据与网络安全讲座
🍅 点击文末小卡片 ,免费获取网络安全全套资料,资料在手,涨薪更快 大数据的价值为大家公认。业界通常以4个“V”来概括大数据的基本特征——Volume(数据体量巨大)、Variety(数据类型繁多)、Value(价值密度低)、Velocity(处理速度快…...
AtCoder Beginner Contest 395 E
点我写题 题意:给个有向图,从1出发,每次可以走一条有向边,花费为1,也可以选择把全部有向边翻转,花费x,问到n的最小花费 思路:最短路dp,定义dis[i][0/1]表示走到i为止&…...
Linux进程管理6 - CFS调度
0、CFS调度器 CFS调度器使用完全公平调度算法。 完全公平调度算法引入虚拟运行时间的概念:虚拟运行时间 = 实际运行时间 * nice_0_weight / 进程的权重。完全公平调度算法使用红黑树把进程按虚拟运行时间从小到大排序,每次调度选择虚拟运行时间最小的进程。时间片 操作系统进…...
张驰咨询:用六西格玛重构动力电池行业的BOM成本逻辑
在动力电池行业,BOM(物料清单)成本每降低1%,都可能改写企业的利润曲线。某头部企业的三元锂电池BOM成本曾较行业标杆高出11%,单电芯利润率被压缩至3%的生死线。然而,通过张驰咨询的六西格玛方法论ÿ…...
pyside6学习专栏(九):在PySide6中使用PySide6.QtCharts绘制6种不同的图表的示例代码
PySide6的QtCharts类支持绘制各种型状的图表,如面积区域图、饼状图、折线图、直方图、线条曲线图、离散点图等,下面的代码是采用示例数据绘制这6种图表的示例代码,并可实现动画显示效果,实际使用时参照代码中示例数据的格式将实际数据替换即可…...
SpringBoot获取YAML配置文件中的属性值(二):使用Environment环境组件读取值
Spring Boot 使用 Properties 和 YAML 配置文件文件,系列文章: 《Spring使用@Value注解与@PropertySource注解加载配置文件》 《SpringBoot获取YAML配置文件中的属性值(一):使用@Value注解、@ConfigurationProperties注解》 《SpringBoot获取YAML配置文件中的属性值(二)…...
14天 -- Redis 的持久化机制有哪些?Redis 主从复制的实现原理是什么? Redis 数据过期后的删除策略是什么?
Redis 的持久化机制有哪些? Redis 是一种高性能的键值存储系统,主要用于缓存、消息队列等场景。为了防止数据丢失,Redis 提供了多种持久化机制,主要包括以下两种: 1. RDB(Redis Database Backupÿ…...
《深度学习实战》第10集:联邦学习与隐私保护
第10集:联邦学习与隐私保护 2025年3月4日更新了代码,补充了实例程序运行截图 和 如何提高模型准确率的方法 系统梳理 集集精彩 代码验证 保证实战 随着数据隐私问题日益受到关注,联邦学习(Federated Learning) 作为一…...
如何解决跨域请求的问题(CORS)?
文章目录 1. 引言2. 理解 CORS2.1 CORS 基本概念2.2 同源策略与跨域分类 3. CORS 的核心机制3.1 预检请求(Preflight Request)3.2 简单请求 4. 服务器端配置 CORS4.1 关键响应头4.2 Node.js (Express) 示例4.3 其他后端语言配置 5. 前端处理 CORS 请求5.…...
【数据结构】二叉树总结篇
遍历 递归 递归三部曲: 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生存指南: #…...
