SMACC2
Loading...
Searching...
No Matches
cp_trajectory_executor.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#pragma once
22
23#include <smacc2/component.hpp>
24
27
28#include <moveit/move_group_interface/move_group_interface.h>
29#include <moveit_msgs/msg/move_it_error_codes.hpp>
30#include <moveit_msgs/msg/robot_trajectory.hpp>
31
32#include <chrono>
33#include <optional>
34#include <string>
35
36namespace cl_moveit2z
37{
42{
43 std::optional<double> maxVelocityScaling;
44 std::optional<double> maxAccelerationScaling;
45 bool recordToHistory = true;
46 std::optional<std::string> trajectoryName;
47};
48
53{
54 bool success;
55 moveit_msgs::msg::MoveItErrorCodes errorCode;
56 std::string errorMessage;
57 std::chrono::duration<double> executionTime;
58
60 {
61 errorCode.val = moveit_msgs::msg::MoveItErrorCodes::FAILURE;
62 }
63};
64
77{
78public:
80 virtual ~CpTrajectoryExecutor() = default;
81
85 inline void onInitialize() override
86 {
88
89 // CpTrajectoryHistory is optional but recommended
91
93 {
94 RCLCPP_INFO(
95 getLogger(),
96 "[CpTrajectoryExecutor] Component initialized with trajectory history recording enabled");
97 }
98 else
99 {
100 RCLCPP_WARN(
101 getLogger(),
102 "[CpTrajectoryExecutor] Component initialized without CpTrajectoryHistory "
103 "(trajectory history will not be recorded)");
104 }
105 }
106
115 const moveit_msgs::msg::RobotTrajectory & trajectory, const ExecutionOptions & options = {})
116 {
117 ExecutionResult result;
118
119 if (!moveit2zClient_)
120 {
121 result.errorMessage = "ClMoveit2z client not available";
122 RCLCPP_ERROR(getLogger(), "[CpTrajectoryExecutor] %s", result.errorMessage.c_str());
123 return result;
124 }
125
126 auto & moveGroup = moveit2zClient_->moveGroupClientInterface;
127
128 try
129 {
130 // Apply execution options
131 applyExecutionOptions(*moveGroup, options);
132
133 RCLCPP_INFO(
134 getLogger(), "[CpTrajectoryExecutor] Executing trajectory with %lu points...",
135 trajectory.joint_trajectory.points.size());
136
137 // Track execution time
138 auto startTime = std::chrono::steady_clock::now();
139
140 // Execute trajectory
141 result.errorCode = moveGroup->execute(trajectory);
142
143 auto endTime = std::chrono::steady_clock::now();
144 result.executionTime = std::chrono::duration<double>(endTime - startTime);
145
146 result.success = (result.errorCode.val == moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
147
148 if (result.success)
149 {
150 RCLCPP_INFO(
151 getLogger(), "[CpTrajectoryExecutor] Trajectory execution succeeded (%.2f seconds)",
152 result.executionTime.count());
153 }
154 else
155 {
156 result.errorMessage =
157 "Trajectory execution failed with error code: " + std::to_string(result.errorCode.val);
158 RCLCPP_WARN(getLogger(), "[CpTrajectoryExecutor] %s", result.errorMessage.c_str());
159 }
160
161 // Record to history if enabled
162 if (options.recordToHistory && trajectoryHistory_)
163 {
164 std::string trajName = options.trajectoryName.value_or("unnamed_trajectory");
165 recordToHistory(trajectory, result.errorCode, trajName);
166 }
167 }
168 catch (const std::exception & e)
169 {
170 result.success = false;
171 result.errorMessage = std::string("Exception during trajectory execution: ") + e.what();
172 RCLCPP_ERROR(getLogger(), "[CpTrajectoryExecutor] %s", result.errorMessage.c_str());
173 }
174
175 return result;
176 }
177
188 const moveit::planning_interface::MoveGroupInterface::Plan & plan,
189 const ExecutionOptions & options = {})
190 {
191 return execute(plan.trajectory_, options);
192 }
193
199 inline void cancel()
200 {
201 if (!moveit2zClient_)
202 {
203 RCLCPP_ERROR(getLogger(), "[CpTrajectoryExecutor] Cannot cancel: client not available");
204 return;
205 }
206
207 auto & moveGroup = moveit2zClient_->moveGroupClientInterface;
208
209 try
210 {
211 moveGroup->stop();
212 RCLCPP_INFO(getLogger(), "[CpTrajectoryExecutor] Trajectory execution cancelled");
213 }
214 catch (const std::exception & e)
215 {
216 RCLCPP_ERROR(
217 getLogger(), "[CpTrajectoryExecutor] Exception during cancellation: %s", e.what());
218 }
219 }
220
227
228private:
231
239 moveit::planning_interface::MoveGroupInterface & moveGroup, const ExecutionOptions & options)
240 {
241 if (options.maxVelocityScaling)
242 {
243 moveGroup.setMaxVelocityScalingFactor(*options.maxVelocityScaling);
244 }
245
246 if (options.maxAccelerationScaling)
247 {
248 moveGroup.setMaxAccelerationScalingFactor(*options.maxAccelerationScaling);
249 }
250 }
251
259 inline void recordToHistory(
260 const moveit_msgs::msg::RobotTrajectory & trajectory,
261 const moveit_msgs::msg::MoveItErrorCodes & errorCode, const std::string & name)
262 {
264 {
265 return;
266 }
267
268 try
269 {
270 trajectoryHistory_->pushTrajectory(name, trajectory, errorCode);
271 RCLCPP_DEBUG(
272 getLogger(), "[CpTrajectoryExecutor] Recorded trajectory '%s' to history", name.c_str());
273 }
274 catch (const std::exception & e)
275 {
276 RCLCPP_WARN(
277 getLogger(), "[CpTrajectoryExecutor] Failed to record trajectory to history: %s", e.what());
278 }
279 }
280};
281
282} // namespace cl_moveit2z
std::shared_ptr< moveit::planning_interface::MoveGroupInterface > moveGroupClientInterface
Component for centralized trajectory execution.
ExecutionResult execute(const moveit_msgs::msg::RobotTrajectory &trajectory, const ExecutionOptions &options={})
Execute a trajectory synchronously.
CpTrajectoryHistory * getTrajectoryHistory()
Get the trajectory history component.
virtual ~CpTrajectoryExecutor()=default
void recordToHistory(const moveit_msgs::msg::RobotTrajectory &trajectory, const moveit_msgs::msg::MoveItErrorCodes &errorCode, const std::string &name)
Record trajectory to history component.
void applyExecutionOptions(moveit::planning_interface::MoveGroupInterface &moveGroup, const ExecutionOptions &options)
Apply execution options to MoveGroupInterface.
void cancel()
Cancel ongoing execution.
void onInitialize() override
Initialize the component and get references to required components/clients.
ExecutionResult executePlan(const moveit::planning_interface::MoveGroupInterface::Plan &plan, const ExecutionOptions &options={})
Execute a motion plan synchronously.
void pushTrajectory(std::string name, const moveit_msgs::msg::RobotTrajectory &trajectory, moveit_msgs::msg::MoveItErrorCodes result)
void requiresClient(TClient *&requiredClientStorage)
rclcpp::Logger getLogger() const
void requiresComponent(TComponent *&requiredComponentStorage, bool throwExceptionIfNotExist)
Configuration options for trajectory execution.
std::optional< double > maxVelocityScaling
std::optional< double > maxAccelerationScaling
std::optional< std::string > trajectoryName
Result of a trajectory execution operation.
std::chrono::duration< double > executionTime
moveit_msgs::msg::MoveItErrorCodes errorCode