SMACC2
Loading...
Searching...
No Matches
cb_end_effector_rotate.hpp
Go to the documentation of this file.
1// Copyright 2025 Robosoft Inc.
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
15/*****************************************************************************************************************
16 *
17 * Authors: Pablo Inigo Blasco, Brett Aldrich
18 *
19 *****************************************************************************************************************/
20
21#include <tf2_ros/buffer.h>
22#include <tf2_ros/transform_listener.h>
23#include <ament_index_cpp/get_package_share_directory.hpp>
26#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
28
29using namespace std::chrono_literals;
30
31namespace cl_moveit2z
32{
33// spins the end effector joint (or any other arbitrary joint etting the tipLink parameter)
35{
36public:
37 CbEndEffectorRotate(double deltaRadians, std::optional<std::string> tipLink = std::nullopt)
39 {
40 deltaRadians_ = deltaRadians;
41 }
42
44
45 virtual void onEntry() override
46 {
47 // Use CpTfListener component for transform lookups
48 CpTfListener * tfListener = nullptr;
49 this->requiresComponent(tfListener, smacc2::ComponentRequirement::SOFT); // Optional component
50
51 tf2::Stamped<tf2::Transform> endEffectorInPivotFrame;
52
53 int attempts = 3;
54
56 if (!tipLink_)
57 {
58 tipLink_ = this->cpMoveGroup_->moveGroupClientInterface->getEndEffectorLink();
59 RCLCPP_WARN_STREAM(
60 getLogger(),
61 "[" << getName() << "] tip unspecified, using default end effector: " << *tipLink_);
62 }
63
64 while (attempts > 0)
65 {
66 try
67 {
68 auto pivotFrameName = this->cpMoveGroup_->moveGroupClientInterface->getEndEffectorLink();
69
70 if (tfListener != nullptr)
71 {
72 // Use component-based TF listener (preferred)
73 auto transformOpt =
74 tfListener->lookupTransform(pivotFrameName, *tipLink_, rclcpp::Time());
75
76 if (transformOpt)
77 {
78 tf2::fromMsg(transformOpt.value(), endEffectorInPivotFrame);
79 tf2::toMsg(endEffectorInPivotFrame, this->planePivotPose_.pose);
80 this->planePivotPose_.header.frame_id = endEffectorInPivotFrame.frame_id_;
81 this->planePivotPose_.header.stamp =
82 rclcpp::Time(endEffectorInPivotFrame.stamp_.time_since_epoch().count());
83 break;
84 }
85 else
86 {
87 RCLCPP_ERROR_STREAM(
88 getLogger(), "[" << getName() << "] Failed to lookup transform from " << *tipLink_
89 << " to " << pivotFrameName << ". Attempt countdown: " << attempts);
90 rclcpp::sleep_for(500ms);
91 attempts--;
92 }
93 }
94 else
95 {
96 // Fallback to legacy TF2 usage if component not available
97 RCLCPP_WARN_STREAM(
98 getLogger(),
99 "[" << getName()
100 << "] CpTfListener component not available, using legacy TF2 (consider "
101 "adding CpTfListener component)");
102 tf2_ros::Buffer tfBuffer(getNode()->get_clock());
103 tf2_ros::TransformListener tfListenerLegacy(tfBuffer);
104
105 tf2::fromMsg(
106 tfBuffer.lookupTransform(
107 pivotFrameName, *tipLink_, rclcpp::Time(), rclcpp::Duration(10s)),
108 endEffectorInPivotFrame);
109
110 tf2::toMsg(endEffectorInPivotFrame, this->planePivotPose_.pose);
111 this->planePivotPose_.header.frame_id = endEffectorInPivotFrame.frame_id_;
112 this->planePivotPose_.header.stamp =
113 rclcpp::Time(endEffectorInPivotFrame.stamp_.time_since_epoch().count());
114 break;
115 }
116 }
117 catch (const std::exception & e)
118 {
119 RCLCPP_ERROR_STREAM(getLogger(), e.what() << ". Attempt countdown: " << attempts);
120 rclcpp::sleep_for(500ms);
121 attempts--;
122 }
123 }
124
125 RCLCPP_INFO_STREAM(getLogger(), "[" << getName() << "] pivotPose: " << planePivotPose_);
126
127 RCLCPP_INFO_STREAM(
128 getLogger(), "[" << getName() << "] calling base CbCircularPivotMotion::onEntry");
130 }
131
132 std::optional<std::string> tipLink;
133};
134
135} // namespace cl_moveit2z
geometry_msgs::msg::PoseStamped planePivotPose_
CbEndEffectorRotate(double deltaRadians, std::optional< std::string > tipLink=std::nullopt)
std::shared_ptr< moveit::planning_interface::MoveGroupInterface > moveGroupClientInterface
Component for shared TF2 transform management across all behaviors.
std::optional< geometry_msgs::msg::TransformStamped > lookupTransform(const std::string &target_frame, const std::string &source_frame, const rclcpp::Time &time=rclcpp::Time(0))
Thread-safe transform lookup.
virtual rclcpp::Logger getLogger() const
virtual rclcpp::Node::SharedPtr getNode() const
void requiresComponent(SmaccComponentType *&storage, ComponentRequirement requirementType=ComponentRequirement::SOFT)