Skip to content

Commit 490f19d

Browse files
RuntimeManager Interface (UBC-Thunderbots#3573)
* interface completed * cleanup * [pre-commit.ci lite] apply automatic fixes * cleanup * [pre-commit.ci lite] apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent 95dc687 commit 490f19d

10 files changed

Lines changed: 162 additions & 28 deletions

File tree

environment_setup/setup_software.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,9 @@ sudo cp "$CURR_DIR/../src/software/autoref/DIV_B.txt" "/opt/tbotspython/autoRefe
143143

144144
print_status_msg "Finished setting up AutoRef"
145145

146-
# setup external_ai
147-
sudo mkdir /opt/tbotspython/external_ai
148-
sudo chown -R $USER:$USER /opt/tbotspython/external_ai/
146+
# setup external_runtimes
147+
sudo mkdir /opt/tbotspython/external_runtimes
148+
sudo chown -R $USER:$USER /opt/tbotspython/external_runtimes/
149149

150150
# Install Bazel
151151
print_status_msg "Installing Bazel"

src/software/thunderscope/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ py_binary(
2020
":util",
2121
"//software/thunderscope/binary_context_managers:full_system",
2222
"//software/thunderscope/binary_context_managers:game_controller",
23+
"//software/thunderscope/binary_context_managers:runtime_manager",
2324
"//software/thunderscope/binary_context_managers:simulator",
2425
],
2526
)

src/software/thunderscope/binary_context_managers/BUILD

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,12 @@ py_library(
5050
"//software/thunderscope:time_provider",
5151
],
5252
)
53+
54+
py_library(
55+
name = "runtime_manager",
56+
srcs = [
57+
"runtime_installer.py",
58+
"runtime_loader.py",
59+
"runtime_manager.py",
60+
],
61+
)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# TODO: #3559
2+
class RuntimeInstaller:
3+
"""Delegate class for handling runtime installation and remote interfacing"""
4+
5+
def __init__(self):
6+
pass
7+
8+
def fetch_remote_runtimes(self) -> list[str]:
9+
"""Requests a list of available runtimes from the remote. This is an expensive operation
10+
and should only be called when necessary.
11+
:return: A unique list of names for available runtimes
12+
"""
13+
return []
14+
15+
def install_runtime(self, version: str) -> None:
16+
"""Installs the runtime of the specified version or throws an error upon failure.
17+
Ensures that the runtime is compatible with the current platform
18+
:param version: Version of the runtime hosted on the remote to install
19+
"""
20+
pass
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from software.thunderscope.constants import RuntimeManagerConstants
2+
3+
4+
# TODO: #3557
5+
class RuntimeLoader:
6+
"""Delegate class for handling local runtimes and managing runtime selection"""
7+
8+
def __init__(self):
9+
self.cached_runtimes = None
10+
11+
def fetch_installed_runtimes(self) -> list[str]:
12+
"""Fetches the list of available runtimes from the local disk
13+
:return: A list of names for available runtimes
14+
"""
15+
if self.cached_runtimes:
16+
return self.cached_runtimes.keys()
17+
else:
18+
return []
19+
20+
def load_existing_runtimes(self, yellow_runtime: str, blue_runtime: str) -> None:
21+
"""Loads the yellow and blue runtimes specified by saving them in the local disk.
22+
:param blue_runtime: Unique name of the blue runtime to set
23+
:param yellow_runtime: Unique name of the yellow runtime to set
24+
"""
25+
config = {}
26+
self._set_runtime_config(config)
27+
pass
28+
29+
def fetch_runtime_config(self) -> dict[str, str]:
30+
"""Fetches the runtime configuration from the local disk.
31+
:return: Returns the runtime configuration as a map
32+
"""
33+
return {
34+
RuntimeManagerConstants.RUNTIME_CONFIG_BLUE_KEY: RuntimeManagerConstants.DEFAULT_BINARY_PATH,
35+
RuntimeManagerConstants.RUNTIME_CONFIG_YELLOW_KEY: RuntimeManagerConstants.DEFAULT_BINARY_PATH,
36+
}
37+
38+
def _create_runtime_config(self) -> None:
39+
"""Creates the runtime configuration file on disk and throws an error upon failure."""
40+
pass
41+
42+
def _set_runtime_config(self, config: dict[str, str]) -> None:
43+
"""Sets/persists the runtime configuration file on disk and creates the configuration
44+
file if it doesn't exist.
45+
:param config: The runtime configuration containing
46+
- color_runtime : absolute path of external runtime, or
47+
- color_runtime : relative path of DEFAULT_BINARY_PATH
48+
"""
49+
pass
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from software.thunderscope.binary_context_managers.runtime_installer import (
2+
RuntimeInstaller,
3+
)
4+
from software.thunderscope.binary_context_managers.runtime_loader import RuntimeLoader
5+
6+
7+
class RuntimeManager:
8+
"""Class for interfacing with AI runtimes/backends (full system or external) on the disk"""
9+
10+
def __init__(self):
11+
self.runtime_installer = RuntimeInstaller()
12+
self.runtime_loader = RuntimeLoader()
13+
14+
def fetch_remote_runtimes(self) -> list[str]:
15+
"""Requests a list of available runtimes from the remote. Includes DEFAULT_BINARY_NAME by default
16+
:return: A unique list of names for available runtimes
17+
"""
18+
return self.runtime_installer.fetch_remote_runtimes()
19+
20+
def install_runtime(self, version: str) -> None:
21+
"""Installs the runtime of the specified version or throws an error upon failure.
22+
:param version: Version of the runtime hosted on the remote to install
23+
"""
24+
self.runtime_installer.install_runtime(version)
25+
26+
def fetch_installed_runtimes(self) -> list[str]:
27+
"""Fetches the list of available runtimes from the local disk
28+
:return: A list of names for available runtimes
29+
"""
30+
return self.runtime_loader.fetch_installed_runtimes()
31+
32+
def load_existing_runtime(self, yellow_runtime: str, blue_runtime: str) -> None:
33+
"""Loads the runtimes of the specified name or throws an error upon failure.
34+
:param blue_runtime: name of the blue runtime to load
35+
:param yellow_runtime: name of the yellow runtime to load
36+
"""
37+
self.runtime_loader.load_existing_runtimes(yellow_runtime, blue_runtime)
38+
39+
def fetch_runtime_config(self) -> dict[str, str]:
40+
"""Fetches the runtime configuration from the local disk
41+
:return: Returns the runtime configuration as a map
42+
"""
43+
return self.runtime_loader.fetch_runtime_config()
44+
45+
46+
runtime_manager_instance = RuntimeManager()

