SMACC2
Loading...
Searching...
No Matches
cb_move_joints.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 <algorithm>
24#include <future>
25#include <map>
26#include <sstream>
27#include <string>
28
34
35namespace cl_moveit2z
36{
38{
39public:
40 std::optional<double> scalingFactor_;
41 std::map<std::string, double> jointValueTarget_;
42 std::optional<std::string> group_;
43
45
46 CbMoveJoints(const std::map<std::string, double> & jointValueTarget)
47 : jointValueTarget_(jointValueTarget)
48 {
49 }
50
51 virtual void onEntry() override
52 {
54
55 if (this->group_)
56 {
57 moveit::planning_interface::MoveGroupInterface move_group(
58 getNode(), moveit::planning_interface::MoveGroupInterface::Options(*(this->group_)));
59 this->moveJoints(move_group);
60 }
61 else
62 {
64 }
65 }
66
67 virtual void onExit() override {}
68
69protected:
70 static std::string currentJointStatesToString(
71 moveit::planning_interface::MoveGroupInterface & moveGroupInterface,
72 std::map<std::string, double> & targetJoints)
73 {
74 auto state = moveGroupInterface.getCurrentState();
75
76 if (state == nullptr) return std::string();
77
78 auto vnames = state->getVariableNames();
79
80 std::stringstream ss;
81
82 for (auto & tgj : targetJoints)
83 {
84 auto it = std::find(vnames.begin(), vnames.end(), tgj.first);
85 auto index = std::distance(vnames.begin(), it);
86
87 ss << tgj.first << ":" << state->getVariablePosition(index) << std::endl;
88 }
89
90 return ss.str();
91 }
92
93 void moveJoints(moveit::planning_interface::MoveGroupInterface & moveGroupInterface)
94 {
95 if (jointValueTarget_.size() == 0)
96 {
97 RCLCPP_WARN(getLogger(), "[CbMoveJoints] No joint value specified. Skipping planning call.");
99 this->postFailureEvent();
100 return;
101 }
102
103 // Try to use CpMotionPlanner component (preferred)
104 CpMotionPlanner * motionPlanner = nullptr;
105 this->requiresComponent(
106 motionPlanner, smacc2::ComponentRequirement::SOFT); // Optional component
107
108 bool success = false;
109 moveit::planning_interface::MoveGroupInterface::Plan computedMotionPlan;
110
111 if (motionPlanner != nullptr)
112 {
113 // Use component-based motion planner (preferred)
114 RCLCPP_INFO(getLogger(), "[CbMoveJoints] Using CpMotionPlanner component for joint planning");
115
116 PlanningOptions options;
117 if (scalingFactor_)
118 {
120 }
121
122 auto result = motionPlanner->planToJointTarget(jointValueTarget_, options);
123
124 success = result.success;
125 if (success)
126 {
127 computedMotionPlan = result.plan;
128 RCLCPP_INFO(getLogger(), "[CbMoveJoints] Planning succeeded (via CpMotionPlanner)");
129 }
130 else
131 {
132 RCLCPP_WARN(
133 getLogger(), "[CbMoveJoints] Planning failed (via CpMotionPlanner): %s",
134 result.errorMessage.c_str());
135 }
136 }
137 else
138 {
139 // Fallback to legacy direct API calls
140 RCLCPP_WARN(
141 getLogger(),
142 "[CbMoveJoints] CpMotionPlanner component not available, using legacy planning "
143 "(consider adding CpMotionPlanner component)");
144
145 if (scalingFactor_) moveGroupInterface.setMaxVelocityScalingFactor(*scalingFactor_);
146
147 moveGroupInterface.setJointValueTarget(jointValueTarget_);
148
149 auto result = moveGroupInterface.plan(computedMotionPlan);
150
151 success = (result == moveit::core::MoveItErrorCode::SUCCESS);
152
153 RCLCPP_INFO(
154 getLogger(), "[CbMoveJoints] Planning %s (legacy mode, code: %d)",
155 success ? "SUCCESS" : "FAILED", result.val);
156 }
157
158 // Execution
159 if (success)
160 {
161 // Try to use CpTrajectoryExecutor component (preferred)
162 CpTrajectoryExecutor * trajectoryExecutor = nullptr;
163 this->requiresComponent(
164 trajectoryExecutor, smacc2::ComponentRequirement::SOFT); // Optional component
165
166 bool executionSuccess = false;
167
168 if (trajectoryExecutor != nullptr)
169 {
170 // Use component-based trajectory executor (preferred)
171 RCLCPP_INFO(
172 getLogger(), "[CbMoveJoints] Using CpTrajectoryExecutor component for execution");
173
174 ExecutionOptions execOptions;
175 execOptions.trajectoryName = this->getName();
176 if (scalingFactor_)
177 {
178 execOptions.maxVelocityScaling = *scalingFactor_;
179 }
180
181 auto execResult = trajectoryExecutor->executePlan(computedMotionPlan, execOptions);
182 executionSuccess = execResult.success;
183
184 if (executionSuccess)
185 {
186 RCLCPP_INFO(getLogger(), "[CbMoveJoints] Execution succeeded (via CpTrajectoryExecutor)");
187 }
188 else
189 {
190 RCLCPP_WARN(
191 getLogger(), "[CbMoveJoints] Execution failed (via CpTrajectoryExecutor): %s",
192 execResult.errorMessage.c_str());
193 }
194 }
195 else
196 {
197 // Fallback to legacy direct execution
198 RCLCPP_WARN(
199 getLogger(),
200 "[CbMoveJoints] CpTrajectoryExecutor component not available, using legacy execution "
201 "(consider adding CpTrajectoryExecutor component)");
202
203 auto executionResult = moveGroupInterface.execute(computedMotionPlan);
204 executionSuccess = (executionResult == moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
205
206 RCLCPP_INFO(
207 getLogger(), "[CbMoveJoints] Execution %s (legacy mode)",
208 executionSuccess ? "succeeded" : "failed");
209 }
210
211 // Post events
212 if (executionSuccess)
213 {
214 RCLCPP_INFO_STREAM(
215 getLogger(),
216 "[" << this->getName() << "] motion execution succeeded. Throwing success event.");
218 this->postSuccessEvent();
219 }
220 else
221 {
222 RCLCPP_WARN_STREAM(
223 getLogger(), "[" << this->getName() << "] motion execution failed. Throwing fail event.");
225 this->postFailureEvent();
226 }
227 }
228 else
229 {
230 auto statestr = currentJointStatesToString(moveGroupInterface, jointValueTarget_);
231 RCLCPP_WARN_STREAM(
232 getLogger(), "[" << this->getName() << "] planning failed. Throwing fail event."
233 << std::endl
234 << statestr);
236 this->postFailureEvent();
237 }
238 }
239
241};
242} // namespace cl_moveit2z
virtual void onEntry() override
static std::string currentJointStatesToString(moveit::planning_interface::MoveGroupInterface &moveGroupInterface, std::map< std::string, double > &targetJoints)
CpMoveGroupInterface * cpMoveGroup_
CbMoveJoints(const std::map< std::string, double > &jointValueTarget)
std::map< std::string, double > jointValueTarget_
void moveJoints(moveit::planning_interface::MoveGroupInterface &moveGroupInterface)
virtual void onExit() override
std::optional< double > scalingFactor_
std::optional< std::string > group_
Component for centralized motion planning operations.
PlanningResult planToJointTarget(const std::map< std::string, double > &jointTargets, const PlanningOptions &options={})
Plan to joint values.
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< double > maxVelocityScaling
std::optional< std::string > trajectoryName
Configuration options for motion planning.
std::optional< double > maxVelocityScaling