5454namespace ur_controllers
5555{
5656
57+ template <class RTBox >
58+ auto get_rt_box_from_non_rt (RTBox& rt_box)
59+ {
60+ int tries = 0 ;
61+ auto return_val = rt_box.try_get ();
62+ while (!return_val.has_value ()) {
63+ if (tries > 9 ) {
64+ RCLCPP_ERROR (rclcpp::get_logger (" PassthroughTrajectoryController" ), " Failed to get value from realtime box." );
65+ return decltype (return_val){};
66+ }
67+ RCLCPP_WARN (rclcpp::get_logger (" PassthroughTrajectoryController" ), " Waiting for value to be set in realtime box, "
68+ " retrying..." );
69+ rclcpp::sleep_for (std::chrono::milliseconds (50 ));
70+ return_val = rt_box.try_get ();
71+ tries++;
72+ }
73+ return return_val;
74+ }
75+
76+ template <class RTBox , class ValueType >
77+ bool set_rt_box_from_non_rt (RTBox& rt_box, const ValueType& value)
78+ {
79+ int tries = 0 ;
80+ while (!rt_box.try_set (value)) {
81+ if (tries > 9 ) {
82+ RCLCPP_ERROR (rclcpp::get_logger (" PassthroughTrajectoryController" ), " Failed to get value from realtime box." );
83+ return false ;
84+ }
85+ RCLCPP_WARN (rclcpp::get_logger (" PassthroughTrajectoryController" ), " Waiting for value to be set in realtime box, "
86+ " retrying..." );
87+ rclcpp::sleep_for (std::chrono::milliseconds (50 ));
88+ tries++;
89+ }
90+ return true ;
91+ }
92+
93+ std::optional<PassthroughTrajectoryController::RealtimeGoalHandlePtr>
94+ PassthroughTrajectoryController::get_rt_goal_from_non_rt ()
95+ {
96+ RealtimeGoalHandlePtr active_goal = nullptr ;
97+ int tries = 0 ;
98+ while (!rt_active_goal_.try_get ([&active_goal](const RealtimeGoalHandlePtr& goal) { active_goal = goal; })) {
99+ if (tries > 9 ) {
100+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to get active goal from realtime box." );
101+ return std::nullopt ;
102+ }
103+ RCLCPP_WARN (get_node ()->get_logger (), " Waiting for active goal to be read, retrying..." );
104+ rclcpp::sleep_for (std::chrono::milliseconds (50 ));
105+ tries++;
106+ }
107+ return active_goal;
108+ }
109+
110+ bool PassthroughTrajectoryController::set_rt_goal_from_non_rt (RealtimeGoalHandlePtr& rt_goal)
111+ {
112+ int tries = 0 ;
113+ while (!rt_active_goal_.try_set ([&rt_goal](RealtimeGoalHandlePtr& goal) { goal = rt_goal; })) {
114+ if (tries > 9 ) {
115+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to set active goal in realtime box." );
116+ return false ;
117+ }
118+ RCLCPP_WARN (get_node ()->get_logger (), " Waiting for active goal to be set, retrying..." );
119+ rclcpp::sleep_for (std::chrono::milliseconds (50 ));
120+ tries++;
121+ }
122+ return true ;
123+ }
124+
57125double duration_to_double (const builtin_interfaces::msg::Duration& duration)
58126{
59127 return duration.sec + (duration.nanosec / 1000000000.0 );
@@ -65,14 +133,18 @@ controller_interface::CallbackReturn PassthroughTrajectoryController::on_init()
65133 passthrough_params_ = passthrough_param_listener_->get_params ();
66134 current_index_ = 0 ;
67135 auto joint_names = passthrough_params_.joints ;
68- joint_names_.try_set (joint_names);
136+ if (!set_rt_box_from_non_rt (joint_names_, joint_names)) {
137+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to set joint names in realtime box." );
138+ return controller_interface::CallbackReturn::ERROR;
139+ }
69140 number_of_joints_ = joint_names.size ();
70141 state_interface_types_ = passthrough_params_.state_interfaces ;
71142 scaling_factor_ = 1.0 ;
72143 clock_ = get_node ()->get_clock ();
73144 return controller_interface::CallbackReturn::SUCCESS;
74145}
75146
147+ // Not part of real time loop
76148controller_interface::CallbackReturn
77149PassthroughTrajectoryController::on_configure (const rclcpp_lifecycle::State& previous_state)
78150{
@@ -83,12 +155,11 @@ PassthroughTrajectoryController::on_configure(const rclcpp_lifecycle::State& pre
83155
84156 joint_state_interface_names_.reserve (number_of_joints_ * state_interface_types_.size ());
85157
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 ." );
158+ auto joint_names_internal = get_rt_box_from_non_rt (joint_names_ );
159+ if (!joint_names_internal. has_value () ) {
160+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to get joint names from realtime box ." );
89161 return controller_interface::CallbackReturn::ERROR;
90162 }
91-
92163 for (const auto & joint_name : *joint_names_internal) {
93164 for (const auto & interface_type : state_interface_types_) {
94165 joint_state_interface_names_.emplace_back (joint_name + " /" + interface_type);
@@ -458,9 +529,9 @@ bool PassthroughTrajectoryController::check_goal_tolerances(
458529 std::shared_ptr<const control_msgs::action::FollowJointTrajectory::Goal> goal)
459530{
460531 auto & tolerances = goal->goal_tolerance ;
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 ." );
532+ auto joint_names_internal = get_rt_box_from_non_rt (joint_names_ );
533+ if (!joint_names_internal. has_value () ) {
534+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to get joint names from realtime box ." );
464535 return false ;
465536 }
466537
@@ -567,26 +638,26 @@ rclcpp_action::CancelResponse PassthroughTrajectoryController::goal_cancelled_ca
567638 const std::shared_ptr<rclcpp_action::ServerGoalHandle<control_msgs::action::FollowJointTrajectory>> goal_handle)
568639{
569640 // Check that cancel request refers to currently active goal (if any)
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 ));
641+ auto goal = get_rt_goal_from_non_rt ();
642+ if (!goal.has_value ()) {
643+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to get goal handle." );
644+ return rclcpp_action::CancelResponse::REJECT;
575645 }
646+ RealtimeGoalHandlePtr active_goal = goal.value ();
576647
577648 if (active_goal && active_goal->gh_ == goal_handle) {
578649 RCLCPP_INFO (get_node ()->get_logger (), " Cancelling active trajectory requested." );
579650
651+ auto new_goal = RealtimeGoalHandlePtr ();
652+ if (!set_rt_goal_from_non_rt (new_goal)) {
653+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to reset active goal, cancel request failed." );
654+ return rclcpp_action::CancelResponse::REJECT;
655+ }
656+
580657 // Mark the current goal as canceled
581658 auto result = std::make_shared<FollowJTrajAction::Result>();
582659 active_goal->setCanceled (result);
583660
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-
590661 trajectory_active_ = false ;
591662 }
592663 return rclcpp_action::CancelResponse::ACCEPT;
@@ -601,21 +672,40 @@ void PassthroughTrajectoryController::goal_accepted_callback(
601672 current_index_ = 0 ;
602673
603674 // TODO(fexner): Merge goal tolerances with default tolerances
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." );
675+ auto map = create_joint_mapping (goal_handle->get_goal ()->trajectory .joint_names );
676+ if (map.empty ()) {
677+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to create joint trajectory mapping, aborting goal." );
678+ auto result = std::make_shared<control_msgs::action::FollowJointTrajectory::Result>();
679+ result->error_code =
680+ control_msgs::action::FollowJointTrajectory::Result::INVALID_JOINTS; // Not entirely sure, if this is the
681+ // correct error code.
682+ result->error_string = " Failed to create joint mapping." ;
683+ goal_handle->abort (result);
684+ return ;
685+ }
686+
687+ if (!set_rt_box_from_non_rt (joint_trajectory_mapping_, map)) {
688+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to set joint trajectory mapping in realtime box." );
689+ auto result = std::make_shared<control_msgs::action::FollowJointTrajectory::Result>();
690+ result->error_code = control_msgs::action::FollowJointTrajectory::Result::INVALID_JOINTS;
691+ result->error_string = " Failed to set joint trajectory mapping." ;
692+ goal_handle->abort (result);
608693 return ;
609694 }
610695
611696 // sort goal tolerances to match internal joint order
612697 std::vector<control_msgs::msg::JointTolerance> goal_tolerances;
613698 if (!goal_handle->get_goal ()->goal_tolerance .empty ()) {
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." );
699+ auto joint_names_internal = get_rt_box_from_non_rt (joint_names_);
700+ if (!joint_names_internal.has_value ()) {
701+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to get joint names, aborting goal." );
702+ auto result = std::make_shared<control_msgs::action::FollowJointTrajectory::Result>();
703+ result->error_code = control_msgs::action::FollowJointTrajectory::Result::INVALID_JOINTS;
704+ result->error_string = " Failed to get joint names." ;
705+ goal_handle->abort (result);
617706 return ;
618707 }
708+
619709 std::stringstream ss;
620710 ss << " Using goal tolerances\n " ;
621711 for (auto & joint_name : *joint_names_internal) {
@@ -630,39 +720,52 @@ void PassthroughTrajectoryController::goal_accepted_callback(
630720 }
631721 RCLCPP_INFO_STREAM (get_node ()->get_logger (), ss.str ());
632722 }
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." );
723+
724+ if (!set_rt_box_from_non_rt (goal_tolerance_, goal_tolerances)) {
725+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to set goal tolerances in realtime box." );
726+ auto result = std::make_shared<control_msgs::action::FollowJointTrajectory::Result>();
727+ result->error_code = control_msgs::action::FollowJointTrajectory::Result::INVALID_GOAL;
728+ result->error_string = " Failed to set goal tolerances." ;
729+ goal_handle->abort (result);
636730 return ;
637731 }
638732
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." );
733+ if (!set_rt_box_from_non_rt (goal_time_tolerance_, goal_handle->get_goal ()->goal_time_tolerance )) {
734+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to set goal time tolerance in realtime box." );
735+ auto result = std::make_shared<control_msgs::action::FollowJointTrajectory::Result>();
736+ result->error_code = control_msgs::action::FollowJointTrajectory::Result::INVALID_GOAL;
737+ result->error_string = " Failed to set goal time tolerance." ;
738+ goal_handle->abort (result);
642739 return ;
643740 }
741+
644742 RCLCPP_INFO_STREAM (get_node ()->get_logger (),
645743 " Goal time tolerance: " << duration_to_double (goal_handle->get_goal ()->goal_time_tolerance )
646744 << " sec" );
647745
746+ RealtimeGoalHandlePtr rt_goal = std::make_shared<RealtimeGoalHandle>(goal_handle);
747+ if (!set_rt_goal_from_non_rt (rt_goal)) {
748+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to set active goal, aborting goal." );
749+ auto result = std::make_shared<control_msgs::action::FollowJointTrajectory::Result>();
750+ result->error_code = control_msgs::action::FollowJointTrajectory::Result::INVALID_GOAL;
751+ result->error_string = " Failed to set active goal." ;
752+ goal_handle->abort (result);
753+ return ;
754+ }
755+
648756 // Action handling will be done from the timer callback to avoid those things in the realtime
649757 // thread. First, we delete the existing (if any) timer by resetting the pointer and then create a new
650758 // one.
651759 //
652- RealtimeGoalHandlePtr rt_goal = std::make_shared<RealtimeGoalHandle>(goal_handle);
653760 rt_goal->execute ();
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- }
659761 goal_handle_timer_.reset ();
660762 goal_handle_timer_ = get_node ()->create_wall_timer (action_monitor_period_.to_chrono <std::chrono::nanoseconds>(),
661763 std::bind (&RealtimeGoalHandle::runNonRealtime, rt_goal));
662764 trajectory_active_ = true ;
663765 return ;
664766}
665767
768+ // Called from RT thread
666769bool PassthroughTrajectoryController::check_goal_tolerance ()
667770{
668771 auto goal_tolerance = goal_tolerance_.try_get ();
@@ -737,9 +840,10 @@ std::unordered_map<std::string, size_t>
737840PassthroughTrajectoryController::create_joint_mapping (const std::vector<std::string>& joint_names) const
738841{
739842 std::unordered_map<std::string, size_t > joint_mapping;
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." );
843+ auto joint_names_internal = get_rt_box_from_non_rt (joint_names_);
844+ if (!joint_names_internal.has_value ()) {
845+ RCLCPP_ERROR (get_node ()->get_logger (), " Failed to get joint names from realtime box." );
846+ return joint_mapping;
743847 }
744848
745849 for (auto & joint_name : *joint_names_internal) {
@@ -750,6 +854,7 @@ PassthroughTrajectoryController::create_joint_mapping(const std::vector<std::str
750854 }
751855 return joint_mapping;
752856}
857+
753858} // namespace ur_controllers
754859
755860#include " pluginlib/class_list_macros.hpp"
0 commit comments