Skip to content

Commit 47ad668

Browse files
EAGERx as dependency instead of submodule. (#228)
* EAGERx as dependeny instead of submodule. Docs and demos updated accordingly * Fix typo * Minor fixes * Update test_pep8.py * Loosen pyqglet requirements to solve dependency issue * Loosen pyglet requitement to solve dependency issue * Update dependencies * Update dependencies * Update EAGERx * Fix typo * Add rendering toggle to eagerx demos Co-authored-by: Jelle Luijkx <[email protected]> Co-authored-by: ad-daniel <[email protected]>
1 parent 6113fa2 commit 47ad668

File tree

19 files changed

+316
-195
lines changed

19 files changed

+316
-195
lines changed

Diff for: .gitmodules

-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
11
[submodule "src/opendr/perception/panoptic_segmentation/efficient_ps/algorithm/EfficientPS"]
22
path = src/opendr/perception/panoptic_segmentation/efficient_ps/algorithm/EfficientPS
33
url = https://github.com/DeepSceneSeg/EfficientPS.git
4-
[submodule "src/opendr/utils/eagerx/eagerx"]
5-
path = projects/control/eagerx/eagerx
6-
url = https://github.com/eager-dev/eagerx.git
7-
branch = opendr_v1.0
8-

Diff for: Makefile

-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ install_compilation_dependencies:
3939
@+cd dependencies; ./install_onnx.sh
4040
@+make --silent -C src/opendr/control/mobile_manipulation $(TARGET) OPENDR_HOME="$(OPENDR_HOME)";
4141
@+make --silent -C src/opendr/control/single_demo_grasp $(TARGET) OPENDR_HOME="$(OPENDR_HOME)";
42-
@+make --silent -C projects/control/eagerx $(TARGET) OPENDR_HOME="$(OPENDR_HOME)";
4342

4443
styletest:
4544
@+echo "Testing file licences and code-style"
@@ -77,4 +76,3 @@ help:
7776
@+echo
7877
@+echo -e "\033[32;1mNote:\033[0m You seem to have a processor with $(NUMBER_OF_PROCESSORS) virtual cores,"
7978
@+echo -e " hence the \033[33;1m-j$(THREADS)\033[0m option to speed-up the compilation."
80-

Diff for: docs/reference/eagerx.md

+22-21
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,32 @@ The source code for EAGERx is available [here](https://github.com/eager-dev/eage
2020
Documentation is available online: [https://eagerx.readthedocs.io](https://eagerx.readthedocs.io)
2121

2222

23-
### Examples
23+
### EAGERx Demos
2424

2525
**Prerequisites**: EAGERx requires ROS Noetic and Python 3.8 to be installed.
2626

27-
After installation of the OpenDR toolkit, you can run one of the available examples as follows.
28-
29-
First source the workspace:
30-
27+
1. **[demo_full_state](../../projects/control/eagerx/demos/demo_full_state.py)**:
28+
Here, we wrap the OpenAI gym within EAGERx.
29+
The agent learns to map low-dimensional angular observations to torques.
30+
2. **[demo_pid](../../projects/control/eagerx/demos/demo_pid.py)**:
31+
Here, we add a PID controller, tuned to stabilize the pendulum in the upright position, as a pre-processing node.
32+
The agent now maps low-dimensional angular observations to reference torques.
33+
In turn, the reference torques are converted to torques by the PID controller, and applied to the system.
34+
3. **[demo_classifier](../../projects/control/eagerx/demos/demo_classifier.py)**:
35+
Instead of using low-dimensional angular observations, the environment now produces pixel images of the pendulum.
36+
In order to speed-up learning, we use a pre-trained classifier to convert these pixel images to estimated angular observations.
37+
Then, the agent uses these estimated angular observations similarly as in 'demo_2_pid' to successfully swing-up the pendulum.
38+
39+
Example usage:
3140
```bash
32-
source $OPENDR_HOME/projects/control/eagerx/eagerx_ws/devel/setup.bash
41+
cd $OPENDR_HOME/projects/control/eagerx/demos
42+
python3 [demo_name]
3343
```
3444

35-
Now you can run one of the demos in the terminal where you sourced the workspace:
36-
37-
```bash
38-
source $OPENDR_HOME/projects/control/eagerx/eagerx_ws/devel/setup.bash
39-
rosrun eagerx_example_opendr [demo_name]
40-
```
45+
where possible values for [demo_name] are: *demo_full_state.py*, *demo_pid.py*, *demo_classifier.py*
4146

42-
where possible values for [demo_name] are:
43-
- **demo_1_full_state**: Here, we wrap the OpenAI gym within EAGERx.
44-
The agent learns to map low-dimensional angular observations to torques.
45-
- **demo_2_pid**: Here, we add a PID controller, tuned to stabilize the pendulum in the upright position, as a pre-processing node.
46-
The agent now maps low-dimensional angular observations to reference torques.
47-
In turn, the reference torques are converted to torques by the PID controller, and applied to the system.
48-
- **demo_3_classifier**: Instead of using low-dimensional angular observations, the environment now produces pixel images of the pendulum.
49-
In order to speed-up learning, we use a pre-trained classifier to convert these pixel images to estimated angular observations.
50-
Then, the agent uses these estimated angular observations similarly as in 'demo_2_pid' to successfully swing-up the pendulum.
47+
Setting `--device cpu` performs training and inference on CPU.
48+
Setting `--name example` sets the name of the environment.
49+
Setting `--eps 200` sets the number of training episodes.
50+
Setting `--eval-eps 10` sets the number of evaluation episodes.
51+
Adding `--render` enables rendering of the environment.

Diff for: projects/control/eagerx/Makefile

-39
This file was deleted.

Diff for: projects/control/eagerx/README.md

+31-48
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,49 @@
1-
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
2-
3-
# EAGERx
1+
# EAGERx Demos
42

53
Engine Agnostic Gym Environment with Reactive extension (EAGERx) is a toolkit that will allow users to apply (deep) reinforcement learning for both simulated and real robots as well as combinations thereof.
64
Documentation is available [here](../../../docs/reference/eagerx.md).
75
The source code of EAGERx is available [here](https://github.com/eager-dev/eagerx)
86

9-
### Installation
10-
117
**Prerequisites**: EAGERx requires ROS Noetic and Python 3.8 to be installed.
128

13-
Follow the OpenDR installation instructions.
14-
Next, one should also install the appropriate runtime dependencies:
15-
16-
```bash
17-
cd $OPENDR_HOME
18-
make install_runtime_dependencies
19-
```
20-
21-
Now the user is ready to go!
22-
23-
24-
### Examples
25-
26-
**Prerequisites**: EAGERx requires ROS Noetic and Python 3.8 to be installed.
27-
28-
After installation of the OpenDR toolkit, you can run one of the available examples as follows.
29-
30-
First source the workspace:
31-
32-
```bash
33-
source $OPENDR_HOME/projects/control/eagerx/eagerx_ws/devel/setup.bash
34-
```
35-
36-
Now you can run one of the demos in the terminal where you sourced the workspace:
37-
9+
This folder contains minimal code usage examples that showcase some of EAGERx's features.
10+
Specifically the following examples are provided:
11+
1. **[demo_full_state](demos/demo_full_state.py)**:
12+
Here, we wrap the OpenAI gym within EAGERx.
13+
The agent learns to map low-dimensional angular observations to torques.
14+
2. **[demo_pid](demos/demo_pid.py)**:
15+
Here, we add a PID controller, tuned to stabilize the pendulum in the upright position, as a pre-processing node.
16+
The agent now maps low-dimensional angular observations to reference torques.
17+
In turn, the reference torques are converted to torques by the PID controller, and applied to the system.
18+
3. **[demo_classifier](demos/demo_classifier.py)**:
19+
Instead of using low-dimensional angular observations, the environment now produces pixel images of the pendulum.
20+
In order to speed-up learning, we use a pre-trained classifier to convert these pixel images to estimated angular observations.
21+
Then, the agent uses these estimated angular observations similarly as in 'demo_2_pid' to successfully swing-up the pendulum.
22+
23+
Example usage:
3824
```bash
39-
source $OPENDR_HOME/projects/control/eagerx/eagerx_ws/devel/setup.bash
40-
rosrun eagerx_example_opendr [demo_name]
25+
cd $OPENDR_HOME/projects/control/eagerx/demos
26+
python3 [demo_name]
4127
```
4228

43-
where possible values for [demo_name] are:
44-
- **demo_1_full_state**: Here, we wrap the OpenAI gym within EAGERx.
45-
The agent learns to map low-dimensional angular observations to torques.
46-
- **demo_2_pid**: Here, we add a PID controller, tuned to stabilize the pendulum in the upright position, as a pre-processing node.
47-
The agent now maps low-dimensional angular observations to reference torques.
48-
In turn, the reference torques are converted to torques by the PID controller, and applied to the system.
49-
- **demo_3_classifier**: Instead of using low-dimensional angular observations, the environment now produces pixel images of the pendulum.
50-
In order to speed-up learning, we use a pre-trained classifier to convert these pixel images to estimated angular observations.
51-
Then, the agent uses these estimated angular observations similarly as in 'demo_2_pid' to successfully swing-up the pendulum.
29+
where possible values for [demo_name] are: *demo_full_state.py*, *demo_pid.py*, *demo_classifier.py*
5230

31+
Setting `--device cpu` performs training and inference on CPU.
32+
Setting `--name example` sets the name of the environment.
33+
Setting `--eps 200` sets the number of training episodes.
34+
Setting `--eval-eps 10` sets the number of evaluation episodes.
35+
Adding `--render` enables rendering of the environment.
5336

5437
## Citing EAGERx
5538

5639
To cite EAGERx in publications:
5740
```bibtex
58-
@misc{eagerx,
59-
author = {Van der Heijden, Bas and Luijkx, Jelle},
60-
title = {EAGERx: Engine Agnostic Gym Environment with Reactive extension},
61-
year = {2021},
62-
publisher = {GitHub},
63-
journal = {GitHub repository},
64-
howpublished = {\url{https://github.com/eager-dev/eagerx}},
41+
@article{eagerx,
42+
author = {van der Heijden, Bas and Luijkx, Jelle, and Ferranti, Laura and Kober, Jens and Babuska, Robert},
43+
title = {EAGER: Engine Agnostic Gym Environment for Robotics},
44+
year = {2022},
45+
publisher = {GitHub},
46+
journal = {GitHub repository},
47+
howpublished = {\url{https://github.com/eager-dev/eagerx}}
6548
}
6649
```

Diff for: projects/control/eagerx/data/with_actions.h5

27.3 MB
Binary file not shown.

Diff for: projects/control/eagerx/demos/__init__.py

Whitespace-only changes.

Diff for: projects/control/eagerx/demos/demo_classifier.py

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/usr/bin/env python
2+
# Copyright 2020-2022 OpenDR European Project
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
import argparse
17+
18+
# EAGERx imports
19+
from eagerx import Object, Bridge, Node, initialize, log
20+
from eagerx.core.graph import Graph
21+
import eagerx.bridges.openai_gym as eagerx_gym
22+
import eagerx_examples # noqa: F401
23+
24+
# Import stable-baselines
25+
import stable_baselines3 as sb
26+
27+
28+
def example_classifier(name, eps, eval_eps, device, render=False):
29+
# Start roscore & initialize main thread as node
30+
initialize("eagerx", anonymous=True, log_level=log.INFO)
31+
32+
# Define object
33+
pendulum = Object.make(
34+
"GymObject",
35+
"pendulum",
36+
sensors=["image", "observation", "reward", "done"],
37+
gym_env_id="Pendulum-v0",
38+
gym_rate=20,
39+
gym_always_render=True,
40+
render_shape=[28, 28],
41+
)
42+
43+
# Define PID controller & classifier
44+
classifier = Node.make("Classifier", "classifier", rate=20, cam_rate=20, data="../data/with_actions.h5")
45+
pid = Node.make("PidController", "pid", rate=20, gains=[8, 1, 0], y_range=[-4, 4])
46+
47+
# Define graph (agnostic) & connect nodes
48+
graph = Graph.create(nodes=[classifier, pid], objects=[pendulum])
49+
graph.connect(source=pendulum.sensors.reward, observation="reward")
50+
graph.connect(source=pendulum.sensors.done, observation="done")
51+
graph.connect(source=classifier.outputs.state, observation="state")
52+
# Connect Classifier
53+
graph.connect(source=classifier.outputs.state, target=pid.inputs.y)
54+
graph.connect(source=pendulum.sensors.image, target=classifier.inputs.image)
55+
# Connect PID
56+
graph.connect(action="yref", target=pid.inputs.yref)
57+
graph.connect(source=pid.outputs.u, target=pendulum.actuators.action)
58+
# Add rendering
59+
if render:
60+
graph.render(source=pendulum.sensors.image, rate=10, display=True)
61+
62+
# Define bridge
63+
bridge = Bridge.make("GymBridge", rate=20)
64+
65+
# Initialize Environment (agnostic graph + bridge)
66+
env = eagerx_gym.EagerGym(name=name, rate=20, graph=graph, bridge=bridge)
67+
if render:
68+
env.render(mode='human')
69+
70+
# Initialize and train stable-baselines model
71+
model = sb.SAC("MlpPolicy", env, verbose=1, device=device)
72+
model.learn(total_timesteps=int(eps * 200))
73+
74+
# Evaluate trained policy
75+
for i in range(eval_eps):
76+
obs, done = env.reset(), False
77+
while not done:
78+
action, _ = model.predict(obs, deterministic=True)
79+
action = env.action_space.sample()
80+
obs, reward, done, info = env.step(action)
81+
env.shutdown()
82+
83+
84+
if __name__ == "__main__":
85+
parser = argparse.ArgumentParser()
86+
parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cpu", choices=["cuda", "cpu"])
87+
parser.add_argument("--name", help="Name of the environment", type=str, default="example")
88+
parser.add_argument("--eps", help="Number of training episodes", type=int, default=200)
89+
parser.add_argument("--eval_eps", help="Number of evaluation episodes", type=int, default=20)
90+
parser.add_argument("--render", help="Toggle rendering", action='store_true')
91+
92+
args = parser.parse_args()
93+
94+
example_classifier(name=args.name, eps=args.eps, eval_eps=args.eval_eps, device=args.device, render=args.render)

Diff for: projects/control/eagerx/demos/demo_full_state.py

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#!/usr/bin/env python
2+
# Copyright 2020-2022 OpenDR European Project
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
import argparse
17+
18+
# EAGERx imports
19+
from eagerx import Object, Bridge, initialize, log
20+
from eagerx.core.graph import Graph
21+
import eagerx.bridges.openai_gym as eagerx_gym
22+
import eagerx_examples # noqa: F401
23+
24+
# Import stable-baselines
25+
import stable_baselines3 as sb
26+
27+
28+
def example_full_state(name, eps, eval_eps, device, render=False):
29+
# Start roscore & initialize main thread as node
30+
initialize("eagerx", anonymous=True, log_level=log.INFO)
31+
32+
# Define object
33+
sensors = ["observation", "reward", "done"]
34+
if render:
35+
sensors.append("image")
36+
pendulum = Object.make("GymObject", "pendulum", sensors=sensors, gym_env_id="Pendulum-v0", gym_rate=20)
37+
38+
# Define graph (agnostic) & connect nodes
39+
graph = Graph.create(objects=[pendulum])
40+
graph.connect(source=pendulum.sensors.observation, observation="observation", window=1)
41+
graph.connect(source=pendulum.sensors.reward, observation="reward", window=1)
42+
graph.connect(source=pendulum.sensors.done, observation="done", window=1)
43+
graph.connect(action="action", target=pendulum.actuators.action, window=1)
44+
if render:
45+
graph.render(source=pendulum.sensors.image, rate=10, display=False)
46+
47+
# Define bridge
48+
bridge = Bridge.make("GymBridge", rate=20)
49+
50+
# Initialize Environment (agnostic graph + bridge)
51+
env = eagerx_gym.EagerGym(name=name, rate=20, graph=graph, bridge=bridge)
52+
if render:
53+
env.render(mode='human')
54+
55+
# Initialize and train stable-baselines model
56+
model = sb.SAC("MlpPolicy", env, verbose=1, device=device)
57+
model.learn(total_timesteps=int(eps * 200))
58+
59+
# Evaluate trained policy
60+
for i in range(eval_eps):
61+
obs, done = env.reset(), False
62+
while not done:
63+
action, _ = model.predict(obs, deterministic=True)
64+
obs, reward, done, info = env.step(action)
65+
env.shutdown()
66+
67+
68+
if __name__ == "__main__":
69+
parser = argparse.ArgumentParser()
70+
parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cpu", choices=["cuda", "cpu"])
71+
parser.add_argument("--name", help="Name of the environment", type=str, default="example")
72+
parser.add_argument("--eps", help="Number of training episodes", type=int, default=200)
73+
parser.add_argument("--eval_eps", help="Number of evaluation episodes", type=int, default=20)
74+
parser.add_argument("--render", help="Toggle rendering", action='store_true')
75+
76+
args = parser.parse_args()
77+
78+
example_full_state(name=args.name, eps=args.eps, eval_eps=args.eval_eps, device=args.device, render=args.render)

0 commit comments

Comments
 (0)