nepyope commited on
Commit
a91de1d
·
verified ·
1 Parent(s): 58bc650

Update env.py

Browse files
Files changed (1) hide show
  1. env.py +37 -118
env.py CHANGED
@@ -1,65 +1,12 @@
1
- # env.py
2
 
3
  from pathlib import Path
4
- import os
5
  import sys
6
- import errno
7
- import yaml
8
  import gymnasium as gym
9
  from gymnasium import spaces
10
  import numpy as np
11
  from huggingface_hub import snapshot_download
12
-
13
- # Download the full repo and get its path
14
- _REPO_PATH = Path(snapshot_download(repo_id='lerobot/unitree-g1-mujoco', revision=None, cache_dir=None))
15
-
16
- # Add the repo to sys.path so we can import sim module
17
- if str(_REPO_PATH) not in sys.path:
18
- sys.path.insert(0, str(_REPO_PATH))
19
-
20
- from sim.simulator_factory import SimulatorFactory, init_channel
21
-
22
- # lock file shared across processes
23
- _LOCK_PATH = Path.home() / ".unitree_g1_mujoco_sim.lock"
24
-
25
-
26
- def _acquire_lock():
27
- """
28
- try to create a lock file.
29
- returns True if this process acquired the lock (i.e. we should start the sim),
30
- False if some other process already did.
31
- """
32
- try:
33
- fd = os.open(str(_LOCK_PATH), os.O_CREAT | os.O_EXCL | os.O_WRONLY)
34
- os.close(fd)
35
- return True
36
- except OSError as e:
37
- if e.errno == errno.EEXIST:
38
- # lock already exists -> another process started the sim
39
- return False
40
- raise
41
-
42
-
43
- def _release_lock():
44
- try:
45
- _LOCK_PATH.unlink()
46
- except FileNotFoundError:
47
- pass
48
-
49
-
50
- class DummyEnv(gym.Env):
51
- def __init__(self):
52
- super().__init__()
53
- self.action_space = spaces.Box(-1, 1, shape=(1,), dtype=np.float32)
54
- self.observation_space = spaces.Box(-1, 1, shape=(1,), dtype=np.float32)
55
-
56
- def reset(self, seed=None, options=None):
57
- super().reset(seed=seed)
58
- return np.zeros(1, dtype=np.float32), {}
59
-
60
- def step(self, action):
61
- return np.zeros(1, dtype=np.float32), 0.0, False, False, {}
62
-
63
 
