Thank you for sharing your configuration library. Hierarchical parameter loading is a very useful feature, and I find it an exciting topic. I have a few comments and feedback on the design after reading your README and open questions.
On More Layers
To support more layers, one idea could be defining a PATH
variable such as
ROS_CONFIG_PATH="~/cfg_dir/device/:~/cfg_dir/model/"
This is very good because we do not need to dictate a particular (single) config directory, and we can easily define config directories that are conventionally spread over the filesystem. For example, this layout uses conventional /opt
, /run
, and /etc
directories.
ROS_CONFIG_PATH="/etc/<namespace>/config:/run/<namespace>/config:/opt/<namespace>/config"
And users can extend/alter them easily:
export ROS_CONFIG_PATH="~/<namespace>/config:${ROS_CONFIG_PATH}"
Substitutions and Evals!
Regarding substitution and eval functionality, I think it is an overkill. If I use your !eval
statements, my parameter files would be useless without your tooling. This is something I never want. And this is a big liability for your development too. Now you must carry the responsibility of not only your own company but everyone who uses your tooling. Many problems in open-source projects start from such decisions (ROS I am looking at you).
If you really insist on such advanced features, the template language must be something standardized and widespread, like the GNU utility envsubst
or jinja
at least. Other utilities and templating languages may be considered as an alternative but it is better to avoid developing a custom format or relying exclusively on Python evals. The value I see here is in the configuration hierarchy, not in the templating. This is even more if we think that Google (jsonnet
) and Apple (pkl
) already provide extensive solutions for configuration templating.
Testing for Direct Node Execution and Beyond
A not-so-much-documented feature of ROS is the ability to execute node executables directly. I remember it took some time for me to figure out how to pass parameters, but it is as follows:
node-exec --ros-args --params-file my_param.yml
Direct execution does not perform variable substitution, which is a feature of ROS launch. This is another reason I suggest not using $(find-pkg ...)
statements in parameter files, but sometimes I see this is abused. Therefore, I want to emphasize that any parameter solution should be functional when executing nodes directly without relying on Launch. I think your library is fine as I can use it directly like this:
config print --config-directory my_cfg_dir /home/user/param_config.yaml
node-exec --ros-args --params-file /home/user/param_config.yaml
It is, of course, better that ROS node executables have such functionality built-in, perhaps via utilizing ROS_CONFIG_PATH
. Maybe this would evolve into a more fundamental solution.
Can it be done via a new rcl-yaml-param-parser
? Any comment?