src/software/thunderscope/constants.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,3 +386,14 @@ class LogLevels(StrEnum):
386386
INFO = "INFO"
387387
WARNING = "WARNING"
388388
FATAL = "FATAL"
389+
390+
391+
class RuntimeManagerConstants:
392+
"""Constants for Runtime Manager"""
393+
394+
RUNTIME_CONFIG_BLUE_KEY = "blue_path_to_binary"
395+
RUNTIME_CONFIG_YELLOW_KEY = "yellow_path_to_binary"
396+
DEFAULT_BINARY_PATH = "software/unix_full_system"
397+
DEFAULT_BINARY_NAME = "localhost"
398+
EXTERNAL_RUNTIMES_PATH = "/opt/tbotspython/external_runtimes"
399+
RUNTIME_CONFIG_PATH = f"{EXTERNAL_RUNTIMES_PATH}/runtime_config.toml"

src/software/thunderscope/gl/widgets/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ py_library(
66
name = "gl_runtime_installer",
77
srcs = ["gl_runtime_installer.py"],
88
deps = [
9+
"//software/thunderscope/binary_context_managers:runtime_manager",
910
requirement("pyqtgraph"),
1011
],
1112
)

src/software/thunderscope/gl/widgets/gl_runtime_installer.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
QVBoxLayout,
88
)
99

10+
from software.thunderscope.binary_context_managers.runtime_manager import (
11+
runtime_manager_instance,
12+
)
13+
1014