64
  def make_env(
65
  n_envs=1,
@@ -70,78 +17,50 @@ def make_env(
70
  **kwargs,
71
  ):
72
  """
73
- first caller (in any process) behaves exactly like run_sim.main():
74
- - loads config
75
- - prints banner
76
- - init_channel
77
- - creates simulator
78
- - starts simulator (blocking, as_thread=False)
79
-
80
- other callers in other processes see the lock and **do not** start the sim again,
81
- they just return DummyEnv().
82
  """
83
- # hard-override to the same defaults as run_sim.py
84
- publish_images = True
85
- camera_port = 5555
86
- cameras = None
87
 
88
- # only the process that acquires the lock starts the simulator
89
- is_owner = _acquire_lock()
90
- if is_owner:
91
- try:
92
- # --- run_sim.py: main() body ---
93
 
94
- config_path = _REPO_PATH / "config.yaml"
95
- with open(config_path) as f:
96
- config = yaml.safe_load(f)
 
97
 
98
- enable_offscreen = publish_images or config.get("ENABLE_OFFSCREEN", False)
 
 
 
 
 
99
 
100
- print("=" * 60)
101
- print("🤖 Starting Unitree G1 MuJoCo Simulator")
102
- print("=" * 60)
103
- print(f"📁 Scene: {config['ROBOT_SCENE']}")
104
- print(f"⏱️ Timestep: {config['SIMULATE_DT']}s ({int(1/config['SIMULATE_DT'])} Hz)")
105
- print(f"👁️ Visualization: {'ON' if config.get('ENABLE_ONSCREEN', True) else 'OFF'}")
106
 
107
- camera_configs = {}
108
- if enable_offscreen:
109
- camera_list = cameras or ["head_camera"]
110
- for cam_name in camera_list:
111
- camera_configs[cam_name] = {"height": 480, "width": 640}
112
- print(f"📷 Cameras: {', '.join(camera_list)} → ZMQ port {camera_port}")
113
 
114
- print("=" * 60)
 
 
 
 
115
 
116
- init_channel(config=config)
 
117
 
118
- sim = SimulatorFactory.create_simulator(
119
- config=config,
120
- env_name="default",
121
- onscreen=config.get("ENABLE_ONSCREEN", True),
122
- offscreen=enable_offscreen,
123
- camera_configs=camera_configs,
124
- )
125
 
126
- print("\nSimulator running. Press Ctrl+C to exit.")
127
- if enable_offscreen and publish_images:
128
- print(f"Camera images publishing on tcp://localhost:{camera_port}")
 
129
 
130
- try:
131
- SimulatorFactory.start_simulator(
132
- sim,
133
- as_thread=False, # blocking, identical to run_sim.py
134
- enable_image_publish=publish_images,
135
- camera_port=camera_port,
136
- )
137
- except KeyboardInterrupt:
138
- print("\nShutting down simulator...")
139
- sim.close()
140
- finally:
141
- _release_lock()
142
- else:
143
- # another process already started the simulator; do nothing here
144
- pass
145
 
146
- # after (or while) the sim is running/exited, return a dummy env
147
- return DummyEnv()
 
 
1
 
2
  from pathlib import Path
3
+ import subprocess
4
  import sys
 
 
5
  import gymnasium as gym
6
  from gymnasium import spaces
7
  import numpy as np
8
  from huggingface_hub import snapshot_download
9
+ snapshot_download(repo_id='lerobot/unitree-g1-mujoco', revision=None, cache_dir=None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  def make_env(
12
  n_envs=1,
 
17
  **kwargs,
18
  ):
19
  """
20
+ just launch run_sim.py as a subprocess (non-blocking)
21
+ then return a dummy gym env.
 
 
 
 
 
 
 
22
  """
 
 
 
 
23
 
24
+ # path to this repo's run_sim.py
25
+ repo_dir = Path(__file__).parent
26
+ run_sim = repo_dir / "run_sim.py"
 
 
27
 
28
+ print("=" * 60)
29
+ print("launching run_sim.py as subprocess")
30
+ print("path:", run_sim)
31
+ print("=" * 60)
32
 
33
+ # subprocess: completely independent simulator
34
+ proc = subprocess.Popen(
35
+ [sys.executable, str(run_sim)],
36
+ stdout=subprocess.PIPE,
37
+ stderr=subprocess.STDOUT,
38
+ )
39
 
40
+ print(f"simulator started as pid={proc.pid}")
 
 
 
 
 
41
 
42
+ # minimal env for envhub
43
+ class DummyEnv(gym.Env):
44
+ metadata = {"render_modes": []}
 
 
 
45
 
46
+ def __init__(self, process):
47
+ super().__init__()
48
+ self.process = process
49
+ self.action_space = spaces.Box(-1, 1, shape=(1,), dtype=np.float32)
50
+ self.observation_space = spaces.Box(-1, 1, shape=(1,), dtype=np.float32)
51
 
52
+ def reset(self, seed=None, options=None):
53
+ return np.zeros(1, dtype=np.float32), {}
54
 
55
+ def step(self, action):
56
+ return np.zeros(1, dtype=np.float32), 0.0, False, False, {}
 
 
 
 
 
57
 
58
+ def close(self):
59
+ if self.process.poll() is None:
60
+ print("terminating simulator subprocess...")
61
+ self.process.terminate()
62
 
63
+ def run(self):
64
+ pass
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
+ return DummyEnv(proc)