SMACC2
Loading...
Searching...
No Matches
cb_move_end_effector.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#pragma once
22
23#include <tf2/impl/utils.h>
29#include <future>
31#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
32
33using namespace std::chrono_literals;
34
35namespace cl_moveit2z
36{
38{
39public:
40 geometry_msgs::msg::PoseStamped targetPose;
41 std::string tip_link_;
42 std::optional<std::string> group_;
43
45
46 CbMoveEndEffector(geometry_msgs::msg::PoseStamped target_pose, std::string tip_link = "")
47 : targetPose(target_pose)
48 {
49 tip_link_ = tip_link;
50 }
51
52 virtual void onEntry() override
53 {
55
56 if (this->group_)
57 {
58 RCLCPP_DEBUG(
59 getLogger(), "[CbMoveEndEfector] new thread started to move absolute end effector");
60 moveit::planning_interface::MoveGroupInterface move_group(getNode(), *group_);
61 this->moveToAbsolutePose(move_group, targetPose);
62 RCLCPP_DEBUG(
63 getLogger(), "[CbMoveEndEfector] to move absolute end effector thread destroyed");
64 }
65 else
66 {
67 RCLCPP_DEBUG(
68 getLogger(), "[CbMoveEndEfector] new thread started to move absolute end effector");
70 RCLCPP_DEBUG(
71 getLogger(), "[CbMoveEndEfector] to move absolute end effector thread destroyed");
72 }
73 }
74
75protected:
77 moveit::planning_interface::MoveGroupInterface & moveGroupInterface,
78 geometry_msgs::msg::PoseStamped & targetObjectPose)
79 {
80 RCLCPP_DEBUG(getLogger(), "[CbMoveEndEffector] Synchronous sleep of 1 seconds");
81 rclcpp::sleep_for(500ms);
82
83 // Try to use CpMotionPlanner component (preferred)
84 CpMotionPlanner * motionPlanner = nullptr;
86 motionPlanner, smacc2::ComponentRequirement::SOFT); // Optional component
87
88 bool success = false;
89 moveit::planning_interface::MoveGroupInterface::Plan computedMotionPlan;
90
91 RCLCPP_INFO_STREAM(
92 getLogger(), "[CbMoveEndEffector] Target End effector Pose: " << targetObjectPose);
93
94 if (motionPlanner != nullptr)
95 {
96 // Use component-based motion planner (preferred)
97 RCLCPP_INFO(getLogger(), "[CbMoveEndEffector] Using CpMotionPlanner component for planning");
98
99 PlanningOptions options;
100 options.planningTime = 1.0;
101 options.poseReferenceFrame = targetObjectPose.header.frame_id;
102
103 std::optional<std::string> tipLinkOpt;
104 if (!tip_link_.empty())
105 {
106 tipLinkOpt = tip_link_;
107 }
108
109 auto result = motionPlanner->planToPose(targetObjectPose, tipLinkOpt, options);
110
111 success = result.success;
112 if (success)
113 {
114 computedMotionPlan = result.plan;
115 RCLCPP_INFO(getLogger(), "[CbMoveEndEffector] Planning succeeded (via CpMotionPlanner)");
116 }
117 else
118 {
119 RCLCPP_WARN(
120 getLogger(), "[CbMoveEndEffector] Planning failed (via CpMotionPlanner): %s",
121 result.errorMessage.c_str());
122 }
123 }
124 else
125 {
126 // Fallback to legacy direct API calls
127 RCLCPP_WARN(
128 getLogger(),
129 "[CbMoveEndEffector] CpMotionPlanner component not available, using legacy planning "
130 "(consider adding CpMotionPlanner component)");
131
132 moveGroupInterface.setPlanningTime(1.0);
133 moveGroupInterface.setPoseTarget(targetObjectPose, tip_link_);
134 moveGroupInterface.setPoseReferenceFrame(targetObjectPose.header.frame_id);
135
136 success =
137 (moveGroupInterface.plan(computedMotionPlan) == moveit::core::MoveItErrorCode::SUCCESS);
138 RCLCPP_INFO(
139 getLogger(), "[CbMoveEndEffector] Planning %s (legacy mode)",
140 success ? "succeeded" : "FAILED");
141 }
142
143 // Execution
144 if (success)
145 {
146 // Try to use CpTrajectoryExecutor component (preferred)
147 CpTrajectoryExecutor * trajectoryExecutor = nullptr;
148 this->requiresComponent(
149 trajectoryExecutor, smacc2::ComponentRequirement::SOFT); // Optional component
150
151 bool executionSuccess = false;
152
153 if (trajectoryExecutor != nullptr)
154 {
155 // Use component-based trajectory executor (preferred)
156 RCLCPP_INFO(
157 getLogger(), "[CbMoveEndEffector] Using CpTrajectoryExecutor component for execution");
158
159 ExecutionOptions execOptions;
160 execOptions.trajectoryName = this->getName();
161
162 auto execResult = trajectoryExecutor->executePlan(computedMotionPlan, execOptions);
163 executionSuccess = execResult.success;
164
165 if (executionSuccess)
166 {
167 RCLCPP_INFO(
168 getLogger(), "[CbMoveEndEffector] Execution succeeded (via CpTrajectoryExecutor)");
169 }
170 else
171 {
172 RCLCPP_WARN(
173 getLogger(), "[CbMoveEndEffector] Execution failed (via CpTrajectoryExecutor): %s",
174 execResult.errorMessage.c_str());
175 }
176 }
177 else
178 {
179 // Fallback to legacy direct execution
180 RCLCPP_WARN(
181 getLogger(),
182 "[CbMoveEndEffector] CpTrajectoryExecutor component not available, using legacy "
183 "execution "
184 "(consider adding CpTrajectoryExecutor component)");
185
186 auto executionResult = moveGroupInterface.execute(computedMotionPlan);
187 executionSuccess = (executionResult == moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
188
189 RCLCPP_INFO(
190 getLogger(), "[CbMoveEndEffector] Execution %s (legacy mode)",
191 executionSuccess ? "succeeded" : "failed");
192 }
193
194 // Post events
195 if (executionSuccess)
196 {
198 this->postSuccessEvent();
199 }
200 else
201 {
203 this->postFailureEvent();
204 }
205 }
206 else
207 {
208 RCLCPP_INFO(getLogger(), "[CbMoveEndEffector] planning failed, skipping execution");
210 this->postFailureEvent();
211 }
212
213 RCLCPP_DEBUG(getLogger(), "[CbMoveEndEffector] Synchronous sleep of 1 seconds");
214 rclcpp::sleep_for(500ms);
215
216 return success;
217 }
218
220};
221} // namespace cl_moveit2z
bool moveToAbsolutePose(moveit::planning_interface::MoveGroupInterface &moveGroupInterface, geometry_msgs::msg::PoseStamped &targetObjectPose)
std::optional< std::string > group_
CbMoveEndEffector(geometry_msgs::msg::PoseStamped target_pose, std::string tip_link="")
geometry_msgs::msg::PoseStamped targetPose
Component for centralized motion planning operations.
PlanningResult planToPose(const geometry_msgs::msg::PoseStamped &target, const std::optional< std::string > &tipLink=std::nullopt, const PlanningOptions &options={})
Plan to a Cartesian pose.
std::shared_ptr< moveit::planning_interface::MoveGroupInterface > moveGroupClientInterface
Component for centralized trajectory execution.
ExecutionResult executePlan(const moveit::planning_interface::MoveGroupInterface::Plan &plan, const ExecutionOptions &options={})
Execute a motion plan synchronously.
virtual rclcpp::Logger getLogger() const
virtual rclcpp::Node::SharedPtr getNode() const
void requiresComponent(SmaccComponentType *&storage, ComponentRequirement requirementType=ComponentRequirement::SOFT)
Configuration options for trajectory execution.
std::optional< std::string > trajectoryName
Configuration options for motion planning.
std::optional< std::string > poseReferenceFrame
std::optional< double > planningTime