SMACC2
Loading...
Searching...
No Matches
cb_end_effector_rotate.hpp
Go to the documentation of this file.
1// Copyright 2021 RobosoftAI 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->movegroupClient_->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 =
69 this->movegroupClient_->moveGroupClientInterface->getEndEffectorLink();
70
71 if (tfListener != nullptr)
72 {
73 // Use component-based TF listener (preferred)
74 auto transformOpt =
75 tfListener->lookupTransform(pivotFrameName, *tipLink_, rclcpp::Time());
76
77 if (transformOpt)
78 {
79 tf2::fromMsg(transformOpt.value(), endEffectorInPivotFrame);
80 tf2::toMsg(endEffectorInPivotFrame, this->planePivotPose_.pose);
81 this->planePivotPose_.header.frame_id = endEffectorInPivotFrame.frame_id_;
82 this->planePivotPose_.header.stamp =
83 rclcpp::Time(endEffectorInPivotFrame.stamp_.time_since_epoch().count());
84 break;
85 }
86 else
87 {
88 RCLCPP_ERROR_STREAM(
89 getLogger(), "[" << getName() << "] Failed to lookup transform from " << *tipLink_
90 << " to " << pivotFrameName << ". Attempt countdown: " << attempts);
91 rclcpp::sleep_for(500ms);
92 attempts--;
93 }
94 }
95 else
96 {
97 // Fallback to legacy TF2 usage if component not available
98 RCLCPP_WARN_STREAM(
99 getLogger(),
100 "[" << getName()
101 << "] CpTfListener component not available, using legacy TF2 (consider "
102 "adding CpTfListener component)");
103 tf2_ros::Buffer tfBuffer(getNode()->get_clock());
104 tf2_ros::TransformListener tfListenerLegacy(tfBuffer);
105
106 tf2::fromMsg(
107 tfBuffer.lookupTransform(
108 pivotFrameName, *tipLink_, rclcpp::Time(), rclcpp::Duration(10s)),
109 endEffectorInPivotFrame);
110
111 tf2::toMsg(endEffectorInPivotFrame, this->planePivotPose_.pose);
112 this->planePivotPose_.header.frame_id = endEffectorInPivotFrame.frame_id_;
113 this->planePivotPose_.header.stamp =
114 rclcpp::Time(endEffectorInPivotFrame.stamp_.time_since_epoch().count());
115 break;
116 }
117 }
118 catch (const std::exception & e)
119 {
120 RCLCPP_ERROR_STREAM(getLogger(), e.what() << ". Attempt countdown: " << attempts);
121 rclcpp::sleep_for(500ms);
122 attempts--;
123 }
124 }
125
126 RCLCPP_INFO_STREAM(getLogger(), "[" << getName() << "] pivotPose: " << planePivotPose_);
127
128 RCLCPP_INFO_STREAM(
129 getLogger(), "[" << getName() << "] calling base CbCircularPivotMotion::onEntry");
131 }
132
133 std::optional<std::string> tipLink;
134};
135
136} // 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 requiresClient(SmaccClientType *&storage)
void requiresComponent(SmaccComponentType *&storage, ComponentRequirement requirementType=ComponentRequirement::SOFT)