sierra-research 1.3.11__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.11.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 -251
- sierra/core/graphs/stacked_surface_graph.py +0 -220
- sierra/core/graphs/summary_line_graph.py +0 -371
- 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 -320
- 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.11.data/data/share/man/man1/sierra-cli.1 +0 -2349
- sierra_research-1.3.11.data/data/share/man/man7/sierra-examples.7 +0 -508
- sierra_research-1.3.11.data/data/share/man/man7/sierra-exec-envs.7 +0 -331
- sierra_research-1.3.11.data/data/share/man/man7/sierra-glossary.7 +0 -285
- sierra_research-1.3.11.data/data/share/man/man7/sierra-platforms.7 +0 -358
- sierra_research-1.3.11.data/data/share/man/man7/sierra-usage.7 +0 -729
- sierra_research-1.3.11.data/data/share/man/man7/sierra.7 +0 -78
- sierra_research-1.3.11.dist-info/METADATA +0 -492
- sierra_research-1.3.11.dist-info/RECORD +0 -133
- sierra_research-1.3.11.dist-info/top_level.txt +0 -1
- {sierra_research-1.3.11.dist-info → sierra_research-1.5.0.dist-info}/entry_points.txt +0 -0
- {sierra_research-1.3.11.dist-info → sierra_research-1.5.0.dist-info/licenses}/LICENSE +0 -0
@@ -1,175 +0,0 @@
|
|
1
|
-
# Copyright 2021 John Harwell, All rights reserved.
|
2
|
-
#
|
3
|
-
# SPDX-License-Identifier: MIT
|
4
|
-
#
|
5
|
-
"""
|
6
|
-
Command line parsing and validation for the :term:`ROS1+robot` platform.
|
7
|
-
"""
|
8
|
-
|
9
|
-
# Core packages
|
10
|
-
import typing as tp
|
11
|
-
import argparse
|
12
|
-
|
13
|
-
# 3rd party packages
|
14
|
-
|
15
|
-
# Project packages
|
16
|
-
from sierra.core import types, ros1, config
|
17
|
-
import sierra.core.cmdline as cmd
|
18
|
-
|
19
|
-
|
20
|
-
class PlatformCmdline(cmd.BaseCmdline):
|
21
|
-
"""Defines :term:`ROS1` extensions to :class:`~sierra.core.cmdline.CoreCmdline`.
|
22
|
-
|
23
|
-
"""
|
24
|
-
|
25
|
-
def __init__(self,
|
26
|
-
parents: tp.Optional[tp.List[argparse.ArgumentParser]],
|
27
|
-
stages: tp.List[int]) -> None:
|
28
|
-
|
29
|
-
if parents is not None:
|
30
|
-
self.parser = argparse.ArgumentParser(parents=parents,
|
31
|
-
add_help=False,
|
32
|
-
allow_abbrev=False)
|
33
|
-
else:
|
34
|
-
self.parser = argparse.ArgumentParser(add_help=False,
|
35
|
-
allow_abbrev=False)
|
36
|
-
|
37
|
-
self.scaffold_cli()
|
38
|
-
self.init_cli(stages)
|
39
|
-
|
40
|
-
def scaffold_cli(self) -> None:
|
41
|
-
self.multistage = self.parser.add_argument_group('Multi-stage options',
|
42
|
-
'Options which are used in multiple pipeline stages')
|
43
|
-
self.stage1 = self.parser.add_argument_group('Stage1: Experiment generation')
|
44
|
-
self.stage2 = self.parser.add_argument_group('Stage2: Experiment execution'
|
45
|
-
'For running real robot experiments')
|
46
|
-
|
47
|
-
def init_cli(self, stages: tp.List[int]) -> None:
|
48
|
-
if -1 in stages:
|
49
|
-
self.init_multistage()
|
50
|
-
|
51
|
-
if 1 in stages:
|
52
|
-
self.init_stage1()
|
53
|
-
|
54
|
-
if 2 in stages:
|
55
|
-
self.init_stage2()
|
56
|
-
|
57
|
-
def init_multistage(self) -> None:
|
58
|
-
self.multistage.add_argument("--skip-online-check",
|
59
|
-
help="""
|
60
|
-
|
61
|
-
If passed, then the usual 'is this robot
|
62
|
-
online' checks will be skipped.
|
63
|
-
|
64
|
-
""" + self.stage_usage_doc([1, 2]),
|
65
|
-
action='store_true')
|
66
|
-
|
67
|
-
self.multistage.add_argument("--online-check-method",
|
68
|
-
choices=['ping+ssh', 'nc+ssh'],
|
69
|
-
help="""
|
70
|
-
|
71
|
-
How SIERRA should check if a given robot is
|
72
|
-
online. Valid values:
|
73
|
-
|
74
|
-
- ``ping+ssh`` - First, verify that you can
|
75
|
-
ping each the hostname/IP associated with
|
76
|
-
each robot. Second, verify that
|
77
|
-
passwordless ssh to the hostname/IP
|
78
|
-
works. This is the most common option.
|
79
|
-
|
80
|
-
- ``nc+ssh`` - First, verify that an ssh
|
81
|
-
connection exists from the SIERRA host
|
82
|
-
machine to the robot on the specified
|
83
|
-
port using netcat. Second, verify that
|
84
|
-
passwordless ssh to the robot on the
|
85
|
-
specified port works. This is useful when
|
86
|
-
connecting to the robots through a
|
87
|
-
reverse SSH tunnel, which can be
|
88
|
-
necessary if the robots don't have a
|
89
|
-
fixed IP address and cannot be addressed
|
90
|
-
by FQDN (looking at you eduroam...).
|
91
|
-
|
92
|
-
""",
|
93
|
-
default='ping+ssh')
|
94
|
-
|
95
|
-
def init_stage1(self) -> None:
|
96
|
-
self.stage1.add_argument("--skip-sync",
|
97
|
-
help="""
|
98
|
-
|
99
|
-
If passed, then the generated experiment will not
|
100
|
-
be synced to robots. This is useful when:
|
101
|
-
|
102
|
-
- You are developing your :term:`Project` and
|
103
|
-
just want to check locally if the experiment
|
104
|
-
is being generated properly.
|
105
|
-
|
106
|
-
- You have a lot of robots and/or the network
|
107
|
-
connection from the SIERRA host machine to
|
108
|
-
the robots is slow, and copying the
|
109
|
-
experiment multiple times as you tweak
|
110
|
-
parameters takes a long time.
|
111
|
-
|
112
|
-
""" + self.stage_usage_doc([1]),
|
113
|
-
action='store_true')
|
114
|
-
|
115
|
-
def init_stage2(self) -> None:
|
116
|
-
self.stage2.add_argument("--exec-inter-run-pause",
|
117
|
-
metavar="SECONDS",
|
118
|
-
help="""
|
119
|
-
|
120
|
-
How long to pause between :term:`Experimental
|
121
|
-
Runs <Experimental Run>`, giving you time to
|
122
|
-
reset the environment, move robots, etc.
|
123
|
-
|
124
|
-
""" + self.stage_usage_doc([2]),
|
125
|
-
type=int,
|
126
|
-
default=config.kROS['inter_run_pause'])
|
127
|
-
|
128
|
-
self.stage2.add_argument("--exec-resume",
|
129
|
-
help="""
|
130
|
-
|
131
|
-
Resume a batch experiment that was
|
132
|
-
killed/stopped/etc last time SIERRA was
|
133
|
-
run.
|
134
|
-
|
135
|
-
""" + self.stage_usage_doc([2]),
|
136
|
-
action='store_true',
|
137
|
-
default=False)
|
138
|
-
|
139
|
-
@staticmethod
|
140
|
-
def cmdopts_update(cli_args, cmdopts: types.Cmdopts) -> None:
|
141
|
-
"""Update cmdopts with ROS1+robot-specific cmdline options.
|
142
|
-
|
143
|
-
"""
|
144
|
-
ros1.cmdline.ROSCmdline.cmdopts_update(cli_args, cmdopts)
|
145
|
-
updates = {
|
146
|
-
# Multistage
|
147
|
-
'exec_jobs_per_node': 1, # (1 job/robot)
|
148
|
-
'skip_online_check': cli_args.skip_online_check,
|
149
|
-
'online_check_method': cli_args.online_check_method,
|
150
|
-
|
151
|
-
# stage 1
|
152
|
-
'skip_sync': cli_args.skip_sync,
|
153
|
-
|
154
|
-
# stage 2
|
155
|
-
'exec_resume': cli_args.exec_resume,
|
156
|
-
'exec_inter_run_pause': cli_args.exec_inter_run_pause
|
157
|
-
}
|
158
|
-
|
159
|
-
cmdopts.update(updates)
|
160
|
-
|
161
|
-
|
162
|
-
class CmdlineValidator(ros1.cmdline.ROSCmdlineValidator):
|
163
|
-
"""
|
164
|
-
Stub implementation.
|
165
|
-
"""
|
166
|
-
|
167
|
-
|
168
|
-
def sphinx_cmdline_stage1():
|
169
|
-
parent = ros1.cmdline.ROSCmdline([1]).parser
|
170
|
-
return PlatformCmdline([parent], [1]).parser
|
171
|
-
|
172
|
-
|
173
|
-
def sphinx_cmdline_stage2():
|
174
|
-
parent = ros1.cmdline.ROSCmdline([2]).parser
|
175
|
-
return PlatformCmdline([parent], [2]).parser
|
@@ -1,112 +0,0 @@
|
|
1
|
-
# Copyright 2021 John Harwell, All rights reserved.
|
2
|
-
#
|
3
|
-
# SPDX-License-Identifier: MIT
|
4
|
-
"""Classes for generating common XML modifications to :term:`ROS1` input files.
|
5
|
-
|
6
|
-
I.e., changes which are platform-specific, but applicable to all projects using
|
7
|
-
ROS with a real robot execution environment.
|
8
|
-
|
9
|
-
"""
|
10
|
-
# Core packages
|
11
|
-
import logging
|
12
|
-
import pathlib
|
13
|
-
|
14
|
-
# 3rd party packages
|
15
|
-
import yaml
|
16
|
-
|
17
|
-
# Project packages
|
18
|
-
from sierra.core.experiment import spec, xml, definition
|
19
|
-
from sierra.core import types, ros1, config, utils
|
20
|
-
|
21
|
-
|
22
|
-
class PlatformExpDefGenerator(ros1.generators.ROSExpDefGenerator):
|
23
|
-
"""
|
24
|
-
Init the object.
|
25
|
-
|
26
|
-
Attributes:
|
27
|
-
|
28
|
-
controller: The controller used for the experiment.
|
29
|
-
cmdopts: Dictionary of parsed cmdline parameters.
|
30
|
-
"""
|
31
|
-
|
32
|
-
def __init__(self,
|
33
|
-
exp_spec: spec.ExperimentSpec,
|
34
|
-
controller: str,
|
35
|
-
cmdopts: types.Cmdopts,
|
36
|
-
**kwargs) -> None:
|
37
|
-
super().__init__(exp_spec, controller, cmdopts, **kwargs)
|
38
|
-
|
39
|
-
self.logger = logging.getLogger(__name__)
|
40
|
-
|
41
|
-
def generate(self) -> definition.XMLExpDef:
|
42
|
-
exp_def = super().generate()
|
43
|
-
|
44
|
-
self.logger.debug("Writing separate <master> launch file")
|
45
|
-
exp_def.write_config.add({
|
46
|
-
'src_parent': '.',
|
47
|
-
'src_tag': 'master',
|
48
|
-
'opath_leaf': '_master' + config.kROS['launch_file_ext'],
|
49
|
-
'create_tags': None,
|
50
|
-
'rename_to': 'launch',
|
51
|
-
'dest_parent': None
|
52
|
-
})
|
53
|
-
|
54
|
-
# Add <robot> tag
|
55
|
-
if not exp_def.has_tag("./robot"):
|
56
|
-
exp_def.tag_add(".",
|
57
|
-
"robot",
|
58
|
-
{})
|
59
|
-
if not exp_def.has_tag("./robot/group/[@ns='sierra']"):
|
60
|
-
exp_def.tag_add("./robot",
|
61
|
-
"group",
|
62
|
-
{
|
63
|
-
'ns': 'sierra'
|
64
|
-
})
|
65
|
-
|
66
|
-
return exp_def
|
67
|
-
|
68
|
-
|
69
|
-
class PlatformExpRunDefUniqueGenerator(ros1.generators.ROSExpRunDefUniqueGenerator):
|
70
|
-
def __init__(self,
|
71
|
-
*args,
|
72
|
-
**kwargs) -> None:
|
73
|
-
ros1.generators.ROSExpRunDefUniqueGenerator.__init__(
|
74
|
-
self, *args, **kwargs)
|
75
|
-
|
76
|
-
def generate(self, exp_def: definition.XMLExpDef):
|
77
|
-
exp_def = super().generate(exp_def)
|
78
|
-
main_path = pathlib.Path(self.cmdopts['project_config_root'],
|
79
|
-
config.kYAML.main)
|
80
|
-
|
81
|
-
with utils.utf8open(main_path) as f:
|
82
|
-
main_config = yaml.load(f, yaml.FullLoader)
|
83
|
-
|
84
|
-
n_robots = utils.get_n_robots(main_config,
|
85
|
-
self.cmdopts,
|
86
|
-
self.launch_stem_path.parent,
|
87
|
-
exp_def)
|
88
|
-
|
89
|
-
for i in range(0, n_robots):
|
90
|
-
prefix = main_config['ros']['robots'][self.cmdopts['robot']]['prefix']
|
91
|
-
exp_def.write_config.add({
|
92
|
-
'src_parent': "./robot",
|
93
|
-
'src_tag': f"group/[@ns='{prefix}{i}']",
|
94
|
-
'opath_leaf': f'_robot{i}' + config.kROS['launch_file_ext'],
|
95
|
-
'create_tags': [xml.TagAdd.as_root('launch', {})],
|
96
|
-
'dest_parent': ".",
|
97
|
-
'rename_to': None,
|
98
|
-
'child_grafts': ["./robot/group/[@ns='sierra']"]
|
99
|
-
})
|
100
|
-
|
101
|
-
self.generate_random(exp_def)
|
102
|
-
self.generate_paramfile(exp_def)
|
103
|
-
|
104
|
-
return exp_def
|
105
|
-
|
106
|
-
|
107
|
-
__api__ = [
|
108
|
-
'PlatformExpDefGenerator',
|
109
|
-
'PlatformExpRunDefUniqueGenerator'
|
110
|
-
|
111
|
-
|
112
|
-
]
|
@@ -1,373 +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 logging
|
8
|
-
import typing as tp
|
9
|
-
import os
|
10
|
-
import subprocess
|
11
|
-
import pwd
|
12
|
-
import pathlib
|
13
|
-
|
14
|
-
# 3rd party packages
|
15
|
-
import implements
|
16
|
-
import yaml
|
17
|
-
|
18
|
-
# Project packages
|
19
|
-
from sierra.plugins.platform.ros1robot import cmdline
|
20
|
-
from sierra.core import platform, config, ros1, types, utils
|
21
|
-
from sierra.core.experiment import bindings, definition, xml
|
22
|
-
import sierra.core.variables.batch_criteria as bc
|
23
|
-
|
24
|
-
|
25
|
-
class CmdlineParserGenerator():
|
26
|
-
def __call__(self) -> argparse.ArgumentParser:
|
27
|
-
parent1 = ros1.cmdline.ROSCmdline([-1, 1, 2, 3, 4, 5]).parser
|
28
|
-
return cmdline.PlatformCmdline(parents=[parent1],
|
29
|
-
stages=[-1, 1, 2, 3, 4, 5]).parser
|
30
|
-
|
31
|
-
|
32
|
-
@implements.implements(bindings.IParsedCmdlineConfigurer)
|
33
|
-
class ParsedCmdlineConfigurer():
|
34
|
-
def __init__(self, exec_env: str) -> None:
|
35
|
-
self.exec_env = exec_env
|
36
|
-
self.logger = logging.getLogger('platform.ros1robot')
|
37
|
-
|
38
|
-
def __call__(self, args: argparse.Namespace) -> None:
|
39
|
-
if args.nodefile is None:
|
40
|
-
assert 'SIERRA_NODEFILE' in os.environ,\
|
41
|
-
("Non-ros1robot environment detected: --nodefile not "
|
42
|
-
"passed and 'SIERRA_NODEFILE' not found")
|
43
|
-
args.nodefile = os.environ['SIERRA_NODEFILE']
|
44
|
-
|
45
|
-
assert utils.path_exists(args.nodefile), \
|
46
|
-
f"SIERRA_NODEFILE '{args.nodefile}' does not exist"
|
47
|
-
self.logger.info("Using '%s' as robot hostnames file", args.nodefile)
|
48
|
-
|
49
|
-
assert not args.platform_vc,\
|
50
|
-
"Platform visual capture not supported on ros1robot"
|
51
|
-
|
52
|
-
|
53
|
-
@implements.implements(bindings.IExpRunShellCmdsGenerator)
|
54
|
-
class ExpRunShellCmdsGenerator():
|
55
|
-
def __init__(self,
|
56
|
-
cmdopts: types.Cmdopts,
|
57
|
-
criteria: bc.BatchCriteria,
|
58
|
-
n_robots: int,
|
59
|
-
exp_num: int) -> None:
|
60
|
-
self.cmdopts = cmdopts
|
61
|
-
self.n_robots = n_robots
|
62
|
-
self.exp_num = exp_num
|
63
|
-
self.criteria = criteria
|
64
|
-
self.logger = logging.getLogger('platform.ros1robot')
|
65
|
-
|
66
|
-
def pre_run_cmds(self,
|
67
|
-
host: str,
|
68
|
-
input_fpath: pathlib.Path,
|
69
|
-
run_num: int) -> tp.List[types.ShellCmdSpec]:
|
70
|
-
|
71
|
-
master_ip = platform.get_local_ip()
|
72
|
-
port = config.kROS['port_base'] + self.exp_num
|
73
|
-
master_uri = f'http://{master_ip}:{port}'
|
74
|
-
|
75
|
-
ros_master = types.ShellCmdSpec(cmd=f'export ROS_MASTER_URI={master_uri};',
|
76
|
-
shell=True,
|
77
|
-
env=True,
|
78
|
-
wait=True)
|
79
|
-
|
80
|
-
if host == 'master':
|
81
|
-
if self.cmdopts['no_master_node']:
|
82
|
-
return []
|
83
|
-
else:
|
84
|
-
return [ros_master]
|
85
|
-
|
86
|
-
main_path = os.path.join(self.cmdopts['project_config_root'],
|
87
|
-
config.kYAML.main)
|
88
|
-
|
89
|
-
main_config = yaml.load(utils.utf8open(main_path), yaml.FullLoader)
|
90
|
-
|
91
|
-
self.logger.debug("Generating pre-exec cmds for run%s slaves: %d robots",
|
92
|
-
run_num,
|
93
|
-
self.n_robots)
|
94
|
-
|
95
|
-
script_yaml = main_config['ros']['robots'][self.cmdopts['robot']]
|
96
|
-
script_file = script_yaml.get('setup_script', "$HOME/.bashrc")
|
97
|
-
|
98
|
-
ros_setup = types.ShellCmdSpec(cmd=f'. {script_file};',
|
99
|
-
shell=True,
|
100
|
-
wait=True,
|
101
|
-
env=True)
|
102
|
-
|
103
|
-
return [ros_setup, ros_master]
|
104
|
-
|
105
|
-
def exec_run_cmds(self,
|
106
|
-
host: str,
|
107
|
-
input_fpath: pathlib.Path,
|
108
|
-
run_num: int) -> tp.List[types.ShellCmdSpec]:
|
109
|
-
if host == 'master':
|
110
|
-
return self._exec_run_cmds_master(host, input_fpath, run_num)
|
111
|
-
else:
|
112
|
-
return self._exec_run_cmds_slave(host, input_fpath, run_num)
|
113
|
-
|
114
|
-
def _exec_run_cmds_master(self,
|
115
|
-
host: str,
|
116
|
-
input_fpath: pathlib.Path,
|
117
|
-
run_num: int) -> tp.List[types.ShellCmdSpec]:
|
118
|
-
|
119
|
-
if self.cmdopts['no_master_node']:
|
120
|
-
return []
|
121
|
-
|
122
|
-
self.logger.debug("Generating exec cmds for run%s master",
|
123
|
-
run_num)
|
124
|
-
|
125
|
-
# ROS master node
|
126
|
-
exp_dirname = self.criteria.gen_exp_names(self.cmdopts)[self.exp_num]
|
127
|
-
exp_template_path = utils.exp_template_path(self.cmdopts,
|
128
|
-
self.criteria.batch_input_root,
|
129
|
-
exp_dirname)
|
130
|
-
cmd = '{0} --wait {1}_run{2}_master{3};'
|
131
|
-
|
132
|
-
cmd = cmd.format(config.kROS['launch_cmd'],
|
133
|
-
str(exp_template_path),
|
134
|
-
run_num,
|
135
|
-
config.kROS['launch_file_ext'])
|
136
|
-
|
137
|
-
# --wait tells roslaunch to wait for the configured master to come up
|
138
|
-
# before launch the "master" code.
|
139
|
-
#
|
140
|
-
# 2022/02/28: -p (apparently) tells roslaunch not to CONNECT to a master
|
141
|
-
# at the specified ort, but to LAUNCH a new master at the specified
|
142
|
-
# port. This is not really documented well.
|
143
|
-
|
144
|
-
master_node = types.ShellCmdSpec(cmd=cmd, shell=True, wait=True)
|
145
|
-
|
146
|
-
return [master_node]
|
147
|
-
|
148
|
-
def _exec_run_cmds_slave(self,
|
149
|
-
host: str,
|
150
|
-
input_fpath: pathlib.Path,
|
151
|
-
run_num: int) -> tp.List[types.ShellCmdSpec]:
|
152
|
-
|
153
|
-
self.logger.debug("Generating exec cmds for run%s slaves: %d robots",
|
154
|
-
run_num,
|
155
|
-
self.n_robots)
|
156
|
-
|
157
|
-
nodes = platform.ExecEnvChecker.parse_nodefile(self.cmdopts['nodefile'])
|
158
|
-
|
159
|
-
if len(nodes) < self.n_robots:
|
160
|
-
self.logger.critical(("Need %d hosts to correctly generate launch "
|
161
|
-
"cmds for run%s with %d robots; %d available"),
|
162
|
-
self.n_robots,
|
163
|
-
run_num,
|
164
|
-
self.n_robots,
|
165
|
-
len(nodes))
|
166
|
-
|
167
|
-
ret = [] # type: tp.List[types.ShellCmdSpec]
|
168
|
-
for i in range(0, self.n_robots):
|
169
|
-
# --wait tells roslaunch to wait for the configured master to
|
170
|
-
# come up before launch the robot code.
|
171
|
-
cmd = '{0} --wait {1}_robot{2}{3} '
|
172
|
-
cmd = cmd.format(config.kROS['launch_cmd'],
|
173
|
-
input_fpath,
|
174
|
-
i,
|
175
|
-
config.kROS['launch_file_ext'])
|
176
|
-
ret.extend([types.ShellCmdSpec(cmd=cmd, shell=True, wait=True)])
|
177
|
-
return ret
|
178
|
-
|
179
|
-
def post_run_cmds(self, host: str) -> tp.List[types.ShellCmdSpec]:
|
180
|
-
if host == 'master':
|
181
|
-
return []
|
182
|
-
else:
|
183
|
-
return [
|
184
|
-
types.ShellCmdSpec(
|
185
|
-
# Can't use killall, because that returns non-zero if things
|
186
|
-
# are cleaned up nicely.
|
187
|
-
cmd='if pgrep roslaunch; then pkill roslaunch; fi;',
|
188
|
-
shell=True,
|
189
|
-
wait=True
|
190
|
-
)
|
191
|
-
]
|
192
|
-
|
193
|
-
|
194
|
-
@implements.implements(bindings.IExpShellCmdsGenerator)
|
195
|
-
class ExpShellCmdsGenerator():
|
196
|
-
def __init__(self,
|
197
|
-
cmdopts: types.Cmdopts,
|
198
|
-
exp_num: int) -> None:
|
199
|
-
self.cmdopts = cmdopts
|
200
|
-
self.exp_num = exp_num
|
201
|
-
self.logger = logging.getLogger('platform.ros1robot')
|
202
|
-
|
203
|
-
def pre_exp_cmds(self) -> tp.List[types.ShellCmdSpec]:
|
204
|
-
local_ip = platform.get_local_ip()
|
205
|
-
port = config.kROS['port_base'] + self.exp_num
|
206
|
-
master_uri = f'http://{local_ip}:{port}'
|
207
|
-
|
208
|
-
self.logger.info("Using ROS_MASTER_URI=%s", master_uri)
|
209
|
-
|
210
|
-
return[
|
211
|
-
types.ShellCmdSpec(
|
212
|
-
# roscore will run on the SIERRA host machine.
|
213
|
-
cmd=f'export ROS_MASTER_URI={master_uri}',
|
214
|
-
shell=True,
|
215
|
-
env=True,
|
216
|
-
wait=True),
|
217
|
-
types.ShellCmdSpec(
|
218
|
-
# Each exppperiment gets their own roscore. Because each roscore
|
219
|
-
# has a different port, this prevents any robots from
|
220
|
-
# pre-emptively starting the next experiment before the rest of
|
221
|
-
# the robots have finished the current one.
|
222
|
-
cmd=f'roscore -p {port} & ',
|
223
|
-
shell=True,
|
224
|
-
wait=False)
|
225
|
-
]
|
226
|
-
|
227
|
-
def exec_exp_cmds(self, exec_opts: types.StrDict) -> tp.List[types.ShellCmdSpec]:
|
228
|
-
return []
|
229
|
-
|
230
|
-
def post_exp_cmds(self) -> tp.List[types.ShellCmdSpec]:
|
231
|
-
# Cleanup roscore processes on the SIERRA host machine which are still
|
232
|
-
# active because they don't know how to clean up after themselves.
|
233
|
-
return [types.ShellCmdSpec(cmd='killall rosmaster;',
|
234
|
-
shell=True,
|
235
|
-
wait=True),
|
236
|
-
types.ShellCmdSpec(cmd='killall roscore;',
|
237
|
-
shell=True,
|
238
|
-
wait=True),
|
239
|
-
types.ShellCmdSpec(cmd='killall rosout;',
|
240
|
-
shell=True,
|
241
|
-
wait=True)]
|
242
|
-
|
243
|
-
|
244
|
-
@implements.implements(bindings.IExpConfigurer)
|
245
|
-
class ExpConfigurer():
|
246
|
-
def __init__(self, cmdopts: types.Cmdopts) -> None:
|
247
|
-
self.cmdopts = cmdopts
|
248
|
-
self.logger = logging.getLogger('platform.ros1robot')
|
249
|
-
|
250
|
-
def cmdfile_paradigm(self) -> str:
|
251
|
-
return 'per-run'
|
252
|
-
|
253
|
-
def for_exp_run(self,
|
254
|
-
exp_input_root: pathlib.Path,
|
255
|
-
run_output_root: pathlib.Path) -> None:
|
256
|
-
pass
|
257
|
-
|
258
|
-
def for_exp(self, exp_input_root: pathlib.Path) -> None:
|
259
|
-
if self.cmdopts['skip_sync']:
|
260
|
-
self.logger.info("Skipping syncing experiment inputs -> robots")
|
261
|
-
return
|
262
|
-
else:
|
263
|
-
self.logger.info("Syncing experiment inputs -> robots")
|
264
|
-
|
265
|
-
checker = platform.ExecEnvChecker(self.cmdopts)
|
266
|
-
nodes = checker.parse_nodefile(self.cmdopts['nodefile'])
|
267
|
-
|
268
|
-
# Use parallel ssh, rsync to push each experiment to all robots in
|
269
|
-
# parallel--takes O(M*N) operation and makes it O(N) more or less.
|
270
|
-
pssh_base = 'parallel-ssh'
|
271
|
-
prsync_base = 'parallel-rsync'
|
272
|
-
|
273
|
-
for node in nodes:
|
274
|
-
remote_login = node.login
|
275
|
-
remote_port = node.port
|
276
|
-
remote_hostname = node.hostname
|
277
|
-
current_username = pwd.getpwuid(os.getuid())[0]
|
278
|
-
|
279
|
-
if not self.cmdopts['skip_online_check']:
|
280
|
-
checker.check_connectivity(remote_login,
|
281
|
-
remote_hostname,
|
282
|
-
remote_port,
|
283
|
-
self.cmdopts['robot'])
|
284
|
-
|
285
|
-
pssh_base += f' -H {remote_login}@{remote_hostname}:{remote_port}'
|
286
|
-
prsync_base += f' -H {remote_login}@{remote_hostname}:{remote_port}'
|
287
|
-
|
288
|
-
# In case the user is different on the remote machine than this one,
|
289
|
-
# and the location of the generated experiment is under /home.
|
290
|
-
robot_input_root = str(exp_input_root).replace(current_username,
|
291
|
-
remote_login)
|
292
|
-
|
293
|
-
mkdir_cmd = (f"{pssh_base} "
|
294
|
-
f"-O StrictHostKeyChecking=no "
|
295
|
-
f"mkdir -p {robot_input_root}")
|
296
|
-
|
297
|
-
rsync_cmd = (f"{prsync_base} "
|
298
|
-
f"-avz "
|
299
|
-
f"-O StrictHostKeyChecking=no "
|
300
|
-
f"{exp_input_root}/ "
|
301
|
-
f"{robot_input_root}/")
|
302
|
-
try:
|
303
|
-
self.logger.trace("Running mkdir: %s", mkdir_cmd) # type: ignore
|
304
|
-
res = subprocess.run(mkdir_cmd,
|
305
|
-
shell=True,
|
306
|
-
check=True,
|
307
|
-
stdout=subprocess.PIPE,
|
308
|
-
stderr=subprocess.PIPE)
|
309
|
-
self.logger.trace("Running rsync: %s", rsync_cmd) # type: ignore
|
310
|
-
res = subprocess.run(rsync_cmd,
|
311
|
-
shell=True,
|
312
|
-
check=True,
|
313
|
-
stdout=subprocess.PIPE,
|
314
|
-
stderr=subprocess.PIPE)
|
315
|
-
except subprocess.CalledProcessError:
|
316
|
-
self.logger.fatal("Unable to sync %s with %s: stdout=%s,stderr=%s",
|
317
|
-
exp_input_root,
|
318
|
-
robot_input_root,
|
319
|
-
res.stdout.decode('utf-8'),
|
320
|
-
res.stderr.decode('utf-8'))
|
321
|
-
raise
|
322
|
-
|
323
|
-
|
324
|
-
@ implements.implements(bindings.IExecEnvChecker)
|
325
|
-
class ExecEnvChecker():
|
326
|
-
def __init__(self, cmdopts: types.Cmdopts) -> None:
|
327
|
-
pass
|
328
|
-
|
329
|
-
def __call__(self) -> None:
|
330
|
-
keys = ['ROS_DISTRO', 'ROS_VERSION']
|
331
|
-
|
332
|
-
for k in keys:
|
333
|
-
assert k in os.environ, \
|
334
|
-
"Non-ROS1+robot environment detected: '{0}' not found".format(
|
335
|
-
k)
|
336
|
-
|
337
|
-
# Check ROS distro
|
338
|
-
assert os.environ['ROS_DISTRO'] in ['kinetic', 'noetic'],\
|
339
|
-
"SIERRA only supports ROS1 kinetic,noetic"
|
340
|
-
|
341
|
-
# Check ROS version
|
342
|
-
assert os.environ['ROS_VERSION'] == "1",\
|
343
|
-
"Wrong ROS version: This plugin is for ROS1"
|
344
|
-
|
345
|
-
|
346
|
-
def population_size_from_pickle(adds_def: tp.Union[xml.AttrChangeSet,
|
347
|
-
xml.TagAddList],
|
348
|
-
main_config: types.YAMLDict,
|
349
|
-
cmdopts: types.Cmdopts) -> int:
|
350
|
-
return ros1.callbacks.population_size_from_pickle(adds_def,
|
351
|
-
main_config,
|
352
|
-
cmdopts)
|
353
|
-
|
354
|
-
|
355
|
-
def population_size_from_def(exp_def: definition.XMLExpDef,
|
356
|
-
main_config: types.YAMLDict,
|
357
|
-
cmdopts: types.Cmdopts) -> int:
|
358
|
-
return ros1.callbacks.population_size_from_def(exp_def,
|
359
|
-
main_config,
|
360
|
-
cmdopts)
|
361
|
-
|
362
|
-
|
363
|
-
def robot_prefix_extract(main_config: types.YAMLDict,
|
364
|
-
cmdopts: types.Cmdopts) -> str:
|
365
|
-
return ros1.callbacks.robot_prefix_extract(main_config, cmdopts)
|
366
|
-
|
367
|
-
|
368
|
-
def pre_exp_diagnostics(cmdopts: types.Cmdopts,
|
369
|
-
logger: logging.Logger) -> None:
|
370
|
-
s = "batch_exp_root='%s',runs/exp=%s"
|
371
|
-
logger.info(s,
|
372
|
-
cmdopts['batch_root'],
|
373
|
-
cmdopts['n_runs'])
|