humalab 0.0.4__py3-none-any.whl → 0.0.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of humalab might be problematic. Click here for more details.

Files changed (39) hide show
  1. humalab/__init__.py +11 -0
  2. humalab/assets/__init__.py +2 -2
  3. humalab/assets/files/resource_file.py +29 -3
  4. humalab/assets/files/urdf_file.py +14 -10
  5. humalab/assets/resource_operator.py +91 -0
  6. humalab/constants.py +39 -5
  7. humalab/dists/bernoulli.py +16 -0
  8. humalab/dists/categorical.py +4 -0
  9. humalab/dists/discrete.py +22 -0
  10. humalab/dists/gaussian.py +22 -0
  11. humalab/dists/log_uniform.py +22 -0
  12. humalab/dists/truncated_gaussian.py +36 -0
  13. humalab/dists/uniform.py +22 -0
  14. humalab/episode.py +196 -0
  15. humalab/humalab.py +116 -153
  16. humalab/humalab_api_client.py +760 -62
  17. humalab/humalab_config.py +0 -13
  18. humalab/humalab_test.py +46 -29
  19. humalab/metrics/__init__.py +5 -5
  20. humalab/metrics/code.py +28 -0
  21. humalab/metrics/metric.py +41 -108
  22. humalab/metrics/scenario_stats.py +95 -0
  23. humalab/metrics/summary.py +24 -18
  24. humalab/run.py +180 -115
  25. humalab/scenarios/__init__.py +4 -0
  26. humalab/scenarios/scenario.py +372 -0
  27. humalab/scenarios/scenario_operator.py +82 -0
  28. humalab/{scenario_test.py → scenarios/scenario_test.py} +150 -269
  29. humalab/utils.py +37 -0
  30. {humalab-0.0.4.dist-info → humalab-0.0.6.dist-info}/METADATA +1 -1
  31. humalab-0.0.6.dist-info/RECORD +39 -0
  32. humalab/assets/resource_manager.py +0 -57
  33. humalab/metrics/dist_metric.py +0 -22
  34. humalab/scenario.py +0 -225
  35. humalab-0.0.4.dist-info/RECORD +0 -34
  36. {humalab-0.0.4.dist-info → humalab-0.0.6.dist-info}/WHEEL +0 -0
  37. {humalab-0.0.4.dist-info → humalab-0.0.6.dist-info}/entry_points.txt +0 -0
  38. {humalab-0.0.4.dist-info → humalab-0.0.6.dist-info}/licenses/LICENSE +0 -0
  39. {humalab-0.0.4.dist-info → humalab-0.0.6.dist-info}/top_level.txt +0 -0
humalab/humalab.py CHANGED
@@ -1,217 +1,180 @@
1
1
  from contextlib import contextmanager
2
+ import sys
3
+ import traceback
2
4
 
3
- from humalab.assets.files.resource_file import ResourceFile
4
- from humalab.assets.files.urdf_file import URDFFile
5
- from humalab.assets.resource_manager import ResourceManager
5
+ from omegaconf import OmegaConf
6
+
7
+ from humalab.constants import DEFAULT_PROJECT
6
8
  from humalab.run import Run
7
9
  from humalab.humalab_config import HumalabConfig
8
- from humalab.humalab_api_client import HumaLabApiClient
9
- from humalab.constants import EpisodeStatus
10
+ from humalab.humalab_api_client import HumaLabApiClient, RunStatus, EpisodeStatus
11
+ import requests
10
12
 
11
13
  import uuid
12
- import os
13
14
 
14
15
  from collections.abc import Generator
15
16
 
16
- from humalab.scenario import Scenario
17
+ from humalab.scenarios.scenario import Scenario
17
18
 
18
19
  _cur_run: Run | None = None
19
20
 
20
21
  def _pull_scenario(client: HumaLabApiClient,
22
+ project: str,
21
23
  scenario: str | list | dict | None = None,
22
24
  scenario_id: str | None = None,) -> str | list | dict | None:
23
25
  if scenario_id is not None:
