@@ -256,8 +256,7 @@ controller_interface::return_type JointTrajectoryController::update(
256256 {
257257 RCLCPP_WARN (get_node ()->get_logger (), " Aborted due to command timeout" );
258258
259- traj_msg_external_point_ptr_.reset ();
260- traj_msg_external_point_ptr_.initRT (set_hold_position ());
259+ add_new_trajectory_msg_RT (set_hold_position ());
261260 }
262261
263262 // Check state/goal tolerance
@@ -358,8 +357,7 @@ controller_interface::return_type JointTrajectoryController::update(
358357
359358 RCLCPP_WARN (get_node ()->get_logger (), " Aborted due to state tolerance violation" );
360359
361- traj_msg_external_point_ptr_.reset ();
362- traj_msg_external_point_ptr_.initRT (set_hold_position ());
360+ add_new_trajectory_msg_RT (set_hold_position ());
363361 }
364362 // check goal tolerance
365363 else if (!before_last_point)
@@ -376,8 +374,7 @@ controller_interface::return_type JointTrajectoryController::update(
376374
377375 RCLCPP_INFO (get_node ()->get_logger (), " Goal reached, success!" );
378376
379- traj_msg_external_point_ptr_.reset ();
380- traj_msg_external_point_ptr_.initRT (set_success_trajectory_point ());
377+ add_new_trajectory_msg_RT (set_success_trajectory_point ());
381378 }
382379 else if (!within_goal_time)
383380 {
@@ -393,8 +390,7 @@ controller_interface::return_type JointTrajectoryController::update(
393390 get_node ()->get_logger (), " Aborted due goal_time_tolerance exceeding by %f seconds" ,
394391 time_difference);
395392
396- traj_msg_external_point_ptr_.reset ();
397- traj_msg_external_point_ptr_.initRT (set_hold_position ());
393+ add_new_trajectory_msg_RT (set_hold_position ());
398394 }
399395 }
400396 }
@@ -403,16 +399,14 @@ controller_interface::return_type JointTrajectoryController::update(
403399 // we need to ensure that there is no pending goal -> we get a race condition otherwise
404400 RCLCPP_ERROR (get_node ()->get_logger (), " Holding position due to state tolerance violation" );
405401
406- traj_msg_external_point_ptr_.reset ();
407- traj_msg_external_point_ptr_.initRT (set_hold_position ());
402+ add_new_trajectory_msg_RT (set_hold_position ());
408403 }
409404 else if (
410405 !before_last_point && !within_goal_time && *(rt_has_pending_goal_.readFromRT ()) == false )
411406 {
412407 RCLCPP_ERROR (get_node ()->get_logger (), " Exceeded goal_time_tolerance: holding position..." );
413408
414- traj_msg_external_point_ptr_.reset ();
415- traj_msg_external_point_ptr_.initRT (set_hold_position ());
409+ add_new_trajectory_msg_RT (set_hold_position ());
416410 }
417411 // else, run another cycle while waiting for outside_goal_tolerance
418412 // to be satisfied (will stay in this state until new message arrives)
@@ -1024,7 +1018,7 @@ controller_interface::CallbackReturn JointTrajectoryController::on_activate(
10241018 }
10251019
10261020 // The controller should start by holding position at the beginning of active state
1027- add_new_trajectory_msg (set_hold_position ());
1021+ add_new_trajectory_msg_nonRT (set_hold_position ());
10281022 rt_is_holding_.writeFromNonRT (true );
10291023
10301024 // parse timeout parameter
@@ -1180,7 +1174,7 @@ void JointTrajectoryController::topic_callback(
11801174 // always replace old msg with new one for now
11811175 if (subscriber_is_active_)
11821176 {
1183- add_new_trajectory_msg (msg);
1177+ add_new_trajectory_msg_nonRT (msg);
11841178 rt_is_holding_.writeFromNonRT (false );
11851179 }
11861180};
@@ -1226,7 +1220,7 @@ rclcpp_action::CancelResponse JointTrajectoryController::goal_cancelled_callback
12261220 rt_active_goal_.writeFromNonRT (RealtimeGoalHandlePtr ());
12271221
12281222 // Enter hold current position mode
1229- add_new_trajectory_msg (set_hold_position ());
1223+ add_new_trajectory_msg_nonRT (set_hold_position ());
12301224 }
12311225 return rclcpp_action::CancelResponse::ACCEPT;
12321226}
@@ -1243,7 +1237,7 @@ void JointTrajectoryController::goal_accepted_callback(
12431237 auto traj_msg =
12441238 std::make_shared<trajectory_msgs::msg::JointTrajectory>(goal_handle->get_goal ()->trajectory );
12451239
1246- add_new_trajectory_msg (traj_msg);
1240+ add_new_trajectory_msg_nonRT (traj_msg);
12471241 rt_is_holding_.writeFromNonRT (false );
12481242 }
12491243
@@ -1516,27 +1510,47 @@ bool JointTrajectoryController::validate_trajectory_msg(
15161510 return true ;
15171511}
15181512
1519- void JointTrajectoryController::add_new_trajectory_msg (
1513+ void JointTrajectoryController::add_new_trajectory_msg_nonRT (
15201514 const std::shared_ptr<trajectory_msgs::msg::JointTrajectory> & traj_msg)
15211515{
15221516 traj_msg_external_point_ptr_.writeFromNonRT (traj_msg);
15231517
1524- // compute gains of controller
1518+ // compute control law
15251519 if (traj_contr_)
15261520 {
1521+ // this can take some time; trajectory won't start until control law is computed
15271522 if (traj_contr_->computeControlLawNonRT (traj_msg) == false )
15281523 {
15291524 RCLCPP_ERROR (get_node ()->get_logger (), " Failed to compute gains for trajectory." );
15301525 }
15311526 }
15321527}
15331528
1529+ void JointTrajectoryController::add_new_trajectory_msg_RT (
1530+ const std::shared_ptr<trajectory_msgs::msg::JointTrajectory> & traj_msg)
1531+ {
1532+ // TODO(christophfroehlich): Need a lock-free write here
1533+ // See https://github.com/ros-controls/ros2_controllers/issues/168
1534+ traj_msg_external_point_ptr_.reset ();
1535+ traj_msg_external_point_ptr_.initRT (traj_msg);
1536+
1537+ // compute control law
1538+ if (traj_contr_)
1539+ {
1540+ // this is used for set_hold_position() only -> this should (and must) not take a long time
1541+ if (traj_contr_->computeControlLawRT (traj_msg) == false )
1542+ {
1543+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to compute gains for trajectory." );
1544+ }
1545+ }
1546+ }
1547+
15341548void JointTrajectoryController::preempt_active_goal ()
15351549{
15361550 const auto active_goal = *rt_active_goal_.readFromNonRT ();
15371551 if (active_goal)
15381552 {
1539- add_new_trajectory_msg (set_hold_position ());
1553+ add_new_trajectory_msg_nonRT (set_hold_position ());
15401554 auto action_res = std::make_shared<FollowJTrajAction::Result>();
15411555 action_res->set__error_code (FollowJTrajAction::Result::INVALID_GOAL);
15421556 action_res->set__error_string (" Current goal cancelled due to new incoming action." );
0 commit comments