composabl-cli-dev 0.9.0.dev66__cp310-cp310-macosx_10_9_universal2.whl → 0.18.6.dev13__cp310-cp310-macosx_10_9_universal2.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.
Files changed (67) hide show
  1. composabl_cli/cli/__init__.cpython-310-darwin.so +0 -0
  2. composabl_cli/cli/cli.cpython-310-darwin.so +0 -0
  3. composabl_cli/cli/cli_agent.cpython-310-darwin.so +0 -0
  4. composabl_cli/cli/cli_benchmark.cpython-310-darwin.so +0 -0
  5. composabl_cli/cli/cli_debug.cpython-310-darwin.so +0 -0
  6. composabl_cli/cli/cli_historian.cpython-310-darwin.so +0 -0
  7. composabl_cli/cli/cli_job.cpython-310-darwin.so +0 -0
  8. composabl_cli/cli/cli_main.cpython-310-darwin.so +0 -0
  9. composabl_cli/cli/cli_perceptor.cpython-310-darwin.so +0 -0
  10. composabl_cli/cli/cli_selector.cpython-310-darwin.so +0 -0
  11. composabl_cli/cli/cli_sim.cpython-310-darwin.so +0 -0
  12. composabl_cli/cli/cli_skill.cpython-310-darwin.so +0 -0
  13. composabl_cli/cli/cli_version.cpython-310-darwin.so +0 -0
  14. composabl_cli/k8s/k8s_train.cpython-310-darwin.so +0 -0
  15. composabl_cli/k8s/util.cpython-310-darwin.so +0 -0
  16. composabl_cli/main/agent.cpython-310-darwin.so +0 -0
  17. composabl_cli/main/perceptor.cpython-310-darwin.so +0 -0
  18. composabl_cli/main/selector.cpython-310-darwin.so +0 -0
  19. composabl_cli/main/sim.cpython-310-darwin.so +0 -0
  20. composabl_cli/main/skill.cpython-310-darwin.so +0 -0
  21. composabl_cli/template/agent_composabl/agent.py +90 -0
  22. composabl_cli/template/agent_docker/agent.py +99 -0
  23. composabl_cli/template/agent_local/agent.py +96 -0
  24. composabl_cli/template/perceptor/pyproject.toml +4 -1
  25. composabl_cli/template/selector_controller/pyproject.toml +12 -0
  26. composabl_cli/template/selector_controller/{{NAME_MODULE}}/controller.py +52 -0
  27. composabl_cli/template/selector_teacher/README.md +67 -0
  28. composabl_cli/template/{skill_coach → selector_teacher}/pyproject.toml +2 -2
  29. composabl_cli/template/{skill_teacher/my_skill → selector_teacher/{{NAME_MODULE}}}/teacher.py +4 -2
  30. composabl_cli/template/sim/pyproject.toml +1 -1
  31. composabl_cli/template/sim/{my_sim → {{NAME_MODULE}}}/sim.py +13 -26
  32. composabl_cli/template/sim/{my_sim → {{NAME_MODULE}}}/sim_impl.py +2 -2
  33. composabl_cli/template/sim_docker/Dockerfile +45 -0
  34. composabl_cli/template/sim_docker/README.md +17 -0
  35. composabl_cli/template/sim_docker/docker/sim-start.sh +14 -0
  36. composabl_cli/template/sim_docker/main.py +55 -0
  37. composabl_cli/template/sim_docker/module/README.md +39 -0
  38. composabl_cli/template/sim_docker/module/pyproject.toml +20 -0
  39. composabl_cli/template/sim_docker/module/{{NAME_MODULE}}/sim.py +253 -0
  40. composabl_cli/template/sim_docker/module/{{NAME_MODULE}}/sim_impl.py +115 -0
  41. composabl_cli/template/skill_controller/pyproject.toml +1 -1
  42. composabl_cli/template/skill_controller/{{NAME_MODULE}}/__init__.py +3 -0
  43. composabl_cli/template/skill_controller/{my_skill → {{NAME_MODULE}}}/controller.py +6 -4
  44. composabl_cli/template/skill_coordinated_population/README.md +67 -0
  45. composabl_cli/template/skill_coordinated_population/pyproject.toml +12 -0
  46. composabl_cli/template/skill_coordinated_population/{{NAME_MODULE}}/__init__.py +3 -0
  47. composabl_cli/template/{skill_coach/my_skill → skill_coordinated_population/{{NAME_MODULE}}}/coach.py +4 -2
  48. composabl_cli/template/skill_coordinated_set/README.md +67 -0
  49. composabl_cli/template/skill_coordinated_set/pyproject.toml +12 -0
  50. composabl_cli/template/skill_coordinated_set/{{NAME_MODULE}}/__init__.py +3 -0
  51. composabl_cli/template/skill_coordinated_set/{{NAME_MODULE}}/coach.py +70 -0
  52. composabl_cli/template/skill_teacher/pyproject.toml +1 -1
  53. composabl_cli/template/skill_teacher/{{NAME_MODULE}}/__init__.py +3 -0
  54. composabl_cli/template/skill_teacher/{{NAME_MODULE}}/teacher.py +70 -0
  55. {composabl_cli_dev-0.9.0.dev66.dist-info → composabl_cli_dev-0.18.6.dev13.dist-info}/METADATA +12 -8
  56. composabl_cli_dev-0.18.6.dev13.dist-info/RECORD +71 -0
  57. {composabl_cli_dev-0.9.0.dev66.dist-info → composabl_cli_dev-0.18.6.dev13.dist-info}/WHEEL +1 -1
  58. composabl_cli_dev-0.9.0.dev66.dist-info/RECORD +0 -44
  59. /composabl_cli/template/perceptor/{my_perceptor → {{NAME_MODULE}}}/__init__.py +0 -0
  60. /composabl_cli/template/perceptor/{my_perceptor → {{NAME_MODULE}}}/perceptor.py +0 -0
  61. /composabl_cli/template/{skill_coach → selector_controller}/README.md +0 -0
  62. /composabl_cli/template/{sim/my_sim → selector_controller/{{NAME_MODULE}}}/__init__.py +0 -0
  63. /composabl_cli/template/{skill_coach/my_skill → selector_teacher/{{NAME_MODULE}}}/__init__.py +0 -0
  64. /composabl_cli/template/{skill_controller/my_skill → sim/{{NAME_MODULE}}}/__init__.py +0 -0
  65. /composabl_cli/template/{skill_teacher/my_skill → sim_docker/module/{{NAME_MODULE}}}/__init__.py +0 -0
  66. {composabl_cli_dev-0.9.0.dev66.dist-info → composabl_cli_dev-0.18.6.dev13.dist-info}/entry_points.txt +0 -0
  67. {composabl_cli_dev-0.9.0.dev66.dist-info → composabl_cli_dev-0.18.6.dev13.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,17 @@
1
+ # README
2
+
3
+ This is an example of how to build a composabl suitable container yourself for full control.
4
+
5
+ ### Build the Sim
6
+
7
+ To build the sim wrapper, run the following command:
8
+
9
+ ```bash
10
+ docker build -t composabl/sim-demo .
11
+ ```
12
+
13
+ ### Run the Sim
14
+
15
+ ```bash
16
+ docker run --rm -it -p 1337:1337 composabl/sim-demo
17
+ ```
@@ -0,0 +1,14 @@
1
+ #!/bin/bash -e
2
+ ################################################################################
3
+ ## File: sim-start.sh
4
+ ## Desc: Start the Composabl Sim Wrapper
5
+ ################################################################################
6
+ PATH_SIM=${1:-/composabl/sim}
7
+ SIM_CONFIG_JSON=${2:-"{}"}
8
+
9
+ HOST=${HOST:-"0.0.0.0"}
10
+ PORT=${PORT:-"1337"}
11
+
12
+ # Start the Sim Client Wrapper
13
+ echo "$0: Starting the Sim Wrapper"
14
+ python3 /opt/composabl/main.py --path $PATH_SIM --config $SIM_CONFIG_JSON --port $PORT --host $HOST
@@ -0,0 +1,55 @@
1
+ # Copyright (C) Composabl, Inc - All Rights Reserved
2
+ # Unauthorized copying of this file, via any medium is strictly prohibited
3
+ # Proprietary and confidential
4
+
5
+ import argparse
6
+ import os
7
+ from typing import Optional
8
+
9
+ from composabl_core.networking.sim.server import make_from_sim_path
10
+
11
+
12
+ async def _run(
13
+ path: Optional[str] = "./",
14
+ host: Optional[str] = "0.0.0.0",
15
+ port: Optional[int] = 1337,
16
+ protocol: Optional[str] = "grpc",
17
+ config: Optional[dict] = {},
18
+ ):
19
+ """
20
+ Try to run the sim situated in the given location
21
+ """
22
+ path_abs = os.path.abspath(path)
23
+
24
+ print(f"Running sim from path: {path_abs}")
25
+ print(f"Params: {path}, {host}, {port}, {protocol}, {config}")
26
+
27
+ server = make_from_sim_path(path, host, port, config=config, protocol=protocol)
28
+ print(f"Running on {host}:{port}")
29
+
30
+ try:
31
+ await server.start()
32
+ except KeyboardInterrupt:
33
+ print("KeyboardInterrupt, Gracefully stopping the server")
34
+ except Exception as e:
35
+ print(f"Unknown error: {e}, Gracefully stopping the server")
36
+ finally:
37
+ print("Stopping the server")
38
+ if server is not None:
39
+ await server.stop()
40
+
41
+
42
+ if __name__ == "__main__":
43
+ parser = argparse.ArgumentParser()
44
+ parser.add_argument("--path", type=str, default="./")
45
+ parser.add_argument("--host", type=str, default="0.0.0.0")
46
+ parser.add_argument("--port", type=int, default=1337)
47
+ parser.add_argument("--protocol", type=str, default="grpc")
48
+ parser.add_argument("--config", type=str, default="{}")
49
+ args = parser.parse_args()
50
+
51
+ config_parsed = eval(args.config)
52
+
53
+ import asyncio
54
+
55
+ asyncio.run(_run(args.path, args.host, args.port, args.protocol, config_parsed))
@@ -0,0 +1,39 @@
1
+ # README
2
+
3
+ ## Tree Structure
4
+
5
+ The template is structured as follows:
6
+
7
+ ```bash
8
+ my-sim/ # Root folder
9
+ ├── my_sim/ # Main package folder
10
+ │ ├── __init__.py # Package init file
11
+ │ ├── sim_impl.py # Sim Implementation
12
+ │ └── sim.py # Sim Itself
13
+ ├── pyproject.toml # Project configuration, containing [composabl]
14
+ ```
15
+
16
+ ## PyProject [composabl] Section
17
+
18
+ We add the `[composabl]` section to the `pyproject.toml` file to specify the sim we are creating as well as its entrypoint. This is used by the Composabl Sim Container to determine how to start the sim.
19
+
20
+ Example:
21
+
22
+ ```toml
23
+ [composabl]
24
+ type = "sim"
25
+ entrypoint = "my_sim.sim_impl:MySimImpl"
26
+ ```
27
+
28
+ ## Development
29
+
30
+ To work on the Sim, you can simply run `composabl sim run <folder>`. This will do the same but locally.
31
+
32
+ ## Preparing for Upload
33
+
34
+ Once we are ready for uploading, we can create a `.zip` file that contains the version and is prefixed with `composabl-sim-`. This can be done with the following command:
35
+
36
+ ```bash
37
+ # Zip the Sim
38
+ zip -r composabl-sim-demo-0.0.1.zip sim-demo/
39
+ ```
@@ -0,0 +1,20 @@
1
+ [project]
2
+ name = "{{NAME}}"
3
+ version = "0.1.0"
4
+ description = "{{DESCRIPTION}}"
5
+ authors = [{ name = "John Doe", email = "john.doe@composabl.com" }]
6
+ dependencies = [
7
+ "composabl-core"
8
+ ]
9
+
10
+ [composabl]
11
+ type = "sim"
12
+ entrypoint = "{{NAME_MODULE}}.sim_impl:SimImpl"
13
+ dependencies_system = [] # include additional apt-get packages to be installed
14
+
15
+ # Include additional data files
16
+ [tool.setuptools.packages.find]
17
+ where = ["{{NAME_MODULE}}"]
18
+
19
+ [tool.setuptools.package-data]
20
+ "*" = ["*.json", "*.pkl"]
@@ -0,0 +1,253 @@
1
+ # Copyright (C) Composabl, Inc - All Rights Reserved
2
+ # Unauthorized copying of this file, via any medium is strictly prohibited
3
+ # Proprietary and confidential
4
+
5
+ import math
6
+ import random
7
+ from typing import Optional
8
+
9
+ import gymnasium as gym
10
+ import numpy as np
11
+ from composabl_core.agent.scenario import Scenario
12
+
13
+
14
+ class Env(gym.Env):
15
+ def __init__(self):
16
+ self.obs_space_constraints = {
17
+ "x": {"low": -400, "high": 400},
18
+ "x_speed": {"low": -100, "high": 100},
19
+ "y": {"low": 0, "high": 1000},
20
+ "y_speed": {"low": -1000, "high": 1000},
21
+ "angle": {"low": -3.15 * 2, "high": 3.15 * 2},
22
+ "angle_speed": {"low": -3, "high": 3},
23
+ }
24
+
25
+ deg_to_rad = 0.01745329
26
+ self.max_gimble = 20 * deg_to_rad
27
+ self.min_gimble = -self.max_gimble
28
+
29
+ self.action_constraints = {
30
+ "angle": {"low": self.min_gimble, "high": self.max_gimble},
31
+ "thrust": {"low": 0.4, "high": 1},
32
+ }
33
+
34
+ low_list = [x["low"] for x in self.obs_space_constraints.values()]
35
+ high_list = [x["high"] for x in self.obs_space_constraints.values()]
36
+
37
+ self.sensor_space = gym.spaces.Box(
38
+ low=np.array(low_list), high=np.array(high_list)
39
+ )
40
+
41
+ low_act_list = [x["low"] for x in self.action_constraints.values()]
42
+ high_act_list = [x["high"] for x in self.action_constraints.values()]
43
+
44
+ self.action_space = gym.spaces.Box(
45
+ low=np.array(low_act_list), high=np.array(high_act_list)
46
+ )
47
+
48
+ self.state_models = {}
49
+ self.reward_models = {}
50
+ self.scenario: Scenario = None
51
+
52
+ self.x_obs0 = 0
53
+ self.x_speed0 = 0
54
+ self.y_obs0 = 1000
55
+ self.y_speed0 = -80
56
+ self.angle0 = -np.pi / 2
57
+ self.ang_speed0 = 0
58
+
59
+ def starship_simulation(self, x, u):
60
+ g = 9.8
61
+ m = 100000 # kg
62
+ min_thrust = 880 * 1000 # N
63
+ max_thrust = 1 * 2210 * 1000 # kN
64
+
65
+ length = 50 # m
66
+ width = 10
67
+
68
+ # Inertia for a uniform density rod
69
+ I = (1 / 12) * m * length**2
70
+
71
+ deg_to_rad = 0.01745329
72
+
73
+ max_gimble = 20 * deg_to_rad
74
+ min_gimble = -max_gimble
75
+
76
+ theta = x[4]
77
+
78
+ thrust = u[0]
79
+ thrust_angle = u[1]
80
+
81
+ # Horizontal force
82
+ F_x = max_thrust * thrust * math.sin(thrust_angle + theta)
83
+ x_dot = x[1]
84
+ x_dotdot = (F_x) / m
85
+
86
+ # Vertical force
87
+ F_y = max_thrust * thrust * math.cos(thrust_angle + theta)
88
+ y_dot = x[3]
89
+ y_dotdot = (F_y) / m - g
90
+
91
+ # Torque
92
+ T = -length / 2 * max_thrust * thrust * math.sin(thrust_angle)
93
+ theta_dot = x[5]
94
+ theta_dotdot = T / I
95
+
96
+ return [x_dot, x_dotdot, y_dot, y_dotdot, theta_dot, theta_dotdot]
97
+
98
+ def reset(
99
+ self,
100
+ *,
101
+ seed: Optional[int] = None,
102
+ options: Optional[dict] = None,
103
+ x_obs0: float = 0,
104
+ x_speed0: float = 0,
105
+ y_obs0: float = 1000,
106
+ y_speed0: float = -80,
107
+ angle0: float = -np.pi / 2,
108
+ ang_speed0: float = 0
109
+ ):
110
+ """
111
+ # x[0] = x position (m)
112
+ # x[1] = x velocity (m/)
113
+ # x[2] = y position (m)
114
+ # x[3] = y velocity (m/s)
115
+ # x[4] = angle (rad)
116
+ # x[5] = angular velocity (rad/s)
117
+
118
+ # u[0] = thrust (percent)
119
+ # u[1] = thrust angle (rad)
120
+
121
+ """
122
+ super().reset(seed=seed)
123
+ self.cnt = 0
124
+ self.min_thrust = 880 * 1000 # N
125
+ self.max_thrust = 1 * 2210 * 1000 # kN
126
+
127
+ # Define scenario in the simulation ******
128
+ if isinstance(self.scenario, Scenario):
129
+ sample = self.scenario.sample()
130
+
131
+ for key in list(sample.keys()):
132
+ setattr(self, key, sample[key])
133
+
134
+ # Set the number of steps and the timestep (dt)
135
+ steps = 400
136
+ self.t_step = 0.04
137
+ self.cnt = 0
138
+
139
+ self.x = np.zeros((steps + 1, 6))
140
+ self.u = np.zeros((steps + 1, 2))
141
+
142
+ self.x[0, :] = [
143
+ self.x_obs0,
144
+ self.x_speed0,
145
+ self.y_obs0,
146
+ self.y_speed0,
147
+ self.angle0,
148
+ self.ang_speed0,
149
+ ]
150
+ self.x[steps - 1, :] = [0, 0, 0, 0, 0, 0]
151
+
152
+ self.x_obs = self.x[self.cnt, 0]
153
+ self.x_speed = self.x[self.cnt, 1]
154
+ self.y_obs = self.x[self.cnt, 2]
155
+ self.y_speed = self.x[self.cnt, 3]
156
+ self.angle = self.x[self.cnt, 4]
157
+ self.ang_speed = self.x[self.cnt, 5]
158
+
159
+ self.t = 0.4
160
+ self.a = 0
161
+ self.reward_value = 0
162
+
163
+ self.obs = {
164
+ "x": self.x_obs,
165
+ "x_speed": self.x_speed,
166
+ "y": self.y_obs,
167
+ "y_speed": self.y_speed,
168
+ "angle": self.angle,
169
+ "angle_speed": self.ang_speed,
170
+ }
171
+
172
+ self.obs = np.array(list(self.obs.values()))
173
+ info = {}
174
+ return self.obs, info
175
+
176
+ def set_scenario(self, scenario):
177
+ self.scenario = scenario
178
+
179
+ def step(self, action):
180
+ terminated = False
181
+ discount = 0
182
+ reward = 0
183
+
184
+ def sumsqr(lt):
185
+ v = sum([x**2 for x in lt])
186
+ return v
187
+
188
+ angle = action[0]
189
+ thrust = action[1]
190
+
191
+ actuator_noise = 0
192
+ self.t = thrust + random.uniform(
193
+ -actuator_noise * thrust, actuator_noise * thrust
194
+ )
195
+ self.a = angle + random.uniform(-actuator_noise * angle, actuator_noise * angle)
196
+
197
+ self.t = np.clip(self.t, 0.4, 1)
198
+ self.a = np.clip(self.a, self.min_gimble, self.max_gimble)
199
+
200
+ # update u
201
+ self.u[self.cnt, 0] = self.t
202
+ self.u[self.cnt, 1] = self.a
203
+
204
+ res = self.starship_simulation(self.x[self.cnt, :], self.u[self.cnt, :])
205
+ res = [v * self.t_step for v in res]
206
+
207
+ self.x[self.cnt + 1, :] = [
208
+ sum(value) for value in zip(self.x[self.cnt, :], res)
209
+ ]
210
+
211
+ # Increase time
212
+ self.cnt += 1
213
+ # update values
214
+ self.x_obs = self.x[self.cnt, 0]
215
+ self.x_speed = self.x[self.cnt, 1]
216
+ self.y_obs = self.x[self.cnt, 2]
217
+ self.y_speed = self.x[self.cnt, 3]
218
+ self.angle = self.x[self.cnt, 4]
219
+ self.ang_speed = self.x[self.cnt, 5]
220
+
221
+ # update obs with new state values
222
+ self.obs = {
223
+ "x": self.x_obs,
224
+ "x_speed": self.x_speed,
225
+ "y": self.y_obs,
226
+ "y_speed": self.y_speed,
227
+ "angle": self.angle,
228
+ "angle_speed": self.ang_speed,
229
+ }
230
+ # add noise
231
+ for key in list(self.obs.keys()):
232
+ val = float(self.obs[key])
233
+ sensor_noise = 0.0
234
+ self.obs[key] = val + random.uniform(
235
+ -val * sensor_noise, val * sensor_noise
236
+ )
237
+
238
+ # end the simulation
239
+ if self.y_obs < 0:
240
+ terminated = True
241
+ elif (
242
+ not self.obs_space_constraints["x"]["low"]
243
+ <= self.x_obs
244
+ <= self.obs_space_constraints["x"]["high"]
245
+ ):
246
+ terminated = True
247
+
248
+ self.obs = np.array(list(self.obs.values()))
249
+ info = {}
250
+ return self.obs, reward, terminated, False, info
251
+
252
+ def render(self, mode="auto"):
253
+ pass
@@ -0,0 +1,115 @@
1
+ # Copyright (C) Composabl, Inc - All Rights Reserved
2
+ # Unauthorized copying of this file, via any medium is strictly prohibited
3
+ # Proprietary and confidential
4
+
5
+ from typing import Any, Dict, SupportsFloat, Tuple
6
+
7
+ import composabl_core.utils.logger as logger_util
8
+ import gymnasium as gym
9
+ from composabl_core.agent.scenario import Scenario
10
+ from composabl_core.networking.sim.server_composabl import ServerComposabl
11
+ from gymnasium.envs.registration import EnvSpec
12
+
13
+ from .sim import Env
14
+
15
+ logger = logger_util.get_logger(__name__)
16
+
17
+
18
+ class SimImpl(ServerComposabl):
19
+ def __init__(self):
20
+ self.env = Env()
21
+
22
+ async def make(self, env_id: str, env_init: dict) -> EnvSpec:
23
+ """
24
+ Make the environment
25
+
26
+ Args:
27
+ - env_id (str): Environment ID
28
+ - env_init (dict): Environment Initialization
29
+
30
+ Returns:
31
+ - EnvSpec: Environment Specification
32
+ """
33
+ spec = {"id": "starship", "max_episode_steps": 400}
34
+ return spec
35
+
36
+ async def sensor_space_info(self) -> gym.Space:
37
+ """
38
+ Get the sensor space information
39
+
40
+ Returns:
41
+ - Space: Sensor Space in Gymnasium Specification
42
+ """
43
+ return self.env.sensor_space
44
+
45
+ async def action_space_info(self) -> gym.Space:
46
+ """
47
+ Get the action space information
48
+
49
+ Returns:
50
+ - Space: Action Space in Gymnasium Specification
51
+ """
52
+ return self.env.action_space
53
+
54
+ async def action_space_sample(self) -> Any:
55
+ """
56
+ Get the action space sample
57
+
58
+ Returns:
59
+ - List[Any]: A list of samples
60
+ """
61
+ return self.env.action_space.sample()
62
+
63
+ async def reset(self) -> Tuple[Any, Dict[str, Any]]:
64
+ """
65
+ Reset the environment
66
+
67
+ Returns:
68
+ - Tuple[Any, Dict[str, Any]]: The observation and the info
69
+ """
70
+ sensors, info = self.env.reset()
71
+ return sensors, info
72
+
73
+ async def step(
74
+ self, action
75
+ ) -> Tuple[Any, SupportsFloat, bool, bool, Dict[str, Any]]:
76
+ """
77
+ Step the environment
78
+
79
+ Args:
80
+ - action: The action to take
81
+
82
+ Returns:
83
+ - Tuple[Any, SupportsFloat, bool, bool, Dict[str, Any]]: The observation, reward, is_truncated, is_done, info
84
+ """
85
+ return self.env.step(action)
86
+
87
+ async def close(self):
88
+ """
89
+ Close the environment
90
+ """
91
+ self.env.close()
92
+
93
+ async def set_scenario(self, scenario):
94
+ """
95
+ Set the scenario
96
+ """
97
+ self.env.scenario = scenario
98
+
99
+ async def get_scenario(self):
100
+ """
101
+ Get the scenario
102
+ """
103
+ if self.env.scenario is None:
104
+ return Scenario({"dummy": 0})
105
+
106
+ return self.env.scenario
107
+
108
+ async def get_render(self):
109
+ """
110
+ Get the render
111
+
112
+ Args:
113
+ - render_mode: The render mode
114
+ """
115
+ return self.env.get_render_frame()
@@ -4,7 +4,7 @@ version = "0.1.0"
4
4
  description = "{{DESCRIPTION}}"
5
5
  authors = [{ name = "John Doe", email = "john.doe@composabl.com" }]
6
6
  dependencies = [
7
- "composabl-core"
7
+ "composabl-core{{COMPOSABL_DEV}}{{COMPOSABL_CORE_VERSION}}",
8
8
  ]
9
9
 
10
10
  [composabl]
@@ -0,0 +1,3 @@
1
+ # Copyright (C) Composabl, Inc - All Rights Reserved
2
+ # Unauthorized copying of this file, via any medium is strictly prohibited
3
+ # Proprietary and confidential
@@ -2,7 +2,7 @@
2
2
  # Unauthorized copying of this file, via any medium is strictly prohibited
3
3
  # Proprietary and confidential
4
4
 
5
- import math
5
+ from random import randint
6
6
  from typing import Dict, List
7
7
 
8
8
  from composabl_core import SkillController
@@ -19,8 +19,10 @@ class Controller(SkillController):
19
19
  self.counter = 10
20
20
  self.sensor_name = "counter"
21
21
 
22
- async def compute_action(self, transformed_sensors: Dict, action) -> List[bool]:
23
- return None
22
+ async def compute_action(self, transformed_sensors: Dict, action) -> List[float]:
23
+ # generate a random action between -5 and 5
24
+ action = [randint(-5, 5)]
25
+ return action
24
26
 
25
27
  async def compute_success_criteria(self, transformed_sensors: Dict, action) -> bool:
26
28
  return bool(transformed_sensors[self.sensor_name] >= 10)
@@ -35,4 +37,4 @@ class Controller(SkillController):
35
37
  return action
36
38
 
37
39
  async def filtered_sensor_space(self) -> List[str]:
38
- return [self.sensor_name]
40
+ return ["counter"]
@@ -0,0 +1,67 @@
1
+ # README
2
+
3
+ This is a template for creating a new Perceptor. A Perceptor is a component that is responsible for processing data and returning a result. This can be used for example in a Machine Learning model, where the Perceptor is responsible for processing the data and returning the prediction.
4
+
5
+ ## Tree Structure
6
+
7
+ The template is structured as follows:
8
+
9
+ ```bash
10
+ my-perceptor/ # Root folder
11
+ ├── my_perceptor/ # Main package folder
12
+ │ ├── __init__.py # Package init file
13
+ │ └── perceptor.py # Main perceptor file
14
+ ├── pyproject.toml # Project configuration, containing [composabl]
15
+ ```
16
+
17
+ ## PyProject [composabl] Section
18
+
19
+ We add the `[composabl]` section to the `pyproject.toml` file to specify the type of component we are creating as well as its entrypoint. This is used by the Composabl CLI to determine the type of
20
+ component and how to handle it.
21
+
22
+ Example:
23
+
24
+ ```
25
+ [composabl]
26
+ type = "teacher"
27
+ entrypoint = "my_perceptor.perceptor:MyPerceptor"
28
+ ```
29
+
30
+ ## Development
31
+
32
+ To work on the Perceptor, you can simply create a temporary file or main file that starts up and executes the `compute` method of the portable Perceptor. Example, we can create a `test.py` file with:
33
+
34
+ ```python
35
+ from composabl_perceptor_my_perceptor.perceptor import MyPerceptor
36
+
37
+
38
+ async def start():
39
+ p = MyPerceptor()
40
+ res = await t.compute(None, [1.0])
41
+ print(res)
42
+
43
+
44
+ if __name__ == "__main__":
45
+ import asyncio
46
+
47
+ asyncio.run(start())
48
+ ```
49
+
50
+ Which we can then run with
51
+
52
+ ```bash
53
+ # Install the module
54
+ pip install -e my-perceptor
55
+
56
+ # Run the test file
57
+ python my-perceptor/test.py
58
+ ```
59
+
60
+ ### Preparing for Upload
61
+
62
+ Once we are ready for uploading, we can create a `.tar.gz` file that contains the version. This can be done with the following command:
63
+
64
+ ```bash
65
+ # Tar GZ the plugin
66
+ tar -czvf my-perceptor-0.0.1.tar.gz my-perceptor
67
+ ```
@@ -0,0 +1,12 @@
1
+ [project]
2
+ name = "{{NAME}}"
3
+ version = "0.1.0"
4
+ description = "{{DESCRIPTION}}"
5
+ authors = [{ name = "John Doe", email = "john.doe@composabl.com" }]
6
+ dependencies = [
7
+ "composabl-core{{COMPOSABL_DEV}}{{COMPOSABL_CORE_VERSION}}",
8
+ ]
9
+
10
+ [composabl]
11
+ type = "skill-coordinated-population"
12
+ entrypoint = "{{NAME_MODULE}}.coach:Coach"
@@ -0,0 +1,3 @@
1
+ # Copyright (C) Composabl, Inc - All Rights Reserved
2
+ # Unauthorized copying of this file, via any medium is strictly prohibited
3
+ # Proprietary and confidential
@@ -49,7 +49,9 @@ class Coach(SkillCoach):
49
49
  else:
50
50
  return -2 * math.exp(-abs(counter - 10)) + 100
51
51
 
52
- async def compute_action_mask(self, transformed_sensors: Dict, action) -> List[bool]:
52
+ async def compute_action_mask(
53
+ self, transformed_sensors: Dict, action
54
+ ) -> List[bool]:
53
55
  return None
54
56
 
55
57
  async def compute_success_criteria(self, transformed_sensors: Dict, action) -> bool:
@@ -65,4 +67,4 @@ class Coach(SkillCoach):
65
67
  return action
66
68
 
67
69
  async def filtered_sensor_space(self) -> List[str]:
68
- return [self.sensor_name]
70
+ return ["counter"]