24
- scenario_response = client.get_scenario(uuid=scenario_id)
26
+ scenario_arr = scenario_id.split(":")
27
+ if len(scenario_arr) < 1:
28
+ raise ValueError("Invalid scenario_id format. Expected 'scenario_id' or 'scenario_name:version'.")
29
+ scenario_real_id = scenario_arr[0]
30
+ scenario_version = int(scenario_arr[1]) if len(scenario_arr) > 1 else None
31
+
32
+ scenario_response = client.get_scenario(
33
+ project_name=project,
34
+ uuid=scenario_real_id, version=scenario_version)
25
35
  return scenario_response["yaml_content"]
26
36
  return scenario
27
37
 
28
38
  @contextmanager
29
- def init(entity: str | None = None,
30
- project: str | None = None,
39
+ def init(project: str | None = None,
31
40
  name: str | None = None,
32
41
  description: str | None = None,
33
42
  id: str | None = None,
34
43
  tags: list[str] | None = None,
35
44
  scenario: str | list | dict | None = None,
36
45
  scenario_id: str | None = None,
46
+ seed: int | None=None,
47
+ auto_create_scenario: bool = False,
48
+ # num_env: int | None = None,
49
+
37
50
  base_url: str | None = None,
38
51
  api_key: str | None = None,
39
- seed: int | None=None,
40
52
  timeout: float | None = None,
41
- num_env: int | None = None
42
53
  ) -> Generator[Run, None, None]:
54
+ """
55
+ Initialize a new HumaLab run.
56
+
57
+ Args:
58
+ project: The project name under which to create the run.
59
+ name: The name of the run.
60
+ description: A description of the run.
61
+ id: The unique identifier for the run. If None, a new UUID will be generated.
62
+ tags: A list of tags to associate with the run.
63
+ scenario: The scenario configuration as a string, list, or dict.
64
+ scenario_id: The unique identifier of a pre-defined scenario to use.
65
+ base_url: The base URL of the HumaLab server.
66
+ api_key: The API key for authentication.
67
+ seed: An optional seed for scenario randomization.
68
+ timeout: The timeout for API requests.
69
+ auto_create_scenario: Whether to automatically create the scenario if it does not exist.
70
+ # num_env: The number of parallel environments to run. (Not supported yet.)
71
+ """
43
72
  global _cur_run
44
73
  run = None
45
74
  try:
46
- humalab_config = HumalabConfig()
47
- entity = entity or humalab_config.entity
48
- project = project or "default"
75
+ project = project or DEFAULT_PROJECT
49
76
  name = name or ""
50
77
  description = description or ""
51
78
  id = id or str(uuid.uuid4())
52
79
 
53
- base_url = base_url or humalab_config.base_url
54
- api_key = api_key or humalab_config.api_key
55
- timeout = timeout or humalab_config.timeout
56
-
57
80
  api_client = HumaLabApiClient(base_url=base_url,
58
81
  api_key=api_key,
59
82
  timeout=timeout)
60
83
  final_scenario = _pull_scenario(client=api_client,
84
+ project=project,
61
85
  scenario=scenario,
62
86
  scenario_id=scenario_id)
87
+
88
+ project_resp = api_client.create_project(name=project)
89
+
63
90
  scenario_inst = Scenario()
64
- scenario_inst.init(run_id=id,
65
- scenario=final_scenario,
91
+ scenario_inst.init(scenario=final_scenario,
66
92
  seed=seed,
67
- episode_id=str(uuid.uuid4()),
68
- num_env=num_env)
93
+ scenario_id=scenario_id,
94
+ #num_env=num_env,
95
+ )
96
+ if scenario_id is None and scenario is not None and auto_create_scenario:
97
+ scenario_response = api_client.create_scenario(
98
+ project_name=project_resp['name'],
99
+ name=f"{name} scenario",
100
+ description="Auto-created scenario",
101
+ yaml_content=OmegaConf.to_yaml(scenario_inst.template),
102
+ )
103
+ scenario_id = scenario_response['uuid']
104
+ try:
105
+ run_response = api_client.get_run(run_id=id)
106
+ api_client.update_run(
107
+ run_id=run_response['run_id'],
108
+ name=name,
109
+ description=description,
110
+ tags=tags,
111
+ status=RunStatus.RUNNING,
112
+ )
113
+
114
+ except requests.HTTPError as e:
115
+ if e.response.status_code == 404:
116
+ # If not found then create a new run,
117
+ # so ignore not found error.
118
+ run_response = None
119
+ else:
120
+ # Otherwise re-raise the exception.
121
+ raise
122
+
123
+ if run_response is None:
124
+ run_response = api_client.create_run(name=name,
125
+ project_name=project_resp['name'],
126
+ description=description,
127
+ tags=tags)
128
+ id = run_response['run_id']
129
+ api_client.update_run(
130
+ run_id=id,
131
+ description=description,
132
+ )
69
133
 
70
134
  run = Run(
71
- entity=entity,
72
- project=project,
73
- name=name,
74
- description=description,
75
- id=id,
76
- tags=tags,
135
+ project=project_resp['name'],
136
+ name=run_response["name"],
137
+ description=run_response.get("description"),
138
+ id=run_response['run_id'],
139
+ tags=run_response.get("tags"),
77
140
  scenario=scenario_inst,
141
+
142
+ base_url=base_url,
143
+ api_key=api_key,
144
+ timeout=timeout
78
145
  )
146
+
79
147
  _cur_run = run
80
148
  yield run
81
- finally:
82
- if run:
83
- run.finish()
84
-
85
-
86
- def finish(status: EpisodeStatus = EpisodeStatus.PASS,
87
- quiet: bool | None = None) -> None:
149
+ except Exception as e:
150
+ if _cur_run:
151
+ exc_type, exc_value, exc_traceback = sys.exc_info()
152
+ formatted_traceback = ''.join(traceback.format_exception(exc_type, exc_value, exc_traceback))
153
+ finish(status=RunStatus.ERRORED,
154
+ err_msg=formatted_traceback)
155
+ raise
156
+ else:
157
+ if _cur_run:
158
+ print("Finishing run...")
159
+ finish(status=RunStatus.FINISHED)
160
+
161
+ def discard() -> None:
162
+ finish(status=RunStatus.CANCELED)
163
+
164
+ def finish(status: RunStatus = RunStatus.FINISHED,
165
+ err_msg: str | None = None) -> None:
88
166
  global _cur_run
89
167
  if _cur_run:
90
- _cur_run.finish(status=status, quiet=quiet)
168
+ _cur_run.finish(status=status, err_msg=err_msg)
169
+ _cur_run = None
91
170
 
92
171
  def login(api_key: str | None = None,
93
172
  relogin: bool | None = None,
94
173
  host: str | None = None,
95
174
  force: bool | None = None,
96
175
  timeout: float | None = None) -> bool:
97
- # TODO: Validate api_key against host given.
98
- # and retrieve entity information.
99
176
  humalab_config = HumalabConfig()
100
177
  humalab_config.api_key = api_key or humalab_config.api_key
101
178
  humalab_config.base_url = host or humalab_config.base_url
102
179
  humalab_config.timeout = timeout or humalab_config.timeout
103
180
  return True
104
-
105
-
106
- if __name__ == "__main__":
107
- login(api_key="GSdIImnRJs1TQRpkN74PyIVHhX8_PISLOI9NVF6uO94",
108
- host="http://localhost:8000")
109
-
110
- with init(entity="default",
111
- project="test",
112
- name="my first run",
113
- description="testing the humalab sdk",
114
- tags=["tag1", "tag2"],
115
- scenario_id="cb9668c6-99fe-490c-a97c-e8c1f06b54a6",
116
- num_env=None) as run:
117
- print(f"Run ID: {run.id}")
118
- print(f"Run Name: {run.name}")
119
- print(f"Run Description: {run.description}")
120
- print(f"Run Tags: {run.tags}")
121
- print(f"Run Scenario YAML:\n{run.scenario.yaml}")
122
-
123
- scenario = run.scenario
124
- # Simulate some operations
125
- print("CUP position: ", scenario.scenario.cup.position)
126
- print("CUP orientation: ", scenario.scenario.cup.orientation)
127
- print("Asset: ", scenario.scenario.cup.asset)
128
- print("Friction: ", scenario.scenario.cup.friction)
129
- print("Num Objects: ", scenario.scenario.num_objects)
130
- scenario.reset()
131
- print("======================SCENARIO RESET==========================")
132
- print("CUP position: ", scenario.scenario.cup.position)
133
- print("CUP orientation: ", scenario.scenario.cup.orientation)
134
- print("Asset: ", scenario.scenario.cup.asset)
135
- print("Friction: ", scenario.scenario.cup.friction)
136
- print("Num Objects: ", scenario.scenario.num_objects)
137
-
138
- scenario_string = """
139
- scenario:
140
- cup:
141
- position: "${uniform: [0.7, 0.7, 0.7],
142
- [1.5, 1.3, 0.7], [2, 3]}"
143
- orientation: "${uniform: 0.3, 0.7}"
144
- asset: "${categorical: ['lerobot', 'apple2', 'apple3'], [0.1, 0.3, 0.5]}"
145
- friction: "${gaussian: 0.3, 0.05}"
146
- hello: 13
147
- jkjk: test
148
- num_objects: "${discrete: 5, 10}"
149
- dfdjkjk: "hello"
150
- """
151
- with init(entity="default",
152
- project="test",
153
- name="my first run",
154
- description="testing the humalab sdk",
155
- tags=["tag1", "tag2"],
156
- scenario=scenario_string,
157
- num_env=None) as run:
158
- print(f"Run ID: {run.id}")
159
- print(f"Run Name: {run.name}")
160
- print(f"Run Description: {run.description}")
161
- print(f"Run Tags: {run.tags}")
162
- print(f"Run Scenario YAML:\n{run.scenario.yaml}")
163
-
164
- scenario = run.scenario
165
- # Simulate some operations
166
- print("CUP position: ", scenario.scenario.cup.position)
167
- print("CUP orientation: ", scenario.scenario.cup.orientation)
168
- print("Asset: ", scenario.scenario.cup.asset)
169
- print("Friction: ", scenario.scenario.cup.friction)
170
- print("Num Objects: ", scenario.scenario.num_objects)
171
- scenario.reset()
172
- print("======================SCENARIO RESET==========================")
173
- print("CUP position: ", scenario.scenario.cup.position)
174
- print("CUP orientation: ", scenario.scenario.cup.orientation)
175
- print("Asset: ", scenario.scenario.cup.asset)
176
- print("Friction: ", scenario.scenario.cup.friction)
177
- print("Num Objects: ", scenario.scenario.num_objects)
178
-
179
- resource = ResourceManager()
180
- urdf_file: URDFFile = resource.download(name="lerobot", version=1)
181
- print("URDF File: ", urdf_file.filename)
182
- print("URDF Description: ", urdf_file.description)
183
- print("URDF Created At: ", urdf_file.created_at)
184
- print("URDF Root Path: ", urdf_file._root_path)
185
- print("URDF Root Path: ", urdf_file._urdf_filename)
186
-
187
- urdf_file: URDFFile = resource.download(name="lerobot")
188
- print("URDF File: ", urdf_file.filename)
189
- print("URDF Description: ", urdf_file.description)
190
- print("URDF Created At: ", urdf_file.created_at)
191
- print("URDF Root Path: ", urdf_file._root_path)
192
- print("URDF Root Path: ", urdf_file._urdf_filename)
193
-
194
- atlas_file: ResourceFile = resource.download(name="atlas_description_test")
195
- print("Atlas File: ", atlas_file.filename)
196
- print("Atlas Description: ", atlas_file.description)
197
- print("Atlas Created At: ", atlas_file.created_at)
198
-
199
-
200
- """
201
- humalab_config = HumalabConfig()
202
- base_url = humalab_config.base_url
203
- api_key = humalab_config.api_key
204
- timeout = humalab_config.timeout
205
-
206
- api_client = HumaLabApiClient(base_url=base_url,
207
- api_key=api_key,
208
- timeout=timeout)
209
- resource = api_client.get_resource(name="lerobot", version=1)
210
- print("Resource metadata: ", resource)
211
- file_content = api_client.download_resource(name="lerobot")
212
- filename = os.path.basename(resource['resource_url'])
213
- filename = os.path.join(humalab_config.workspace_path, filename)
214
- with open(filename, "wb") as f:
215
- f.write(file_content)
216
- print(f"Resource file downloaded: {filename}")
217
- """