Skip to content

Commit f62c27d

Browse files
Automatic download of TmrlData when missing
1 parent 19d776f commit f62c27d

File tree

8 files changed

+170
-33
lines changed

8 files changed

+170
-33
lines changed

readme/Install.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Prerequisites
22
* Windows / Linux
33
* Python >= 3.7
4-
* A recent NVIDIA GPU (required only on the training computer if you plan to train your own AI)
4+
* A recent NVIDIA GPU (required only on the training computer if you plan to train your own models)
55

66
#### If using Anaconda on Windows:
77

@@ -47,6 +47,13 @@ To install the `tmrl` python library, open your favorite terminal and run:
4747
```shell
4848
pip install tmrl
4949
```
50+
51+
Then, validate the installation:
52+
53+
```shell
54+
python -m tmrl --install
55+
```
56+
5057
#### Additional information for Windows / Trackmania 2020:
5158

5259
If running on Windows, during the installation, a driver will be installed to emulate a virtual gamepad.
@@ -74,6 +81,8 @@ If at some point you want to do a clean re-install of `tmrl`:
7481
- Delete the `TmrlData` folder from your home folder
7582
- `pip install tmrl`
7683

84+
## Set up TMRL
85+
7786
### (Optional) Configure/manage TMRL:
7887

7988
The `TmrlData` folder is your _"control pannel"_, it contains everything `tmrl` uses and generates:
@@ -95,6 +104,15 @@ In particular, you may want to adapt the following entries:
95104

96105
You can delete the content of all folders (but not the folders themselves) whenever you like (except `config.json`, a default version is provided in `resources` if you delete this).
97106

107+
To reset the library, delete the entire `TmrlData` folder and run:
108+
109+
```shell
110+
python -m tmrl --install
111+
```
112+
113+
This will download and extract the `TmrlData` folder back to its original state.
114+
115+
98116
### (Optional) Check that everything works:
99117

100118
Launch TrackMania 2020, launch a track, then press `f3` to open the OpenPlanet menu, open the logs by clicking `OpenPlanet > Log`, and in the OpenPlanet menu click `Developer > (Re)load plugin > TMRL Grab Data`.

readme/install_linux.md

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,13 @@ Open a terminal and run:
7474
```bash
7575
pip3 install tmrl
7676
```
77-
This installs the `tmrl` library in your active python environment and creates a `TmrlData` folder in your home directory.
77+
78+
Validate:
79+
```bash
80+
python -m tmrl --install
81+
```
82+
83+
The `tmrl` library is now installed in your active python environment and has created a `TmrlData` folder in your home directory.
7884

7985
Navigate to your TrackMania Proton folder:
8086

@@ -94,30 +100,4 @@ cp ~/TmrlData/resources/tmrl-test.Map.Gbx Documents/Trackmania/Maps/My Maps/.
94100

95101
## Set up `tmrl`
96102

