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