Skip to content

Commit 05e5ee4

Browse files
URJalaurfeex
authored andcommitted
Update passthrough controller to use RealtimeThreadSafeBox
1 parent cc5fcdd commit 05e5ee4

File tree

2 files changed

+118
-27
lines changed

2 files changed

+118
-27
lines changed

ur_controllers/include/ur_controllers/passthrough_trajectory_controller.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
#include <vector>
5252

5353
#include <controller_interface/controller_interface.hpp>
54-
#include <realtime_tools/realtime_buffer.hpp>
54+
#include <realtime_tools/realtime_thread_safe_box.hpp>
5555
#include <realtime_tools/realtime_server_goal_handle.hpp>
5656
#include <rclcpp_action/server.hpp>
5757
#include <rclcpp_action/create_server.hpp>
@@ -114,11 +114,11 @@ class PassthroughTrajectoryController : public controller_interface::ControllerI
114114
using FollowJTrajAction = control_msgs::action::FollowJointTrajectory;
115115
using RealtimeGoalHandle = realtime_tools::RealtimeServerGoalHandle<FollowJTrajAction>;
116116
using RealtimeGoalHandlePtr = std::shared_ptr<RealtimeGoalHandle>;
117-
using RealtimeGoalHandleBuffer = realtime_tools::RealtimeBuffer<RealtimeGoalHandlePtr>;
117+
using RealtimeGoalHandleBuffer = realtime_tools::RealtimeThreadSafeBox<RealtimeGoalHandlePtr>;
118118

119119
RealtimeGoalHandleBuffer rt_active_goal_; ///< Currently active action goal, if any.
120120
rclcpp::TimerBase::SharedPtr goal_handle_timer_; ///< Timer to frequently check on the running goal
121-
realtime_tools::RealtimeBuffer<std::unordered_map<std::string, size_t>> joint_trajectory_mapping_;
121+
realtime_tools::RealtimeThreadSafeBox<std::unordered_map<std::string, size_t>> joint_trajectory_mapping_;
122122

123123
rclcpp::Duration action_monitor_period_ = rclcpp::Duration(50ms);
124124

@@ -147,7 +147,7 @@ class PassthroughTrajectoryController : public controller_interface::ControllerI
147147
void goal_accepted_callback(
148148
std::shared_ptr<rclcpp_action::ServerGoalHandle<control_msgs::action::FollowJointTrajectory>> goal_handle);
149149

150-
realtime_tools::RealtimeBuffer<std::vector<std::string>> joint_names_;
150+
realtime_tools::RealtimeThreadSafeBox<std::vector<std::string>> joint_names_;
151151
std::vector<std::string> state_interface_types_;
152152

153153
std::vector<std::string> joint_state_interface_names_;
@@ -162,8 +162,8 @@ class PassthroughTrajectoryController : public controller_interface::ControllerI
162162

163163
trajectory_msgs::msg::JointTrajectory active_joint_traj_;
164164
// std::vector<control_msgs::msg::JointTolerance> path_tolerance_;
165-
realtime_tools::RealtimeBuffer<std::vector<control_msgs::msg::JointTolerance>> goal_tolerance_;
166-
realtime_tools::RealtimeBuffer<rclcpp::Duration> goal_time_tolerance_{ rclcpp::Duration(0, 0) };
165+
realtime_tools::RealtimeThreadSafeBox<std::vector<control_msgs::msg::JointTolerance>> goal_tolerance_;
166+
realtime_tools::RealtimeThreadSafeBox<rclcpp::Duration> goal_time_tolerance_{ rclcpp::Duration(0, 0) };
167167

168168
std::atomic<size_t> current_index_;
169169
std::atomic<bool> trajectory_active_;

ur_controllers/src/passthrough_trajectory_controller.cpp