1115
class GLRuntimeInstallerDialog(QDialog):
1216
"""Modal that displays selectable list of runtimes to install"""
@@ -19,8 +23,7 @@ def __init__(self, parent: QWidget):
1923
"""
2024
super().__init__(parent)
2125

22-
# TODO (#3559): get list of runtimes from GET request
23-
runtimes = [f"runtime_{i}" for i in range(10)]
26+
runtimes = runtime_manager_instance.fetch_remote_runtimes()
2427

2528
self.setWindowTitle("Install runtimes")
2629
self.setModal(True)

src/software/thunderscope/thunderscope_main.py

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,29 @@
88
import google.protobuf
99
from google.protobuf.internal import api_implementation
1010

11+
from software.thunderscope.binary_context_managers.runtime_manager import (
12+
runtime_manager_instance,
13+
)
14+
1115
protobuf_impl_type = api_implementation.Type()
1216
assert protobuf_impl_type == "upb", (
1317
f"Trying to use the {protobuf_impl_type} protobuf implementation. "
1418
"Please use the upb implementation, available in python protobuf version 4.21.0 and above."
1519
f"The current version of protobuf is {google.protobuf.__version__}"
1620
)
1721

18-
1922
from software.thunderscope.thunderscope import Thunderscope
2023
from software.thunderscope.constants import LogLevels
2124
from software.thunderscope.binary_context_managers import *
2225
from proto.import_all_protos import *
2326
from software.py_constants import *
2427
from software.thunderscope.robot_communication import RobotCommunication
2528
from software.thunderscope.wifi_communication_manager import WifiCommunicationManager
26-
from software.thunderscope.constants import EstopMode, ProtoUnixIOTypes
29+
from software.thunderscope.constants import (
30+
EstopMode,
31+
ProtoUnixIOTypes,
32+
RuntimeManagerConstants,
33+
)
2734
from software.thunderscope.estop_helpers import get_estop_config
2835
from software.thunderscope.proto_unix_io import ProtoUnixIO
2936
import software.thunderscope.thunderscope_config as config
@@ -432,31 +439,16 @@ def __ticker(tick_rate_ms: int) -> None:
432439
tick_rate_ms, tscope.proto_unix_io_map[ProtoUnixIOTypes.SIM], tscope
433440
)
434441

435-
# Libraries to use for yellow
436-
437-
# TODO (#3557) Set external_ai variables to follow toml file in /opt/tbotspython/external_ai/ai_config.toml
438-
blue_external_ai = None
439-
yellow_external_ai = None
440-
441-
# If ai selected is default, use the unix full system generated by the current branch build in the bazel sand blue_full_system_proto_unix_io
442-
# Else, find the unix full system in opt
443-
blue_path_to_binary = (
444-
"software/unix_full_system"
445-
if not blue_external_ai
446-
else "/opt/tbotspython/external_ai/{}".format(blue_external_ai)
447-
)
448-
449-
yellow_path_to_binary = (
450-
"software/unix_full_system"
451-
if not yellow_external_ai
452-
else "/opt/tbotspython/external_ai/{}".format(yellow_external_ai)
453-
)
442+
# Fetch the AI runtime/backends
443+
runtime_config = runtime_manager_instance.fetch_runtime_config()
454444

455445
# Launch all binaries
456446
with Simulator(
457447
args.simulator_runtime_dir, args.debug_simulator, args.enable_realism
458448
) as simulator, FullSystem(
459-
path_to_binary=blue_path_to_binary,
449+
path_to_binary=runtime_config[
450+
RuntimeManagerConstants.RUNTIME_CONFIG_BLUE_KEY
451+
],
460452
full_system_runtime_dir=args.blue_full_system_runtime_dir,
461453
debug_full_system=args.debug_blue_full_system,
462454
friendly_colour_yellow=False,
@@ -465,7 +457,9 @@ def __ticker(tick_rate_ms: int) -> None:
465457
running_in_realtime=(not args.ci_mode),
466458
log_level=args.log_level,
467459
) as blue_fs, FullSystem(
468-
path_to_binary=yellow_path_to_binary,
460+
path_to_binary=runtime_config[
461+
RuntimeManagerConstants.RUNTIME_CONFIG_YELLOW_KEY
462+
],
469463
full_system_runtime_dir=args.yellow_full_system_runtime_dir,
470464
debug_full_system=args.debug_yellow_full_system,
471465
friendly_colour_yellow=True,

0 commit comments

Comments
 (0)