-
Notifications
You must be signed in to change notification settings - Fork 199
Engine configuration utility #1828
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 10 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
732c5cd
Create the configuration utility
Gamenot 24cd940
Gen header.
Gamenot c8e9e29
Fix types test.
Gamenot 0589ab3
Add test.
Gamenot 1394667
Fix test types.
Gamenot 45715ba
Update config to take in file locations.
Gamenot 9296335
Ensure the ini config file is included.
Gamenot 693683d
Add missing docstring and formatting
Gamenot d43d4be
Fix ambiguity with smarts and smarts.core.smarts
Gamenot 949b640
Update documentation
Gamenot dc983c9
Update docs/sim/configuration.rst
Gamenot e577d66
Move sim configuration to next steps.
Gamenot a6ab9fc
Assign pybullet frequency to make clear.
Gamenot db8cdc9
Update docs/sim/configuration.rst
Gamenot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.. _todo: | ||
|
||
TODO List | ||
========= | ||
|
||
A list of current documentation TODO. | ||
|
||
.. todolist_:: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
.. _configuration: | ||
|
||
Configuration | ||
============= | ||
|
||
You can change the behavior of the underlying SMARTS engine. | ||
|
||
Configuration of the engine can come from several sources. These locations take precidence as noted: | ||
Gamenot marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
1. Individual ``SMARTS_`` prefixed environment variables (e.g. ``SMARTS_SENSOR_WORKER_COUNT``) | ||
2. Local directory engine configuration (./smarts_engine.ini ) | ||
3. Local user engine configuration, ``~/.smarts/engine.ini``, if local directory configuration is not found. | ||
4. Global engine configuration, ``/etc/smarts/engine.ini``, if local configuration is not found. | ||
5. Package default configuration, ``$PYTHON_PATH/smarts/engine.ini``, if global configuration is not found. | ||
|
||
Note that configuration files resolve all settings at the first found configuration file (they do not layer.) | ||
|
||
Options | ||
------- | ||
|
||
All settings demostrated as environment variables are formatted to ``UPPERCASE`` and prefixed with ``SMARTS_`` (e.g. ``[core] logging`` can be configured with ``SMARTS_CORE_LOGGING``) | ||
Gamenot marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
These settings are as follows: | ||
|
||
.. todo:: | ||
|
||
List engine settings |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
# MIT License | ||
# | ||
# Copyright (C) 2023. Huawei Technologies Co., Ltd. All rights reserved. | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining a copy | ||
# of this software and associated documentation files (the "Software"), to deal | ||
# in the Software without restriction, including without limitation the rights | ||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
# copies of the Software, and to permit persons to whom the Software is | ||
# furnished to do so, subject to the following conditions: | ||
# | ||
# The above copyright notice and this permission notice shall be included in | ||
# all copies or substantial portions of the Software. | ||
# | ||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE | ||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
# THE SOFTWARE. | ||
import configparser | ||
import functools | ||
import os | ||
from pathlib import Path | ||
from typing import Any, Callable, Optional, Union | ||
|
||
_UNSET = object() | ||
|
||
|
||
class Config: | ||
"""A configuration utility that handles configuration from file and environment variable. | ||
|
||
Args: | ||
config_file (Union[str, Path]): The path to the configuration file. | ||
environment_prefix (str, optional): The prefix given to the environment variables. Defaults to "". | ||
|
||
Raises: | ||
FileNotFoundError: If the configuration file cannot be found at the given file location. | ||
""" | ||
|
||
def __init__( | ||
self, config_file: Union[str, Path], environment_prefix: str = "" | ||
) -> None: | ||
self._config = configparser.ConfigParser( | ||
interpolation=configparser.ExtendedInterpolation() | ||
) | ||
self._environment_prefix = environment_prefix.upper() | ||
self._environment_variable_format_string = self._environment_prefix + "_{}_{}" | ||
|
||
if isinstance(config_file, str): | ||
config_file = Path(config_file) | ||
config_file = config_file.resolve() | ||
if not config_file.is_file(): | ||
raise FileNotFoundError(f"Configuration file not found at {config_file}") | ||
|
||
self._config.read(str(config_file.absolute())) | ||
|
||
@property | ||
def environment_prefix(self): | ||
"""The prefix that environment variables configuration is provided with.""" | ||
return self._environment_prefix | ||
|
||
@functools.lru_cache(maxsize=100) | ||
def get_setting( | ||
self, | ||
section: str, | ||
option: str, | ||
default: Any = _UNSET, | ||
cast: Callable[[str], Any] = str, | ||
) -> Optional[Any]: | ||
"""Finds the given configuration checking the following in order: environment variable, | ||
configuration file, and default. | ||
|
||
Args: | ||
section (str): The grouping that the configuration option is under. | ||
option (str): The specific configuration option. | ||
default (Any, optional): The default if the requested configuration option is not found. Defaults to _UNSET. | ||
cast (Callable, optional): A function that takes a string and returns the desired type. Defaults to str. | ||
|
||
|
||
Returns: | ||
Optional[str]: The value of the configuration. | ||
|
||
Raises: | ||
KeyError: If the configuration option is not found in the configuration file and no default is provided. | ||
configparser.NoSectionError: If the section in the configuration file is not found and no default is provided. | ||
""" | ||
env_variable = self._environment_variable_format_string.format( | ||
section.upper(), option.upper() | ||
) | ||
setting = os.getenv(env_variable) | ||
if setting is not None: | ||
return cast(setting) | ||
try: | ||
value = self._config[section][option] | ||
except (configparser.NoSectionError, KeyError): | ||
if default is _UNSET: | ||
raise | ||
return default | ||
return cast(value) | ||
|
||
def __call__( | ||
self, | ||
section: str, | ||
option: str, | ||
default: Any = _UNSET, | ||
cast: Callable[[str], Any] = str, | ||
) -> Optional[Any]: | ||
return self.get_setting(section, option, default, cast) | ||
|
||
def __repr__(self) -> str: | ||
return f"Config(config_file={ {k: dict(v.items()) for k, v in self._config.items(raw=True)} }, environment_prefix={self._environment_prefix})" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,7 +32,7 @@ | |
from smarts.core.plan import Plan | ||
from smarts.core.utils.logging import timeit | ||
|
||
from . import models | ||
from . import config, models | ||
from .actor import ActorRole, ActorState | ||
from .agent_interface import AgentInterface | ||
from .agent_manager import AgentManager | ||
|
@@ -728,7 +728,9 @@ def _setup_bullet_client(self, client: bc.BulletClient): | |
client.configureDebugVisualizer( | ||
pybullet.COV_ENABLE_GUI, 0 # pylint: disable=no-member | ||
) | ||
|
||
max_pybullet_freq = config()( | ||
"physics", "max_pybullet_freq", default=MAX_PYBULLET_FREQ, cast=int | ||
) | ||
# PyBullet defaults the timestep to 240Hz. Several parameters are tuned with | ||
# this value in mind. For example the number of solver iterations and the error | ||
# reduction parameters (erp) for contact, friction and non-contact joints. | ||
|
@@ -741,11 +743,11 @@ def _setup_bullet_client(self, client: bc.BulletClient): | |
self._pybullet_period = ( | ||
self._fixed_timestep_sec | ||
if self._fixed_timestep_sec | ||
else 1 / MAX_PYBULLET_FREQ | ||
else 1 / max_pybullet_freq | ||
) | ||
client.setPhysicsEngineParameter( | ||
fixedTimeStep=self._pybullet_period, | ||
numSubSteps=int(self._pybullet_period * MAX_PYBULLET_FREQ), | ||
numSubSteps=int(self._pybullet_period * max_pybullet_freq), | ||
numSolverIterations=10, | ||
solverResidualThreshold=0.001, | ||
# warmStartingFactor=0.99 | ||
|
@@ -857,10 +859,10 @@ def __del__(self): | |
" go away.", | ||
e, | ||
) | ||
except (AttributeError, KeyboardInterrupt): | ||
except (TypeError, KeyboardInterrupt): | ||
return | ||
raise exception | ||
|
||
def _teardown_vehicles(self, vehicle_ids): | ||
self._vehicle_index.teardown_vehicles_by_vehicle_ids(vehicle_ids) | ||
self._clear_collisions(vehicle_ids) | ||
|
@@ -1281,7 +1283,18 @@ def fixed_timestep_sec(self) -> float: | |
def fixed_timestep_sec(self, fixed_timestep_sec: float): | ||
if not fixed_timestep_sec: | ||
# This is the fastest we could possibly run given constraints from pybullet | ||
self._rounder = rounder_for_dt(round(1 / MAX_PYBULLET_FREQ, 6)) | ||
self._rounder = rounder_for_dt( | ||
round( | ||
1 | ||
/ config()( | ||
"physics", | ||
"max_pybullet_freq", | ||
default=MAX_PYBULLET_FREQ, | ||
cast=int, | ||
), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think pulling this out as a separate variable would make the expression more readable. |
||
6, | ||
) | ||
) | ||
else: | ||
self._rounder = rounder_for_dt(fixed_timestep_sec) | ||
self._fixed_timestep_sec = fixed_timestep_sec | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe keep files under a given toctree in the same folder?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is hard to find where to put this since
api/*
is generated dynamically but environment variables and configuration files are related tosim
but are relevant to API. Maybe not relevant enough. I am going to move it to resources.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am thinking
resources
is not quite the right spot for it either so I am moving it to next steps.