nepyope commited on
Commit
e154616
·
verified ·
1 Parent(s): 08ed788

Update env.py

Browse files
Files changed (1) hide show
  1. env.py +71 -51
env.py CHANGED
@@ -1,6 +1,5 @@
1
  # env.py
2
 
3
-
4
  from pathlib import Path
5
  import yaml
6
  from huggingface_hub import snapshot_download
@@ -8,67 +7,53 @@ import os
8
  import gymnasium as gym
9
  from gymnasium import spaces
10
  import numpy as np
11
- snapshot_download(repo_id='lerobot/unitree-g1-mujoco', revision=None, cache_dir=None)
12
 
13
  from sim.simulator_factory import SimulatorFactory, init_channel
14
 
 
 
 
 
15
 
16
- class UnitreeG1SimulationEnvironment:
17
  """
18
- Unitree G1 Simulation Environment for EnvHub.
 
19
  """
20
- def __init__(self, config_path=None):
21
- # Load config
22
- config_path = Path(__file__).parent / "config.yaml"
23
- with open(config_path) as f:
24
- self.config = yaml.safe_load(f)
25
 
 
 
26
 
27
-
28
- # optional cleanup
29
- def close(self):
30
- self.sim.close()
31
-
32
- def make_env(n_envs=1, use_async_envs: bool = False,
33
- publish_images=True, camera_port=5555, cameras=None, **kwargs):
34
- """
35
- Required entrypoint for EnvHub.
36
- Returns an environment instance with running simulator.
37
- """
38
- # Use default values
39
- publish_images = True
40
- camera_port = 5555
41
- cameras = None
42
-
43
- # Load config
44
  config_path = Path(__file__).parent / "config.yaml"
45
  with open(config_path) as f:
46
  config = yaml.safe_load(f)
47
-
48
- # Override config with default values
49
  enable_offscreen = publish_images or config.get("ENABLE_OFFSCREEN", False)
50
-
51
- print("="*60)
52
- print("🤖 Starting Unitree G1 MuJoCo Simulator")
53
- print("="*60)
54
- print(f"📁 Scene: {config['ROBOT_SCENE']}")
55
- print(f"⏱️ Timestep: {config['SIMULATE_DT']}s ({int(1/config['SIMULATE_DT'])} Hz)")
56
- print(f"👁️ Visualization: {'ON' if config.get('ENABLE_ONSCREEN', True) else 'OFF'}")
57
-
58
- # Configure cameras if requested
59
  camera_configs = {}
60
  if enable_offscreen:
61
  camera_list = cameras or ["head_camera"]
62
  for cam_name in camera_list:
63
  camera_configs[cam_name] = {"height": 480, "width": 640}
64
- print(f"📷 Cameras: {', '.join(camera_list)} → ZMQ port {camera_port}")
65
-
66
- print("="*60)
67
-
68
- # Initialize DDS channel
69
  init_channel(config=config)
