Skip to content

Commit 2e6fd31

Browse files
committed
feat: added webcam live viewer and vla executer
1 parent a5295f6 commit 2e6fd31

File tree

2 files changed

+268
-0
lines changed

2 files changed

+268
-0
lines changed

python/examples/liveviewer.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import argparse
2+
import cv2
3+
from matplotlib import pyplot as plt
4+
from rcsss.camera.interface import BaseCameraConfig
5+
from rcsss.camera.realsense import RealSenseCameraSet, RealSenseSetConfig
6+
7+
8+
if __name__ == "__main__":
9+
# arg parse to get the key for the camera
10+
parser = argparse.ArgumentParser()
11+
parser.add_argument("--camera", type=str, default="side")
12+
args = parser.parse_args()
13+
14+
cameras = {
15+
"side2": BaseCameraConfig(identifier="244222071045"), # old wrist
16+
# "wrist": BaseCameraConfig(identifier="218622278131"), # new realsense
17+
"bird_eye": BaseCameraConfig(identifier="243522070364"), # bird eye
18+
# "side": BaseCameraConfig(identifier="243522070385"),
19+
"side": BaseCameraConfig(identifier="243522070385"), # side
20+
}
21+
22+
cam_cfg = RealSenseSetConfig(
23+
cameras=cameras,
24+
resolution_width=1280,
25+
resolution_height=720,
26+
frame_rate=15,
27+
enable_imu=False, # does not work with imu, why?
28+
enable_ir=True,
29+
enable_ir_emitter=False,
30+
)
31+
32+
camera_set = RealSenseCameraSet(cam_cfg)
33+
frame_set = camera_set.poll_frame_set()
34+
35+
# data = cv2.rotate(frame_set.frames[args.camera].camera.color.data, cv2.ROTATE_90_COUNTERCLOCKWISE)
36+
data = frame_set.frames[args.camera].camera.color.data
37+
img = plt.imshow(data)
38+
plt.show(block=False)
39+
plt.pause(0.1)
40+
41+
# while True:
42+
for i in range(300):
43+
frame_set = camera_set.poll_frame_set()
44+
45+
# # save the images in the frameset
46+
# for key, frame in frame_set.frames.items():
47+
# cv2.imwrite(f"{key}.png", frame.camera.color.data)
48+
# break
49+
50+
# img.set_data(frame_set.frames[args.camera].camera.color.data)
51+
# # data = cv2.rotate(frame_set.frames[args.camera].camera.color.data, cv2.ROTATE_90_COUNTERCLOCKWISE)
52+
# plt.draw()
53+
# plt.pause(0.5)
54+
55+
# save the images in the frameset
56+
for key, frame in frame_set.frames.items():
57+
# cv2.imwrite(f"{key}.png", frame.camera.color.data)
58+
# save in rgb
59+
cv2.imwrite(f"{key}.png", cv2.cvtColor(frame.camera.color.data, cv2.COLOR_BGR2RGB))

