-
Notifications
You must be signed in to change notification settings - Fork 222
/
Copy pathpassthrough_controller.cpp
189 lines (160 loc) · 6.75 KB
/
passthrough_controller.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// Copyright (c) 2023, PAL Robotics
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "passthrough_controller/passthrough_controller.hpp"
#include "controller_interface/helpers.hpp"
#include "pluginlib/class_list_macros.hpp"
namespace passthrough_controller
{
controller_interface::CallbackReturn PassthroughController::on_init()
{
try
{
param_listener_ = std::make_shared<ParamListener>(get_node());
params_ = param_listener_->get_params();
}
catch (const std::exception & e)
{
fprintf(stderr, "Exception thrown during init stage with message: %s \n", e.what());
return controller_interface::CallbackReturn::ERROR;
}
return controller_interface::CallbackReturn::SUCCESS;
}
controller_interface::InterfaceConfiguration
PassthroughController::command_interface_configuration() const
{
controller_interface::InterfaceConfiguration command_interfaces_config;
command_interfaces_config.type = controller_interface::interface_configuration_type::INDIVIDUAL;
command_interfaces_config.names = command_interface_names_;
return command_interfaces_config;
}
controller_interface::InterfaceConfiguration PassthroughController::state_interface_configuration()
const
{
return controller_interface::InterfaceConfiguration{
controller_interface::interface_configuration_type::NONE};
}
controller_interface::CallbackReturn PassthroughController::on_configure(
const rclcpp_lifecycle::State & /*previous_state*/)
{
params_ = param_listener_->get_params();
command_interface_names_ = params_.interfaces;
joints_cmd_sub_ = this->get_node()->create_subscription<DataType>(
"~/commands", rclcpp::SystemDefaultsQoS(),
[this](const DataType::SharedPtr msg)
{
// check if message is correct size, if not ignore
if (msg->data.size() == command_interface_names_.size())
{
rt_buffer_ptr_.writeFromNonRT(msg);
}
else
{
RCLCPP_ERROR(
this->get_node()->get_logger(), "Invalid command received of %zu size, expected %zu size",
msg->data.size(), command_interface_names_.size());
}
});
// pre-reserve command interfaces
command_interfaces_.reserve(command_interface_names_.size());
RCLCPP_INFO(this->get_node()->get_logger(), "configure successful");
// The names should be in the same order as for command interfaces for easier matching
reference_interface_names_ = command_interface_names_;
// for any case make reference interfaces size of command interfaces
reference_interfaces_.resize(
reference_interface_names_.size(), std::numeric_limits<double>::quiet_NaN());
for (size_t i = 0; i < reference_interface_names_.size(); i++)
{
REGISTER_ROS2_CONTROL_INTROSPECTION(reference_interface_names_[i], &reference_interfaces_[i]);
}
return controller_interface::CallbackReturn::SUCCESS;
}
controller_interface::CallbackReturn PassthroughController::on_activate(
const rclcpp_lifecycle::State & /*previous_state*/)
{
// check if we have all resources defined in the "points" parameter
// also verify that we *only* have the resources defined in the "points" parameter
// ATTENTION(destogl): Shouldn't we use ordered interface all the time?
std::vector<std::reference_wrapper<hardware_interface::LoanedCommandInterface>>
ordered_interfaces;
if (
!controller_interface::get_ordered_interfaces(
command_interfaces_, command_interface_names_, std::string(""), ordered_interfaces) ||
command_interface_names_.size() != ordered_interfaces.size())
{
RCLCPP_ERROR(
this->get_node()->get_logger(), "Expected %zu command interfaces, got %zu",
command_interface_names_.size(), ordered_interfaces.size());
return controller_interface::CallbackReturn::ERROR;
}
// reset command buffer if a command came through callback when controller was inactive
rt_buffer_ptr_ = realtime_tools::RealtimeBuffer<std::shared_ptr<DataType>>(nullptr);
RCLCPP_INFO(this->get_node()->get_logger(), "activate successful");
std::fill(
reference_interfaces_.begin(), reference_interfaces_.end(),
std::numeric_limits<double>::quiet_NaN());
return controller_interface::CallbackReturn::SUCCESS;
}
controller_interface::CallbackReturn PassthroughController::on_deactivate(
const rclcpp_lifecycle::State & /*previous_state*/)
{
// reset command buffer
rt_buffer_ptr_ = realtime_tools::RealtimeBuffer<std::shared_ptr<DataType>>(nullptr);
return controller_interface::CallbackReturn::SUCCESS;
}
bool PassthroughController::on_set_chained_mode(bool /*chained_mode*/) { return true; }
controller_interface::return_type PassthroughController::update_and_write_commands(
const rclcpp::Time & /*time*/, const rclcpp::Duration & /*period*/)
{
for (size_t i = 0; i < command_interfaces_.size(); ++i)
{
if (!std::isnan(reference_interfaces_[i]))
{
command_interfaces_[i].set_value(reference_interfaces_[i]);
}
}
return controller_interface::return_type::OK;
}
std::vector<hardware_interface::CommandInterface>
PassthroughController::on_export_reference_interfaces()
{
std::vector<hardware_interface::CommandInterface> reference_interfaces;
for (size_t i = 0; i < reference_interface_names_.size(); ++i)
{
reference_interfaces.push_back(hardware_interface::CommandInterface(
get_node()->get_name(), reference_interface_names_[i], &reference_interfaces_[i]));
}
return reference_interfaces;
}
controller_interface::return_type PassthroughController::update_reference_from_subscribers(
const rclcpp::Time & /*time*/, const rclcpp::Duration & /*period*/)
{
auto joint_commands = rt_buffer_ptr_.readFromRT();
// message is valid
if (!(!joint_commands || !(*joint_commands)))
{
if (reference_interfaces_.size() != (*joint_commands)->data.size())
{
RCLCPP_ERROR_THROTTLE(
get_node()->get_logger(), *(get_node()->get_clock()), 1000,
"command size (%zu) does not match number of reference interfaces (%zu)",
(*joint_commands)->data.size(), reference_interfaces_.size());
return controller_interface::return_type::ERROR;
}
reference_interfaces_ = (*joint_commands)->data;
}
return controller_interface::return_type::OK;
}
} // namespace passthrough_controller
PLUGINLIB_EXPORT_CLASS(
passthrough_controller::PassthroughController, controller_interface::ChainableControllerInterface)