Skip to content

Commit ba2a2f8

Browse files
committed
Set parameters at node construction
1 parent d82ce96 commit ba2a2f8

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed

rclcpp/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ find_package(ament_cmake_ros REQUIRED)
66
find_package(builtin_interfaces REQUIRED)
77
find_package(rcl REQUIRED)
88
find_package(rcl_interfaces REQUIRED)
9+
find_package(rcl_yaml_param_parser REQUIRED)
910
find_package(rmw REQUIRED)
1011
find_package(rmw_implementation REQUIRED)
1112
find_package(rosidl_generator_cpp REQUIRED)
@@ -98,6 +99,7 @@ add_library(${PROJECT_NAME}
9899
# specific order: dependents before dependencies
99100
ament_target_dependencies(${PROJECT_NAME}
100101
"rcl"
102+
"rcl_yaml_param_parser"
101103
"builtin_interfaces"
102104
"rosidl_typesupport_cpp"
103105
"rosidl_generator_cpp")
@@ -120,6 +122,8 @@ ament_export_libraries(${PROJECT_NAME})
120122

121123
ament_export_dependencies(ament_cmake)
122124
ament_export_dependencies(rcl)
125+
# TODO(sloretz) Delete this if it doesn't end up being used in an installed header
126+
ament_export_dependencies(rcl_yaml_param_parser)
123127
ament_export_dependencies(builtin_interfaces)
124128
ament_export_dependencies(rosidl_typesupport_cpp)
125129
ament_export_dependencies(rosidl_typesupport_c)

rclcpp/package.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<build_export_depend>rosidl_typesupport_cpp</build_export_depend>
2424

2525
<depend>rcl</depend>
26+
<depend>rcl_yaml_param_parser</depend>
2627
<depend>rmw_implementation</depend>
2728

2829
<exec_depend>ament_cmake</exec_depend>

rclcpp/src/rclcpp/node_interfaces/node_parameters.cpp

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <vector>
2222

2323
#include "rcl_interfaces/srv/list_parameters.hpp"
24+
#include "rcl_yaml_param_parser/parser.h"
2425
#include "rclcpp/create_publisher.hpp"
2526
#include "rcutils/logging_macros.h"
2627
#include "rmw/qos_profiles.h"
@@ -50,6 +51,118 @@ NodeParameters::NodeParameters(
5051
rmw_qos_profile_parameter_events,
5152
use_intra_process,
5253
allocator);
54+
55+
// Get the node's allocator
56+
const rcl_node_t * node = node_base->get_rcl_node_handle();
57+
if (NULL == node) {
58+
throw std::runtime_error("Need valid node handle in NodeParameters");
59+
}
60+
const rcl_node_options_t * options = rcl_node_get_options(node);
61+
if (NULL == options) {
62+
throw std::runtime_error("Need valid node options NodeParameters");
63+
}
64+
65+
// TODO(sloretz) remove when circular dependency between rcl and rcl_yaml_param_parser is solved
66+
// TODO(sloretz) Somehow need to get yaml parameters from RCL
67+
const std::string yaml_path("/tmp/sloretz-test-params.yaml");
68+
rcl_params_t * yaml_params = rcl_yaml_node_struct_init(options->allocator);
69+
if (NULL == yaml_params) {
70+
throw std::runtime_error("Failed to initialize yaml params struct");
71+
}
72+
if (!rcl_parse_yaml_file(yaml_path.c_str(), yaml_params, options->allocator)) {
73+
throw std::runtime_error("Failed to parse parameters " + yaml_path);
74+
}
75+
76+
// Get namespace + node name
77+
const std::string node_name = node_base->get_name();
78+
const std::string node_namespace = node_base->get_namespace();
79+
if (0u == node_namespace.size() || 0u == node_name.size()) {
80+
// Should never happen
81+
throw std::runtime_error("Node name and namespace were not set");
82+
}
83+
std::string combined_name;
84+
if ('/' == node_namespace.at(node_namespace.size()-1)) {
85+
combined_name = node_namespace + node_name;
86+
} else {
87+
combined_name = node_namespace + '/' + node_name;
88+
}
89+
90+
// TODO(sloretz) should yaml param parser provide node names with a leading slash?
91+
// Strip leading slash
92+
combined_name.erase(combined_name.begin());
93+
94+
// Convert c structs into a list of parameters to set
95+
std::vector<rclcpp::parameter::ParameterVariant> parameters;
96+
for (size_t n = 0; n < yaml_params->num_nodes; ++n) {
97+
if (combined_name != yaml_params->node_names[n]) {
98+
continue;
99+
}
100+
const rcl_node_params_t * const params_node = &(yaml_params->params[n]);
101+
for (size_t p = 0; p < params_node->num_params; ++p) {
102+
const std::string param_name = params_node->parameter_names[p];
103+
const rcl_variant_t * const param_value = &(params_node->parameter_values[p]);
104+
105+
if (param_value->bool_value) {
106+
parameters.emplace_back(param_name, *(param_value->bool_value));
107+
} else if (param_value->integer_value) {
108+
parameters.emplace_back(param_name, *(param_value->integer_value));
109+
} else if (param_value->double_value) {
110+
parameters.emplace_back(param_name, *(param_value->double_value));
111+
} else if (param_value->string_value) {
112+
parameters.emplace_back(param_name, std::string(param_value->string_value));
113+
} else if (param_value->byte_array_value) {
114+
const rcl_byte_array_t * const byte_array = param_value->byte_array_value;
115+
std::vector<uint8_t> bytes;
116+
bytes.reserve(byte_array->size);
117+
for (size_t v = 0; v < byte_array->size; ++v) {
118+
bytes.push_back(byte_array->values[v]);
119+
}
120+
parameters.emplace_back(param_name, bytes);
121+
} else if (param_value->bool_array_value) {
122+
const rcl_bool_array_t * const bool_array = param_value->bool_array_value;
123+
std::vector<bool> bools;
124+
bools.reserve(bool_array->size);
125+
for (size_t v = 0; v < bool_array->size; ++v) {
126+
bools.push_back(bool_array->values[v]);
127+
}
128+
parameters.emplace_back(param_name, bools);
129+
} else if (param_value->integer_array_value) {
130+
const rcl_int64_array_t * const int_array = param_value->integer_array_value;
131+
std::vector<int64_t> integers;
132+
integers.reserve(int_array->size);
133+
for (size_t v = 0; v < int_array->size; ++v) {
134+
integers.push_back(int_array->values[v]);
135+
}
136+
parameters.emplace_back(param_name, integers);
137+
} else if (param_value->double_array_value) {
138+
const rcl_double_array_t * const double_array = param_value->double_array_value;
139+
std::vector<double> doubles;
140+
doubles.reserve(double_array->size);
141+
for (size_t v = 0; v < double_array->size; ++v) {
142+
doubles.push_back(double_array->values[v]);
143+
}
144+
parameters.emplace_back(param_name, doubles);
145+
} else if (param_value->string_array_value) {
146+
const rcutils_string_array_t * const string_array = param_value->string_array_value;
147+
std::vector<std::string> strings;
148+
strings.reserve(string_array->size);
149+
for (size_t v = 0; v < string_array->size; ++v) {
150+
strings.emplace_back(string_array->data[v]);
151+
}
152+
parameters.emplace_back(param_name, strings);
153+
} else {
154+
rcl_yaml_node_struct_fini(yaml_params, options->allocator);
155+
throw std::runtime_error("Invalid parameter from parser");
156+
}
157+
}
158+
}
159+
rcl_yaml_node_struct_fini(yaml_params, options->allocator);
160+
161+
// Set the parameters
162+
rcl_interfaces::msg::SetParametersResult result = set_parameters_atomically(parameters);
163+
if (!result.successful) {
164+
throw std::runtime_error("Failed to set initial parameters");
165+
}
53166
}
54167

55168
NodeParameters::~NodeParameters()

0 commit comments

Comments
 (0)