python/rcsss/control/run_vla.py

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
from dataclasses import dataclass
2+
import logging
3+
from time import sleep
4+
from PIL import Image
5+
import cv2
6+
import gymnasium as gym
7+
import numpy as np
8+
import matplotlib.pyplot as plt
9+
from rcsss.envs.wrappers import RHCWrapper, StorageWrapper
10+
from omegaconf import OmegaConf
11+
from rcsss._core.sim import FR3, FR3State
12+
from rcsss.camera.realsense import RealSenseCameraSet
13+
from rcsss.config import read_config_yaml
14+
15+
# from rcsss.desk import FCI, Desk
16+
from rcsss.control.fr3_desk import FCI, Desk, DummyResourceManager
17+
from rcsss.control.utils import load_creds_fr3_desk
18+
from rcsss.envs.base import ControlMode, RelativeTo, RobotInstance
19+
from rcsss.envs.factories import default_fr3_hw_gripper_cfg, default_fr3_hw_robot_cfg, default_fr3_sim_gripper_cfg, default_fr3_sim_robot_cfg, default_mujoco_cameraset_cfg, default_realsense, fr3_hw_env, fr3_sim_env
20+
import requests
21+
import json_numpy
22+
23+
from agents.policies import Act, Obs
24+
from agents.client import RemoteAgent
25+
from rcsss.envs.base import ControlMode
26+
27+
json_numpy.patch()
28+
29+
30+
logger = logging.getLogger(__name__)
31+
logger.setLevel(logging.INFO)
32+
33+
34+
ROBOT_INSTANCE = RobotInstance.HARDWARE
35+
# CAMERA_GUI = "rgb_side"
36+
# INSTRUCTION = "pick up the blue cube"
37+
INSTRUCTION = "pick up the can"
38+
39+
default_cfg = OmegaConf.create(
40+
{"host": "dep-eng-air-p-1.hosts.utn.de", "port": 9000, "model": "openvla", "robot_ip": "192.168.101.1", "debug": True}
41+
# {"host": "dep-eng-air-p-1.hosts.utn.de", "port": 7000, "model": "octo", "robot_ip": "192.168.101.1", "debug": False}
42+
# {"host": "localhost", "port": 8080, "model": "chatgpt", "robot_ip": "192.168.101.1", "debug": False}
43+
)
44+
cli_conf = OmegaConf.from_cli()
45+
cfg = OmegaConf.merge(cli_conf, default_cfg)
46+
DEBUG = cfg.debug
47+
48+
49+
class RobotControl:
50+
def __init__(self, env: gym.Env, instruction: str, model_host: str, model_port: int, model_name: str):
51+
self.env = env
52+
self.gripper_state = 1
53+
54+
self.instruction = instruction
55+
self.remote_agent = RemoteAgent(model_host, model_port, model_name)
56+
57+
if not DEBUG:
58+
self.env.get_wrapper_attr("log_files")(self.remote_agent.git_status())
59+
60+
def get_obs(self, obs: dict) -> Obs:
61+
# bird_eye=obs["frames"]["bird_eye"]["rgb"]
62+
# wrist=obs["frames"]["wrist"]["rgb"]
63+
64+
side = obs["frames"]["side"]["rgb"]
65+
# side = obs["frames"]["default_free"]["rgb"]
66+
# side = obs["frames"]["openvla_view"]["rgb"]
67+
68+
side = np.array(Image.fromarray(side).resize(
69+
(256, 256), Image.Resampling.LANCZOS))
70+
71+
72+
73+
74+
# center crop square
75+
# h = side.shape[0]
76+
# start_w = (side.shape[1] - h) // 2
77+
# end_w = start_w + h
78+
# side = side[:, start_w:end_w]
79+
# bird_eye = bird_eye[:, start_w:end_w]
80+
# wrist = wrist[:, start_w:end_w]
81+
82+
# rotate side by 90 degrees
83+
# side = cv2.rotate(side, cv2.ROTATE_90_COUNTERCLOCKWISE)
84+
85+
# rescale side to 256x256
86+
# side = cv2.resize(side, dsize=(256, 256), interpolation=cv2.INTER_CUBIC)
87+
# bird_eye = cv2.resize(bird_eye, dsize=(256, 256), interpolation=cv2.INTER_CUBIC)
88+
# wrist = cv2.resize(wrist, dsize=(256, 256), interpolation=cv2.INTER_CUBIC)
89+
90+
# TODO: add some noise, use other cameras, record what is happening
91+
92+
# return {"bird_eye": bird_eye, "wrist": wrist, "side": side, "gripper": obs["gripper"]}
93+
# return Obs(rgb_bird_eye=bird_eye, rgb_wrist=wrist, rgb_side=side, gripper=obs["gripper"], rgb=obs["frames"])
94+
return Obs(rgb_side=side, gripper=obs["gripper"]) #, info={"rgb": obs["frames"], "xyzrpy": obs["xyzrpy"]})
95+
96+
def step(self, action) -> tuple[bool, list[str], dict]:
97+
# TODO Check if the model indicates when an action is finished.
98+
logger.info("Executing command")
99+
# only translation
100+
# action[3:6] = [0, 0, 0]
101+
# obs, _, _, truncated, info = self.env.step({"xyzrpy": action[:6], "gripper": action[6]})
102+
print("action", action)
103+
obs, _, _, truncated, info = self.env.step(action)
104+
del info["observations"]
105+
print("info", info)
106+
# TODO: ik success from info
107+
return False, obs, info
108+
109+
def loop(self):
110+
# Initialize the environment and obtain the initial observation
111+
obs, _ = self.env.reset()
112+
info = {}
113+
114+
logger.info("Initializing")
115+
obs_dict = self.get_obs(obs)
116+
117+
# img = plt.imshow(obs_dict[CAMERA_GUI])
118+
# plt.show(block=False)
119+
# plt.pause(0.1)
120+
self.remote_agent.reset(obs_dict, instruction=self.instruction)
121+
122+
logger.info("Starting control loop")
123+
while True:
124+
logger.info("Getting action")
125+
obs_dict.info = info
126+
action = self.remote_agent.act(obs_dict)
127+
if action.done:
128+
logger.info("done issues by agent, shutting down")
129+
break
130+
logger.info(f"action issued by agent: {action.action}")
131+
132+
done, obs, info = self.step(action.action)
133+
obs_dict = self.get_obs(obs)
134+
# img.set_data(obs_dict.rgb_side)
135+
# plt.draw()
136+
# plt.pause(0.5)
137+
138+
if done:
139+
break
140+
141+
142+
def main():
143+
if ROBOT_INSTANCE == RobotInstance.HARDWARE:
144+
user, pw = load_creds_fr3_desk()
145+
resource_manger = FCI(Desk(cfg.robot_ip, user, pw), unlock=False, lock_when_done=False, guiding_mode_when_done=True)
146+
else:
147+
resource_manger = DummyResourceManager()
148+
with resource_manger:
149+
150+
if ROBOT_INSTANCE == RobotInstance.HARDWARE:
151+
camera_dict = {
152+
# "wrist": "244222071045",
153+
# "bird_eye": "243522070364",
154+
# "side": "243522070385",
155+
"side": "244222071045",
156+
}
157+
158+
camera_set = default_realsense(camera_dict)
159+
# env = utils.fr3_hw_env(
160+
# ip=cfg.robot_ip,
161+
# camera_set = camera_set,
162+
# control_mode=ControlMode.CARTESIAN_TRPY,
163+
# collision_guard=None,
164+
# gripper=True,
165+
# max_relative_movement=(0.1, np.deg2rad(5)),
166+
# asynchronous=True,
167+
# relative_to=RelativeTo.LAST_STEP,
168+
# )
169+
env = fr3_hw_env(
170+
ip=cfg.robot_ip,
171+
camera_set = camera_set,
172+
robot_cfg=default_fr3_hw_robot_cfg(),
173+
control_mode=ControlMode.CARTESIAN_TRPY,
174+
collision_guard=None,
175+
gripper_cfg=default_fr3_hw_gripper_cfg(),
176+
max_relative_movement=(0.1, np.deg2rad(5)),
177+
relative_to=RelativeTo.LAST_STEP,
178+
)
179+
else:
180+
env = fr3_sim_env(
181+
control_mode=ControlMode.CARTESIAN_TRPY,
182+
robot_cfg=default_fr3_sim_robot_cfg(),
183+
gripper_cfg=default_fr3_sim_gripper_cfg(),
184+
camera_set_cfg=default_mujoco_cameraset_cfg(),
185+
max_relative_movement=(0.5, np.deg2rad(0)),
186+
# mjcf="/home/juelg/code/frankcsy/robot-control-stack/build/_deps/scenes-src/scenes/fr3_empty_world/scene.xml",
187+
mjcf="/home/juelg/code/frankcsy/models/scenes/lab/scene.xml",
188+
relative_to=RelativeTo.LAST_STEP,
189+
)
190+
env.get_wrapper_attr("sim").open_gui()
191+
if not DEBUG:
192+
env = StorageWrapper(env, path="octo_realv1_async", instruction=INSTRUCTION, record_numpy=False)
193+
194+
# record videos
195+
video_path = env.path / "videos"
196+
video_path.mkdir(parents=True, exist_ok=True)
197+
camera_set.record_video(video_path, 0)
198+
199+
env = RHCWrapper(env, exec_horizon=1)
200+
controller = RobotControl(env, INSTRUCTION, cfg.host, cfg.port, cfg.model)
201+
# controller = RobotControl(env, "Pick up the Yellow Brick from the Top", cfg.host, cfg.port, cfg.model)
202+
# controller = RobotControl(env, "Move Yellow Box to the Right", cfg.host, cfg.port, cfg.model)
203+
input("press enter to start")
204+
with env:
205+
controller.loop()
206+
207+
208+
if __name__ == "__main__":
209+
main()

0 commit comments

Comments
 (0)