ros2_control - galactic
Loading...
Searching...
No Matches
gripper_action_controller_impl.hpp
1// Copyright 2014, SRI International
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
16
17#ifndef GRIPPER_CONTROLLERS__GRIPPER_ACTION_CONTROLLER_IMPL_HPP_
18#define GRIPPER_CONTROLLERS__GRIPPER_ACTION_CONTROLLER_IMPL_HPP_
19
20#include "gripper_controllers/gripper_action_controller.hpp"
21
22#include <memory>
23#include <string>
24
26{
27using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn;
28
29template <const char * HardwareInterface>
30void GripperActionController<HardwareInterface>::preempt_active_goal()
31{
32 // Cancels the currently active goal
33 if (rt_active_goal_)
34 {
35 // Marks the current goal as canceled
36 rt_active_goal_->setCanceled(std::make_shared<GripperCommandAction::Result>());
37 rt_active_goal_.reset();
38 }
39}
40
41template <const char * HardwareInterface>
42CallbackReturn GripperActionController<HardwareInterface>::on_init()
43{
44 try
45 {
46 // with the lifecycle node being initialized, we can declare parameters
47 auto_declare<double>("action_monitor_rate", 20.0);
48 auto_declare<std::string>("joint", joint_name_);
49 auto_declare<double>("goal_tolerance", 0.01);
50 auto_declare<double>("max_effort", 0.0);
51 auto_declare<double>("stall_velocity_threshold", 0.001);
52 auto_declare<double>("stall_timeout", 1.0);
53 }
54 catch (const std::exception & e)
55 {
56 fprintf(stderr, "Exception thrown during init stage with message: %s \n", e.what());
57 return CallbackReturn::ERROR;
58 }
59
60 return CallbackReturn::SUCCESS;
61}
62
63template <const char * HardwareInterface>
64controller_interface::return_type GripperActionController<HardwareInterface>::update(
65 const rclcpp::Time & /*time*/, const rclcpp::Duration & /*period*/)
66{
67 command_struct_rt_ = *(command_.readFromRT());
68
69 const double current_position = joint_position_state_interface_->get().get_value();
70 const double current_velocity = joint_velocity_state_interface_->get().get_value();
71
72 const double error_position = command_struct_rt_.position_ - current_position;
73 const double error_velocity = -current_velocity;
74
75 check_for_success(node_->now(), error_position, current_position, current_velocity);
76
77 // Hardware interface adapter: Generate and send commands
78 computed_command_ = hw_iface_adapter_.updateCommand(
79 command_struct_rt_.position_, 0.0, error_position, error_velocity,
80 command_struct_rt_.max_effort_);
81 return controller_interface::return_type::OK;
82}
83
84template <const char * HardwareInterface>
85rclcpp_action::GoalResponse GripperActionController<HardwareInterface>::goal_callback(
86 const rclcpp_action::GoalUUID &, std::shared_ptr<const GripperCommandAction::Goal>)
87{
88 RCLCPP_INFO(node_->get_logger(), "Received & accepted new action goal");
89 return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
90}
91
92template <const char * HardwareInterface>
93void GripperActionController<HardwareInterface>::accepted_callback(
94 std::shared_ptr<GoalHandle> goal_handle) // Try to update goal
95{
96 {
97 auto rt_goal = std::make_shared<RealtimeGoalHandle>(goal_handle);
98
99 // Accept new goal
100 preempt_active_goal();
101
102 // This is the non-realtime command_struct
103 // We use command_ for sharing
104 command_struct_.position_ = goal_handle->get_goal()->command.position;
105 command_struct_.max_effort_ = goal_handle->get_goal()->command.max_effort;
106 command_.writeFromNonRT(command_struct_);
107
108 pre_alloc_result_->reached_goal = false;
109 pre_alloc_result_->stalled = false;
110
111 last_movement_time_ = node_->now();
112 rt_active_goal_ = rt_goal;
113 rt_active_goal_->execute();
114 }
115 // Setup goal status checking timer
116 goal_handle_timer_ = node_->create_wall_timer(
117 action_monitor_period_.to_chrono<std::chrono::seconds>(),
118 std::bind(&RealtimeGoalHandle::runNonRealtime, rt_active_goal_));
119}
120
121template <const char * HardwareInterface>
122rclcpp_action::CancelResponse GripperActionController<HardwareInterface>::cancel_callback(
123 const std::shared_ptr<GoalHandle> goal_handle)
124{
125 RCLCPP_INFO(node_->get_logger(), "Got request to cancel goal");
126
127 // Check that cancel request refers to currently active goal (if any)
128 if (rt_active_goal_ && rt_active_goal_->gh_ == goal_handle)
129 {
130 // Enter hold current position mode
131 set_hold_position();
132
133 RCLCPP_INFO(
134 node_->get_logger(), "Canceling active action goal because cancel callback received.");
135
136 // Mark the current goal as canceled
137 auto action_res = std::make_shared<GripperCommandAction::Result>();
138 rt_active_goal_->setCanceled(action_res);
139 // Reset current goal
140 rt_active_goal_.reset();
141 }
142 return rclcpp_action::CancelResponse::ACCEPT;
143}
144
145template <const char * HardwareInterface>
146void GripperActionController<HardwareInterface>::set_hold_position()
147{
148 command_struct_.position_ = joint_position_state_interface_->get().get_value();
149 command_struct_.max_effort_ = default_max_effort_;
150 command_.writeFromNonRT(command_struct_);
151}
152
153template <const char * HardwareInterface>
154void GripperActionController<HardwareInterface>::check_for_success(
155 const rclcpp::Time & time, double error_position, double current_position,
156 double current_velocity)
157{
158 if (!rt_active_goal_)
159 {
160 return;
161 }
162
163 if (fabs(error_position) < goal_tolerance_)
164 {
165 pre_alloc_result_->effort = computed_command_;
166 pre_alloc_result_->position = current_position;
167 pre_alloc_result_->reached_goal = true;
168 pre_alloc_result_->stalled = false;
169 rt_active_goal_->setSucceeded(pre_alloc_result_);
170 rt_active_goal_.reset();
171 }
172 else
173 {
174 if (fabs(current_velocity) > stall_velocity_threshold_)
175 {
176 last_movement_time_ = time;
177 }
178 else if ((time - last_movement_time_).seconds() > stall_timeout_)
179 {
180 pre_alloc_result_->effort = computed_command_;
181 pre_alloc_result_->position = current_position;
182 pre_alloc_result_->reached_goal = false;
183 pre_alloc_result_->stalled = true;
184 rt_active_goal_->setAborted(pre_alloc_result_);
185 rt_active_goal_.reset();
186 }
187 }
188}
189
190template <const char * HardwareInterface>
191CallbackReturn GripperActionController<HardwareInterface>::on_configure(
192 const rclcpp_lifecycle::State &)
193{
194 const auto logger = node_->get_logger();
195
196 // Action status checking update rate
197 const auto action_monitor_rate = node_->get_parameter("action_monitor_rate").as_double();
198 action_monitor_period_ =
199 rclcpp::Duration::from_seconds(1.0 / node_->get_parameter("action_monitor_rate").as_double());
200 RCLCPP_INFO_STREAM(
201 logger, "Action status changes will be monitored at " << action_monitor_rate << "Hz.");
202
203 // Controlled joint
204 joint_name_ = node_->get_parameter("joint").as_string();
205 if (joint_name_.empty())
206 {
207 RCLCPP_ERROR(logger, "Could not find joint name on param server");
208 return CallbackReturn::ERROR;
209 }
210
211 // Default tolerances
212 goal_tolerance_ = node_->get_parameter("goal_tolerance").as_double();
213 goal_tolerance_ = fabs(goal_tolerance_);
214 // Max allowable effort
215 default_max_effort_ = node_->get_parameter("max_effort").as_double();
216 default_max_effort_ = fabs(default_max_effort_);
217 // Stall - stall velocity threshold, stall timeout
218 stall_velocity_threshold_ = node_->get_parameter("stall_velocity_threshold").as_double();
219 stall_timeout_ = node_->get_parameter("stall_timeout").as_double();
220
221 return CallbackReturn::SUCCESS;
222}
223template <const char * HardwareInterface>
224CallbackReturn GripperActionController<HardwareInterface>::on_activate(
225 const rclcpp_lifecycle::State &)
226{
227 auto position_command_interface_it = std::find_if(
228 command_interfaces_.begin(), command_interfaces_.end(),
229 [](const hardware_interface::LoanedCommandInterface & command_interface) {
230 return command_interface.get_interface_name() == hardware_interface::HW_IF_POSITION;
231 });
232 if (position_command_interface_it == command_interfaces_.end())
233 {
234 RCLCPP_ERROR(node_->get_logger(), "Expected 1 position command interface");
235 return CallbackReturn::ERROR;
236 }
237 if (position_command_interface_it->get_name() != joint_name_)
238 {
239 RCLCPP_ERROR_STREAM(
240 node_->get_logger(), "Position command interface is different than joint name `"
241 << position_command_interface_it->get_name() << "` != `" << joint_name_
242 << "`");
243 return CallbackReturn::ERROR;
244 }
245 const auto position_state_interface_it = std::find_if(
246 state_interfaces_.begin(), state_interfaces_.end(),
247 [](const hardware_interface::LoanedStateInterface & state_interface) {
248 return state_interface.get_interface_name() == hardware_interface::HW_IF_POSITION;
249 });
250 if (position_state_interface_it == state_interfaces_.end())
251 {
252 RCLCPP_ERROR(node_->get_logger(), "Expected 1 position state interface");
253 return CallbackReturn::ERROR;
254 }
255 if (position_state_interface_it->get_name() != joint_name_)
256 {
257 RCLCPP_ERROR_STREAM(
258 node_->get_logger(), "Position state interface is different than joint name `"
259 << position_state_interface_it->get_name() << "` != `" << joint_name_
260 << "`");
261 return CallbackReturn::ERROR;
262 }
263 const auto velocity_state_interface_it = std::find_if(
264 state_interfaces_.begin(), state_interfaces_.end(),
265 [](const hardware_interface::LoanedStateInterface & state_interface) {
266 return state_interface.get_interface_name() == hardware_interface::HW_IF_VELOCITY;
267 });
268 if (velocity_state_interface_it == state_interfaces_.end())
269 {
270 RCLCPP_ERROR(node_->get_logger(), "Expected 1 velocity state interface");
271 return CallbackReturn::ERROR;
272 }
273 if (velocity_state_interface_it->get_name() != joint_name_)
274 {
275 RCLCPP_ERROR_STREAM(
276 node_->get_logger(), "Velocity command interface is different than joint name `"
277 << velocity_state_interface_it->get_name() << "` != `" << joint_name_
278 << "`");
279 return CallbackReturn::ERROR;
280 }
281
282 joint_position_command_interface_ = *position_command_interface_it;
283 joint_position_state_interface_ = *position_state_interface_it;
284 joint_velocity_state_interface_ = *velocity_state_interface_it;
285
286 // Hardware interface adapter
287 hw_iface_adapter_.init(joint_position_command_interface_, node_);
288
289 // Command - non RT version
290 command_struct_.position_ = joint_position_state_interface_->get().get_value();
291 command_struct_.max_effort_ = default_max_effort_;
292
293 // Result
294 pre_alloc_result_ = std::make_shared<control_msgs::action::GripperCommand::Result>();
295 pre_alloc_result_->position = command_struct_.position_;
296 pre_alloc_result_->reached_goal = false;
297 pre_alloc_result_->stalled = false;
298
299 // Action interface
300 action_server_ = rclcpp_action::create_server<control_msgs::action::GripperCommand>(
301 node_, "~/gripper_cmd",
302 std::bind(
303 &GripperActionController::goal_callback, this, std::placeholders::_1, std::placeholders::_2),
304 std::bind(&GripperActionController::cancel_callback, this, std::placeholders::_1),
305 std::bind(&GripperActionController::accepted_callback, this, std::placeholders::_1));
306
307 return CallbackReturn::SUCCESS;
308}
309
310template <const char * HardwareInterface>
311CallbackReturn GripperActionController<HardwareInterface>::on_deactivate(
312 const rclcpp_lifecycle::State &)
313{
314 joint_position_command_interface_ = std::experimental::nullopt;
315 joint_position_state_interface_ = std::experimental::nullopt;
316 joint_velocity_state_interface_ = std::experimental::nullopt;
317 release_interfaces();
318 return CallbackReturn::SUCCESS;
319}
320
321template <const char * HardwareInterface>
324{
325 return {
326 controller_interface::interface_configuration_type::INDIVIDUAL,
327 {joint_name_ + "/" + hardware_interface::HW_IF_POSITION}};
328}
329
330template <const char * HardwareInterface>
333{
334 return {
335 controller_interface::interface_configuration_type::INDIVIDUAL,
336 {joint_name_ + "/" + hardware_interface::HW_IF_POSITION,
337 joint_name_ + "/" + hardware_interface::HW_IF_VELOCITY}};
338}
339
340template <const char * HardwareInterface>
342: controller_interface::ControllerInterface(),
343 action_monitor_period_(rclcpp::Duration::from_seconds(0))
344{
345}
346
347} // namespace gripper_action_controller
348
349#endif // GRIPPER_CONTROLLERS__GRIPPER_ACTION_CONTROLLER_IMPL_HPP_
Controller for executing a gripper command action for simple single-dof grippers.
Definition gripper_action_controller.hpp:62
GRIPPER_ACTION_CONTROLLER_PUBLIC controller_interface::InterfaceConfiguration state_interface_configuration() const override
command_interface_configuration This controller requires the position and velocity state interfaces f...
Definition gripper_action_controller_impl.hpp:332
GRIPPER_ACTION_CONTROLLER_PUBLIC controller_interface::InterfaceConfiguration command_interface_configuration() const override
command_interface_configuration This controller requires the position command interfaces for the cont...
Definition gripper_action_controller_impl.hpp:323
Definition loaned_command_interface.hpp:27
Definition loaned_state_interface.hpp:27
Definition gripper_action_controller.hpp:49
constexpr char HW_IF_VELOCITY[]
Constant defining velocity interface.
Definition hardware_interface_type_values.hpp:23
constexpr char HW_IF_POSITION[]
Constant defining position interface.
Definition hardware_interface_type_values.hpp:21
Configuring what command/state interfaces to claim.
Definition controller_interface.hpp:63