97-
98-
### Configure/manage TMRL:
99-
100-
The `TmrlData` folder is your _"control pannel"_, it contains everything `tmrl` uses and generates:
101-
- The `checkpoints` subfolder is used by the trainer process: it contains persistent checkpoints of your training,
102-
- The `weights` subfolder is used by the worker process: it contains snapshots of your trained policies,
103-
- The `reward` subfolder is used by the worker process: it contains your reward function,
104-
- The `dataset` subfolder is for RL developers (to use with custom replay buffers),
105-
- The `config` subfolder contains a configuration file that you probably want to tweak.
106-
107-
Navigate to `TmrlData\config` and open `config.json` in a text editor.
108-
109-
In particular, you may want to adapt the following entries:
110-
- `RUN_NAME`: set a new name for starting training from scratch
111-
- `LOCALHOST_WORKER`: set to `false` for `workers` not on the same computer as the `server`
112-
- `LOCALHOST_TRAINER`: set to `false` for `trainer` not on the same computer as the `server`
113-
- `PUBLIC_IP_SERVER`: public IP of the `server` if not running on localhost
114-
- `PORT` needs to be forwarded on the `server` if not running on localhost
115-
- `WANDB_PROJECT`, `WANDB_ENTITY` and `WANDB_KEY` can be replaced by you own [wandb](https://wandb.ai/site) credentials for monitoring training
116-
117-
You can delete the content of all folders (but not the folders themselves) whenever you like (except `config.json`, a default version is provided in `resources` if you delete this).
118-
119-
### Check that everything works:
120-
121-
Launch TrackMania 2020, launch a track, then press `f3` to open the OpenPlanet menu, open the logs by clicking `OpenPlanet > Log`, and in the OpenPlanet menu click `Developer > (Re)load plugin > TMRL Grab Data`.
122-
You should see a message like "waiting for incoming connection" appear in the logs.
123-
Press `f3` again to close the menu.
103+
Find out how to configure the library [here](Install.md#set-up-tmrl).

setup.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
sys.exit('Sorry, Python < 3.7 is not supported.')
1414

1515

16+
# NB: the following code is duplicated under tmrl.tools.init_package.init_tmrl,
17+
# don't forget to update both whenever changing RESOURCES_URL.
18+
19+
1620
RESOURCES_URL = "https://github.com/trackmania-rl/tmrl/releases/download/v0.6.0/resources.zip"
1721

1822

@@ -133,13 +137,13 @@ def url_retrieve(url: str, outfile: Path, overwrite: bool = False):
133137

134138
setup(
135139
name='tmrl',
136-
version='0.6.1',
140+
version='0.6.2',
137141
description='Network-based framework for real-time robot learning',
138142
long_description=README,
139143
long_description_content_type='text/markdown',
140144
keywords='reinforcement learning, robot learning, trackmania, self driving, roborace',
141145
url='https://github.com/trackmania-rl/tmrl',
142-
download_url='https://github.com/trackmania-rl/tmrl/archive/refs/tags/v0.6.1.tar.gz',
146+
download_url='https://github.com/trackmania-rl/tmrl/archive/refs/tags/v0.6.2.tar.gz',
143147
author='Yann Bouteiller, Edouard Geze',
144148
145149
license='MIT',

tmrl/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
\nPlease install pywin32 manually.")
2626
raise RuntimeError("Please install pywin32 manually: https://github.com/mhammond/pywin32")
2727

28+
# TMRL folder initialization:
29+
from tmrl.tools.init_package.init_tmrl import TMRL_FOLDER
2830

2931
# do not remove this
3032
from dataclasses import dataclass

tmrl/__main__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,15 @@ def main(args):
6363
check_env_tm20lidar()
6464
else:
6565
check_env_tm20full()
66+
elif args.install:
67+
logging.info(f"TMRL folder: {cfg.TMRL_FOLDER}")
6668
else:
6769
raise ArgumentTypeError('Enter a valid argument')
6870

6971

7072
if __name__ == "__main__":
7173
parser = ArgumentParser()
74+
parser.add_argument('--install', action='store_true', help='checks TMRL installation')
7275
parser.add_argument('--server', action='store_true', help='launches the server')
7376
parser.add_argument('--trainer', action='store_true', help='launches the trainer')
7477
parser.add_argument('--worker', action='store_true', help='launches a rollout worker')

tmrl/config/config_constants.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
# standard library imports
2+
3+
import logging
4+
25
import os
36
from pathlib import Path
4-
import logging
57
import json
68
import platform
79
from packaging import version
810

911

1012
__compatibility__ = "0.6.0"
1113

14+
# TMRL FOLDER: =======================================================
15+
1216
SYSTEM = platform.system()
1317
RTGYM_VERSION = "real-time-gym-v1" if SYSTEM == "Windows" else "real-time-gym-ts-v1"
1418

1519
TMRL_FOLDER = Path.home() / "TmrlData"
20+
21+
if not TMRL_FOLDER.exists():
22+
raise RuntimeError(f"Missing folder: {TMRL_FOLDER}")
23+
1624
CHECKPOINTS_FOLDER = TMRL_FOLDER / "checkpoints"
1725
DATASET_FOLDER = TMRL_FOLDER / "dataset"
1826
REWARD_FOLDER = TMRL_FOLDER / "reward"

tmrl/tools/init_package/init_pywin32.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Adapted from https://github.com/mhammond/pywin32/blob/main/pywin32_postinstall.py
22

3-
# May have to be adapted in the future if becomming incompatible with new version of pywin32.
3+
# May have to be adapted in the future if becoming incompatible with new versions of pywin32.
44

55
# postinstall script for pywin32
66
#

tmrl/tools/init_package/init_tmrl.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import logging
2+
3+
import platform
4+
from pathlib import Path
5+
6+
7+
def rmdir(directory):
8+
directory = Path(directory)
9+
for item in directory.iterdir():
10+
if item.is_dir():
11+
rmdir(item)
12+
else:
13+
item.unlink()
14+
directory.rmdir()
15+
16+
17+
def init_tmrl_data():
18+
"""
19+
Wipes and re-generates the TmrlData folder.
20+
"""
21+
from shutil import copy2
22+
from zipfile import ZipFile
23+
import urllib.request
24+
import urllib.error
25+
import socket
26+
27+
resources_url = "https://github.com/trackmania-rl/tmrl/releases/download/v0.6.0/resources.zip"
28+
29+
def url_retrieve(url: str, outfile: Path, overwrite: bool = False):
30+
"""
31+
Adapted from https://www.scivision.dev/python-switch-urlretrieve-requests-timeout/
32+
"""
33+
outfile = Path(outfile).expanduser().resolve()
34+
if outfile.is_dir():
35+
raise ValueError("Please specify full filepath, including filename")
36+
if overwrite or not outfile.is_file():
37+
outfile.parent.mkdir(parents=True, exist_ok=True)
38+
try:
39+
urllib.request.urlretrieve(url, str(outfile))
40+
except (socket.gaierror, urllib.error.URLError) as err:
41+
raise ConnectionError(f"could not download {url} due to {err}")
42+
43+
# destination folder:
44+
home_folder = Path.home()
45+
tmrl_folder = home_folder / "TmrlData"
46+
47+
# Wipe the tmrl folder:
48+
if tmrl_folder.exists():
49+
rmdir(tmrl_folder)
50+
51+
# download relevant items IF THE tmrl FOLDER DOESN'T EXIST:
52+
assert not tmrl_folder.exists(), f"Failed to delete {tmrl_folder}"
53+
54+
checkpoints_folder = tmrl_folder / "checkpoints"
55+
dataset_folder = tmrl_folder / "dataset"
56+
reward_folder = tmrl_folder / "reward"
57+
weights_folder = tmrl_folder / "weights"
58+
config_folder = tmrl_folder / "config"
59+
checkpoints_folder.mkdir(parents=True, exist_ok=True)
60+
dataset_folder.mkdir(parents=True, exist_ok=True)
61+
reward_folder.mkdir(parents=True, exist_ok=True)
62+
weights_folder.mkdir(parents=True, exist_ok=True)
63+
config_folder.mkdir(parents=True, exist_ok=True)
64+
65+
# download resources:
66+
resources_target = tmrl_folder / "resources.zip"
67+
url_retrieve(resources_url, resources_target)
68+
69+
# unzip downloaded resources:
70+
with ZipFile(resources_target, 'r') as zip_ref:
71+
zip_ref.extractall(tmrl_folder)
72+
73+
# delete zip file:
74+
resources_target.unlink()
75+
76+
# copy relevant files:
77+
resources_folder = tmrl_folder / "resources"
78+
copy2(resources_folder / "config.json", config_folder)
79+
copy2(resources_folder / "reward.pkl", reward_folder)
80+
copy2(resources_folder / "SAC_4_LIDAR_pretrained.tmod", weights_folder)
81+
copy2(resources_folder / "SAC_4_imgs_pretrained.tmod", weights_folder)
82+
83+
# on Windows, look for OpenPlanet:
84+
if platform.system() == "Windows":
85+
openplanet_folder = home_folder / "OpenplanetNext"
86+
87+
if openplanet_folder.exists():
88+
# copy the OpenPlanet script:
89+
try:
90+
# remove old script if found
91+
op_scripts_folder = openplanet_folder / 'Scripts'
92+
if op_scripts_folder.exists():
93+
to_remove = [op_scripts_folder / 'Plugin_GrabData_0_1.as',
94+
op_scripts_folder / 'Plugin_GrabData_0_1.as.sig',
95+
op_scripts_folder / 'Plugin_GrabData_0_2.as',
96+
op_scripts_folder / 'Plugin_GrabData_0_2.as.sig']
97+
for old_file in to_remove:
98+
if old_file.exists():
99+
old_file.unlink()
100+
# copy new plugin
101+
op_plugins_folder = openplanet_folder / 'Plugins'
102+
op_plugins_folder.mkdir(parents=True, exist_ok=True)
103+
tm20_plugin_1 = resources_folder / 'Plugins' / 'TMRL_GrabData.op'
104+
tm20_plugin_2 = resources_folder / 'Plugins' / 'TMRL_SaveGhost.op'
105+
copy2(tm20_plugin_1, op_plugins_folder)
106+
copy2(tm20_plugin_2, op_plugins_folder)
107+
except Exception as e:
108+
print(
109+
f"An exception was caught when trying to copy the OpenPlanet plugin automatically. \
110+
Please copy the plugin manually for TrackMania 2020 support. The caught exception was: {str(e)}.")
111+
else:
112+
# warn the user that OpenPlanet couldn't be found:
113+
print(f"The OpenPlanet folder was not found at {openplanet_folder}. \
114+
Please copy the OpenPlanet script and signature manually for TrackMania 2020 support.")
115+
116+
117+
TMRL_FOLDER = Path.home() / "TmrlData"
118+
119+
if not TMRL_FOLDER.exists():
120+
logging.warning(f"The TMRL folder was not found on your machine. Attempting download...")
121+
init_tmrl_data()
122+
logging.info(f"TMRL folder successfully downloaded, please wait for initialization to complete...")

0 commit comments

Comments
 (0)