diff --git a/Makefile b/Makefile index 2f4d53421..124cd4e89 100644 --- a/Makefile +++ b/Makefile @@ -68,6 +68,7 @@ doxygen: doxygen Doxyfile smoketest: + # Call this target with WITH_VTD=1 to include VTD binding tests. $(call print_header, "Running smoke tests...") @${CLOE_LAUNCH} clean -P conanfile.py @\time -f "\nTotal smoketest time (real) = %e sec" bats tests diff --git a/Makefile.all b/Makefile.all index 80e5a5dd8..d296ec6b9 100644 --- a/Makefile.all +++ b/Makefile.all @@ -81,10 +81,10 @@ CONAN_OPTIONS := WITH_ENGINE := 1 ## WITH_VTD -## Usage: make WITH_VTD=0 -## Default: 1 +## Usage: make WITH_VTD=1 +## Default: 0 ## -WITH_VTD := 1 +WITH_VTD := 0 ## BUILD_TESTS ## Usage: make BUILD_TESTS=0 package @@ -139,9 +139,9 @@ ALL_PKGS := $(filter-out engine, ${ALL_PKGS}) CONAN_OPTIONS += -o cloe:with_engine=False endif -ifeq (${WITH_VTD},0) +ifeq (${WITH_VTD},1) ALL_PKGS := $(filter-out plugins/vtd, ${ALL_PKGS}) -CONAN_OPTIONS += -o cloe:with_vtd=False +CONAN_OPTIONS += -o cloe:with_vtd=True endif ifeq (${BUILD_TESTS},0) diff --git a/Makefile.setup b/Makefile.setup index b069a0ae8..fba8b8f84 100644 --- a/Makefile.setup +++ b/Makefile.setup @@ -16,18 +16,21 @@ APT_ARGS := --no-install-recommends -y PACMAN := $(shell command -v pacman 2>/dev/null) PACMAN_ARGS := --noconfirm --needed -PIPX := $(shell command -v pipx 2>/dev/null) -PIPX_INSTALL_ARGS := - PIP := $(or \ - $(shell command -v pipx 2>/dev/null), \ $(shell command -v pip3 2>/dev/null), \ $(shell command -v pip 2>/dev/null) \ ) -ifndef PIPX +ifeq (${VIRTUAL_ENV}, ) PIP_INSTALL_ARGS := --user --upgrade else -PIP_INSTALL_ARGS := ${PIPX_INSTALL_ARGS} +PIP_INSTALL_ARGS := --upgrade +endif + +PIPX := $(shell command -v pipx 2>/dev/null) +PIPX_INSTALL_ARGS := +ifndef PIPX +PIPX := ${PIP} +PIPX_INSTALL_ARGS := ${PIP_INSTALL_ARGS} endif .PHONY: help @@ -35,16 +38,17 @@ endif .SILENT: help help:: echo "Available setup targets:" - echo " setup to perform Git repository setup" - echo " install-system-deps to install build (and development) system requirements" - echo " install-python-deps to install build (and development) Python requirements" + echo " setup to perform Git repository setup" + echo " install-system-deps to install build (and development) system requirements" + echo " install-python-deps to install Python runtime requirements with ${PIP}" + echo " install-python-tools to install Python development tools with ${PIPX}" echo .PHONY: setup setup: git config --local core.hooksPath .git-hooks/ -.PHONY: install-system-deps install-ubuntu-deps install-archlinux-deps install-python-deps +.PHONY: install-system-deps install-ubuntu-deps install-archlinux-deps install-python-deps install-python-tools install-system-deps:: # Ubuntu ---------------------------------------------------------------------- @@ -112,19 +116,20 @@ endif # Python ---------------------------------------------------------------------- ifdef PIP -install-deps:: install-python-deps +install-deps:: install-python-deps install-python-tools endif install-python-deps:: command -v ${PIP} >/dev/null 2>&1 ${PIP} install ${PIP_INSTALL_ARGS} \ + click \ conan \ libtmux \ + toml \ ; -ifndef WITHOUT_DEV_DEPS -install-python-deps:: - command -v ${PIP} >/dev/null 2>&1 +install-python-tools:: + command -v ${PIPX} >/dev/null 2>&1 for pkg in \ black \ mypy \ @@ -134,6 +139,5 @@ install-python-deps:: yq \ ; \ do \ - ${PIP} install ${PIP_INSTALL_ARGS} $${pkg}; \ + ${PIPX} install ${PIPX_INSTALL_ARGS} $${pkg}; \ done -endif diff --git a/conanfile.py b/conanfile.py index 0794b9286..a1b9784e1 100644 --- a/conanfile.py +++ b/conanfile.py @@ -18,7 +18,7 @@ class Cloe(ConanFile): default_options = { "test": True, "pedantic": True, - "with_vtd": True, + "with_vtd": False, "with_engine": True, } generators = "cmake" diff --git a/dist/docker/Dockerfile.archlinux b/dist/docker/Dockerfile.archlinux index 5c8ab9b02..2b546891b 100644 --- a/dist/docker/Dockerfile.archlinux +++ b/dist/docker/Dockerfile.archlinux @@ -18,7 +18,7 @@ RUN pacman -Syu --noconfirm --needed make && \ RUN pip3 install --upgrade pip && \ make -f /cloe/Makefile.setup \ - WITHOUT_DEV_DEPS=yes PIP_INSTALL_ARGS="" \ + PIP_INSTALL_ARGS="" \ install-python-deps # Install and Setup Conan @@ -33,8 +33,10 @@ RUN conan profile new --detect default && \ # Build and Install Cloe WORKDIR /cloe COPY . /cloe -RUN make export-vtd export && \ +RUN make export-vendor export && \ make WITH_VTD=0 package-all && \ + export LC_ALL=C.UTF-8 LANG=C.UTF-8 && \ + make WITH_VTD=0 smoketest && \ make WITH_VTD=0 INSTALL_DIR="/deploy" deploy && \ conan remove \* -b -f diff --git a/dist/docker/Dockerfile.ubuntu b/dist/docker/Dockerfile.ubuntu index c1178656d..18e82c350 100644 --- a/dist/docker/Dockerfile.ubuntu +++ b/dist/docker/Dockerfile.ubuntu @@ -26,7 +26,7 @@ RUN apt-get update && \ RUN pip3 install --upgrade pip && \ make -f /cloe/Makefile.setup \ - WITHOUT_DEV_DEPS=yes PIP_INSTALL_ARGS="" \ + PIP_INSTALL_ARGS="" \ install-python-deps # Install and Setup Conan @@ -58,6 +58,9 @@ RUN \ # You can specify more than one package here, see the Makefile for more # information on the WITH_*, PACKAGES, NOBUILD_PKGS, and BUILD_PKGS variables. make WITH_VTD=0 package-all && \ + # Run smoketests. + export LC_ALL=C.UTF-8 LANG=C.UTF-8 && \ + make WITH_VTD=0 smoketest && \ # Deploy all the Cloe packages to INSTALL_DIR, which is /usr/local by # default. This will also populate BUILD_DIR, so that should be removed # afterwards to prevent this image from getting too big. diff --git a/tests/setup_bats.bash b/tests/setup_bats.bash index 48d59b024..77e7a5b70 100644 --- a/tests/setup_bats.bash +++ b/tests/setup_bats.bash @@ -37,6 +37,13 @@ cloe_engine() { for var in ${CLOE_OVERRIDE_ENV[@]}; do cloe_launch_args+=(--override-env=${var}) done + if [[ "${WITH_VTD}" -eq "1" ]]; then + cloe_launch_args+=(-o) + cloe_launch_args+=("with_vtd=True") + fi + for var in ${CLOE_LAUNCH_ARGS[@]}; do + cloe_launch_args+=(${var}) + done local user_args=() while [[ $# -ne 0 ]]; do @@ -75,6 +82,13 @@ cloe_shell() { for var in ${CLOE_OVERRIDE_ENV[@]}; do cloe_launch_args+=(--override-env=${var}) done + if [[ "${WITH_VTD}" -eq "1" ]]; then + cloe_launch_args+=(-o) + cloe_launch_args+=("with_vtd=True") + fi + for var in ${CLOE_LAUNCH_ARGS[@]}; do + cloe_launch_args+=(${var}) + done local user_args=("$@") diff --git a/tests/test_engine.bats b/tests/test_engine.bats index 35e1d540d..414b180e9 100755 --- a/tests/test_engine.bats +++ b/tests/test_engine.bats @@ -2,12 +2,21 @@ load setup_bats +test_vtd_plugin_exists() { + # VTD_ROOT is only available in the shell. + cloe_shell -c 'test -d "${VTD_ROOT}"' +} + @test "Expect schema equality : test_engine_json_schema.json" { if ! type diff &>/dev/null; then skip "required program diff not present" fi - diff <(cloe_engine usage -j 2>/dev/null) test_engine_json_schema.json + if test_vtd_plugin_exists; then + diff <(cloe_engine usage -j 2>/dev/null) test_engine_json_schema_with_vtd.json + else + diff <(cloe_engine usage -j 2>/dev/null) test_engine_json_schema.json + fi } @test "Expect check success : test_engine_smoketest.json" { diff --git a/tests/test_engine_json_schema.json b/tests/test_engine_json_schema.json index 6ac787c0b..0b56a855e 100644 --- a/tests/test_engine_json_schema.json +++ b/tests/test_engine_json_schema.json @@ -1095,270 +1095,6 @@ "binding" ], "type": "object" - }, - { - "additionalProperties": true, - "properties": { - "args": { - "additionalProperties": false, - "properties": { - "camera": { - "additionalProperties": false, - "properties": { - "focus_on": { - "description": "player to focus on", - "type": "string" - }, - "third_person": { - "description": "whether to use third person camera", - "type": "boolean" - } - }, - "type": "object" - }, - "configuration_rety_attempts": { - "description": "attempts to retry connection on broken pipe", - "maximum": 65535, - "minimum": 0, - "type": "integer" - }, - "connection": { - "additionalProperties": false, - "description": "scp connection parameters", - "properties": { - "host": { - "description": "hostname of connection", - "type": "string" - }, - "port": { - "description": "port of connection", - "maximum": 65535, - "minimum": 0, - "type": "integer" - }, - "retry_attempts": { - "description": "connection retry attempts", - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "retry_delay_s": { - "description": "time delay between connection attempts", - "maximum": 3.4028234663852886e+38, - "minimum": -3.4028234663852886e+38, - "type": "number" - } - }, - "type": "object" - }, - "dat_file": { - "description": "filepath to write VTD data output to", - "type": "string" - }, - "image_generator": { - "description": "switch whether VTD should use image generator", - "type": "boolean" - }, - "label_vehicle": { - "description": "how to label vehicle modes in VTD [off,text,human,symbol,unicode]", - "enum": [ - "off", - "text", - "human", - "symbol", - "unicode" - ], - "type": "string" - }, - "paramserver": { - "additionalProperties": false, - "description": "parameter sever connection parameters", - "properties": { - "host": { - "description": "hostname of connection", - "type": "string" - }, - "port": { - "description": "port of connection", - "maximum": 65535, - "minimum": 0, - "type": "integer" - }, - "retry_attempts": { - "description": "connection retry attempts", - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "retry_delay_s": { - "description": "time delay between connection attempts", - "maximum": 3.4028234663852886e+38, - "minimum": -3.4028234663852886e+38, - "type": "number" - } - }, - "type": "object" - }, - "project": { - "description": "indicate which project to find the scenario in (informative)", - "type": "string" - }, - "rdb_params": { - "additionalProperties": false, - "description": "rdb connection parameters", - "properties": { - "retry_attempts": { - "description": "connection retry attempts", - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "retry_delay_s": { - "description": "time delay between connection attempts", - "maximum": 3.4028234663852886e+38, - "minimum": -3.4028234663852886e+38, - "type": "number" - } - }, - "type": "object" - }, - "scenario": { - "description": "VTD scenario to use (project must already be loaded)", - "type": "string" - }, - "sensor_initial_port": { - "description": "initial port for sensor communication", - "maximum": 65535, - "minimum": 0, - "type": "integer" - }, - "setup": { - "description": "indicate which setup you are using", - "type": "string" - }, - "task_control_params": { - "additionalProperties": false, - "description": "task control connection parameters", - "properties": { - "retry_attempts": { - "description": "connection retry attempts", - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "retry_delay_s": { - "description": "time delay between connection attempts", - "maximum": 3.4028234663852886e+38, - "minimum": -3.4028234663852886e+38, - "type": "number" - } - }, - "type": "object" - }, - "vehicles": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "components": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "from": { - "description": "VTD sensor to retrieve the component data from", - "type": "string" - }, - "override": { - "description": "Override an existing component with the same name", - "type": "boolean" - }, - "type": { - "description": "Component type to register", - "type": "string" - } - }, - "type": "object" - }, - "description": "component definitions", - "type": "object" - }, - "sensors": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "mock_level": { - "additionalProperties": false, - "description": "Sensor data mock level", - "properties": { - "detected_lane_boundaries": { - "description": "mock level for detected lane boundaries", - "enum": [ - "overwrite_none", - "interpolate_missing", - "overwrite_all" - ], - "type": "string" - }, - "detected_moving_objects": { - "description": "mock level for detected moving objects", - "enum": [ - "overwrite_none", - "interpolate_missing", - "overwrite_all" - ], - "type": "string" - }, - "mounting_position": { - "description": "mock level for sensor mounting position", - "enum": [ - "overwrite_none", - "interpolate_missing", - "overwrite_all" - ], - "type": "string" - } - }, - "type": "object" - }, - "protocol": { - "description": "VTD module manager sensor connection protocol ( rdb | osi )", - "enum": [ - "rdb", - "osi" - ], - "type": "string" - }, - "xml": { - "description": "VTD module manager sensor configuration", - "type": "string" - } - }, - "type": "object" - }, - "description": "sensor definitions", - "type": "object" - } - }, - "type": "object" - }, - "description": "vehicle configuration like sensors and component mapping", - "type": "object" - } - }, - "type": "object" - }, - "binding": { - "const": "vtd", - "description": "name of simulator binding" - }, - "name": { - "description": "identifier of simulator instance", - "type": "string" - } - }, - "required": [ - "binding" - ], - "type": "object" } ] }, diff --git a/tests/test_engine_json_schema_with_vtd.json b/tests/test_engine_json_schema_with_vtd.json new file mode 100644 index 000000000..6ac787c0b --- /dev/null +++ b/tests/test_engine_json_schema_with_vtd.json @@ -0,0 +1,1755 @@ +{ + "additionalProperties": false, + "properties": { + "controllers": { + "description": "controller configuration", + "items": { + "oneOf": [ + { + "additionalProperties": true, + "properties": { + "args": { + "additionalProperties": false, + "properties": { + "acc": { + "additionalProperties": false, + "description": "ACC configuration", + "properties": { + "derivative_factor_dist_control": { + "description": "factor to tune the D term of the PID distance controller", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + }, + "derivative_factor_speed_control": { + "description": "factor to tune the D term of the PID speed controller", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + }, + "ego_sensor": { + "description": "ego sensor component to read from", + "type": "string" + }, + "integral_factor_dist_control": { + "description": "factor to tune the I term of the PID distance controller", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + }, + "integral_factor_speed_control": { + "description": "factor to tune the I term of the PID speed controller", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + }, + "latlong_actuator": { + "description": "actuator to write to", + "type": "string" + }, + "limit_acceleration": { + "description": "acceleration limit in [m/s^2]", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + }, + "limit_deceleration": { + "description": "how much deceleration is allowed, in [m/s^2]", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + }, + "proportional_factor_dist_control": { + "description": "factor to tune the P term of the PID distance controller", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + }, + "proportional_factor_speed_control": { + "description": "factor to tune the P term of the PID speed controller", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + }, + "world_sensor": { + "description": "world_sensor component to read from", + "type": "string" + } + }, + "type": "object" + }, + "aeb": { + "additionalProperties": false, + "description": "AEB configuration", + "properties": { + "always_full_stop": { + "description": "whether to brake to a full-stop on activation", + "type": "boolean" + }, + "ego_sensor": { + "description": "ego sensor component to read from", + "type": "string" + }, + "enabled": { + "description": "whether automatic emergency braking is enabled", + "type": "boolean" + }, + "latlong_actuator": { + "description": "actuator to write to", + "type": "string" + }, + "limit_deceleration": { + "description": "how much deceleration is allowed, in [m/s^2]", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + }, + "world_sensor": { + "description": "world_sensor component to read from", + "type": "string" + } + }, + "type": "object" + }, + "lka": { + "additionalProperties": false, + "description": "LKA configuration", + "properties": { + "adjustment_rad": { + "description": "wheel angle adjustment in [rad]", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + }, + "enabled": { + "description": "whether lane keeping assist is enabled", + "type": "boolean" + }, + "latlong_actuator": { + "description": "actuator to write to", + "type": "string" + }, + "lerp_factor": { + "description": "linear interpolation factor with domain (0-1]", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + }, + "tolerance": { + "description": "absolute tolerance in [m]", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + }, + "world_sensor": { + "description": "world_sensor component to read from", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "binding": { + "const": "basic", + "description": "name of simulator binding" + }, + "name": { + "description": "identifier of simulator instance", + "type": "string" + } + }, + "required": [ + "binding" + ], + "type": "object" + }, + { + "additionalProperties": true, + "properties": { + "args": null, + "binding": { + "const": "demo_printer", + "description": "name of simulator binding" + }, + "name": { + "description": "identifier of simulator instance", + "type": "string" + } + }, + "required": [ + "binding" + ], + "type": "object" + }, + { + "additionalProperties": true, + "properties": { + "args": { + "additionalProperties": false, + "properties": { + "halt_progress_at": { + "description": "time in ns at which to halt all progress", + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "progress_per_step": { + "description": "progress to make each step", + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "type": "object" + }, + "binding": { + "const": "demo_stuck", + "description": "name of simulator binding" + }, + "name": { + "description": "identifier of simulator instance", + "type": "string" + } + }, + "required": [ + "binding" + ], + "type": "object" + }, + { + "additionalProperties": true, + "properties": { + "args": { + "additionalProperties": false, + "properties": { + "components": { + "description": "array of components to be extracted", + "items": { + "type": "string" + }, + "type": "array" + }, + "output_file": { + "description": "file path to write groundtruth output to", + "type": "string" + }, + "output_type": { + "description": "type of output file to write" + } + }, + "type": "object" + }, + "binding": { + "const": "gndtruth_extractor", + "description": "name of simulator binding" + }, + "name": { + "description": "identifier of simulator instance", + "type": "string" + } + }, + "required": [ + "binding" + ], + "type": "object" + }, + { + "additionalProperties": true, + "properties": { + "args": null, + "binding": { + "const": "nop", + "description": "name of simulator binding" + }, + "name": { + "description": "identifier of simulator instance", + "type": "string" + } + }, + "required": [ + "binding" + ], + "type": "object" + }, + { + "additionalProperties": true, + "properties": { + "args": { + "additionalProperties": false, + "properties": { + "init_phase": { + "description": "time during which initialization is performed", + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "lane_sensor_components": { + "description": "array of lane-sensor components to be checked", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "binding": { + "const": "virtue", + "description": "name of simulator binding" + }, + "name": { + "description": "identifier of simulator instance", + "type": "string" + } + }, + "required": [ + "binding" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "defaults": { + "additionalProperties": false, + "properties": { + "components": { + "description": "component default configurations", + "items": { + "additionalProperties": false, + "properties": { + "args": { + "description": "defaults to set for binding/name combination" + }, + "binding": { + "description": "name of binding", + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "name": { + "description": "globally unique identifier for component", + "oneOf": [ + { + "type": "null" + }, + { + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$", + "type": "string" + } + ] + } + }, + "required": [ + "args" + ], + "type": "object" + }, + "type": "array" + }, + "controllers": { + "description": "controller default configurations", + "items": { + "additionalProperties": false, + "properties": { + "args": { + "description": "defaults to set for binding/name combination" + }, + "binding": { + "description": "name of binding", + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "name": { + "description": "globally unique identifier for component", + "oneOf": [ + { + "type": "null" + }, + { + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$", + "type": "string" + } + ] + } + }, + "required": [ + "args" + ], + "type": "object" + }, + "type": "array" + }, + "simulators": { + "description": "simulator default configurations", + "items": { + "additionalProperties": false, + "properties": { + "args": { + "description": "defaults to set for binding/name combination" + }, + "binding": { + "description": "name of binding", + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "name": { + "description": "globally unique identifier for component", + "oneOf": [ + { + "type": "null" + }, + { + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$", + "type": "string" + } + ] + } + }, + "required": [ + "args" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "engine": { + "additionalProperties": false, + "description": "engine configuration", + "properties": { + "hooks": { + "additionalProperties": false, + "properties": { + "post_disconnect": { + "description": "post-disconnect hooks to execute", + "items": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "args": { + "description": "arguments to executable", + "items": { + "type": "string" + }, + "type": "array" + }, + "ignore_failure": { + "description": "whether to ignore execution failure", + "type": "boolean" + }, + "mode": { + "description": "synchronization mode to use", + "enum": [ + "sync", + "async", + "detach" + ], + "type": "string" + }, + "output": { + "description": "how to log command output", + "enum": [ + "never", + "normal", + "always" + ], + "type": "string" + }, + "path": { + "comment": "path should be executable", + "description": "path to executable", + "minLength": 1, + "type": "string" + } + }, + "required": [ + "path" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "command": { + "description": "command to execute within shell", + "minLength": 1, + "type": "string" + }, + "ignore_failure": { + "description": "whether to ignore execution failure", + "type": "boolean" + }, + "mode": { + "description": "synchronization mode to use", + "enum": [ + "sync", + "async", + "detach" + ], + "type": "string" + }, + "output": { + "description": "how to log command output", + "enum": [ + "never", + "normal", + "always" + ], + "type": "string" + } + }, + "required": [ + "command" + ], + "type": "object" + }, + { + "description": "command to execute within shell", + "minLength": 1, + "type": "string" + } + ] + }, + "type": "array" + }, + "pre_connect": { + "description": "pre-connect hooks to execute", + "items": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "args": { + "description": "arguments to executable", + "items": { + "type": "string" + }, + "type": "array" + }, + "ignore_failure": { + "description": "whether to ignore execution failure", + "type": "boolean" + }, + "mode": { + "description": "synchronization mode to use", + "enum": [ + "sync", + "async", + "detach" + ], + "type": "string" + }, + "output": { + "description": "how to log command output", + "enum": [ + "never", + "normal", + "always" + ], + "type": "string" + }, + "path": { + "comment": "path should be executable", + "description": "path to executable", + "minLength": 1, + "type": "string" + } + }, + "required": [ + "path" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "command": { + "description": "command to execute within shell", + "minLength": 1, + "type": "string" + }, + "ignore_failure": { + "description": "whether to ignore execution failure", + "type": "boolean" + }, + "mode": { + "description": "synchronization mode to use", + "enum": [ + "sync", + "async", + "detach" + ], + "type": "string" + }, + "output": { + "description": "how to log command output", + "enum": [ + "never", + "normal", + "always" + ], + "type": "string" + } + }, + "required": [ + "command" + ], + "type": "object" + }, + { + "description": "command to execute within shell", + "minLength": 1, + "type": "string" + } + ] + }, + "type": "array" + } + }, + "type": "object" + }, + "ignore": { + "description": "JSON pointers to sections that should be ignored", + "items": { + "type": "string" + }, + "type": "array" + }, + "keep_alive": { + "description": "keep simulation alive after termination", + "type": "boolean" + }, + "output": { + "additionalProperties": false, + "properties": { + "clobber": { + "description": "whether to clobber existing files or not", + "type": "boolean" + }, + "files": { + "additionalProperties": false, + "properties": { + "config": { + "description": "file to store config in", + "oneOf": [ + { + "type": "null" + }, + { + "comment": "path should either not exist or be a file", + "type": "string" + } + ] + }, + "result": { + "description": "file to store simulation result in", + "oneOf": [ + { + "type": "null" + }, + { + "comment": "path should either not exist or be a file", + "type": "string" + } + ] + }, + "triggers": { + "description": "file to store triggers in", + "oneOf": [ + { + "type": "null" + }, + { + "comment": "path should either not exist or be a file", + "type": "string" + } + ] + } + }, + "type": "object" + }, + "path": { + "description": "directory to dump output files in, relative to registry path", + "oneOf": [ + { + "type": "null" + }, + { + "comment": "path should either not exist or be a directory", + "type": "string" + } + ] + } + }, + "type": "object" + }, + "plugin_path": { + "description": "list of directories to scan for plugins", + "items": { + "type": "string" + }, + "type": "array" + }, + "plugins": { + "additionalProperties": false, + "properties": { + "allow_clobber": { + "description": "replace same-named plugins", + "type": "boolean" + }, + "ignore_failure": { + "description": "ignore plugin loading errors", + "type": "boolean" + }, + "ignore_missing": { + "description": "ignore not-exist errors", + "type": "boolean" + } + }, + "type": "object" + }, + "polling_interval": { + "description": "milliseconds to sleep when polling for next state", + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "registry_path": { + "description": "cloe registry directory", + "oneOf": [ + { + "type": "null" + }, + { + "comment": "path should either not exist or be a directory", + "type": "string" + } + ] + }, + "security": { + "additionalProperties": false, + "properties": { + "enable_command_action": { + "description": "whether to enable the command action", + "type": "boolean" + }, + "enable_hooks_section": { + "description": "whether to enable engine hooks", + "type": "boolean" + }, + "enable_include_section": { + "description": "whether to allow config files to include other files", + "type": "boolean" + }, + "max_include_depth": { + "description": "how many recursive includes are allowed", + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + }, + "triggers": { + "additionalProperties": false, + "properties": { + "ignore_source": { + "description": "ignore trigger source when reading in triggers", + "type": "boolean" + } + }, + "type": "object" + }, + "watchdog": { + "additionalProperties": false, + "properties": { + "default_timeout": { + "description": "default timeout if not overridden, 0 for no timeout", + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "mode": { + "description": "modus operandi of watchdog [one of: off, log, abort, kill]", + "enum": [ + "off", + "log", + "abort", + "kill" + ], + "type": "string" + }, + "state_timeouts": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + ] + }, + "description": "timeout specific to a given state, 0 for no timeout", + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "include": { + "description": "include configurations", + "items": { + "comment": "path should exist and be a file", + "type": "string" + }, + "type": "array" + }, + "logging": { + "description": "logging configuration", + "items": { + "additionalProperties": false, + "properties": { + "level": { + "description": "level of the logger", + "oneOf": [ + { + "type": "null" + }, + { + "enum": [ + "trace", + "debug", + "info", + "warning", + "error", + "fatal", + "off" + ], + "type": "string" + } + ] + }, + "name": { + "description": "name of the logger to configure", + "type": "string" + }, + "pattern": { + "description": "pattern of the logger", + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": "array" + }, + "plugins": { + "description": "plugin configuration", + "items": { + "additionalProperties": false, + "properties": { + "allow_clobber": { + "description": "replace same-named plugins", + "oneOf": [ + { + "type": "null" + }, + { + "type": "boolean" + } + ] + }, + "ignore_failure": { + "description": "ignore plugin loading errors", + "oneOf": [ + { + "type": "null" + }, + { + "type": "boolean" + } + ] + }, + "ignore_missing": { + "description": "ignore not-exist errors", + "oneOf": [ + { + "type": "null" + }, + { + "type": "boolean" + } + ] + }, + "name": { + "description": "alternative name plugin is available by", + "oneOf": [ + { + "type": "null" + }, + { + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$", + "type": "string" + } + ] + }, + "path": { + "description": "absolute or relative path to plugin", + "minLength": 1, + "type": "string" + }, + "prefix": { + "description": "prefix the plugin name with this", + "oneOf": [ + { + "type": "null" + }, + { + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$", + "type": "string" + } + ] + } + }, + "required": [ + "path" + ], + "type": "object" + }, + "type": "array" + }, + "server": { + "additionalProperties": false, + "description": "server configuration", + "properties": { + "api_prefix": { + "description": "endpoint prefix for API resources", + "type": "string" + }, + "listen": { + "description": "whether web server is enabled", + "type": "boolean" + }, + "listen_address": { + "description": "address web server should listen at", + "type": "string" + }, + "listen_port": { + "description": "port web server should listen at", + "maximum": 65535, + "minimum": 0, + "type": "integer" + }, + "listen_threads": { + "description": "threads web server should use", + "maximum": 65535, + "minimum": 0, + "type": "integer" + }, + "static_prefix": { + "description": "endpoint prefix for static resources", + "type": "string" + } + }, + "type": "object" + }, + "simulation": { + "additionalProperties": false, + "description": "simulation configuration", + "properties": { + "abort_on_controller_failure": { + "description": "abort simulation on controller failure", + "type": "boolean" + }, + "controller_retry_limit": { + "description": "times to retry controller processing before aborting", + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "controller_retry_sleep": { + "description": "time to sleep before retrying controller process", + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "model_step_width": { + "description": "default model time step in ns", + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "namespace": { + "description": "namespace for simulation events and actions", + "oneOf": [ + { + "type": "null" + }, + { + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$", + "type": "string" + } + ] + } + }, + "type": "object" + }, + "simulators": { + "description": "simulator configuration", + "items": { + "oneOf": [ + { + "additionalProperties": true, + "properties": { + "args": { + "additionalProperties": false, + "properties": { + "vehicles": { + "description": "list of vehicle names to make available", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "binding": { + "const": "minimator", + "description": "name of simulator binding" + }, + "name": { + "description": "identifier of simulator instance", + "type": "string" + } + }, + "required": [ + "binding" + ], + "type": "object" + }, + { + "additionalProperties": true, + "properties": { + "args": { + "additionalProperties": false, + "properties": { + "vehicles": { + "description": "list of vehicle names to make available", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "binding": { + "const": "nop", + "description": "name of simulator binding" + }, + "name": { + "description": "identifier of simulator instance", + "type": "string" + } + }, + "required": [ + "binding" + ], + "type": "object" + }, + { + "additionalProperties": true, + "properties": { + "args": { + "additionalProperties": false, + "properties": { + "camera": { + "additionalProperties": false, + "properties": { + "focus_on": { + "description": "player to focus on", + "type": "string" + }, + "third_person": { + "description": "whether to use third person camera", + "type": "boolean" + } + }, + "type": "object" + }, + "configuration_rety_attempts": { + "description": "attempts to retry connection on broken pipe", + "maximum": 65535, + "minimum": 0, + "type": "integer" + }, + "connection": { + "additionalProperties": false, + "description": "scp connection parameters", + "properties": { + "host": { + "description": "hostname of connection", + "type": "string" + }, + "port": { + "description": "port of connection", + "maximum": 65535, + "minimum": 0, + "type": "integer" + }, + "retry_attempts": { + "description": "connection retry attempts", + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "retry_delay_s": { + "description": "time delay between connection attempts", + "maximum": 3.4028234663852886e+38, + "minimum": -3.4028234663852886e+38, + "type": "number" + } + }, + "type": "object" + }, + "dat_file": { + "description": "filepath to write VTD data output to", + "type": "string" + }, + "image_generator": { + "description": "switch whether VTD should use image generator", + "type": "boolean" + }, + "label_vehicle": { + "description": "how to label vehicle modes in VTD [off,text,human,symbol,unicode]", + "enum": [ + "off", + "text", + "human", + "symbol", + "unicode" + ], + "type": "string" + }, + "paramserver": { + "additionalProperties": false, + "description": "parameter sever connection parameters", + "properties": { + "host": { + "description": "hostname of connection", + "type": "string" + }, + "port": { + "description": "port of connection", + "maximum": 65535, + "minimum": 0, + "type": "integer" + }, + "retry_attempts": { + "description": "connection retry attempts", + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "retry_delay_s": { + "description": "time delay between connection attempts", + "maximum": 3.4028234663852886e+38, + "minimum": -3.4028234663852886e+38, + "type": "number" + } + }, + "type": "object" + }, + "project": { + "description": "indicate which project to find the scenario in (informative)", + "type": "string" + }, + "rdb_params": { + "additionalProperties": false, + "description": "rdb connection parameters", + "properties": { + "retry_attempts": { + "description": "connection retry attempts", + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "retry_delay_s": { + "description": "time delay between connection attempts", + "maximum": 3.4028234663852886e+38, + "minimum": -3.4028234663852886e+38, + "type": "number" + } + }, + "type": "object" + }, + "scenario": { + "description": "VTD scenario to use (project must already be loaded)", + "type": "string" + }, + "sensor_initial_port": { + "description": "initial port for sensor communication", + "maximum": 65535, + "minimum": 0, + "type": "integer" + }, + "setup": { + "description": "indicate which setup you are using", + "type": "string" + }, + "task_control_params": { + "additionalProperties": false, + "description": "task control connection parameters", + "properties": { + "retry_attempts": { + "description": "connection retry attempts", + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "retry_delay_s": { + "description": "time delay between connection attempts", + "maximum": 3.4028234663852886e+38, + "minimum": -3.4028234663852886e+38, + "type": "number" + } + }, + "type": "object" + }, + "vehicles": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "components": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "from": { + "description": "VTD sensor to retrieve the component data from", + "type": "string" + }, + "override": { + "description": "Override an existing component with the same name", + "type": "boolean" + }, + "type": { + "description": "Component type to register", + "type": "string" + } + }, + "type": "object" + }, + "description": "component definitions", + "type": "object" + }, + "sensors": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "mock_level": { + "additionalProperties": false, + "description": "Sensor data mock level", + "properties": { + "detected_lane_boundaries": { + "description": "mock level for detected lane boundaries", + "enum": [ + "overwrite_none", + "interpolate_missing", + "overwrite_all" + ], + "type": "string" + }, + "detected_moving_objects": { + "description": "mock level for detected moving objects", + "enum": [ + "overwrite_none", + "interpolate_missing", + "overwrite_all" + ], + "type": "string" + }, + "mounting_position": { + "description": "mock level for sensor mounting position", + "enum": [ + "overwrite_none", + "interpolate_missing", + "overwrite_all" + ], + "type": "string" + } + }, + "type": "object" + }, + "protocol": { + "description": "VTD module manager sensor connection protocol ( rdb | osi )", + "enum": [ + "rdb", + "osi" + ], + "type": "string" + }, + "xml": { + "description": "VTD module manager sensor configuration", + "type": "string" + } + }, + "type": "object" + }, + "description": "sensor definitions", + "type": "object" + } + }, + "type": "object" + }, + "description": "vehicle configuration like sensors and component mapping", + "type": "object" + } + }, + "type": "object" + }, + "binding": { + "const": "vtd", + "description": "name of simulator binding" + }, + "name": { + "description": "identifier of simulator instance", + "type": "string" + } + }, + "required": [ + "binding" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "triggers": { + "description": "triggers", + "items": { + "additionalProperties": false, + "properties": { + "action": { + "anyOf": [ + { + "description": "inline format", + "pattern": "^[a-zA-Z0-9_/]+(=.*)?$", + "type": "string" + }, + { + "additionalProperties": true, + "properties": { + "name": { + "pattern": "^([a-zA-Z_][a-zA-Z0-9_]*/?)+$", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + } + ], + "description": "action" + }, + "at": { + "description": "time at which trigger was executed" + }, + "event": { + "anyOf": [ + { + "description": "inline format", + "pattern": "^[a-zA-Z0-9_/]+(=.*)?$", + "type": "string" + }, + { + "additionalProperties": true, + "properties": { + "name": { + "pattern": "^([a-zA-Z_][a-zA-Z0-9_]*/?)+$", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + } + ], + "description": "event" + }, + "label": { + "description": "description of trigger", + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "since": { + "description": "time since which trigger was in queue" + }, + "source": { + "description": "source from which trigger originates", + "enum": [ + "filesystem", + "network", + "model", + "trigger", + "instance" + ], + "type": "string" + }, + "sticky": { + "description": "whether trigger should be sticky", + "type": "boolean" + } + }, + "required": [ + "action", + "event" + ], + "type": "object" + }, + "type": "array" + }, + "vehicles": { + "description": "vehicle configuration", + "items": { + "additionalProperties": false, + "properties": { + "components": { + "additionalProperties": { + "oneOf": [ + { + "additionalProperties": true, + "properties": { + "args": { + "additionalProperties": false, + "properties": { + "enable": { + "description": "enable or disable component", + "type": "boolean" + }, + "noise": { + "description": "configure noisy parameters", + "items": { + "additionalProperties": false, + "properties": { + "distribution": { + "description": "set distribution binding and arguments", + "oneOf": [ + { + "additionalProperties": false, + "properties": { + "args": { + "additionalProperties": false, + "properties": { + "mean": { + "description": "mean value of normal distribution", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + }, + "std_deviation": { + "description": "standard deviation of normal distribution", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + } + }, + "type": "object" + }, + "binding": { + "const": "normal", + "description": "identifier of this distribution" + } + }, + "required": [ + "binding" + ], + "type": "object" + } + ] + }, + "target": { + "description": "data field of the lane boundary the noise should be applied to", + "enum": [ + "dy_start", + "dx_start", + "heading_start", + "curv_hor_start", + "curv_hor_change", + "dx_end" + ], + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "reuse_seed": { + "description": "whether to get a new seed on reset", + "type": "boolean" + }, + "seed": { + "description": "set random engine seed (effective on reset)", + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + }, + "binding": { + "const": "noisy_lane_sensor", + "description": "name of simulator binding" + }, + "name": { + "description": "identifier of simulator instance", + "type": "string" + } + }, + "required": [ + "binding" + ], + "type": "object" + }, + { + "additionalProperties": true, + "properties": { + "args": { + "additionalProperties": false, + "properties": { + "enable": { + "description": "enable or disable component", + "type": "boolean" + }, + "noise": { + "description": "configure noisy parameters", + "items": { + "additionalProperties": false, + "properties": { + "distribution": { + "description": "set distribution binding and arguments", + "oneOf": [ + { + "additionalProperties": false, + "properties": { + "args": { + "additionalProperties": false, + "properties": { + "mean": { + "description": "mean value of normal distribution", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + }, + "std_deviation": { + "description": "standard deviation of normal distribution", + "maximum": 1.7976931348623157e+308, + "minimum": -1.7976931348623157e+308, + "type": "number" + } + }, + "type": "object" + }, + "binding": { + "const": "normal", + "description": "identifier of this distribution" + } + }, + "required": [ + "binding" + ], + "type": "object" + } + ] + }, + "target": { + "description": "data field of the object the noise should be applied to", + "enum": [ + "translation", + "velocity", + "acceleration" + ], + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "reuse_seed": { + "description": "whether to get a new seed on reset", + "type": "boolean" + }, + "seed": { + "description": "set random engine seed (effective on reset)", + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + }, + "binding": { + "const": "noisy_object_sensor", + "description": "name of simulator binding" + }, + "name": { + "description": "identifier of simulator instance", + "type": "string" + } + }, + "required": [ + "binding" + ], + "type": "object" + }, + { + "additionalProperties": true, + "properties": { + "args": null, + "binding": { + "const": "speedometer", + "description": "name of simulator binding" + }, + "name": { + "description": "identifier of simulator instance", + "type": "string" + } + }, + "required": [ + "binding" + ], + "type": "object" + } + ] + }, + "description": "component configuration of vehicle", + "type": "object" + }, + "from": { + "anyOf": [ + { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "index": { + "description": "index of vehicle in simulator", + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "simulator": { + "description": "simulator", + "minLength": 1, + "type": "string" + } + }, + "required": [ + "index", + "simulator" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "name": { + "description": "name of vehicle in simulator", + "minLength": 1, + "type": "string" + }, + "simulator": { + "description": "simulator", + "minLength": 1, + "type": "string" + } + }, + "required": [ + "name", + "simulator" + ], + "type": "object" + } + ], + "description": "simulator source" + }, + { + "description": "vehicle source", + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$", + "type": "string" + } + ] + }, + "name": { + "description": "globally unique identifier for vehicle", + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$", + "type": "string" + } + }, + "required": [ + "from", + "name" + ], + "type": "object" + }, + "type": "array" + }, + "version": { + "const": "4", + "description": "version of stackfile" + } + }, + "required": [ + "version" + ], + "type": "object" +} diff --git a/tests/test_vtd.bats b/tests/test_vtd.bats index 88b02f996..8ef1a3656 100755 --- a/tests/test_vtd.bats +++ b/tests/test_vtd.bats @@ -9,10 +9,9 @@ teardown_vtd() { test_vtd_plugin_exists() { # VTD_ROOT is only available in the shell. - cloe_shell -c 'test -d ${VTD_ROOT}' + cloe_shell -c 'test -d "${VTD_ROOT}"' } - teardown() { # It's harmless to stop vtd multiple times, so do it in case something goes wrong. if test_vtd_plugin_exists; then