4#include <rsl/export.hpp>
8#include <rcl_interfaces/msg/set_parameters_result.hpp>
9#include <rclcpp/parameter.hpp>
10#include <tl_expected/expected.hpp>
12#include <fmt/ranges.h>
24[[nodiscard]]
auto stringify(T
const& value) -> std::string {
25 if constexpr (std::is_floating_point_v<T>)
return fmt::format(
"{:g}", value);
26 return fmt::format(
"{}", value);
30[[nodiscard]]
auto join_stringified(std::vector<T>
const& values) -> std::string {
31 std::vector<std::string> tokens;
32 tokens.reserve(values.size());
33 for (
auto const& value : values) tokens.push_back(stringify(value));
34 return fmt::format(
"{}", fmt::join(tokens,
", "));
37template <
typename T,
typename Fn>
38[[nodiscard]]
auto size_compare(rclcpp::Parameter
const& parameter,
size_t const size,
39 std::string
const& predicate_description,
40 Fn
const& predicate) -> tl::expected<void, std::string> {
41 static constexpr auto format_string =
"Length of parameter '{}' is '{}' but must be {} '{}'";
42 switch (parameter.get_type()) {
43 case rclcpp::ParameterType::PARAMETER_STRING:
44 if (
auto value = parameter.get_value<std::string>(); !predicate(value.size(), size))
45 return tl::unexpected(fmt::format(format_string, parameter.get_name(), value.size(),
46 predicate_description, size));
49 if (
auto value = parameter.get_value<std::vector<T>>(); !predicate(value.size(), size))
50 return tl::unexpected(fmt::format(format_string, parameter.get_name(), value.size(),
51 predicate_description, size));
56template <
typename T,
typename Fn>
57[[nodiscard]]
auto compare(rclcpp::Parameter
const& parameter, T
const& value,
58 std::string
const& predicate_description,
59 Fn
const& predicate) -> tl::expected<void, std::string> {
60 if (
auto const param_value = parameter.get_value<T>(); !predicate(param_value, value))
61 return tl::unexpected(fmt::format(
"Parameter '{}' with the value '{}' must be {} '{}'",
62 parameter.get_name(), stringify(param_value),
63 predicate_description, stringify(value)));
78[[nodiscard]]
auto unique(rclcpp::Parameter
const& parameter) -> tl::expected<void, std::string> {
79 if (
is_unique(parameter.get_value<std::vector<T>>()))
return {};
80 return tl::unexpected(
81 fmt::format(
"Parameter '{}' must only contain unique values", parameter.get_name()));
91[[nodiscard]]
auto subset_of(rclcpp::Parameter
const& parameter, std::vector<T>
const& valid_values)
92 -> tl::expected<void, std::string> {
93 auto const& values = parameter.get_value<std::vector<T>>();
94 for (
auto const& value : values)
96 return tl::unexpected(
97 fmt::format(
"Entry '{}' in parameter '{}' is not in the set '{{{}}}'", value,
98 parameter.get_name(), fmt::join(valid_values,
", ")));
109[[nodiscard]]
auto fixed_size(rclcpp::Parameter
const& parameter,
size_t const size) {
110 return detail::size_compare<T>(parameter, size,
"equal to", std::equal_to<>());
120[[nodiscard]]
auto size_gt(rclcpp::Parameter
const& parameter,
size_t const size) {
121 return detail::size_compare<T>(parameter, size,
"greater than", std::greater<>());
131[[nodiscard]]
auto size_lt(rclcpp::Parameter
const& parameter,
size_t const size) {
132 return detail::size_compare<T>(parameter, size,
"less than", std::less<>());
143[[nodiscard]]
auto not_empty(rclcpp::Parameter
const& parameter)
144 -> tl::expected<void, std::string> {
145 switch (parameter.get_type()) {
146 case rclcpp::ParameterType::PARAMETER_STRING:
147 if (
auto param_value = parameter.get_value<std::string>(); param_value.empty())
148 return tl::unexpected(
149 fmt::format(
"Parameter '{}' cannot be empty", parameter.get_name()));
152 if (
auto param_value = parameter.get_value<std::vector<T>>(); param_value.empty())
153 return tl::unexpected(
154 fmt::format(
"Parameter '{}' cannot be empty", parameter.get_name()));
166[[nodiscard]]
auto element_bounds(rclcpp::Parameter
const& parameter, T
const& lower,
167 T
const& upper) -> tl::expected<void, std::string> {
168 auto const& param_value = parameter.get_value<std::vector<T>>();
169 for (
auto val : param_value)
170 if (val < lower || val > upper)
171 return tl::unexpected(
172 fmt::format(
"Value '{}' in parameter '{}' must be within bounds '[{}, {}]'",
173 detail::stringify(val), parameter.get_name(), detail::stringify(lower),
174 detail::stringify(upper)));
186 T
const& lower) -> tl::expected<void, std::string> {
187 auto const& param_value = parameter.get_value<std::vector<T>>();
188 for (
auto val : param_value)
190 return tl::unexpected(fmt::format(
191 "Value '{}' in parameter '{}' must be above lower bound of '{}'",
192 detail::stringify(val), parameter.get_name(), detail::stringify(lower)));
204 T
const& upper) -> tl::expected<void, std::string> {
205 auto const& param_value = parameter.get_value<std::vector<T>>();
206 for (
auto val : param_value)
208 return tl::unexpected(fmt::format(
209 "Value '{}' in parameter '{}' must be below upper bound of '{}'",
210 detail::stringify(val), parameter.get_name(), detail::stringify(upper)));
221[[nodiscard]]
auto bounds(rclcpp::Parameter
const& parameter, T
const& lower,
222 T
const& upper) -> tl::expected<void, std::string> {
223 auto const& param_value = parameter.get_value<T>();
224 if (param_value < lower || param_value > upper)
225 return tl::unexpected(
226 fmt::format(
"Parameter '{}' with the value '{}' must be within bounds '[{}, {}]'",
227 parameter.get_name(), detail::stringify(param_value),
228 detail::stringify(lower), detail::stringify(upper)));
240 rclcpp::Parameter
const& parameter, T
const& value) {
241 return detail::compare(parameter, value,
"above lower bound of", std::greater_equal<T>());
252 rclcpp::Parameter
const& parameter, T
const& value) {
253 return detail::compare(parameter, value,
"below upper bound of", std::less_equal<T>());
263[[nodiscard]]
auto lt(rclcpp::Parameter
const& parameter, T
const& value) {
264 return detail::compare(parameter, value,
"less than", std::less<T>());
274[[nodiscard]]
auto gt(rclcpp::Parameter
const& parameter, T
const& value) {
275 return detail::compare(parameter, value,
"greater than", std::greater<T>());
285[[nodiscard]]
auto lt_eq(rclcpp::Parameter
const& parameter, T
const& value) {
286 return detail::compare(parameter, value,
"less than or equal to", std::less_equal<T>());
296[[nodiscard]]
auto gt_eq(rclcpp::Parameter
const& parameter, T
const& value) {
297 return detail::compare(parameter, value,
"greater than or equal to", std::greater_equal<T>());
307[[nodiscard]]
auto one_of(rclcpp::Parameter
const& parameter,
308 std::vector<T>
const& collection) -> tl::expected<void, std::string> {
309 auto const& param_value = parameter.get_value<T>();
310 if (
contains(collection, param_value))
return {};
311 return tl::unexpected(fmt::format(
312 "Parameter '{}' with the value '{}' is not in the set '{{{}}}'", parameter.get_name(),
313 detail::stringify(param_value), detail::join_stringified(collection)));
320 -> rcl_interfaces::msg::SetParametersResult;
auto contains(Collection const &collection, typename Collection::const_reference value)
Determine if a collection contains a value. Example usage:
Definition algorithm.hpp:19
auto is_unique(Collection collection)
Determine if all elements in a collection are unique. Example usage:
Definition algorithm.hpp:37
auto fixed_size(rclcpp::Parameter const ¶meter, size_t const size)
Is the array size of parameter equal to passed in size?
Definition parameter_validators.hpp:109
auto lower_element_bounds(rclcpp::Parameter const ¶meter, T const &lower) -> tl::expected< void, std::string >
Are all elements of parameter greater than lower bound?
Definition parameter_validators.hpp:185
auto bounds(rclcpp::Parameter const ¶meter, T const &lower, T const &upper) -> tl::expected< void, std::string >
Is parameter within bounds (inclusive)?
Definition parameter_validators.hpp:221
auto gt_eq(rclcpp::Parameter const ¶meter, T const &value)
Is parameter greater than or equal to some value?
Definition parameter_validators.hpp:296
auto subset_of(rclcpp::Parameter const ¶meter, std::vector< T > const &valid_values) -> tl::expected< void, std::string >
Are the values in parameter a subset of the valid values?
Definition parameter_validators.hpp:91
auto unique(rclcpp::Parameter const ¶meter) -> tl::expected< void, std::string >
Is every element of rclcpp::Parameter unique?
Definition parameter_validators.hpp:78
auto one_of(rclcpp::Parameter const ¶meter, std::vector< T > const &collection) -> tl::expected< void, std::string >
Is the parameter value one of a set of values?
Definition parameter_validators.hpp:307
auto size_lt(rclcpp::Parameter const ¶meter, size_t const size)
Is the array size of parameter less than passed in size?
Definition parameter_validators.hpp:131
auto upper_element_bounds(rclcpp::Parameter const ¶meter, T const &upper) -> tl::expected< void, std::string >
Are all elements of parameter less than some upper bound?
Definition parameter_validators.hpp:203
auto element_bounds(rclcpp::Parameter const ¶meter, T const &lower, T const &upper) -> tl::expected< void, std::string >
Are all elements of parameter within the bounds (inclusive)?
Definition parameter_validators.hpp:166
auto not_empty(rclcpp::Parameter const ¶meter) -> tl::expected< void, std::string >
Is the size of the value passed in not zero?
Definition parameter_validators.hpp:143
RSL_EXPORT auto to_parameter_result_msg(tl::expected< void, std::string > const &result) -> rcl_interfaces::msg::SetParametersResult
Convert the result of a validator function into a SetParametersResult msg.
auto lower_bounds(rclcpp::Parameter const ¶meter, T const &value)
Is parameter within some lower bound (same as gt_eq)?
Definition parameter_validators.hpp:239
auto lt(rclcpp::Parameter const ¶meter, T const &value)
Is parameter less than some value?
Definition parameter_validators.hpp:263
auto size_gt(rclcpp::Parameter const ¶meter, size_t const size)
Is the array size of parameter greater than passed in size?
Definition parameter_validators.hpp:120
auto gt(rclcpp::Parameter const ¶meter, T const &value)
Is parameter greater than some value?
Definition parameter_validators.hpp:274
auto lt_eq(rclcpp::Parameter const ¶meter, T const &value)
Is parameter less than or equal to some value?
Definition parameter_validators.hpp:285
auto upper_bounds(rclcpp::Parameter const ¶meter, T const &value)
Is parameter within some upper bound (same as lt_eq)?
Definition parameter_validators.hpp:251