Lines changed: 112 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ controller_interface::CallbackReturn PassthroughTrajectoryController::on_init()
6565
passthrough_params_ = passthrough_param_listener_->get_params();
6666
current_index_ = 0;
6767
auto joint_names = passthrough_params_.joints;
68-
joint_names_.writeFromNonRT(joint_names);
68+
joint_names_.try_set(joint_names);
6969
number_of_joints_ = joint_names.size();
7070
state_interface_types_ = passthrough_params_.state_interfaces;
7171
scaling_factor_ = 1.0;
@@ -83,7 +83,12 @@ PassthroughTrajectoryController::on_configure(const rclcpp_lifecycle::State& pre
8383

8484
joint_state_interface_names_.reserve(number_of_joints_ * state_interface_types_.size());
8585

86-
auto joint_names_internal = joint_names_.readFromRT();
86+
auto joint_names_internal = joint_names_.try_get();
87+
if (!joint_names_internal) {
88+
RCLCPP_ERROR(get_node()->get_logger(), "Joint names could not be read, cannot configure controller.");
89+
return controller_interface::CallbackReturn::ERROR;
90+
}
91+
8792
for (const auto& joint_name : *joint_names_internal) {
8893
for (const auto& interface_type : state_interface_types_) {
8994
joint_state_interface_names_.emplace_back(joint_name + "/" + interface_type);
@@ -228,12 +233,22 @@ controller_interface::CallbackReturn PassthroughTrajectoryController::on_deactiv
228233
return controller_interface::CallbackReturn::ERROR;
229234
}
230235
if (trajectory_active_) {
231-
const auto active_goal = *rt_active_goal_.readFromRT();
236+
RealtimeGoalHandlePtr active_goal = nullptr;
237+
bool success = rt_active_goal_.try_get([&active_goal](const RealtimeGoalHandlePtr& goal) { active_goal = goal; });
238+
if (!success) {
239+
RCLCPP_ERROR(get_node()->get_logger(), "Could not read active goal from realtime buffer, deactivation of "
240+
"controller failed.");
241+
return controller_interface::CallbackReturn::ERROR;
242+
}
232243
std::shared_ptr<control_msgs::action::FollowJointTrajectory::Result> result =
233244
std::make_shared<control_msgs::action::FollowJointTrajectory::Result>();
234245
result->set__error_string("Aborting current goal, since the controller is being deactivated.");
235246
active_goal->setAborted(result);
236-
rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr());
247+
success = rt_active_goal_.try_set([](RealtimeGoalHandlePtr& goal) { goal = RealtimeGoalHandlePtr(); });
248+
if (!success) {
249+
RCLCPP_ERROR(get_node()->get_logger(), "Failed to set active goal, deactivation of controller failed.");
250+
return controller_interface::CallbackReturn::ERROR;
251+
}
237252
end_goal();
238253
}
239254
return CallbackReturn::SUCCESS;
@@ -242,7 +257,13 @@ controller_interface::CallbackReturn PassthroughTrajectoryController::on_deactiv
242257
controller_interface::return_type PassthroughTrajectoryController::update(const rclcpp::Time& /*time*/,
243258
const rclcpp::Duration& period)
244259
{
245-
const auto active_goal = *rt_active_goal_.readFromRT();
260+
RealtimeGoalHandlePtr active_goal = nullptr;
261+
const bool read_success =
262+
rt_active_goal_.try_get([&active_goal](const RealtimeGoalHandlePtr& goal) { active_goal = goal; });
263+
if (!read_success) {
264+
RCLCPP_ERROR(get_node()->get_logger(), "Could not read active goal from realtime buffer, skipping cycle.");
265+
return controller_interface::return_type::OK;
266+
}
246267

247268
const auto current_transfer_state = transfer_command_interface_->get().get_optional().value_or(TRANSFER_STATE_IDLE);
248269

@@ -272,8 +293,18 @@ controller_interface::return_type PassthroughTrajectoryController::update(const
272293
write_success &=
273294
trajectory_size_command_interface_->get().set_value(static_cast<double>(active_joint_traj_.points.size()));
274295
}
275-
auto active_goal_time_tol = goal_time_tolerance_.readFromRT();
276-
auto joint_mapping = joint_trajectory_mapping_.readFromRT();
296+
297+
auto active_goal_time_tol = goal_time_tolerance_.try_get();
298+
if (!active_goal_time_tol) {
299+
RCLCPP_ERROR(get_node()->get_logger(), "Could not read goal time tolerance, skipping cycle.");
300+
return controller_interface::return_type::OK;
301+
}
302+
303+
auto joint_mapping = joint_trajectory_mapping_.try_get();
304+
if (!joint_mapping) {
305+
RCLCPP_ERROR(get_node()->get_logger(), "Could not read joint trajectory mapping, skipping cycle.");
306+
return controller_interface::return_type::OK;
307+
}
277308

278309
// Write a new point to the command interface, if the previous point has been read by the hardware interface.
279310
if (current_transfer_state == TRANSFER_STATE_WAITING_FOR_POINT) {
@@ -283,7 +314,12 @@ controller_interface::return_type PassthroughTrajectoryController::update(const
283314
duration_to_double(active_joint_traj_.points[current_index_].time_from_start));
284315

285316
// Write the positions for each joint of the robot
286-
auto joint_names_internal = joint_names_.readFromRT();
317+
auto joint_names_internal = joint_names_.try_get();
318+
if (!joint_names_internal) {
319+
RCLCPP_ERROR(get_node()->get_logger(), "Could not read joint names, skipping cycle.");
320+
return controller_interface::return_type::OK;
321+
}
322+
287323
// We've added the joint interfaces matching the order of the joint names so we can safely access
288324
// them by the index.
289325
for (size_t i = 0; i < number_of_joints_; i++) {
@@ -422,7 +458,12 @@ bool PassthroughTrajectoryController::check_goal_tolerances(
422458
std::shared_ptr<const control_msgs::action::FollowJointTrajectory::Goal> goal)
423459
{
424460
auto& tolerances = goal->goal_tolerance;
425-
auto joint_names_internal = joint_names_.readFromRT();
461+
auto joint_names_internal = joint_names_.try_get();
462+
if (!joint_names_internal) {
463+
RCLCPP_ERROR(get_node()->get_logger(), "Joint names could not be read, cannot check tolerances.");
464+
return false;
465+
}
466+
426467
if (!tolerances.empty()) {
427468
for (auto& tol : tolerances) {
428469
auto found_it = std::find(joint_names_internal->begin(), joint_names_internal->end(), tol.name);
@@ -526,14 +567,26 @@ rclcpp_action::CancelResponse PassthroughTrajectoryController::goal_cancelled_ca
526567
const std::shared_ptr<rclcpp_action::ServerGoalHandle<control_msgs::action::FollowJointTrajectory>> goal_handle)
527568
{
528569
// Check that cancel request refers to currently active goal (if any)
529-
const auto active_goal = *rt_active_goal_.readFromNonRT();
570+
RealtimeGoalHandlePtr active_goal = nullptr;
571+
while (!rt_active_goal_.try_get([&active_goal](const RealtimeGoalHandlePtr& goal) { active_goal = goal; })) {
572+
// Wait until we can read the active goal from the realtime buffer
573+
RCLCPP_WARN(get_node()->get_logger(), "Waiting for active goal to be set, retrying cancel request.");
574+
rclcpp::sleep_for(std::chrono::milliseconds(50));
575+
}
576+
530577
if (active_goal && active_goal->gh_ == goal_handle) {
531578
RCLCPP_INFO(get_node()->get_logger(), "Cancelling active trajectory requested.");
532579

533580
// Mark the current goal as canceled
534581
auto result = std::make_shared<FollowJTrajAction::Result>();
535582
active_goal->setCanceled(result);
536-
rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr());
583+
584+
while (!rt_active_goal_.try_set([](RealtimeGoalHandlePtr& goal) { goal = RealtimeGoalHandlePtr(); })) {
585+
// Wait until we can set the active goal to nullptr
586+
RCLCPP_WARN(get_node()->get_logger(), "Waiting for active goal to be set, retrying cancel request.");
587+
rclcpp::sleep_for(std::chrono::milliseconds(50));
588+
}
589+
537590
trajectory_active_ = false;
538591
}
539592
return rclcpp_action::CancelResponse::ACCEPT;
@@ -548,13 +601,21 @@ void PassthroughTrajectoryController::goal_accepted_callback(
548601
current_index_ = 0;
549602

550603
// TODO(fexner): Merge goal tolerances with default tolerances
551-
552-
joint_trajectory_mapping_.writeFromNonRT(create_joint_mapping(goal_handle->get_goal()->trajectory.joint_names));
604+
bool write_success =
605+
joint_trajectory_mapping_.try_set(create_joint_mapping(goal_handle->get_goal()->trajectory.joint_names));
606+
if (!write_success) {
607+
RCLCPP_ERROR(get_node()->get_logger(), "Failed to set joint trajectory mapping.");
608+
return;
609+
}
553610

554611
// sort goal tolerances to match internal joint order
555612
std::vector<control_msgs::msg::JointTolerance> goal_tolerances;
556613
if (!goal_handle->get_goal()->goal_tolerance.empty()) {
557-
auto joint_names_internal = joint_names_.readFromRT();
614+
auto joint_names_internal = joint_names_.try_get();
615+
if (!joint_names_internal) {
616+
RCLCPP_ERROR(get_node()->get_logger(), "Joint names could not be read, cannot set goal tolerances.");
617+
return;
618+
}
558619
std::stringstream ss;
559620
ss << "Using goal tolerances\n";
560621
for (auto& joint_name : *joint_names_internal) {
@@ -569,8 +630,17 @@ void PassthroughTrajectoryController::goal_accepted_callback(
569630
}
570631
RCLCPP_INFO_STREAM(get_node()->get_logger(), ss.str());
571632
}
572-
goal_tolerance_.writeFromNonRT(goal_tolerances);
573-
goal_time_tolerance_.writeFromNonRT(goal_handle->get_goal()->goal_time_tolerance);
633+
write_success = goal_tolerance_.try_set(goal_tolerances);
634+
if (!write_success) {
635+
RCLCPP_ERROR(get_node()->get_logger(), "Failed to set goal tolerances.");
636+
return;
637+
}
638+
639+
write_success = goal_time_tolerance_.try_set(goal_handle->get_goal()->goal_time_tolerance);
640+
if (!write_success) {
641+
RCLCPP_ERROR(get_node()->get_logger(), "Failed to set goal time tolerance.");
642+
return;
643+
}
574644
RCLCPP_INFO_STREAM(get_node()->get_logger(),
575645
"Goal time tolerance: " << duration_to_double(goal_handle->get_goal()->goal_time_tolerance)
576646
<< " sec");
@@ -581,7 +651,11 @@ void PassthroughTrajectoryController::goal_accepted_callback(
581651
//
582652
RealtimeGoalHandlePtr rt_goal = std::make_shared<RealtimeGoalHandle>(goal_handle);
583653
rt_goal->execute();
584-
rt_active_goal_.writeFromNonRT(rt_goal);
654+
bool write_success;
655+
write_success = rt_active_goal_.try_set([&rt_goal](RealtimeGoalHandlePtr& goal) { goal = rt_goal; });
656+
if (!write_success) {
657+
RCLCPP_ERROR(get_node()->get_logger(), "Failed to set active goal.");
658+
}
585659
goal_handle_timer_.reset();
586660
goal_handle_timer_ = get_node()->create_wall_timer(action_monitor_period_.to_chrono<std::chrono::nanoseconds>(),
587661
std::bind(&RealtimeGoalHandle::runNonRealtime, rt_goal));
@@ -591,9 +665,22 @@ void PassthroughTrajectoryController::goal_accepted_callback(
591665

592666
bool PassthroughTrajectoryController::check_goal_tolerance()
593667
{
594-
auto goal_tolerance = goal_tolerance_.readFromRT();
595-
auto joint_mapping = joint_trajectory_mapping_.readFromRT();
596-
auto joint_names_internal = joint_names_.readFromRT();
668+
auto goal_tolerance = goal_tolerance_.try_get();
669+
if (!goal_tolerance) {
670+
RCLCPP_ERROR(get_node()->get_logger(), "Could not get goal tolerance, cannot check goal tolerance.");
671+
return false;
672+
}
673+
auto joint_mapping = joint_trajectory_mapping_.try_get();
674+
if (!joint_mapping) {
675+
RCLCPP_ERROR(get_node()->get_logger(), "Could not get joint mapping, cannot check goal tolerance.");
676+
return false;
677+
}
678+
auto joint_names_internal = joint_names_.try_get();
679+
if (!joint_names_internal) {
680+
RCLCPP_ERROR(get_node()->get_logger(), "Could not get joint names, cannot check goal tolerance.");
681+
return false;
682+
}
683+
597684
if (goal_tolerance->empty()) {
598685
return true;
599686
}
@@ -650,7 +737,11 @@ std::unordered_map<std::string, size_t>
650737
PassthroughTrajectoryController::create_joint_mapping(const std::vector<std::string>& joint_names) const
651738
{
652739
std::unordered_map<std::string, size_t> joint_mapping;
653-
auto joint_names_internal = joint_names_.readFromNonRT();
740+
auto joint_names_internal = joint_names_.try_get();
741+
if (!joint_names_internal) {
742+
RCLCPP_ERROR(get_node()->get_logger(), "Could not get joint names, cannot create joint mapping.");
743+
}
744+
654745
for (auto& joint_name : *joint_names_internal) {
655746
auto found_it = std::find(joint_names.begin(), joint_names.end(), joint_name);
656747
if (found_it != joint_names.end()) {

0 commit comments

Comments
 (0)