sierra-research 1.3.6__py3-none-any.whl → 1.5.0__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.
- sierra/__init__.py +3 -3
- sierra/core/__init__.py +3 -3
- sierra/core/batchroot.py +223 -0
- sierra/core/cmdline.py +681 -1057
- sierra/core/compare.py +11 -0
- sierra/core/config.py +96 -88
- sierra/core/engine.py +306 -0
- sierra/core/execenv.py +380 -0
- sierra/core/expdef.py +11 -0
- sierra/core/experiment/__init__.py +1 -0
- sierra/core/experiment/bindings.py +150 -101
- sierra/core/experiment/definition.py +414 -245
- sierra/core/experiment/spec.py +83 -85
- sierra/core/exproot.py +44 -0
- sierra/core/generators/__init__.py +10 -0
- sierra/core/generators/experiment.py +528 -0
- sierra/core/generators/generator_factory.py +138 -137
- sierra/core/graphs/__init__.py +23 -0
- sierra/core/graphs/bcbridge.py +94 -0
- sierra/core/graphs/heatmap.py +245 -324
- sierra/core/graphs/pathset.py +27 -0
- sierra/core/graphs/schema.py +77 -0
- sierra/core/graphs/stacked_line.py +341 -0
- sierra/core/graphs/summary_line.py +506 -0
- sierra/core/logging.py +3 -2
- sierra/core/models/__init__.py +3 -1
- sierra/core/models/info.py +19 -0
- sierra/core/models/interface.py +52 -122
- sierra/core/pipeline/__init__.py +2 -5
- sierra/core/pipeline/pipeline.py +228 -126
- sierra/core/pipeline/stage1/__init__.py +10 -0
- sierra/core/pipeline/stage1/pipeline_stage1.py +45 -31
- sierra/core/pipeline/stage2/__init__.py +10 -0
- sierra/core/pipeline/stage2/pipeline_stage2.py +8 -11
- sierra/core/pipeline/stage2/runner.py +401 -0
- sierra/core/pipeline/stage3/__init__.py +12 -0
- sierra/core/pipeline/stage3/gather.py +321 -0
- sierra/core/pipeline/stage3/pipeline_stage3.py +37 -84
- sierra/core/pipeline/stage4/__init__.py +12 -2
- sierra/core/pipeline/stage4/pipeline_stage4.py +36 -354
- sierra/core/pipeline/stage5/__init__.py +12 -0
- sierra/core/pipeline/stage5/pipeline_stage5.py +33 -208
- sierra/core/pipeline/yaml.py +48 -0
- sierra/core/plugin.py +529 -62
- sierra/core/proc.py +11 -0
- sierra/core/prod.py +11 -0
- sierra/core/ros1/__init__.py +5 -1
- sierra/core/ros1/callbacks.py +22 -21
- sierra/core/ros1/cmdline.py +59 -88
- sierra/core/ros1/generators.py +159 -175
- sierra/core/ros1/variables/__init__.py +3 -0
- sierra/core/ros1/variables/exp_setup.py +122 -116
- sierra/core/startup.py +106 -76
- sierra/core/stat_kernels.py +4 -5
- sierra/core/storage.py +13 -32
- sierra/core/trampoline.py +30 -0
- sierra/core/types.py +116 -71
- sierra/core/utils.py +103 -106
- sierra/core/variables/__init__.py +1 -1
- sierra/core/variables/base_variable.py +12 -17
- sierra/core/variables/batch_criteria.py +387 -481
- sierra/core/variables/builtin.py +135 -0
- sierra/core/variables/exp_setup.py +19 -39
- sierra/core/variables/population_size.py +72 -76
- sierra/core/variables/variable_density.py +44 -68
- sierra/core/vector.py +1 -1
- sierra/main.py +256 -88
- sierra/plugins/__init__.py +119 -0
- sierra/plugins/compare/__init__.py +14 -0
- sierra/plugins/compare/graphs/__init__.py +19 -0
- sierra/plugins/compare/graphs/cmdline.py +120 -0
- sierra/plugins/compare/graphs/comparator.py +291 -0
- sierra/plugins/compare/graphs/inter_controller.py +531 -0
- sierra/plugins/compare/graphs/inter_scenario.py +297 -0
- sierra/plugins/compare/graphs/namecalc.py +53 -0
- sierra/plugins/compare/graphs/outputroot.py +73 -0
- sierra/plugins/compare/graphs/plugin.py +147 -0
- sierra/plugins/compare/graphs/preprocess.py +172 -0
- sierra/plugins/compare/graphs/schema.py +37 -0
- sierra/plugins/engine/__init__.py +14 -0
- sierra/plugins/engine/argos/__init__.py +18 -0
- sierra/plugins/{platform → engine}/argos/cmdline.py +144 -151
- sierra/plugins/{platform/argos/variables → engine/argos/generators}/__init__.py +5 -0
- sierra/plugins/engine/argos/generators/engine.py +394 -0
- sierra/plugins/engine/argos/plugin.py +393 -0
- sierra/plugins/{platform/argos/generators → engine/argos/variables}/__init__.py +5 -0
- sierra/plugins/engine/argos/variables/arena_shape.py +183 -0
- sierra/plugins/engine/argos/variables/cameras.py +240 -0
- sierra/plugins/engine/argos/variables/constant_density.py +112 -0
- sierra/plugins/engine/argos/variables/exp_setup.py +82 -0
- sierra/plugins/{platform → engine}/argos/variables/physics_engines.py +83 -87
- sierra/plugins/engine/argos/variables/population_constant_density.py +178 -0
- sierra/plugins/engine/argos/variables/population_size.py +115 -0
- sierra/plugins/engine/argos/variables/population_variable_density.py +123 -0
- sierra/plugins/engine/argos/variables/rendering.py +108 -0
- sierra/plugins/engine/ros1gazebo/__init__.py +18 -0
- sierra/plugins/engine/ros1gazebo/cmdline.py +175 -0
- sierra/plugins/{platform/ros1robot → engine/ros1gazebo}/generators/__init__.py +5 -0
- sierra/plugins/engine/ros1gazebo/generators/engine.py +125 -0
- sierra/plugins/engine/ros1gazebo/plugin.py +404 -0
- sierra/plugins/engine/ros1gazebo/variables/__init__.py +15 -0
- sierra/plugins/engine/ros1gazebo/variables/population_size.py +214 -0
- sierra/plugins/engine/ros1robot/__init__.py +18 -0
- sierra/plugins/engine/ros1robot/cmdline.py +159 -0
- sierra/plugins/{platform/ros1gazebo → engine/ros1robot}/generators/__init__.py +4 -0
- sierra/plugins/engine/ros1robot/generators/engine.py +95 -0
- sierra/plugins/engine/ros1robot/plugin.py +410 -0
- sierra/plugins/{hpc/local → engine/ros1robot/variables}/__init__.py +5 -0
- sierra/plugins/engine/ros1robot/variables/population_size.py +146 -0
- sierra/plugins/execenv/__init__.py +11 -0
- sierra/plugins/execenv/hpc/__init__.py +18 -0
- sierra/plugins/execenv/hpc/adhoc/__init__.py +18 -0
- sierra/plugins/execenv/hpc/adhoc/cmdline.py +30 -0
- sierra/plugins/execenv/hpc/adhoc/plugin.py +131 -0
- sierra/plugins/execenv/hpc/cmdline.py +137 -0
- sierra/plugins/execenv/hpc/local/__init__.py +18 -0
- sierra/plugins/execenv/hpc/local/cmdline.py +31 -0
- sierra/plugins/execenv/hpc/local/plugin.py +145 -0
- sierra/plugins/execenv/hpc/pbs/__init__.py +18 -0
- sierra/plugins/execenv/hpc/pbs/cmdline.py +30 -0
- sierra/plugins/execenv/hpc/pbs/plugin.py +121 -0
- sierra/plugins/execenv/hpc/slurm/__init__.py +18 -0
- sierra/plugins/execenv/hpc/slurm/cmdline.py +30 -0
- sierra/plugins/execenv/hpc/slurm/plugin.py +133 -0
- sierra/plugins/execenv/prefectserver/__init__.py +18 -0
- sierra/plugins/execenv/prefectserver/cmdline.py +66 -0
- sierra/plugins/execenv/prefectserver/dockerremote/__init__.py +18 -0
- sierra/plugins/execenv/prefectserver/dockerremote/cmdline.py +66 -0
- sierra/plugins/execenv/prefectserver/dockerremote/plugin.py +132 -0
- sierra/plugins/execenv/prefectserver/flow.py +66 -0
- sierra/plugins/execenv/prefectserver/local/__init__.py +18 -0
- sierra/plugins/execenv/prefectserver/local/cmdline.py +29 -0
- sierra/plugins/execenv/prefectserver/local/plugin.py +133 -0
- sierra/plugins/{hpc/adhoc → execenv/robot}/__init__.py +1 -0
- sierra/plugins/execenv/robot/turtlebot3/__init__.py +18 -0
- sierra/plugins/execenv/robot/turtlebot3/plugin.py +204 -0
- sierra/plugins/expdef/__init__.py +14 -0
- sierra/plugins/expdef/json/__init__.py +14 -0
- sierra/plugins/expdef/json/plugin.py +504 -0
- sierra/plugins/expdef/xml/__init__.py +14 -0
- sierra/plugins/expdef/xml/plugin.py +386 -0
- sierra/{core/hpc → plugins/proc}/__init__.py +1 -1
- sierra/plugins/proc/collate/__init__.py +15 -0
- sierra/plugins/proc/collate/cmdline.py +47 -0
- sierra/plugins/proc/collate/plugin.py +271 -0
- sierra/plugins/proc/compress/__init__.py +18 -0
- sierra/plugins/proc/compress/cmdline.py +47 -0
- sierra/plugins/proc/compress/plugin.py +123 -0
- sierra/plugins/proc/decompress/__init__.py +18 -0
- sierra/plugins/proc/decompress/plugin.py +96 -0
- sierra/plugins/proc/imagize/__init__.py +15 -0
- sierra/plugins/proc/imagize/cmdline.py +49 -0
- sierra/plugins/proc/imagize/plugin.py +270 -0
- sierra/plugins/proc/modelrunner/__init__.py +16 -0
- sierra/plugins/proc/modelrunner/plugin.py +250 -0
- sierra/plugins/proc/statistics/__init__.py +15 -0
- sierra/plugins/proc/statistics/cmdline.py +64 -0
- sierra/plugins/proc/statistics/plugin.py +390 -0
- sierra/plugins/{hpc → prod}/__init__.py +1 -0
- sierra/plugins/prod/graphs/__init__.py +18 -0
- sierra/plugins/prod/graphs/cmdline.py +269 -0
- sierra/plugins/prod/graphs/collate.py +279 -0
- sierra/plugins/prod/graphs/inter/__init__.py +13 -0
- sierra/plugins/prod/graphs/inter/generate.py +83 -0
- sierra/plugins/prod/graphs/inter/heatmap.py +86 -0
- sierra/plugins/prod/graphs/inter/line.py +134 -0
- sierra/plugins/prod/graphs/intra/__init__.py +15 -0
- sierra/plugins/prod/graphs/intra/generate.py +202 -0
- sierra/plugins/prod/graphs/intra/heatmap.py +74 -0
- sierra/plugins/prod/graphs/intra/line.py +114 -0
- sierra/plugins/prod/graphs/plugin.py +103 -0
- sierra/plugins/prod/graphs/targets.py +63 -0
- sierra/plugins/prod/render/__init__.py +18 -0
- sierra/plugins/prod/render/cmdline.py +72 -0
- sierra/plugins/prod/render/plugin.py +282 -0
- sierra/plugins/storage/__init__.py +5 -0
- sierra/plugins/storage/arrow/__init__.py +18 -0
- sierra/plugins/storage/arrow/plugin.py +38 -0
- sierra/plugins/storage/csv/__init__.py +9 -0
- sierra/plugins/storage/csv/plugin.py +12 -5
- sierra/version.py +3 -2
- sierra_research-1.5.0.dist-info/METADATA +238 -0
- sierra_research-1.5.0.dist-info/RECORD +186 -0
- {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info}/WHEEL +1 -2
- sierra/core/experiment/xml.py +0 -454
- sierra/core/generators/controller_generator_parser.py +0 -34
- sierra/core/generators/exp_creator.py +0 -351
- sierra/core/generators/exp_generators.py +0 -142
- sierra/core/graphs/scatterplot2D.py +0 -109
- sierra/core/graphs/stacked_line_graph.py +0 -249
- sierra/core/graphs/stacked_surface_graph.py +0 -220
- sierra/core/graphs/summary_line_graph.py +0 -369
- sierra/core/hpc/cmdline.py +0 -142
- sierra/core/models/graphs.py +0 -87
- sierra/core/pipeline/stage2/exp_runner.py +0 -286
- sierra/core/pipeline/stage3/imagizer.py +0 -149
- sierra/core/pipeline/stage3/run_collator.py +0 -317
- sierra/core/pipeline/stage3/statistics_calculator.py +0 -478
- sierra/core/pipeline/stage4/graph_collator.py +0 -319
- sierra/core/pipeline/stage4/inter_exp_graph_generator.py +0 -240
- sierra/core/pipeline/stage4/intra_exp_graph_generator.py +0 -317
- sierra/core/pipeline/stage4/model_runner.py +0 -168
- sierra/core/pipeline/stage4/rendering.py +0 -283
- sierra/core/pipeline/stage4/yaml_config_loader.py +0 -103
- sierra/core/pipeline/stage5/inter_scenario_comparator.py +0 -328
- sierra/core/pipeline/stage5/intra_scenario_comparator.py +0 -989
- sierra/core/platform.py +0 -493
- sierra/core/plugin_manager.py +0 -369
- sierra/core/root_dirpath_generator.py +0 -241
- sierra/plugins/hpc/adhoc/plugin.py +0 -125
- sierra/plugins/hpc/local/plugin.py +0 -81
- sierra/plugins/hpc/pbs/__init__.py +0 -9
- sierra/plugins/hpc/pbs/plugin.py +0 -126
- sierra/plugins/hpc/slurm/__init__.py +0 -9
- sierra/plugins/hpc/slurm/plugin.py +0 -130
- sierra/plugins/platform/__init__.py +0 -9
- sierra/plugins/platform/argos/__init__.py +0 -9
- sierra/plugins/platform/argos/generators/platform_generators.py +0 -383
- sierra/plugins/platform/argos/plugin.py +0 -337
- sierra/plugins/platform/argos/variables/arena_shape.py +0 -145
- sierra/plugins/platform/argos/variables/cameras.py +0 -243
- sierra/plugins/platform/argos/variables/constant_density.py +0 -136
- sierra/plugins/platform/argos/variables/exp_setup.py +0 -113
- sierra/plugins/platform/argos/variables/population_constant_density.py +0 -175
- sierra/plugins/platform/argos/variables/population_size.py +0 -102
- sierra/plugins/platform/argos/variables/population_variable_density.py +0 -132
- sierra/plugins/platform/argos/variables/rendering.py +0 -104
- sierra/plugins/platform/ros1gazebo/__init__.py +0 -9
- sierra/plugins/platform/ros1gazebo/cmdline.py +0 -213
- sierra/plugins/platform/ros1gazebo/generators/platform_generators.py +0 -137
- sierra/plugins/platform/ros1gazebo/plugin.py +0 -335
- sierra/plugins/platform/ros1gazebo/variables/__init__.py +0 -10
- sierra/plugins/platform/ros1gazebo/variables/population_size.py +0 -204
- sierra/plugins/platform/ros1robot/__init__.py +0 -9
- sierra/plugins/platform/ros1robot/cmdline.py +0 -175
- sierra/plugins/platform/ros1robot/generators/platform_generators.py +0 -112
- sierra/plugins/platform/ros1robot/plugin.py +0 -373
- sierra/plugins/platform/ros1robot/variables/__init__.py +0 -10
- sierra/plugins/platform/ros1robot/variables/population_size.py +0 -146
- sierra/plugins/robot/__init__.py +0 -9
- sierra/plugins/robot/turtlebot3/__init__.py +0 -9
- sierra/plugins/robot/turtlebot3/plugin.py +0 -194
- sierra_research-1.3.6.data/data/share/man/man1/sierra-cli.1 +0 -2349
- sierra_research-1.3.6.data/data/share/man/man7/sierra-examples.7 +0 -488
- sierra_research-1.3.6.data/data/share/man/man7/sierra-exec-envs.7 +0 -331
- sierra_research-1.3.6.data/data/share/man/man7/sierra-glossary.7 +0 -285
- sierra_research-1.3.6.data/data/share/man/man7/sierra-platforms.7 +0 -358
- sierra_research-1.3.6.data/data/share/man/man7/sierra-usage.7 +0 -725
- sierra_research-1.3.6.data/data/share/man/man7/sierra.7 +0 -78
- sierra_research-1.3.6.dist-info/METADATA +0 -500
- sierra_research-1.3.6.dist-info/RECORD +0 -133
- sierra_research-1.3.6.dist-info/top_level.txt +0 -1
- {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info}/entry_points.txt +0 -0
- {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2025 John Harwell, All rights reserved.
|
3
|
+
#
|
4
|
+
# SPDX-License Identifier: MIT
|
5
|
+
#
|
6
|
+
"""Glue for bridging SIERRA <-> prefect for executing local builds."""
|
7
|
+
|
8
|
+
|
9
|
+
# Core packages
|
10
|
+
import pathlib
|
11
|
+
import subprocess
|
12
|
+
|
13
|
+
|
14
|
+
# 3rd party packages
|
15
|
+
import prefect
|
16
|
+
|
17
|
+
# Project packages
|
18
|
+
|
19
|
+
|
20
|
+
@prefect.task(tags=["sierra-exec-jobs-per-node"])
|
21
|
+
def exec_exp_run(
|
22
|
+
cmd: list[str],
|
23
|
+
scratch_path: pathlib.Path,
|
24
|
+
) -> None:
|
25
|
+
"""Execute the given command.
|
26
|
+
|
27
|
+
Arguments:
|
28
|
+
cmd: Command to execute a single :term:`Experimental Run`.
|
29
|
+
|
30
|
+
scratch_path: Where to write stdout/stderr to.
|
31
|
+
"""
|
32
|
+
flow_run_id = prefect.runtime.task_run.id
|
33
|
+
|
34
|
+
with (
|
35
|
+
open(str(scratch_path) + f"_{flow_run_id}_stdout", "w") as stdout,
|
36
|
+
open(str(scratch_path) + f"_{flow_run_id}_stderr", "w") as stderr,
|
37
|
+
):
|
38
|
+
subprocess.run(
|
39
|
+
cmd,
|
40
|
+
stdout=stdout,
|
41
|
+
stderr=stderr,
|
42
|
+
shell=True,
|
43
|
+
check=True,
|
44
|
+
)
|
45
|
+
|
46
|
+
|
47
|
+
@prefect.flow
|
48
|
+
def sierra(
|
49
|
+
input_root: pathlib.Path,
|
50
|
+
scratch_root: pathlib.Path,
|
51
|
+
) -> None:
|
52
|
+
"""Generate commands, execute the simulation, and package the data.
|
53
|
+
|
54
|
+
Arguments:
|
55
|
+
input_root: Path to the input directory for the :term:`Experiment`.
|
56
|
+
|
57
|
+
scratch_root: Path to the scratch directory for the :term:`Experiment`.
|
58
|
+
"""
|
59
|
+
commands = []
|
60
|
+
with open(input_root / "commands.txt") as f:
|
61
|
+
commands = [line.strip() for line in f.readlines()]
|
62
|
+
|
63
|
+
scratch_stdouts = [scratch_root / f"_run{i}" for i in range(0, len(commands))]
|
64
|
+
|
65
|
+
sim_results = exec_exp_run.map(commands, scratch_stdouts)
|
66
|
+
sim_results.wait()
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Copyright 2021 John Harwell, All rights reserved.
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
"""
|
5
|
+
Container module for the local execution environment.
|
6
|
+
|
7
|
+
See :ref:`plugins/execenv/prefectserver/local`.
|
8
|
+
"""
|
9
|
+
|
10
|
+
# Core packages
|
11
|
+
|
12
|
+
# 3rd party packages
|
13
|
+
|
14
|
+
# Project packages
|
15
|
+
|
16
|
+
|
17
|
+
def sierra_plugin_type() -> str:
|
18
|
+
return "pipeline"
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2025 John Harwell, All rights reserved.
|
3
|
+
#
|
4
|
+
# SPDX-License Identifier: MIT
|
5
|
+
#
|
6
|
+
|
7
|
+
# Core packages
|
8
|
+
import typing as tp
|
9
|
+
import argparse
|
10
|
+
|
11
|
+
# 3rd party packages
|
12
|
+
|
13
|
+
# Project packages
|
14
|
+
from sierra.plugins.execenv import prefectserver
|
15
|
+
from sierra.core import types
|
16
|
+
from sierra.plugins import PluginCmdline
|
17
|
+
|
18
|
+
|
19
|
+
def build(
|
20
|
+
parents: tp.List[argparse.ArgumentParser], stages: tp.List[int]
|
21
|
+
) -> PluginCmdline:
|
22
|
+
"""
|
23
|
+
Get a cmdline parser supporting the ``prefectserver.local`` execution environment.
|
24
|
+
"""
|
25
|
+
return prefectserver.cmdline.PrefectCmdline(parents, stages)
|
26
|
+
|
27
|
+
|
28
|
+
def to_cmdopts(args: argparse.Namespace) -> types.Cmdopts:
|
29
|
+
return prefectserver.cmdline.to_cmdopts(args)
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# Copyright 2025 John Harwell, All rights reserved.
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
"""Prefect plugin for running SIERRA locally."""
|
5
|
+
|
6
|
+
# Core packages
|
7
|
+
import typing as tp
|
8
|
+
import pathlib
|
9
|
+
|
10
|
+
# 3rd party packages
|
11
|
+
import implements
|
12
|
+
|
13
|
+
# Project packages
|
14
|
+
from sierra.core import types
|
15
|
+
from sierra.core.experiment import bindings
|
16
|
+
|
17
|
+
|
18
|
+
@implements.implements(bindings.IBatchShellCmdsGenerator)
|
19
|
+
class BatchShellCmdsGenerator:
|
20
|
+
"""
|
21
|
+
Generate commands to invoke :term:`Prefect` for local computing.
|
22
|
+
"""
|
23
|
+
|
24
|
+
def __init__(self, cmdopts: types.Cmdopts) -> None:
|
25
|
+
self.cmdopts = cmdopts
|
26
|
+
self.api_url = "http://127.0.0.1:4200/api"
|
27
|
+
|
28
|
+
def pre_batch_cmds(self) -> tp.List[types.ShellCmdSpec]:
|
29
|
+
flow_path = pathlib.Path(__file__).parent / "../flow.py"
|
30
|
+
no_prompt = "PREFECT_CLI_PROMPT=false"
|
31
|
+
|
32
|
+
return [
|
33
|
+
# We obviously have to start a local server. We don't have to wait
|
34
|
+
# for the command, because it is backgrounded.
|
35
|
+
types.ShellCmdSpec(
|
36
|
+
cmd=f"env {no_prompt} prefect server start &",
|
37
|
+
shell=True,
|
38
|
+
wait=False,
|
39
|
+
),
|
40
|
+
types.ShellCmdSpec(
|
41
|
+
cmd="sleep 5",
|
42
|
+
shell=True,
|
43
|
+
wait=True,
|
44
|
+
),
|
45
|
+
types.ShellCmdSpec(
|
46
|
+
cmd="prefect config set PREFECT_API_URL={0}".format(self.api_url),
|
47
|
+
shell=True,
|
48
|
+
wait=True,
|
49
|
+
),
|
50
|
+
# 2025-07-29 [JRH]: This doesn't work (workers ignore it and start #
|
51
|
+
# simultaneous sims corresponding to # cores available on the
|
52
|
+
# machine), despite all the docs saying it should. I THINK it's
|
53
|
+
# because global concurrency limits/task concurrency limits only
|
54
|
+
# work with prefect cloud.
|
55
|
+
#
|
56
|
+
# Concurrency limit has to be set BEFORE starting workers.
|
57
|
+
types.ShellCmdSpec(
|
58
|
+
cmd="echo 'y' | prefect gcl delete sierra-exec-jobs-per-node || true",
|
59
|
+
shell=True,
|
60
|
+
wait=True,
|
61
|
+
),
|
62
|
+
types.ShellCmdSpec(
|
63
|
+
cmd="prefect gcl create sierra-exec-jobs-per-node --limit {0}".format(
|
64
|
+
self.cmdopts["exec_jobs_per_node"]
|
65
|
+
),
|
66
|
+
shell=True,
|
67
|
+
wait=True,
|
68
|
+
),
|
69
|
+
types.ShellCmdSpec(
|
70
|
+
cmd="prefect work-pool create --type process {0}".format(
|
71
|
+
self.cmdopts["work_pool"],
|
72
|
+
),
|
73
|
+
shell=True,
|
74
|
+
wait=True,
|
75
|
+
),
|
76
|
+
# We only need to start 1 worker, since each worker can
|
77
|
+
# handle arbitrary concurrency limits. We use a unique name for the pool
|
78
|
+
# and queue names to avoid conflicts if we are on a shared server and
|
79
|
+
# trying to run prefect locally.
|
80
|
+
types.ShellCmdSpec(
|
81
|
+
cmd="{0} prefect worker start "
|
82
|
+
"--pool={1} "
|
83
|
+
"--work-queue={2} &".format(
|
84
|
+
no_prompt,
|
85
|
+
self.cmdopts["work_pool"],
|
86
|
+
self.cmdopts["work_queue"],
|
87
|
+
),
|
88
|
+
shell=True,
|
89
|
+
wait=False,
|
90
|
+
),
|
91
|
+
types.ShellCmdSpec(
|
92
|
+
cmd="until prefect work-pool ls | grep -q 'sierra'; do sleep 1; done",
|
93
|
+
shell=True,
|
94
|
+
wait=True,
|
95
|
+
),
|
96
|
+
# Deploy SIERRA's local experiment execution flow. This flow
|
97
|
+
# executes all runs in all experiments in the batch in parallel. We
|
98
|
+
# use a unique name for the pool name to avoid conflicts if we are
|
99
|
+
# on a shared server and trying to run prefect locally.
|
100
|
+
types.ShellCmdSpec(
|
101
|
+
cmd="{0} prefect deploy {1}:sierra --name sierra/local --pool {2} --work-queue {3}".format(
|
102
|
+
no_prompt,
|
103
|
+
flow_path,
|
104
|
+
self.cmdopts["work_pool"],
|
105
|
+
self.cmdopts["work_queue"],
|
106
|
+
),
|
107
|
+
shell=True,
|
108
|
+
wait=True,
|
109
|
+
),
|
110
|
+
]
|
111
|
+
|
112
|
+
def exec_batch_cmds(self, exec_opts: types.StrDict) -> tp.List[types.ShellCmdSpec]:
|
113
|
+
# The needed flow is already present on the server as a deployment, so
|
114
|
+
# we can just run it directly as many times as we want. You don't need
|
115
|
+
# to set the queue/pool--it is inferred from the flow you are running.
|
116
|
+
flow_cmd = (
|
117
|
+
"prefect deployment run sierra/local "
|
118
|
+
'--params=\'{{"input_root": "{0}","scratch_root": "{1}"}}\' --watch'
|
119
|
+
)
|
120
|
+
# Since this execenv is batch level, so are the outputs and scratch
|
121
|
+
# dirs.
|
122
|
+
flow = flow_cmd.format(exec_opts["batch_root"], exec_opts["batch_scratch_root"])
|
123
|
+
spec = types.ShellCmdSpec(cmd=flow, shell=True, wait=True)
|
124
|
+
|
125
|
+
return [spec]
|
126
|
+
|
127
|
+
def post_batch_cmds(self) -> tp.List[types.ShellCmdSpec]:
|
128
|
+
return [
|
129
|
+
types.ShellCmdSpec(cmd="killall prefect || true", shell=True, wait=True),
|
130
|
+
]
|
131
|
+
|
132
|
+
|
133
|
+
__all__ = ["BatchShellCmdsGenerator"]
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Copyright 2021 John Harwell, All rights reserved.
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
"""
|
5
|
+
Container module for the Turtlebot3 robot execution environment plugin.
|
6
|
+
|
7
|
+
See :ref:`plugins/execenv/realrobot/turtlebot3`.
|
8
|
+
"""
|
9
|
+
|
10
|
+
# Core packages
|
11
|
+
|
12
|
+
# 3rd party packages
|
13
|
+
|
14
|
+
# Project packages
|
15
|
+
|
16
|
+
|
17
|
+
def sierra_plugin_type() -> str:
|
18
|
+
return "pipeline"
|
@@ -0,0 +1,204 @@
|
|
1
|
+
# Copyright 2021 John Harwell, All rights reserved.
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
"""
|
5
|
+
Robot plugin for running SIERRA with a set of Turtlebot3 robots.
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
# Core packages
|
10
|
+
import os
|
11
|
+
import logging
|
12
|
+
import typing as tp
|
13
|
+
import argparse
|
14
|
+
import shutil
|
15
|
+
import pathlib
|
16
|
+
|
17
|
+
# 3rd party packages
|
18
|
+
import implements
|
19
|
+
|
20
|
+
# Project packages
|
21
|
+
from sierra.core import types, execenv, utils
|
22
|
+
from sierra.core.experiment import bindings
|
23
|
+
|
24
|
+
_logger = logging.getLogger(__name__)
|
25
|
+
|
26
|
+
|
27
|
+
def cmdline_postparse_configure(args: argparse.Namespace) -> argparse.Namespace:
|
28
|
+
"""
|
29
|
+
Configure SIERRA for the turtlebot3 execution environment.
|
30
|
+
|
31
|
+
May use the following environment variables:
|
32
|
+
|
33
|
+
- :envvar:`SIERRA_NODEFILE` - If this is not defined ``--nodefile`` must be
|
34
|
+
passed.
|
35
|
+
"""
|
36
|
+
if args.nodefile is None:
|
37
|
+
assert "SIERRA_NODEFILE" in os.environ, (
|
38
|
+
"Non-robot.turtlebot3 environment detected: --nodefile not "
|
39
|
+
"passed and 'SIERRA_NODEFILE' not found"
|
40
|
+
)
|
41
|
+
args.nodefile = os.environ["SIERRA_NODEFILE"]
|
42
|
+
|
43
|
+
assert utils.path_exists(
|
44
|
+
args.nodefile
|
45
|
+
), f"SIERRA_NODEFILE '{args.nodefile}' does not exist"
|
46
|
+
_logger.info("Using '%s' as robot hostnames file", args.nodefile)
|
47
|
+
|
48
|
+
assert not args.engine_vc, "Engine visual capture not supported on robot.turtlebot3"
|
49
|
+
|
50
|
+
return args
|
51
|
+
|
52
|
+
|
53
|
+
@implements.implements(bindings.IExpShellCmdsGenerator)
|
54
|
+
class ExpShellCmdsGenerator:
|
55
|
+
"""Generate the cmds to invoke GNU Parallel to launch ROS on the turtlebots."""
|
56
|
+
|
57
|
+
def __init__(self, cmdopts: types.Cmdopts, exp_num: int) -> None:
|
58
|
+
self.cmdopts = cmdopts
|
59
|
+
self.exp_num = exp_num
|
60
|
+
|
61
|
+
def pre_exp_cmds(self) -> tp.List[types.ShellCmdSpec]:
|
62
|
+
return []
|
63
|
+
|
64
|
+
def post_exp_cmds(self) -> tp.List[types.ShellCmdSpec]:
|
65
|
+
return []
|
66
|
+
|
67
|
+
def exec_exp_cmds(self, exec_opts: types.StrDict) -> tp.List[types.ShellCmdSpec]:
|
68
|
+
jobid = os.getpid()
|
69
|
+
|
70
|
+
# Even if we are passed --nodelist, we still make our own copy of it, so
|
71
|
+
# that the user can safely modify it (if they want to) after running
|
72
|
+
# stage 1.
|
73
|
+
nodelist = pathlib.Path(
|
74
|
+
exec_opts["exp_input_root"], "{0}-nodelist.txt".format(jobid)
|
75
|
+
)
|
76
|
+
|
77
|
+
resume = ""
|
78
|
+
# This can't be --resume, because then GNU parallel looks at the results
|
79
|
+
# directory, and if there is stuff in it, (apparently) assumes that the
|
80
|
+
# job finished...
|
81
|
+
if exec_opts["exec_resume"]:
|
82
|
+
resume = "--resume-failed"
|
83
|
+
|
84
|
+
# Make sure there are no duplicate nodes
|
85
|
+
unique_nodes = types.ShellCmdSpec(
|
86
|
+
cmd="sort -u {0} > {1}".format(exec_opts["nodefile"], nodelist),
|
87
|
+
shell=True,
|
88
|
+
wait=True,
|
89
|
+
)
|
90
|
+
|
91
|
+
# Make sure GNU parallel uses the right shell, because it seems to
|
92
|
+
# defaults to /bin/sh since all cmds are run in a python shell which
|
93
|
+
# does not have $SHELL set.
|
94
|
+
use_bash = types.ShellCmdSpec(
|
95
|
+
cmd="export PARALLEL_SHELL={0}".format(shutil.which("bash")),
|
96
|
+
shell=True,
|
97
|
+
env=True,
|
98
|
+
wait=True,
|
99
|
+
)
|
100
|
+
|
101
|
+
ret = [use_bash, unique_nodes]
|
102
|
+
|
103
|
+
# 1 GNU parallel command to launch each experimental run, because each
|
104
|
+
# run might use all available nodes/robots.
|
105
|
+
for i in range(self.cmdopts["n_runs"]):
|
106
|
+
ret.extend(self._generate_for_run(i, exec_opts, resume, nodelist))
|
107
|
+
|
108
|
+
return ret
|
109
|
+
|
110
|
+
def _generate_for_run(
|
111
|
+
self, i: int, exec_opts: dict, resume: str, nodelist: pathlib.Path
|
112
|
+
) -> tp.List[types.ShellCmdSpec]:
|
113
|
+
ret = []
|
114
|
+
# GNU parallel cmd for robots (slaves)
|
115
|
+
robots = (
|
116
|
+
"parallel {2} "
|
117
|
+
"--jobs {1} "
|
118
|
+
"--results {4} "
|
119
|
+
"--joblog {3} "
|
120
|
+
"--sshloginfile {0} "
|
121
|
+
'--workdir {4} < "{5}"'
|
122
|
+
)
|
123
|
+
|
124
|
+
robots_ipath = (
|
125
|
+
exec_opts["cmdfile_stem_path"] + f"_run{i}_slave" + exec_opts["cmdfile_ext"]
|
126
|
+
)
|
127
|
+
|
128
|
+
robot_log = pathlib.Path(
|
129
|
+
exec_opts["exp_scratch_root"], f"parallel-slaves-run{i}.log"
|
130
|
+
)
|
131
|
+
|
132
|
+
robots = robots.format(
|
133
|
+
nodelist,
|
134
|
+
exec_opts["n_jobs"],
|
135
|
+
resume,
|
136
|
+
robot_log,
|
137
|
+
exec_opts["exp_scratch_root"],
|
138
|
+
robots_ipath,
|
139
|
+
)
|
140
|
+
|
141
|
+
# If no master is spawned, then we need to wait for this GNU
|
142
|
+
# parallel cmd. If the master is spawned, then we wait for THAT
|
143
|
+
# command; waiting for both results in the master never starting
|
144
|
+
# because that cmd is never run.
|
145
|
+
robots_spec = types.ShellCmdSpec(
|
146
|
+
cmd=robots, shell=True, wait=self.cmdopts["no_master_node"]
|
147
|
+
)
|
148
|
+
ret.append(robots_spec)
|
149
|
+
|
150
|
+
if not self.cmdopts["no_master_node"]:
|
151
|
+
ros_master = "parallel {3} --results {1} --joblog {0} '--workdir {1} < {2}'"
|
152
|
+
|
153
|
+
ros_master_ipath = (
|
154
|
+
exec_opts["cmdfile_stem_path"]
|
155
|
+
+ f"_run{i}_master"
|
156
|
+
+ exec_opts["cmdfile_ext"]
|
157
|
+
)
|
158
|
+
|
159
|
+
master_log = pathlib.Path(
|
160
|
+
exec_opts["exp_scratch_root"], f"parallel-master-run{i}.log"
|
161
|
+
)
|
162
|
+
ros_master = ros_master.format(
|
163
|
+
master_log, exec_opts["exp_scratch_root"], ros_master_ipath, resume
|
164
|
+
)
|
165
|
+
|
166
|
+
master_spec = types.ShellCmdSpec(
|
167
|
+
cmd=ros_master, shell=True, wait=not self.cmdopts["no_master_node"]
|
168
|
+
)
|
169
|
+
ret.append(master_spec)
|
170
|
+
|
171
|
+
wait = 'echo "{0} seconds until launching next run!"; ' "sleep {0}s ;".format(
|
172
|
+
self.cmdopts["exec_inter_run_pause"]
|
173
|
+
)
|
174
|
+
wait_spec = types.ShellCmdSpec(cmd=wait, shell=True, wait=True)
|
175
|
+
ret.append(wait_spec)
|
176
|
+
|
177
|
+
return ret
|
178
|
+
|
179
|
+
|
180
|
+
def execenv_check(cmdopts: types.Cmdopts) -> None:
|
181
|
+
"""
|
182
|
+
Verify execution environment in stage 2 for the :term:`ROS1+Robot` engine.
|
183
|
+
|
184
|
+
Checks that a valid list of IPs for robots is set/passed, and checks that
|
185
|
+
they are reachable.
|
186
|
+
"""
|
187
|
+
nodes = execenv.parse_nodefile(cmdopts["nodefile"])
|
188
|
+
for node in nodes:
|
189
|
+
if int(node.n_cores) != 1:
|
190
|
+
_logger.warning(
|
191
|
+
(
|
192
|
+
"Nodefile %s, host %s has multiple "
|
193
|
+
"cores; turtlebots are single core"
|
194
|
+
),
|
195
|
+
cmdopts["nodefile"],
|
196
|
+
node.hostname,
|
197
|
+
)
|
198
|
+
if not cmdopts["skip_online_check"]:
|
199
|
+
execenv.check_connectivity(
|
200
|
+
cmdopts, node.login, node.hostname, node.port, "turtlebot3"
|
201
|
+
)
|
202
|
+
|
203
|
+
|
204
|
+
__all__ = ["cmdline_postparse_configure", "execenv_check", "ExpShellCmdsGenerator"]
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Copyright 2024 John Harwell, All rights reserved.
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
"""
|
5
|
+
Container module for plugins related to :term:`Experiment` definitions.
|
6
|
+
|
7
|
+
Driven by ``--expdef``.
|
8
|
+
"""
|
9
|
+
|
10
|
+
# Core packages
|
11
|
+
|
12
|
+
# 3rd party packages
|
13
|
+
|
14
|
+
# Project packages
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Copyright 2024 John Harwell, All rights reserved.
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
"""Container module for the JSON expdef plugin."""
|
5
|
+
|
6
|
+
# Core packages
|
7
|
+
|
8
|
+
# 3rd party packages
|
9
|
+
|
10
|
+
# Project packages
|
11
|
+
|
12
|
+
|
13
|
+
def sierra_plugin_type() -> str:
|
14
|
+
return "pipeline"
|