-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathyam.py
More file actions
119 lines (100 loc) · 4.41 KB
/
Copy pathyam.py
File metadata and controls
119 lines (100 loc) · 4.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import logging
import numpy as np
from rcs._core.common import BaseCameraConfig, RobotPlatform
from rcs._core.sim import SimConfig
from rcs.envs.configs import EmptyWorldYam
from rcs.envs.storage_wrapper import StorageWrapper
from rcs.operator.interface import TeleopLoop
from rcs.operator.quest import QuestConfig, QuestOperator
from simpub.sim.mj_publisher import MujocoPublisher
logger = logging.getLogger(__name__)
"""
Teleoperation of two YAM arms with the Meta Quest 3. See README.md for the setup of the quest and
the IRIS app; each arm follows its controller while the trigger is held, and the hand trigger
drives the gripper.
To teleoperate real hardware, install the rcs_yam extension (`pip install -ve extensions/rcs_yam`),
bring up the CAN interfaces (`sudo ip link set can0 up type can bitrate 1000000`, same for can1)
and set ROBOT_INSTANCE to RobotPlatform.HARDWARE.
RealSense cameras are recorded on hardware when CAMERA_DICT is set, which needs the rcs_realsense
extension (`pip install -ve extensions/rcs_realsense`).
"""
ROBOT_INSTANCE = RobotPlatform.HARDWARE
# The teleop loop matches robots to controllers by name: each arm is named after the controller
# that drives it.
CAN_CHANNELS = {"left": "can0", "right": "can1"}
MQ3_ADDR = "10.42.0.1"
RECORD_FPS = 30
# Serial numbers of the RealSense cameras, use `rs-enumerate-devices -s` to list them.
# Set CAMERA_DICT to None to disable cameras.
CAMERA_DICT = {
"right_wrist": "230422272017",
"left_wrist": "230422271040",
}
# CAMERA_DICT = None
INCLUDE_DEPTH = False
DATASET_PATH = "yam_teleop"
INSTRUCTION = "pick up cube"
config = QuestConfig(
mq3_addr=MQ3_ADDR,
simulation=ROBOT_INSTANCE == RobotPlatform.SIMULATION,
switched_left_right=True,
display_cameras=False,
read_frequency=90,
)
def get_env():
if ROBOT_INSTANCE == RobotPlatform.HARDWARE:
from rcs_yam.configs import DefaultYamDualMultiHardwareEnv
from rcs_yam.creators import HardwareCameraCreatorConfig
env_creator = DefaultYamDualMultiHardwareEnv()
env_creator.left_channel = CAN_CHANNELS["left"]
env_creator.right_channel = CAN_CHANNELS["right"]
# The dual config already enables async_control, so the setters do not wait for the arms.
hw_cfg = env_creator.config()
camera_cfgs: dict[str, HardwareCameraCreatorConfig] = {}
if CAMERA_DICT is not None:
camera_cfgs["realsense"] = HardwareCameraCreatorConfig(
camera_type_id="realsense",
camera_cfgs={
name: BaseCameraConfig(
identifier=identifier,
resolution_width=1280,
resolution_height=720,
frame_rate=30,
)
for name, identifier in CAMERA_DICT.items()
},
)
hw_cfg.camera_cfgs = camera_cfgs or None
hw_cfg.control_mode = config.operator_class.control_mode[0]
hw_cfg.relative_to = config.operator_class.control_mode[1]
hw_cfg.max_relative_movement = (0.5, np.deg2rad(90))
hw_cfg.wrapper_cfg.binary_gripper = False
hw_cfg.wrapper_cfg.include_depth = INCLUDE_DEPTH
env_rel = env_creator.create_env(hw_cfg)
operator = QuestOperator(config)
else:
scene = EmptyWorldYam()
sim_cfg_data = scene.config()
sim_cfg_data.sim_cfg = SimConfig(
async_control=True, realtime=True, frequency=RECORD_FPS, max_convergence_steps=500
)
sim_cfg_data.control_mode = config.operator_class.control_mode[0]
sim_cfg_data.relative_to = config.operator_class.control_mode[1]
sim_cfg_data.max_relative_movement = (0.5, np.deg2rad(90))
sim_cfg_data.wrapper_cfg.binary_gripper = False
env_rel = scene.create_env(sim_cfg_data)
sim = env_rel.get_wrapper_attr("sim")
MujocoPublisher(sim.model, sim.data, MQ3_ADDR, visible_geoms_groups=list(range(1, 3)))
operator = QuestOperator(config, sim)
env_rel = StorageWrapper(
env_rel, DATASET_PATH, INSTRUCTION, batch_size=32, max_rows_per_group=100, max_rows_per_file=1000
)
return env_rel, operator
def main():
env_rel, operator = get_env()
env_rel.reset()
tele = TeleopLoop(env_rel, operator, env_frequency=RECORD_FPS, robot_platform=ROBOT_INSTANCE)
with env_rel, tele: # type: ignore
tele.environment_step_loop()
if __name__ == "__main__":
main()