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
@@ -1,337 +0,0 @@
|
|
1
|
-
# Copyright 2021 John Harwell, All rights reserved.
|
2
|
-
#
|
3
|
-
# SPDX-License-Identifier: MIT
|
4
|
-
|
5
|
-
# Core packages
|
6
|
-
import argparse
|
7
|
-
import os
|
8
|
-
import random
|
9
|
-
import typing as tp
|
10
|
-
import re
|
11
|
-
import shutil
|
12
|
-
import logging
|
13
|
-
import sys
|
14
|
-
import pathlib
|
15
|
-
import psutil
|
16
|
-
|
17
|
-
# 3rd party packages
|
18
|
-
import implements
|
19
|
-
import packaging.version
|
20
|
-
|
21
|
-
# Project packages
|
22
|
-
from sierra.plugins.platform.argos import cmdline
|
23
|
-
from sierra.core import hpc, config, types, utils, platform
|
24
|
-
from sierra.core.experiment import bindings, definition, xml
|
25
|
-
import sierra.core.variables.batch_criteria as bc
|
26
|
-
|
27
|
-
|
28
|
-
@implements.implements(bindings.ICmdlineParserGenerator)
|
29
|
-
class CmdlineParserGenerator():
|
30
|
-
"""
|
31
|
-
Get the cmdline parser to use with the :term:`ARGoS` platform.
|
32
|
-
|
33
|
-
Combination of the ARGoS cmdline extensions and the HPC cmdline.
|
34
|
-
"""
|
35
|
-
|
36
|
-
def __call__(self) -> argparse.ArgumentParser:
|
37
|
-
parser = hpc.cmdline.HPCCmdline([-1, 1, 2, 3, 4, 5]).parser
|
38
|
-
return cmdline.PlatformCmdline(parents=[parser],
|
39
|
-
stages=[-1, 1, 2, 3, 4, 5]).parser
|
40
|
-
|
41
|
-
|
42
|
-
@implements.implements(bindings.IParsedCmdlineConfigurer)
|
43
|
-
class ParsedCmdlineConfigurer():
|
44
|
-
def __init__(self, exec_env: str) -> None:
|
45
|
-
self.exec_env = exec_env
|
46
|
-
self.logger = logging.getLogger('platform.argos')
|
47
|
-
|
48
|
-
def __call__(self, args: argparse.Namespace) -> None:
|
49
|
-
# No configuration needed for stages 3-5
|
50
|
-
if not any(stage in args.pipeline for stage in [1, 2]):
|
51
|
-
return
|
52
|
-
|
53
|
-
if self.exec_env == 'hpc.local':
|
54
|
-
self._hpc_local(args)
|
55
|
-
elif self.exec_env == 'hpc.adhoc':
|
56
|
-
self._hpc_adhoc(args)
|
57
|
-
elif self.exec_env == 'hpc.slurm':
|
58
|
-
self._hpc_slurm(args)
|
59
|
-
elif self.exec_env == 'hpc.pbs':
|
60
|
-
self._hpc_pbs(args)
|
61
|
-
else:
|
62
|
-
raise RuntimeError(f"'{self.exec_env}' unsupported on ARGoS")
|
63
|
-
|
64
|
-
def _hpc_pbs(self, args: argparse.Namespace) -> None:
|
65
|
-
self.logger.debug("Configuring ARGoS for PBS execution")
|
66
|
-
# For HPC, we want to use the the maximum # of simultaneous jobs per
|
67
|
-
# node such that there is no thread oversubscription. We also always
|
68
|
-
# want to allocate each physics engine its own thread for maximum
|
69
|
-
# performance, per the original ARGoS paper.
|
70
|
-
#
|
71
|
-
# However, PBS does not have an environment variable for # jobs/node, so
|
72
|
-
# we have to rely on the user to set this appropriately.
|
73
|
-
args.physics_n_engines = int(
|
74
|
-
float(os.environ['PBS_NUM_PPN']) / args.exec_jobs_per_node)
|
75
|
-
|
76
|
-
self.logger.debug("Allocated %s physics engines/run, %s parallel runs/node",
|
77
|
-
args.physics_n_engines,
|
78
|
-
args.exec_jobs_per_node)
|
79
|
-
|
80
|
-
def _hpc_slurm(self, args: argparse.Namespace) -> None:
|
81
|
-
self.logger.debug("Configuring ARGoS for SLURM execution")
|
82
|
-
# For HPC, we want to use the the maximum # of simultaneous jobs per
|
83
|
-
# node such that there is no thread oversubscription. We also always
|
84
|
-
# want to allocate each physics engine its own thread for maximum
|
85
|
-
# performance, per the original ARGoS paper.
|
86
|
-
#
|
87
|
-
# We rely on the user to request their job intelligently so that
|
88
|
-
# SLURM_TASKS_PER_NODE is appropriate.
|
89
|
-
if args.exec_jobs_per_node is None:
|
90
|
-
res = re.search(r"^[^\(]+", os.environ['SLURM_TASKS_PER_NODE'])
|
91
|
-
assert res is not None, \
|
92
|
-
"Unexpected format in SLURM_TASKS_PER_NODE: '{0}'".format(
|
93
|
-
os.environ['SLURM_TASKS_PER_NODE'])
|
94
|
-
args.exec_jobs_per_node = int(res.group(0))
|
95
|
-
|
96
|
-
args.physics_n_engines = int(os.environ['SLURM_CPUS_PER_TASK'])
|
97
|
-
|
98
|
-
self.logger.debug("Allocated %s physics engines/run, %s parallel runs/node",
|
99
|
-
args.physics_n_engines,
|
100
|
-
args.exec_jobs_per_node)
|
101
|
-
|
102
|
-
def _hpc_local(self, args: argparse.Namespace) -> None:
|
103
|
-
self.logger.debug("Configuring ARGoS for LOCAL execution")
|
104
|
-
if any(stage in args.pipeline for stage in [1, 2]):
|
105
|
-
assert args.physics_n_engines is not None,\
|
106
|
-
'--physics-n-engines is required for --exec-env=hpc.local when running stage{1,2}'
|
107
|
-
|
108
|
-
ppn_per_run_req = args.physics_n_engines
|
109
|
-
|
110
|
-
if args.exec_jobs_per_node is None:
|
111
|
-
# Every physics engine gets at least 1 core
|
112
|
-
parallel_jobs = int(psutil.cpu_count() / float(ppn_per_run_req))
|
113
|
-
if parallel_jobs == 0:
|
114
|
-
self.logger.warning(("Local machine has %s logical cores, but "
|
115
|
-
"%s physics engines/run requested; "
|
116
|
-
"allocating anyway"),
|
117
|
-
psutil.cpu_count(),
|
118
|
-
ppn_per_run_req)
|
119
|
-
parallel_jobs = 1
|
120
|
-
|
121
|
-
# Make sure we don't oversubscribe cores--each simulation needs at
|
122
|
-
# least 1 core.
|
123
|
-
args.exec_jobs_per_node = min(args.n_runs, parallel_jobs)
|
124
|
-
|
125
|
-
self.logger.debug("Allocated %s physics engines/run, %s parallel runs/node",
|
126
|
-
args.physics_n_engines,
|
127
|
-
args.exec_jobs_per_node)
|
128
|
-
|
129
|
-
def _hpc_adhoc(self, args: argparse.Namespace) -> None:
|
130
|
-
self.logger.debug("Configuring ARGoS for ADHOC execution")
|
131
|
-
|
132
|
-
nodes = platform.ExecEnvChecker.parse_nodefile(args.nodefile)
|
133
|
-
ppn = sys.maxsize
|
134
|
-
for node in nodes:
|
135
|
-
ppn = min(ppn, node.n_cores)
|
136
|
-
|
137
|
-
# For HPC, we want to use the the maximum # of simultaneous jobs per
|
138
|
-
# node such that there is no thread oversubscription. We also always
|
139
|
-
# want to allocate each physics engine its own thread for maximum
|
140
|
-
# performance, per the original ARGoS paper.
|
141
|
-
if args.exec_jobs_per_node is None:
|
142
|
-
args.exec_jobs_per_node = int(float(args.n_runs) / len(nodes))
|
143
|
-
|
144
|
-
args.physics_n_engines = int(ppn / args.exec_jobs_per_node)
|
145
|
-
|
146
|
-
self.logger.debug("Allocated %s physics engines/run, %s parallel runs/node",
|
147
|
-
args.physics_n_engines,
|
148
|
-
args.exec_jobs_per_node)
|
149
|
-
|
150
|
-
|
151
|
-
@implements.implements(bindings.IExpRunShellCmdsGenerator)
|
152
|
-
class ExpRunShellCmdsGenerator():
|
153
|
-
def __init__(self,
|
154
|
-
cmdopts: types.Cmdopts,
|
155
|
-
criteria: bc.BatchCriteria,
|
156
|
-
n_robots: int,
|
157
|
-
exp_num: int) -> None:
|
158
|
-
self.cmdopts = cmdopts
|
159
|
-
self.display_port = -1
|
160
|
-
|
161
|
-
def pre_run_cmds(self,
|
162
|
-
host: str,
|
163
|
-
input_fpath: pathlib.Path,
|
164
|
-
run_num: int) -> tp.List[types.ShellCmdSpec]:
|
165
|
-
# When running ARGoS under Xvfb in order to headlessly render frames, we
|
166
|
-
# need to start a per-instance Xvfb server that we tell ARGoS to use via
|
167
|
-
# the DISPLAY environment variable, which will then be killed when the
|
168
|
-
# shell GNU parallel spawns to run each line in the commands file exits.
|
169
|
-
|
170
|
-
if host == 'slave':
|
171
|
-
if self.cmdopts['platform_vc']:
|
172
|
-
self.display_port = random.randint(0, 1000000)
|
173
|
-
cmd1 = f"Xvfb :{self.display_port} -screen 0, 1600x1200x24 &"
|
174
|
-
cmd2 = f"export DISPLAY=:{self.display_port};"
|
175
|
-
spec1 = types.ShellCmdSpec(cmd=cmd1, shell=True, wait=True)
|
176
|
-
spec2 = types.ShellCmdSpec(cmd=cmd2,
|
177
|
-
shell=True,
|
178
|
-
wait=True,
|
179
|
-
env=True)
|
180
|
-
return [spec1, spec2]
|
181
|
-
|
182
|
-
return []
|
183
|
-
|
184
|
-
def exec_run_cmds(self,
|
185
|
-
host: str,
|
186
|
-
input_fpath: pathlib.Path,
|
187
|
-
run_num: int) -> tp.List[types.ShellCmdSpec]:
|
188
|
-
shellname = platform.get_executable_shellname(config.kARGoS['launch_cmd'])
|
189
|
-
cmd = '{0} -c {1}{2}'.format(shellname,
|
190
|
-
str(input_fpath),
|
191
|
-
config.kARGoS['launch_file_ext'])
|
192
|
-
|
193
|
-
# ARGoS is pretty good about not printing stuff if we pass these
|
194
|
-
# arguments. We don't want to pass > /dev/null so that we get the
|
195
|
-
# text of any exceptions that cause ARGoS to crash.
|
196
|
-
if self.cmdopts['exec_devnull']:
|
197
|
-
cmd += ' --log-file /dev/null --logerr-file /dev/null'
|
198
|
-
|
199
|
-
cmd += ';'
|
200
|
-
|
201
|
-
return [types.ShellCmdSpec(cmd=cmd, shell=True, wait=True)]
|
202
|
-
|
203
|
-
def post_run_cmds(self, host: str) -> tp.List[types.ShellCmdSpec]:
|
204
|
-
return []
|
205
|
-
|
206
|
-
|
207
|
-
@implements.implements(bindings.IExpShellCmdsGenerator)
|
208
|
-
class ExpShellCmdsGenerator():
|
209
|
-
def __init__(self,
|
210
|
-
cmdopts: types.Cmdopts,
|
211
|
-
exp_num: int) -> None:
|
212
|
-
self.cmdopts = cmdopts
|
213
|
-
|
214
|
-
def pre_exp_cmds(self) -> tp.List[types.ShellCmdSpec]:
|
215
|
-
return []
|
216
|
-
|
217
|
-
def exec_exp_cmds(self, exec_opts: types.StrDict) -> tp.List[types.ShellCmdSpec]:
|
218
|
-
return []
|
219
|
-
|
220
|
-
def post_exp_cmds(self) -> tp.List[types.ShellCmdSpec]:
|
221
|
-
# Cleanup Xvfb processes which were started in the background. If SIERRA
|
222
|
-
# was run with --exec-resume, then there may be no Xvfb processes to
|
223
|
-
# kill, so we can't (in general) check the return code.
|
224
|
-
if self.cmdopts['platform_vc']:
|
225
|
-
return [types.ShellCmdSpec(cmd='killall Xvfb', shell=True, wait=True)]
|
226
|
-
|
227
|
-
return []
|
228
|
-
|
229
|
-
|
230
|
-
@implements.implements(bindings.IExpConfigurer)
|
231
|
-
class ExpConfigurer():
|
232
|
-
def __init__(self, cmdopts: types.Cmdopts) -> None:
|
233
|
-
self.cmdopts = cmdopts
|
234
|
-
|
235
|
-
def for_exp_run(self,
|
236
|
-
exp_input_root: pathlib.Path,
|
237
|
-
run_output_root: pathlib.Path) -> None:
|
238
|
-
if self.cmdopts['platform_vc']:
|
239
|
-
argos = config.kRendering['argos']
|
240
|
-
frames_fpath = run_output_root / argos['frames_leaf']
|
241
|
-
utils.dir_create_checked(frames_fpath, exist_ok=True)
|
242
|
-
|
243
|
-
def for_exp(self, exp_input_root: pathlib.Path) -> None:
|
244
|
-
pass
|
245
|
-
|
246
|
-
def cmdfile_paradigm(self) -> str:
|
247
|
-
return 'per-exp'
|
248
|
-
|
249
|
-
|
250
|
-
@implements.implements(bindings.IExecEnvChecker)
|
251
|
-
class ExecEnvChecker(platform.ExecEnvChecker):
|
252
|
-
def __init__(self, cmdopts: types.Cmdopts) -> None:
|
253
|
-
super().__init__(cmdopts)
|
254
|
-
self.logger = logging.getLogger('platform.argos')
|
255
|
-
|
256
|
-
def __call__(self) -> None:
|
257
|
-
keys = ['ARGOS_PLUGIN_PATH']
|
258
|
-
|
259
|
-
for k in keys:
|
260
|
-
assert k in os.environ, \
|
261
|
-
f"Non-ARGoS environment detected: '{k}' not found"
|
262
|
-
|
263
|
-
# Check we can find ARGoS
|
264
|
-
proc = self.check_for_simulator(config.kARGoS['launch_cmd'])
|
265
|
-
|
266
|
-
# Check ARGoS version
|
267
|
-
stdout = proc.stdout.decode('utf-8')
|
268
|
-
stderr = proc.stderr.decode('utf-8')
|
269
|
-
res = re.search(r'[0-9]+.[0-9]+.[0-9]+-beta[0-9]+', stdout)
|
270
|
-
assert res is not None, \
|
271
|
-
f"ARGOS_VERSION not in stdout: stdout='{stdout}',stderr='{stderr}'"
|
272
|
-
|
273
|
-
self.logger.trace("Parsed ARGOS_VERSION: %s", # type: ignore
|
274
|
-
res.group(0))
|
275
|
-
|
276
|
-
version = packaging.version.parse(res.group(0))
|
277
|
-
min_version = config.kARGoS['min_version']
|
278
|
-
|
279
|
-
assert version >= min_version,\
|
280
|
-
f"ARGoS version {version} < min required {min_version}"
|
281
|
-
|
282
|
-
if self.cmdopts['platform_vc']:
|
283
|
-
assert shutil.which('Xvfb') is not None, "Xvfb not found"
|
284
|
-
|
285
|
-
|
286
|
-
def population_size_from_pickle(chgs: tp.Union[xml.AttrChangeSet,
|
287
|
-
xml.TagAddList],
|
288
|
-
main_config: types.YAMLDict,
|
289
|
-
cmdopts: types.Cmdopts) -> int:
|
290
|
-
for path, attr, value in chgs:
|
291
|
-
if path == ".//arena/distribute/entity" and attr == "quantity":
|
292
|
-
return int(value)
|
293
|
-
|
294
|
-
return -1
|
295
|
-
|
296
|
-
|
297
|
-
def arena_dims_from_criteria(criteria: bc.BatchCriteria) -> tp.List[utils.ArenaExtent]:
|
298
|
-
dims = []
|
299
|
-
for exp in criteria.gen_attr_changelist():
|
300
|
-
for c in exp:
|
301
|
-
if c.path == ".//arena" and c.attr == "size":
|
302
|
-
d = utils.Vector3D.from_str(c.value)
|
303
|
-
dims.append(utils.ArenaExtent(d))
|
304
|
-
|
305
|
-
assert len(dims) > 0,\
|
306
|
-
"Scenario dimensions not contained in batch criteria"
|
307
|
-
|
308
|
-
return dims
|
309
|
-
|
310
|
-
|
311
|
-
def robot_type_from_def(exp_def: definition.XMLExpDef) -> tp.Optional[str]:
|
312
|
-
"""
|
313
|
-
Get the entity type of the robots managed by ARGoS.
|
314
|
-
|
315
|
-
.. NOTE:: Assumes homgeneous systems.
|
316
|
-
"""
|
317
|
-
for robot in config.kARGoS['spatial_hash2D']:
|
318
|
-
if exp_def.has_tag(f'.//arena/distribute/entity/{robot}'):
|
319
|
-
return robot
|
320
|
-
|
321
|
-
return None
|
322
|
-
|
323
|
-
|
324
|
-
def population_size_from_def(exp_def: definition.XMLExpDef,
|
325
|
-
main_config: types.YAMLDict,
|
326
|
-
cmdopts: types.Cmdopts) -> int:
|
327
|
-
return population_size_from_pickle(exp_def.attr_chgs, main_config, cmdopts)
|
328
|
-
|
329
|
-
|
330
|
-
def pre_exp_diagnostics(cmdopts: types.Cmdopts,
|
331
|
-
logger: logging.Logger) -> None:
|
332
|
-
s = "batch_exp_root='%s',runs/exp=%s,threads/job=%s,n_jobs=%s"
|
333
|
-
logger.info(s,
|
334
|
-
cmdopts['batch_root'],
|
335
|
-
cmdopts['n_runs'],
|
336
|
-
cmdopts['physics_n_threads'],
|
337
|
-
cmdopts['exec_jobs_per_node'])
|
@@ -1,145 +0,0 @@
|
|
1
|
-
# Copyright 2018 John Harwell, All rights reserved.
|
2
|
-
#
|
3
|
-
# SPDX-License-Identifier: MIT
|
4
|
-
|
5
|
-
# Core packages
|
6
|
-
import typing as tp
|
7
|
-
|
8
|
-
# 3rd party packages
|
9
|
-
import implements
|
10
|
-
|
11
|
-
# Project packages
|
12
|
-
from sierra.core.variables.base_variable import IBaseVariable
|
13
|
-
from sierra.core.utils import ArenaExtent
|
14
|
-
from sierra.core.experiment import xml
|
15
|
-
|
16
|
-
kWALL_WIDTH = 0.4
|
17
|
-
|
18
|
-
|
19
|
-
@implements.implements(IBaseVariable)
|
20
|
-
class ArenaShape():
|
21
|
-
|
22
|
-
"""Maps a list of desired arena dimensions sets of XML changes.
|
23
|
-
|
24
|
-
This class is a base class which should (almost) never be used on its
|
25
|
-
own. Instead, derived classes defined in this file should be used instead.
|
26
|
-
|
27
|
-
Attributes:
|
28
|
-
|
29
|
-
extents: List of arena extents.
|
30
|
-
|
31
|
-
"""
|
32
|
-
|
33
|
-
def __init__(self, extents: tp.List[ArenaExtent]) -> None:
|
34
|
-
self.extents = extents
|
35
|
-
self.attr_changes = [] # type: tp.List[xml.AttrChangeSet]
|
36
|
-
|
37
|
-
def gen_attr_changelist(self) -> tp.List[xml.AttrChangeSet]:
|
38
|
-
"""Generate changes necessary setup ARGoS with the specified arena sizes.
|
39
|
-
|
40
|
-
"""
|
41
|
-
if not self.attr_changes:
|
42
|
-
for extent in self.extents:
|
43
|
-
self.attr_changes.append(self._gen_chgs_for_extent(extent))
|
44
|
-
|
45
|
-
return self.attr_changes
|
46
|
-
|
47
|
-
def _gen_chgs_for_extent(self, extent: ArenaExtent) -> xml.AttrChangeSet:
|
48
|
-
|
49
|
-
xsize = extent.xsize()
|
50
|
-
ysize = extent.ysize()
|
51
|
-
zsize = extent.zsize()
|
52
|
-
|
53
|
-
chgs = xml.AttrChangeSet(xml.AttrChange(".//arena",
|
54
|
-
"size",
|
55
|
-
f"{xsize},{ysize},{zsize}"),
|
56
|
-
xml.AttrChange(".//arena",
|
57
|
-
"center",
|
58
|
-
"{0:.9f},{1:.9f},{2}".format(xsize / 2.0,
|
59
|
-
ysize / 2.0,
|
60
|
-
zsize / 2.0)))
|
61
|
-
|
62
|
-
# We restrict the places robots can spawn within the arena as follows:
|
63
|
-
#
|
64
|
-
# - Subtract width of the walls so that robots do not spawn inside walls
|
65
|
-
# (which ARGoS seems to allow?).
|
66
|
-
#
|
67
|
-
# - Subtract a little bit more so robots don't get into weird states by
|
68
|
-
# being near arena boundaries on the first timestep.
|
69
|
-
#
|
70
|
-
# - All robots start on the ground with Z=0.
|
71
|
-
chgs.add(xml.AttrChange(".//arena/distribute/position",
|
72
|
-
"max",
|
73
|
-
"{0:.9f}, {1:.9f}, 0".format(
|
74
|
-
xsize - 2.0 * kWALL_WIDTH * 1.1,
|
75
|
-
ysize - 2.0 * kWALL_WIDTH * 1.1)
|
76
|
-
))
|
77
|
-
chgs.add(xml.AttrChange(".//arena/distribute/position",
|
78
|
-
"min",
|
79
|
-
"{0:.9f}, {1:.9f}, 0".format(
|
80
|
-
2.0 * kWALL_WIDTH * 1.1,
|
81
|
-
2.0 * kWALL_WIDTH * 1.1)
|
82
|
-
))
|
83
|
-
|
84
|
-
chgs.add(xml.AttrChange(".//arena/*[@id='wall_north']",
|
85
|
-
"size",
|
86
|
-
"{0:.9f}, {1:.9f}, 0.5".format(xsize,
|
87
|
-
kWALL_WIDTH)))
|
88
|
-
|
89
|
-
chgs.add(xml.AttrChange(".//arena/*[@id='wall_north']/body",
|
90
|
-
"position",
|
91
|
-
"{0:.9f}, {1:.9f}, 0".format(xsize / 2.0, ysize)))
|
92
|
-
chgs.add(xml.AttrChange(".//arena/*[@id='wall_south']",
|
93
|
-
"size",
|
94
|
-
"{0:.9f}, {1:.9f}, 0.5".format(xsize, kWALL_WIDTH)))
|
95
|
-
|
96
|
-
chgs.add(xml.AttrChange(".//arena/*[@id='wall_north']/body",
|
97
|
-
"position",
|
98
|
-
"{0:.9f}, {1:.9f}, 0".format(xsize / 2.0, ysize)))
|
99
|
-
chgs.add(xml.AttrChange(".//arena/*[@id='wall_south']",
|
100
|
-
"size",
|
101
|
-
"{0:.9f}, {1:.9f}, 0.5".format(xsize, kWALL_WIDTH)))
|
102
|
-
chgs.add(xml.AttrChange(".//arena/*[@id='wall_south']/body",
|
103
|
-
"position",
|
104
|
-
"{0:.9f}, 0, 0 ".format(xsize / 2.0)))
|
105
|
-
|
106
|
-
# East wall needs to have its X coordinate offset by the width of the
|
107
|
-
# wall / 2 in order to be centered on the boundary for the arena. This
|
108
|
-
# is necessary to ensure that the maximum X coordinate that robots can
|
109
|
-
# access is LESS than the upper boundary of physics engines incident
|
110
|
-
# along the east wall.
|
111
|
-
#
|
112
|
-
# I think this is a bug in ARGoS.
|
113
|
-
chgs.add(xml.AttrChange(".//arena/*[@id='wall_east']",
|
114
|
-
"size",
|
115
|
-
"{0:.9f}, {1:.9f}, 0.5".format(kWALL_WIDTH,
|
116
|
-
ysize + kWALL_WIDTH)))
|
117
|
-
chgs.add(xml.AttrChange(".//arena/*[@id='wall_east']/body",
|
118
|
-
"position",
|
119
|
-
"{0:.9f}, {1:.9f}, 0".format(xsize - kWALL_WIDTH / 2.0,
|
120
|
-
ysize / 2.0)))
|
121
|
-
|
122
|
-
chgs.add(xml.AttrChange(".//arena/*[@id='wall_west']",
|
123
|
-
"size",
|
124
|
-
"{0:.9f}, {1:.9f}, 0.5".format(kWALL_WIDTH,
|
125
|
-
ysize + kWALL_WIDTH)))
|
126
|
-
chgs.add(xml.AttrChange(".//arena/*[@id='wall_west']/body",
|
127
|
-
"position",
|
128
|
-
"0, {0:.9f}, 0".format(ysize / 2.0)))
|
129
|
-
|
130
|
-
return chgs
|
131
|
-
|
132
|
-
def gen_tag_rmlist(self) -> tp.List[xml.TagRmList]:
|
133
|
-
return []
|
134
|
-
|
135
|
-
def gen_tag_addlist(self) -> tp.List[xml.TagAddList]:
|
136
|
-
return []
|
137
|
-
|
138
|
-
def gen_files(self) -> None:
|
139
|
-
pass
|
140
|
-
|
141
|
-
|
142
|
-
__api__ = [
|
143
|
-
'kWALL_WIDTH',
|
144
|
-
'ArenaShape',
|
145
|
-
]
|