70
-
71
- # Create simulator
72
  sim = SimulatorFactory.create_simulator(
73
  config=config,
74
  env_name="default",
@@ -76,18 +61,52 @@ def make_env(n_envs=1, use_async_envs: bool = False,
76
  offscreen=enable_offscreen,
77
  camera_configs=camera_configs,
78
  )
79
-
80
- # Start simulator (blocking)
81
- print("\nSimulator running. Press Ctrl+C to exit.")
 
82
  if enable_offscreen and publish_images:
83
- print(f"Camera images publishing on tcp://localhost:{camera_port}")
 
84
  SimulatorFactory.start_simulator(
85
  sim,
86
- as_thread=False,
87
  enable_image_publish=publish_images,
88
  camera_port=camera_port,
89
  )
90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  class DummyEnv(gym.Env):
92
  def __init__(self):
93
  super().__init__()
@@ -102,6 +121,7 @@ def make_env(n_envs=1, use_async_envs: bool = False,
102
  return np.zeros(1, dtype=np.float32), 0.0, False, False, {}
103
 
104
  def run(self):
 
105
  pass
106
-
107
- return DummyEnv()
 
1
  # env.py
2
 
 
3
  from pathlib import Path
4
  import yaml
5
  from huggingface_hub import snapshot_download
 
7
  import gymnasium as gym
8
  from gymnasium import spaces
9
  import numpy as np
 
10
 
11
  from sim.simulator_factory import SimulatorFactory, init_channel
12
 
13
+ # global state to ensure we only start the simulator once per process
14
+ _SIM_STARTED = False
15
+ _SIM_INSTANCE = None
16
+
17
 
18
+ def _launch_simulator_once(publish_images=True, camera_port=5555, cameras=None):
19
  """
20
+ create and start the simulator only once per python process.
21
+ subsequent calls are no-ops and just return the same sim.
22
  """
23
+ global _SIM_STARTED, _SIM_INSTANCE
 
 
 
 
24
 
25
+ if _SIM_STARTED:
26
+ return _SIM_INSTANCE
27
 
28
+ # load config
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  config_path = Path(__file__).parent / "config.yaml"
30
  with open(config_path) as f:
31
  config = yaml.safe_load(f)
32
+
33
+ # override with defaults from make_env
34
  enable_offscreen = publish_images or config.get("ENABLE_OFFSCREEN", False)
35
+
36
+ print("=" * 60)
37
+ print("🤖 starting unitree g1 mujoco simulator")
38
+ print("=" * 60)
39
+ print(f"📁 scene: {config['ROBOT_SCENE']}")
40
+ print(f"⏱️ timestep: {config['SIMULATE_DT']}s ({int(1 / config['SIMULATE_DT'])} hz)")
41
+ print(f"👁️ visualization: {'ON' if config.get('ENABLE_ONSCREEN', True) else 'OFF'}")
42
+
43
+ # configure cameras if requested
44
  camera_configs = {}
45
  if enable_offscreen:
46
  camera_list = cameras or ["head_camera"]
47
  for cam_name in camera_list:
48
  camera_configs[cam_name] = {"height": 480, "width": 640}
49
+ print(f"📷 cameras: {', '.join(camera_list)} → zmq port {camera_port}")
50
+
51
+ print("=" * 60)
52
+
53
+ # init dds channel
54
  init_channel(config=config)
55
+
56
+ # create simulator
57
  sim = SimulatorFactory.create_simulator(
58
  config=config,
59
  env_name="default",
 
61
  offscreen=enable_offscreen,
62
  camera_configs=camera_configs,
63
  )
64
+
65
+ # start simulator in a background thread so make_env can return
66
+ # (if you really want blocking, set as_thread=False and don't return DummyEnv)
67
+ print("\nsimulator running (background thread). press ctrl+c in main script to exit.")
68
  if enable_offscreen and publish_images:
69
+ print(f"camera images publishing on tcp://localhost:{camera_port}")
70
+
71
  SimulatorFactory.start_simulator(
72
  sim,
73
+ as_thread=True,
74
  enable_image_publish=publish_images,
75
  camera_port=camera_port,
76
  )
77
 
78
+ _SIM_STARTED = True
79
+ _SIM_INSTANCE = sim
80
+ return sim
81
+
82
+
83
+ def make_env(
84
+ n_envs=1,
85
+ use_async_envs: bool = False,
86
+ publish_images=True,
87
+ camera_port=5555,
88
+ cameras=None,
89
+ **kwargs,
90
+ ):
91
+ """
92
+ factory used by your runner:
93
+ from env import make_env
94
+ env = make_env()
95
+ calling this multiple times in the same process will NOT start multiple sims.
96
+ """
97
+
98
+ # force defaults if you want
99
+ publish_images = True
100
+ camera_port = 5555
101
+ cameras = None
102
+
103
+ # ensure simulator is running (only once)
104
+ _launch_simulator_once(
105
+ publish_images=publish_images,
106
+ camera_port=camera_port,
107
+ cameras=cameras,
108
+ )
109
+
110
  class DummyEnv(gym.Env):
111
  def __init__(self):
112
  super().__init__()
 
121
  return np.zeros(1, dtype=np.float32), 0.0, False, False, {}
122
 
123
  def run(self):
124
+ # optional: expose sim control here later if you want
125
  pass
126
+
127
+ return DummyEnv()