-
Notifications
You must be signed in to change notification settings - Fork 310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[HW Interface] Change creation, exportation and storing of Command-/StateInterface + Support for variant #1240
Changes from all commits
56f9b17
7f97182
0a25035
168f427
e1ac94c
0894883
94eb6a8
715ccac
468b0c7
6869198
239a25b
213cbae
295b620
a133e2b
bfab95c
c2db38f
3232114
fb3c074
3378fcf
6667d40
a6ab1f0
1ffdb84
4199be1
2d6e7ea
3a53368
e9c2669
1cea7f2
84002fd
b05f585
05ec1bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,53 +44,91 @@ return_type ChainableControllerInterface::update( | |
return ret; | ||
} | ||
|
||
std::vector<hardware_interface::StateInterface> | ||
std::vector<std::shared_ptr<hardware_interface::StateInterface>> | ||
ChainableControllerInterface::export_state_interfaces() | ||
{ | ||
auto state_interfaces = on_export_state_interfaces(); | ||
std::vector<std::shared_ptr<hardware_interface::StateInterface>> state_interfaces_ptrs_vec; | ||
state_interfaces_ptrs_vec.reserve(state_interfaces.size()); | ||
|
||
// check if the names of the controller state interfaces begin with the controller's name | ||
for (const auto & interface : state_interfaces) | ||
{ | ||
if (interface.get_prefix_name() != get_node()->get_name()) | ||
{ | ||
RCLCPP_FATAL( | ||
get_node()->get_logger(), | ||
"The name of the interface '%s' does not begin with the controller's name. This is " | ||
"mandatory for state interfaces. No state interface will be exported. Please " | ||
"correct and recompile the controller with name '%s' and try again.", | ||
interface.get_name().c_str(), get_node()->get_name()); | ||
state_interfaces.clear(); | ||
break; | ||
std::string error_msg = | ||
"The prefix of the interface '" + interface.get_prefix_name() + | ||
"' does not equal the controller's name '" + get_node()->get_name() + | ||
"'. This is mandatory for state interfaces. No state interface will be exported. Please " | ||
"correct and recompile the controller with name '" + | ||
get_node()->get_name() + "' and try again."; | ||
throw std::runtime_error(error_msg); | ||
} | ||
|
||
state_interfaces_ptrs_vec.push_back( | ||
std::make_shared<hardware_interface::StateInterface>(interface)); | ||
} | ||
|
||
return state_interfaces; | ||
return state_interfaces_ptrs_vec; | ||
} | ||
|
||
std::vector<hardware_interface::CommandInterface> | ||
std::vector<std::shared_ptr<hardware_interface::CommandInterface>> | ||
ChainableControllerInterface::export_reference_interfaces() | ||
{ | ||
auto reference_interfaces = on_export_reference_interfaces(); | ||
std::vector<std::shared_ptr<hardware_interface::CommandInterface>> reference_interfaces_ptrs_vec; | ||
reference_interfaces_ptrs_vec.reserve(reference_interfaces.size()); | ||
|
||
// BEGIN (Handle export change): for backward compatibility | ||
// check if the "reference_interfaces_" variable is resized to number of interfaces | ||
if (reference_interfaces_.size() != reference_interfaces.size()) | ||
{ | ||
// TODO(destogl): Should here be "FATAL"? It is fatal in terms of controller but not for the | ||
// framework | ||
Comment on lines
+86
to
+87
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i have to check this will comment later i would prefer fixing everything and providing as well. |
||
std::string error_msg = | ||
"The internal storage for reference values 'reference_interfaces_' variable has size '" + | ||
std::to_string(reference_interfaces_.size()) + "', but it is expected to have the size '" + | ||
std::to_string(reference_interfaces.size()) + | ||
"' equal to the number of exported reference interfaces. Please correct and recompile the " | ||
"controller with name '" + | ||
get_node()->get_name() + "' and try again."; | ||
throw std::runtime_error(error_msg); | ||
} | ||
// END | ||
|
||
// check if the names of the reference interfaces begin with the controller's name | ||
for (const auto & interface : reference_interfaces) | ||
const auto ref_interface_size = reference_interfaces.size(); | ||
for (auto & interface : reference_interfaces) | ||
{ | ||
if (interface.get_prefix_name() != get_node()->get_name()) | ||
{ | ||
RCLCPP_FATAL( | ||
get_node()->get_logger(), | ||
"The name of the interface '%s' does not begin with the controller's name. This is " | ||
"mandatory " | ||
" for reference interfaces. No reference interface will be exported. Please correct and " | ||
"recompile the controller with name '%s' and try again.", | ||
interface.get_name().c_str(), get_node()->get_name()); | ||
reference_interfaces.clear(); | ||
break; | ||
std::string error_msg = "The name of the interface " + interface.get_name() + | ||
" does not begin with the controller's name. This is mandatory for " | ||
"reference interfaces. Please " | ||
"correct and recompile the controller with name " + | ||
get_node()->get_name() + " and try again."; | ||
throw std::runtime_error(error_msg); | ||
} | ||
|
||
std::shared_ptr<hardware_interface::CommandInterface> interface_ptr = | ||
std::make_shared<hardware_interface::CommandInterface>(std::move(interface)); | ||
reference_interfaces_ptrs_vec.push_back(interface_ptr); | ||
reference_interfaces_ptrs_.insert(std::make_pair(interface_ptr->get_name(), interface_ptr)); | ||
} | ||
|
||
return reference_interfaces; | ||
if (reference_interfaces_ptrs_.size() != ref_interface_size) | ||
{ | ||
std::string error_msg = | ||
"The internal storage for reference ptrs 'reference_interfaces_ptrs_' variable has size '" + | ||
std::to_string(reference_interfaces_ptrs_.size()) + | ||
"', but it is expected to have the size '" + std::to_string(ref_interface_size) + | ||
"' equal to the number of exported reference interfaces. Please correct and recompile the " | ||
"controller with name '" + | ||
get_node()->get_name() + "' and try again."; | ||
throw std::runtime_error(error_msg); | ||
} | ||
|
||
return reference_interfaces_ptrs_vec; | ||
} | ||
|
||
bool ChainableControllerInterface::set_chained_mode(bool chained_mode) | ||
|
@@ -130,8 +168,8 @@ ChainableControllerInterface::on_export_state_interfaces() | |
std::vector<hardware_interface::StateInterface> state_interfaces; | ||
for (size_t i = 0; i < exported_state_interface_names_.size(); ++i) | ||
{ | ||
state_interfaces.emplace_back(hardware_interface::StateInterface( | ||
get_node()->get_name(), exported_state_interface_names_[i], &state_interfaces_values_[i])); | ||
state_interfaces.emplace_back( | ||
get_node()->get_name(), exported_state_interface_names_[i], &state_interfaces_values_[i]); | ||
} | ||
return state_interfaces; | ||
} | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -22,12 +22,14 @@ ControllerInterface::ControllerInterface() : ControllerInterfaceBase() {} | |||||
|
||||||
bool ControllerInterface::is_chainable() const { return false; } | ||||||
|
||||||
std::vector<hardware_interface::StateInterface> ControllerInterface::export_state_interfaces() | ||||||
std::vector<std::shared_ptr<hardware_interface::StateInterface>> | ||||||
ControllerInterface::export_state_interfaces() | ||||||
{ | ||||||
return {}; | ||||||
} | ||||||
|
||||||
std::vector<hardware_interface::CommandInterface> ControllerInterface::export_reference_interfaces() | ||||||
std::vector<std::shared_ptr<hardware_interface::CommandInterface>> | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Was wondering if we could do this instead? Just to shorten things... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no because then they would not override the base functions (which have to have this return type because controllers need access to the exported handles to set/get values from them). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think @bmagyar means here that we define a new type, something like:
This should go to the header where On the other ahdn I am not fan of it, as it makes things shorter, but make them also less clear and direct. |
||||||
ControllerInterface::export_reference_interfaces() | ||||||
{ | ||||||
return {}; | ||||||
} | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -761,15 +761,28 @@ controller_interface::return_type ControllerManager::configure_controller( | |
get_logger(), | ||
"Controller '%s' is chainable. Interfaces are being exported to resource manager.", | ||
controller_name.c_str()); | ||
auto state_interfaces = controller->export_state_interfaces(); | ||
auto ref_interfaces = controller->export_reference_interfaces(); | ||
if (ref_interfaces.empty() && state_interfaces.empty()) | ||
std::vector<std::shared_ptr<hardware_interface::StateInterface>> state_interfaces; | ||
std::vector<std::shared_ptr<hardware_interface::CommandInterface>> ref_interfaces; | ||
try | ||
{ | ||
// TODO(destogl): Add test for this! | ||
RCLCPP_ERROR( | ||
get_logger(), | ||
"Controller '%s' is chainable, but does not export any state or reference interfaces.", | ||
controller_name.c_str()); | ||
state_interfaces = controller->export_state_interfaces(); | ||
ref_interfaces = controller->export_reference_interfaces(); | ||
if (ref_interfaces.empty() && state_interfaces.empty()) | ||
{ | ||
// TODO(destogl): Add test for this! | ||
RCLCPP_ERROR( | ||
get_logger(), | ||
"Controller '%s' is chainable, but does not export any reference interfaces. Did you " | ||
"override the on_export_method() correctly?", | ||
controller_name.c_str()); | ||
return controller_interface::return_type::ERROR; | ||
} | ||
} | ||
catch (const std::runtime_error & e) | ||
{ | ||
RCLCPP_FATAL( | ||
get_logger(), "Creation of the reference interfaces failed with following error: %s", | ||
e.what()); | ||
Comment on lines
-764
to
+785
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this section could remain as it was before. Errors could be communicated via prints & empty returned arrays, no need for exceptions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i personally would prefer exceptions since they make clear that an unexpected condition arose which needs some separate handling and ultimately controller manager should decide how to proceed in this case (thats why i cathc there and handle exception). i am not a big fan of implicitly encoding this in the return type. I personally would prefer explicit over implicit here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why can creation fail? |
||
return controller_interface::return_type::ERROR; | ||
} | ||
resource_manager_->import_controller_reference_interfaces(controller_name, ref_interfaces); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do these needs to be shared pointers? I'm just wondering about how best we can keep track of the lifecycle of things moving around...
would a unique_ptr be unusable? I also hate seeing
std::move
in active codebase but it is a fair use-case for this IMOThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i guess no because we want to export the reference interfaces but the controller still needs to have access to them (since value is now stored directly). Its same with the hardware. We could avoid creating shared_ptrs by creating special loans for hw or chainable controllers. But i think should be fine in this case since handles have no lifecycle bit their lifecycle is indirectly connected to the components lifecycle itself. this is managed by resource manager which should be the only part having the pointers besides the components themselves.