Skip to content

Commit 0a6fe52

Browse files
Fix JTC segfault (#164)
* Use a copy of the rt_active_goal to avoid segfault * Use RealtimeBuffer for thread-safety
1 parent 316e4c1 commit 0a6fe52

File tree

2 files changed

+31
-26
lines changed

2 files changed

+31
-26
lines changed

joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,11 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa
149149
using FollowJTrajAction = control_msgs::action::FollowJointTrajectory;
150150
using RealtimeGoalHandle = realtime_tools::RealtimeServerGoalHandle<FollowJTrajAction>;
151151
using RealtimeGoalHandlePtr = std::shared_ptr<RealtimeGoalHandle>;
152+
using RealtimeGoalHandleBuffer = realtime_tools::RealtimeBuffer<RealtimeGoalHandlePtr>;
152153

153154
rclcpp_action::Server<FollowJTrajAction>::SharedPtr action_server_;
154155
bool allow_partial_joints_goal_ = false;
155-
RealtimeGoalHandlePtr rt_active_goal_; ///< Currently active action goal, if any.
156+
RealtimeGoalHandleBuffer rt_active_goal_; ///< Currently active action goal, if any.
156157
rclcpp::TimerBase::SharedPtr goal_handle_timer_;
157158
rclcpp::Duration action_monitor_period_ = rclcpp::Duration(RCUTILS_MS_TO_NS(50));
158159

joint_trajectory_controller/src/joint_trajectory_controller.cpp

+29-25
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,8 @@ JointTrajectoryController::update()
186186
}
187187
}
188188

189-
if (rt_active_goal_) {
189+
const auto active_goal = *rt_active_goal_.readFromRT();
190+
if (active_goal) {
190191
// send feedback
191192
auto feedback = std::make_shared<FollowJTrajAction::Feedback>();
192193
feedback->header.stamp = node_->now();
@@ -195,7 +196,7 @@ JointTrajectoryController::update()
195196
feedback->actual = state_current;
196197
feedback->desired = state_desired;
197198
feedback->error = state_error;
198-
rt_active_goal_->setFeedback(feedback);
199+
active_goal->setFeedback(feedback);
199200

200201
// check abort
201202
if (abort || outside_goal_tolerance) {
@@ -208,17 +209,18 @@ JointTrajectoryController::update()
208209
RCLCPP_WARN(node_->get_logger(), "Aborted due to goal tolerance violation");
209210
result->set__error_code(FollowJTrajAction::Result::GOAL_TOLERANCE_VIOLATED);
210211
}
211-
rt_active_goal_->setAborted(result);
212-
rt_active_goal_.reset();
213-
}
212+
active_goal->setAborted(result);
213+
// TODO(matthew-reynolds): Need a lock-free write here
214+
rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr());
214215

215-
// check goal tolerance
216-
if (!before_last_point) {
216+
// check goal tolerance
217+
} else if (!before_last_point) {
217218
if (!outside_goal_tolerance) {
218219
auto res = std::make_shared<FollowJTrajAction::Result>();
219220
res->set__error_code(FollowJTrajAction::Result::SUCCESSFUL);
220-
rt_active_goal_->setSucceeded(res);
221-
rt_active_goal_.reset();
221+
active_goal->setSucceeded(res);
222+
// TODO(matthew-reynolds): Need a lock-free write here
223+
rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr());
222224

223225
RCLCPP_INFO(node_->get_logger(), "Goal reached, success!");
224226
} else if (default_tolerances_.goal_time_tolerance != 0.0) {
@@ -230,8 +232,9 @@ JointTrajectoryController::update()
230232
if (difference > default_tolerances_.goal_time_tolerance) {
231233
auto result = std::make_shared<FollowJTrajAction::Result>();
232234
result->set__error_code(FollowJTrajAction::Result::GOAL_TOLERANCE_VIOLATED);
233-
rt_active_goal_->setAborted(result);
234-
rt_active_goal_.reset();
235+
active_goal->setAborted(result);
236+
// TODO(matthew-reynolds): Need a lock-free write here
237+
rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr());
235238
RCLCPP_WARN(
236239
node_->get_logger(),
237240
"Aborted due goal_time_tolerance exceeding by %f seconds",
@@ -554,7 +557,8 @@ rclcpp_action::CancelResponse JointTrajectoryController::cancel_callback(
554557
RCLCPP_INFO(node_->get_logger(), "Got request to cancel goal");
555558

556559
// Check that cancel request refers to currently active goal (if any)
557-
if (rt_active_goal_ && rt_active_goal_->gh_ == goal_handle) {
560+
const auto active_goal = *rt_active_goal_.readFromNonRT();
561+
if (active_goal && active_goal->gh_ == goal_handle) {
558562
// Controller uptime
559563
// Enter hold current position mode
560564
set_hold_position();
@@ -565,10 +569,8 @@ rclcpp_action::CancelResponse JointTrajectoryController::cancel_callback(
565569

566570
// Mark the current goal as canceled
567571
auto action_res = std::make_shared<FollowJTrajAction::Result>();
568-
rt_active_goal_->setCanceled(action_res);
569-
570-
// Reset current goal
571-
rt_active_goal_.reset();
572+
active_goal->setCanceled(action_res);
573+
rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr());
572574
}
573575
return rclcpp_action::CancelResponse::ACCEPT;
574576
}
@@ -583,17 +585,18 @@ void JointTrajectoryController::feedback_setup_callback(
583585
goal_handle->get_goal()->trajectory);
584586

585587
add_new_trajectory_msg(traj_msg);
586-
587-
RealtimeGoalHandlePtr rt_goal = std::make_shared<RealtimeGoalHandle>(goal_handle);
588-
rt_goal->preallocated_feedback_->joint_names = joint_names_;
589-
rt_active_goal_ = rt_goal;
590-
rt_active_goal_->execute();
591588
}
592589

590+
// Update the active goal
591+
RealtimeGoalHandlePtr rt_goal = std::make_shared<RealtimeGoalHandle>(goal_handle);
592+
rt_goal->preallocated_feedback_->joint_names = joint_names_;
593+
rt_goal->execute();
594+
rt_active_goal_.writeFromNonRT(rt_goal);
595+
593596
// Setup goal status checking timer
594597
goal_handle_timer_ = node_->create_wall_timer(
595598
action_monitor_period_.to_chrono<std::chrono::seconds>(),
596-
std::bind(&RealtimeGoalHandle::runNonRealtime, rt_active_goal_));
599+
std::bind(&RealtimeGoalHandle::runNonRealtime, rt_goal));
597600
}
598601

599602
void JointTrajectoryController::fill_partial_goal(
@@ -782,12 +785,13 @@ void JointTrajectoryController::add_new_trajectory_msg(
782785

783786
void JointTrajectoryController::preempt_active_goal()
784787
{
785-
if (rt_active_goal_) {
788+
const auto active_goal = *rt_active_goal_.readFromNonRT();
789+
if (active_goal) {
786790
auto action_res = std::make_shared<FollowJTrajAction::Result>();
787791
action_res->set__error_code(FollowJTrajAction::Result::INVALID_GOAL);
788792
action_res->set__error_string("Current goal cancelled due to new incoming action.");
789-
rt_active_goal_->setCanceled(action_res);
790-
rt_active_goal_.reset();
793+
active_goal->setCanceled(action_res);
794+
rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr());
791795
}
792796
}
793797

0 commit comments

Comments
 (0)