Closed 206333308 closed 8 months ago
My device is omega.7, which can feed back six-axis data in real time (absolute quantity rather than variation), but when I use this module I wrote in demo_device_control.py, there may be some problems when executing input2action() (I ‘m not sure), the phenomenon is: 1. The simulation is stuck 2. The generated action is unreasonable。 Thank you very much for your help
import threading
import time
import numpy as np
import omega
from robosuite.devices import Device
from robosuite.utils.transform_utils import rotation_matrix
class Omega7(Device):
def __init__(
self,
pos_sensitivity=400.0,
rot_sensitivity=1.0,
):
print("Opening Omega7 device")
omega.open_device()
self.pos_sensitivity = pos_sensitivity
self.rot_sensitivity = rot_sensitivity
# 6-DOF variables
self.x, self.y, self.z = 0, 0, 0
self.last_x, self.last_y, self.last_z = 0, 0, 0
self.roll, self.pitch, self.yaw = 0, 0, 0
self.last_roll, self.last_pitch, self.last_yaw = 0, 0, 0
self.single_click_and_hold = False
self._control = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
self._lastcontrol = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
self._reset_state = 0
self.rotation = np.array([[-1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, -1.0]])
self._enabled = False
# launch a new listener thread to listen to SpaceMouse
self.thread = threading.Thread(target=self.run)
self.thread.daemon = True
self.thread.start()
def _reset_internal_state(self):
"""
Resets internal state of controller, except for the reset signal.
"""
self.rotation = np.array([[-1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, -1.0]])
# Reset 6-DOF variables
self.x, self.y, self.z = 0, 0, 0
self.roll, self.pitch, self.yaw = 0, 0, 0
# Reset control
self._control = np.zeros(6)
# Reset grasp
self.single_click_and_hold = False
def start_control(self):
"""
Method that should be called externally before controller can
start receiving commands.
"""
self._reset_internal_state()
self._reset_state = 0
self._enabled = True
def get_controller_state(self):
"""
Grabs the current state of the 3D mouse.
Returns:
dict: A dictionary containing dpos, orn, unmodified orn, grasp, and reset
"""
dpos = (self.control - self._lastcontrol)[:3] * 0.005 * self.pos_sensitivity
# dpos = self.control[:3] * 0.005 * self.pos_sensitivity # 此处0.005可能要改
# roll, pitch, yaw = self.control[3:] * 0.005 * self.rot_sensitivity
roll, pitch, yaw = 0 , 0, 0
self.last_x, self.last_y, self.last_z,self.last_roll, self.last_pitch, self.last_yaw = self.x,self.y,self.z,self.roll,self.pitch,self.yaw
self._lastcontrol = [
self.last_x,
self.last_y,
self.last_z,
self.last_roll,
self.last_pitch,
self.last_yaw,
]
# convert RPY to an absolute orientation
drot1 = rotation_matrix(angle=-pitch, direction=[1.0, 0, 0], point=None)[:3, :3]
drot2 = rotation_matrix(angle=roll, direction=[0, 1.0, 0], point=None)[:3, :3]
drot3 = rotation_matrix(angle=yaw, direction=[0, 0, 1.0], point=None)[:3, :3]
self.rotation = self.rotation.dot(drot1.dot(drot2.dot(drot3)))
return dict(
dpos=dpos,
rotation=self.rotation,
raw_drotation=np.array([roll, pitch, yaw]),
grasp=self.control_gripper,
reset=self._reset_state,
)
def run(self):
while True:
self.x,self.y, self.z,self.roll,self.pitch,self.yaw = omega.get_pos_and_orideg()
self._control = [
self.x,
self.y,
self.z,
self.roll,
self.pitch,
self.yaw,
]
# 夹爪功能待完善
@property
def control(self):
"""
Grabs current pose of Spacemouse
Returns:
np.array: 6-DoF control value
"""
return np.array(self._control)
@property
def control_gripper(self):
"""
Maps internal states into gripper commands.
Returns:
float: Whether we're using single click and hold or not
"""
if self.single_click_and_hold:
return 1.0
return 0
# if __name__ == "__main__":
# omega7 = Omega7()
# for i in range(100):
# # while True:
# print(omega7.control, omega7.control_gripper)
# time.sleep(0.02)
if __name__ == "__main__":
omega7 = Omega7()
for i in range(100): # 或者使用 while True: 以持续运行
# 获取控制器状态
controller_state = omega7.get_controller_state()
# 仅打印 dpos 值
print("dpos:", controller_state["dpos"])
time.sleep(0.02) # 控制循环速度,以便更容易阅读输出
"""Teleoperate robot with keyboard or SpaceMouse.
***Choose user input option with the --device argument***
Keyboard:
We use the keyboard to control the end-effector of the robot.
The keyboard provides 6-DoF control commands through various keys.
The commands are mapped to joint velocities through an inverse kinematics
solver from Bullet physics.
Note:
To run this script with macOS, you must run it with root access.
SpaceMouse:
We use the SpaceMouse 3D mouse to control the end-effector of the robot.
The mouse provides 6-DoF control commands. The commands are mapped to joint
velocities through an inverse kinematics solver from Bullet physics.
The two side buttons of SpaceMouse are used for controlling the grippers.
SpaceMouse Wireless from 3Dconnexion: https://www.3dconnexion.com/spacemouse_wireless/en/
We used the SpaceMouse Wireless in our experiments. The paper below used the same device
to collect human demonstrations for imitation learning.
Reinforcement and Imitation Learning for Diverse Visuomotor Skills
Yuke Zhu, Ziyu Wang, Josh Merel, Andrei Rusu, Tom Erez, Serkan Cabi, Saran Tunyasuvunakool,
János Kramár, Raia Hadsell, Nando de Freitas, Nicolas Heess
RSS 2018
Note:
This current implementation only supports macOS (Linux support can be added).
Download and install the driver before running the script:
https://www.3dconnexion.com/service/drivers.html
Additionally, --pos_sensitivity and --rot_sensitivity provide relative gains for increasing / decreasing the user input
device sensitivity
***Choose controller with the --controller argument***
Choice of using either inverse kinematics controller (ik) or operational space controller (osc):
Main difference is that user inputs with ik's rotations are always taken relative to eef coordinate frame, whereas
user inputs with osc's rotations are taken relative to global frame (i.e.: static / camera frame of reference).
Notes:
OSC also tends to be more computationally efficient since IK relies on the backend pybullet IK solver.
***Choose environment specifics with the following arguments***
--environment: Task to perform, e.g.: "Lift", "TwoArmPegInHole", "NutAssembly", etc.
--robots: Robot(s) with which to perform the task. Can be any in
{"Panda", "Sawyer", "IIWA", "Jaco", "Kinova3", "UR5e", "Baxter"}. Note that the environments include sanity
checks, such that a "TwoArm..." environment will only accept either a 2-tuple of robot names or a single
bimanual robot name, according to the specified configuration (see below), and all other environments will
only accept a single single-armed robot name
--config: Exclusively applicable and only should be specified for "TwoArm..." environments. Specifies the robot
configuration desired for the task. Options are {"bimanual", "single-arm-parallel", and "single-arm-opposed"}
-"bimanual": Sets up the environment for a single bimanual robot. Expects a single bimanual robot name to
be specified in the --robots argument
-"single-arm-parallel": Sets up the environment such that two single-armed robots are stationed next to
each other facing the same direction. Expects a 2-tuple of single-armed robot names to be specified
in the --robots argument.
-"single-arm-opposed": Sets up the environment such that two single-armed robots are stationed opposed from
each other, facing each other from opposite directions. Expects a 2-tuple of single-armed robot names
to be specified in the --robots argument.
--arm: Exclusively applicable and only should be specified for "TwoArm..." environments. Specifies which of the
multiple arm eef's to control. The other (passive) arm will remain stationary. Options are {"right", "left"}
(from the point of view of the robot(s) facing against the viewer direction)
--switch-on-grasp: Exclusively applicable and only should be specified for "TwoArm..." environments. If enabled,
will switch the current arm being controlled every time the gripper input is pressed
--toggle-camera-on-grasp: If enabled, gripper input presses will cycle through the available camera angles
Examples:
For normal single-arm environment:
$ python demo_device_control.py --environment PickPlaceCan --robots Sawyer --controller osc
For two-arm bimanual environment:
$ python demo_device_control.py --environment TwoArmLift --robots Baxter --config bimanual --arm left --controller osc
For two-arm multi single-arm robot environment:
$ python demo_device_control.py --environment TwoArmLift --robots Sawyer Sawyer --config single-arm-parallel --controller osc
"""
import argparse
import numpy as np
import robosuite as suite
from robosuite import load_controller_config
from robosuite.utils.input_utils import input2action
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="UR5e", help="Which robot(s) to use in the env")
parser.add_argument(
"--config", type=str, default="single-arm-opposed", help="Specified environment configuration if necessary"
)
parser.add_argument("--arm", type=str, default="right", help="Which arm to control (eg bimanual) 'right' or 'left'")
parser.add_argument("--switch-on-grasp", action="store_true", help="Switch gripper control on gripper action")
parser.add_argument("--toggle-camera-on-grasp", action="store_true", help="Switch camera angle on gripper action")
parser.add_argument("--controller", type=str, default="osc", help="Choice of controller. Can be 'ik' or 'osc'")
parser.add_argument("--device", type=str, default="omega7")
# parser.add_argument("--device", type=str, default="keyboard")
parser.add_argument("--pos-sensitivity", type=float, default=100.0, help="How much to scale position user inputs")
parser.add_argument("--rot-sensitivity", type=float, default=1.0, help="How much to scale rotation user inputs")
args = parser.parse_args() # 参数和设置储存于args
print(args)
# Import controller config for EE IK or OSC (pos/ori) 选择控制器配置
if args.controller == "ik":
controller_name = "IK_POSE"
elif args.controller == "osc":
controller_name = "OSC_POSE"
else:
print("Error: Unsupported controller specified. Must be either 'ik' or 'osc'!")
raise ValueError
# Get controller config 加载控制器配置
controller_config = load_controller_config(default_controller=controller_name)
# Create argument configuration
config = {
"env_name": args.environment,
"robots": args.robots,
"controller_configs": controller_config,
}
# Check if we're using a multi-armed environment and use env_configuration argument if so
if "TwoArm" in args.environment:
config["env_configuration"] = args.config
else:
args.config = None
# Create environment 使用suite.make创建仿真环境,其中包含渲染器、摄像机视图、奖励塑造、控制频率、硬重置等相关参数
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,
)
# Wrap this environment in a visualization wrapper 将仿真环境包装在VisualizationWrapper中以提供可视化功能
env = VisualizationWrapper(env, indicator_configs=None)
# Setup printing options for numbers 设置numpy打印选项格式
np.set_printoptions(formatter={"float": lambda x: "{0:0.3f}".format(x)})
# initialize device 根据用户指定的设备(键盘或SpaceMouse)初始化输入设备并注册按键回调函数
if args.device == "omega7":
from robosuite.devices import Omega7
device = Omega7(pos_sensitivity=args.pos_sensitivity, rot_sensitivity=args.rot_sensitivity)
elif args.device == "keyboard":
from robosuite.devices import Keyboard
device = Keyboard(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(pos_sensitivity=args.pos_sensitivity, rot_sensitivity=args.rot_sensitivity)
else:
raise Exception("Invalid device choice: choose either 'keyboard' or 'spacemouse'.")
while True:
# Reset the environment
obs = env.reset()
# Setup rendering
cam_id = 0
num_cam = len(env.sim.model.camera_names)
env.render()
# Initialize variables that should the maintained between resets
last_grasp = 0
# Initialize device control
device.start_control()
while True:
# Set active robot
active_robot = env.robots[0] if args.config == "bimanual" else env.robots[args.arm == "left"]
# Get the newest action
action, grasp = input2action(
device=device, robot=active_robot, active_arm=args.arm, env_configuration=args.config
)
print(action, grasp)
# If action is none, then this a reset so we should break
if action is None:
break
# If the current grasp is active (1) and last grasp is not (-1) (i.e.: grasping input just pressed),
# toggle arm control and / or camera viewing angle if requested
if last_grasp < 0 < grasp:
if args.switch_on_grasp:
args.arm = "left" if args.arm == "right" else "right"
if args.toggle_camera_on_grasp:
cam_id = (cam_id + 1) % num_cam
env.viewer.set_camera(camera_id=cam_id)
# Update last grasp
last_grasp = grasp
# Fill out the rest of the action space if necessary
rem_action_dim = env.action_dim - action.size
if rem_action_dim > 0:
# Initialize remaining action space
rem_action = np.zeros(rem_action_dim)
# This is a multi-arm setting, choose which arm to control and fill the rest with zeros
if args.arm == "right":
action = np.concatenate([action, rem_action])
elif args.arm == "left":
action = np.concatenate([rem_action, action])
else:
# Only right and left arms supported
print(
"Error: Unsupported arm specified -- "
"must be either 'right' or 'left'! Got: {}".format(args.arm)
)
elif rem_action_dim < 0:
# We're in an environment with no gripper action space, so trim the action space to be the action dim
action = action[: env.action_dim]
# Step through the simulation and render
obs, reward, done, info = env.step(action)
env.render()
I don't know much about the device you are using, so you need to tune the conversion of the scaling yourself. There's little information about getting stuck in input2action
. So can you set some breakpoints in https://github.com/ARISE-Initiative/robosuite/blob/48c1b8a6c077d04399a00db05694d7f9f876ffc9/robosuite/utils/input_utils.py#L181 and see which line is causing the issue?
已经解决,原因是device类中实时获取数据的函数未加延时。推测机理:threading使用这个函数时导致占用过高,影响后续仿真渲染等等。 ‘’‘ def run(self): while True: self.x,self.y,self.z,self.roll,self.pitch,self.yaw = omega.get_pos_and_orideg() self._control = [ self.x, self.y, self.z, self.roll, self.pitch, self.yaw, ]
# 夹爪功能待完善
’‘’
Hi, can you provide more information about this? What kind of device do you want to use? As long as you can get an array of action values, integrating your custom device should be fairly easy.