scenario_simulator_v2 C++ API
noise_parameter_selector.hpp
Go to the documentation of this file.
1 // Copyright 2015 TIER IV, Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef SIMPLE_SENSOR_SIMULATOR__SENSOR_SIMULATION__NOISE_PARAMETER_SELECTOR_HPP_
16 #define SIMPLE_SENSOR_SIMULATOR__SENSOR_SIMULATION__NOISE_PARAMETER_SELECTOR_HPP_
17 
18 #include <boost/math/constants/constants.hpp>
19 #include <execution>
20 #include <get_parameter/get_parameter.hpp>
21 #include <regex>
24 #include <string>
25 #include <vector>
26 
28 {
29 namespace noise_parameter_selector
30 {
32  const std::string & parameter_base_path, double x, double y)
33 {
34  return [parameter_base_path, x, y](const std::string & name) {
35  return [=]() {
36  const auto ellipse_y_radii =
37  common::getParameter<std::vector<double>>(parameter_base_path + "ellipse_y_radii");
38  const auto ellipse_normalized_x_radius =
39  common::getParameter<double>(parameter_base_path + name + ".ellipse_normalized_x_radius");
40  const auto values =
41  common::getParameter<std::vector<double>>(parameter_base_path + name + ".values");
42  if (ellipse_y_radii.size() == values.size()) {
43  /*
44  If the parameter `ellipse_y_radii` contains the value 0.0,
45  division by zero will occur here.
46  However, in that case, the distance will be NaN, which correctly
47  expresses the meaning that "the distance cannot be defined", and
48  this function will work without any problems (zero will be
49  returned).
50  */
51  const auto distance = std::hypot(x / ellipse_normalized_x_radius, y);
52  for (auto i = std::size_t(0); i < ellipse_y_radii.size(); ++i) {
53  if (distance < ellipse_y_radii[i]) {
54  return values[i];
55  }
56  }
57  return 0.0;
58  } else {
59  throw common::Error(
60  "Array size mismatch: ", std::quoted(parameter_base_path + "ellipse_y_radii"), " has ",
61  ellipse_y_radii.size(), " elements, but ",
62  std::quoted(parameter_base_path + name + ".values"), " has ", values.size(),
63  " elements. Both arrays must have the same size.");
64  }
65  };
66  };
67 }
68 
70  const std::string & parameter_name, const std::string & version_base_path) -> std::string
71 {
72  if (const auto next_dot_pos = parameter_name.find('.', version_base_path.length());
73  next_dot_pos != std::string::npos) {
74  return parameter_name.substr(
75  version_base_path.length(), next_dot_pos - version_base_path.length());
76  }
77  return "";
78 }
79 
80 inline auto listAvailableNoiseConfigs(const std::string & topic_name, const std::string & version)
81  -> std::vector<std::string>
82 {
83  const std::string version_base_path = topic_name + ".noise." + version + ".";
84 
85  // Get all parameter names
86  const auto parameter_names =
87  common::getParameterNode()
88  .list_parameters({}, rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE)
89  .names;
90 
91  // Extract unique config names from parameters
92  std::set<std::string> config_names_set;
93  for (const auto & parameter_name : parameter_names) {
94  if (parameter_name.rfind(version_base_path, 0) == 0) {
95  const auto config_name = parseConfigNameFromParameter(parameter_name, version_base_path);
96  if (!config_name.empty()) {
97  config_names_set.insert(config_name);
98  }
99  }
100  }
101 
102  return std::vector<std::string>(config_names_set.begin(), config_names_set.end());
103 }
104 
106  const traffic_simulator_msgs::EntityStatus & entity, const std::string & version,
107  const std::string & topic_name) -> std::string
108 {
109  const std::string version_base_path = topic_name + ".noise." + version + ".";
110  auto matches_noise_application_entities = [&](
112  const std::string & noise_config_name) -> bool {
113  const auto base_path = version_base_path + noise_config_name + ".noise_application_entities.";
114 
115  const auto types = common::getParameter<std::vector<std::string>>(base_path + "types");
116  const auto subtypes = common::getParameter<std::vector<std::string>>(base_path + "subtypes");
117  const auto names = common::getParameter<std::vector<std::string>>(base_path + "names");
118 
119  auto string_with_wildcards_to_regex =
120  [](const std::string & string_with_wildcards) -> std::regex {
121  std::string regex_pattern;
122  for (char c : string_with_wildcards) {
123  regex_pattern += (c == '*') ? ".*" : (c == '?') ? "." : std::string(1, c);
124  }
125  return std::regex(regex_pattern);
126  };
127 
128  return std::any_of(
129  types.begin(), types.end(),
130  [entity_type = boost::lexical_cast<std::string>(entity.type()),
131  string_with_wildcards_to_regex](const auto & target) {
132  return std::regex_match(entity_type, string_with_wildcards_to_regex(target));
133  }) &&
134  std::any_of(
135  subtypes.begin(), subtypes.end(),
136  [entity_subtype = boost::lexical_cast<std::string>(entity.subtype()),
137  string_with_wildcards_to_regex](const auto & target) {
138  return std::regex_match(entity_subtype, string_with_wildcards_to_regex(target));
139  }) &&
140  std::any_of(
141  names.begin(), names.end(),
142  [entity_name = entity.name(), string_with_wildcards_to_regex](const auto & target) {
143  return std::regex_match(entity_name, string_with_wildcards_to_regex(target));
144  });
145  };
146 
147  const auto parameter_names =
148  common::getParameterNode()
149  .list_parameters({}, rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE)
150  .names;
151 
152  if (auto matched_parameter = std::find_if(
153  parameter_names.begin(), parameter_names.end(),
154  [&](const auto & parameter_name) {
155  if (parameter_name.rfind(version_base_path, 0) == 0) {
156  if (auto config_name = parseConfigNameFromParameter(parameter_name, version_base_path);
157  !config_name.empty()) {
158  return matches_noise_application_entities(entity, config_name);
159  }
160  }
161  return false;
162  });
163  matched_parameter != parameter_names.end()) {
164  return parseConfigNameFromParameter(*matched_parameter, version_base_path);
165  } else {
166  return "";
167  }
168 }
169 } // namespace noise_parameter_selector
170 } // namespace simple_sensor_simulator
171 
172 #endif // SIMPLE_SENSOR_SIMULATOR__SENSOR_SIMULATION__NOISE_PARAMETER_SELECTOR_HPP_
auto hypot(const T &from, const U &to)
Definition: hypot.hpp:28
auto findMatchingNoiseConfigForEntity(const traffic_simulator_msgs::EntityStatus &entity, const std::string &version, const std::string &topic_name) -> std::string
Definition: noise_parameter_selector.hpp:105
auto parseConfigNameFromParameter(const std::string &parameter_name, const std::string &version_base_path) -> std::string
Definition: noise_parameter_selector.hpp:69
auto createEllipticalParameterSelector(const std::string &parameter_base_path, double x, double y)
Definition: noise_parameter_selector.hpp:31
auto listAvailableNoiseConfigs(const std::string &topic_name, const std::string &version) -> std::vector< std::string >
Definition: noise_parameter_selector.hpp:80
Definition: constants.hpp:19
auto distance(const geometry_msgs::Pose &pose1, const geometry_msgs::Pose &pose2)
Definition: detection_sensor.cpp:45
std::string string
Definition: junit5.hpp:26
traffic_simulator_msgs::EntityStatus EntityStatus
Definition: helper_functions.hpp:32
Definition: exception.hpp:27