Skip to content
Snippets Groups Projects
Commit 3746a164 authored by Carl Delsey's avatar Carl Delsey
Browse files

Added a custom launch substitution to modify YAML parameters based on launch...

Added a custom launch substitution to modify YAML parameters based on launch params - lifecycle version (#771)

* Initial version copied from old code

* Code now installs

You can `import nav2_common.launch.rewritten_yaml` now.

* Bring RewrittenYaml class into launch scope like other launch packages do

This lets you say:
`from nav2_common.launch import RewrittenYaml`
instead of
`from nav2_common.launch.rewritten_yaml import RewrittenYaml`

* Add support for converting strings to non-string values in YAML

By the time RewrittenYaml gets the rewrite values, they've already been
resolved to strings. This is a problem for use_sim_time because the
code only accepts bools. To work around this RewrritenYaml has an option
to convert all values to an actual type.

* Add dependency in nav2_bringup package so it doesn't get forgotten.
parent 3d123cbe
No related branches found
No related tags found
No related merge requests found
......@@ -16,6 +16,7 @@
<exec_depend>launch_ros</exec_depend>
<exec_depend>navigation2</exec_depend>
<exec_depend>nav2_common</exec_depend>
<test_depend>ament_lint_common</test_depend>
<test_depend>ament_lint_auto</test_depend>
......
......@@ -3,6 +3,9 @@ cmake_minimum_required(VERSION 3.5)
project(nav2_common NONE)
find_package(ament_cmake_core REQUIRED)
find_package(ament_cmake_python REQUIRED)
ament_python_install_package(nav2_common)
ament_package(
CONFIG_EXTRAS "nav2_common-extras.cmake"
......
from .rewritten_yaml import RewrittenYaml
from typing import Dict
from typing import List
from typing import Text
import yaml
import tempfile
import launch
class DictItemReference:
def __init__(self, dictionary, key):
self.dictionary = dictionary
self.dictKey = key
def key(self):
return self.dictKey
def setValue(self, value):
self.dictionary[self.dictKey] = value
class RewrittenYaml(launch.Substitution):
"""
Substitution that modifies the given Yaml file.
"""
def __init__(self,
source_file: launch.SomeSubstitutionsType,
rewrites: Dict,
convert_types = False) -> None:
super().__init__()
from launch.utilities import normalize_to_list_of_substitutions # import here to avoid loop
self.__source_file = normalize_to_list_of_substitutions(source_file)
self.__rewrites = {}
self.__convert_types = convert_types
for key in rewrites:
self.__rewrites[key] = normalize_to_list_of_substitutions(rewrites[key])
@property
def name(self) -> List[launch.Substitution]:
"""Getter for name."""
return self.__source_file
def describe(self) -> Text:
"""Return a description of this substitution as a string."""
return ''
def perform(self, context: launch.LaunchContext) -> Text:
yaml_filename = launch.utilities.perform_substitutions(context, self.name)
rewritten_yaml = tempfile.NamedTemporaryFile(mode='w', delete=False)
resolved_rewrites = self.resolve_rewrites(context)
data = yaml.load(open(yaml_filename, 'r'))
self.substitute_values(data, resolved_rewrites)
yaml.dump(data, rewritten_yaml)
rewritten_yaml.close()
return rewritten_yaml.name
def resolve_rewrites(self, context):
resolved = {}
for key in self.__rewrites:
resolved[key] = launch.utilities.perform_substitutions(context, self.__rewrites[key])
return resolved
def substitute_values(self, yaml, rewrites):
for key in self.getYamlKeys(yaml):
if key.key() in rewrites:
raw_value = rewrites[key.key()]
key.setValue(self.convert(raw_value))
def getYamlKeys(self, yamlData):
try:
for key in yamlData.keys():
for k in self.getYamlKeys(yamlData[key]):
yield k
yield DictItemReference(yamlData, key)
except AttributeError:
return
def convert(self, text_value):
if self.__convert_types:
# try converting to float
try:
return float(text_value)
except ValueError:
pass
# try converting to int
try:
return int(text_value)
except ValueError:
pass
# try converting to bool
if text_value.lower() == "true":
return True
if text_value.lower() == "false":
return False
#nothing else worked so fall through and return text
return text_value
......@@ -9,6 +9,8 @@
<buildtool_depend>ament_cmake_core</buildtool_depend>
<build_depend>ament_cmake_python</build_depend>
<buildtool_export_depend>ament_cmake_core</buildtool_export_depend>
<export>
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment