121 const std::vector<geometry_msgs::msg::PoseStamped> & waypoints,
126 if (waypoints.empty())
136 result.
errorMessage =
"ClMoveit2z client not available";
148 "[CpJointSpaceTrajectoryPlanner] Getting current state for trajectory planning");
149 auto currentState = moveGroup->getCurrentState(100);
152 result.
errorMessage =
"Failed to get current robot state";
159 std::string groupName = options.groupName.value_or(moveGroup->getName());
160 std::string tipLink = options.tipLink.value_or(moveGroup->getEndEffectorLink());
163 getLogger(),
"[CpJointSpaceTrajectoryPlanner] Planning for group '%s' with tip link '%s'",
164 groupName.c_str(), tipLink.c_str());
167 auto jointNames = currentState->getJointModelGroup(groupName)->getActiveJointModelNames();
170 std::vector<double> jointPositions;
171 currentState->copyJointGroupPositions(groupName, jointPositions);
173 std::vector<std::vector<double>> trajectory;
174 std::vector<rclcpp::Duration> trajectoryTimeStamps;
176 trajectory.push_back(jointPositions);
177 trajectoryTimeStamps.push_back(rclcpp::Duration(0s));
180 auto & first = waypoints.front();
181 rclcpp::Time referenceTime(first.header.stamp);
184 int ikAttemptsRemaining = options.ikAttempts;
185 for (
size_t k = 0; k < waypoints.size(); k++)
187 auto & pose = waypoints[k];
190 auto req = std::make_shared<moveit_msgs::srv::GetPositionIK::Request>();
191 req->ik_request.ik_link_name = tipLink;
192 req->ik_request.robot_state.joint_state.name = jointNames;
193 req->ik_request.robot_state.joint_state.position = jointPositions;
194 req->ik_request.group_name = groupName;
195 req->ik_request.avoid_collisions = options.avoidCollisions;
196 req->ik_request.pose_stamped = pose;
199 getLogger(),
"[CpJointSpaceTrajectoryPlanner] Computing IK for waypoint %lu/%lu", k + 1,
203 auto resFuture =
ikClient_->async_send_request(req);
204 auto status = resFuture.wait_for(options.ikTimeout);
206 if (status != std::future_status::ready)
208 result.
errorMessage =
"IK service timeout at waypoint " + std::to_string(k);
215 auto res = resFuture.get();
216 auto & prevTrajPoint = trajectory.back();
219 for (
size_t j = 0; j < res->solution.joint_state.position.size(); j++)
221 auto & jointName = res->solution.joint_state.name[j];
222 auto it = std::find(jointNames.begin(), jointNames.end(), jointName);
223 if (it != jointNames.end())
225 int index = std::distance(jointNames.begin(), it);
226 jointPositions[index] = res->solution.joint_state.position[j];
231 bool shouldCheck = k > 0 || !options.allowInitialDiscontinuity;
232 int discontinuityJointIndex = -1;
233 double discontinuityDelta = -1;
237 for (
size_t jointIndex = 0; jointIndex < jointPositions.size(); jointIndex++)
239 double deltaJoint = jointPositions[jointIndex] - prevTrajPoint[jointIndex];
240 if (fabs(deltaJoint) > options.maxJointDiscontinuity)
242 discontinuityDelta = deltaJoint;
243 discontinuityJointIndex = jointIndex;
250 if (ikAttemptsRemaining > 0 && discontinuityJointIndex != -1)
254 ikAttemptsRemaining--;
257 "[CpJointSpaceTrajectoryPlanner] IK discontinuity detected, retrying (%d attempts "
259 ikAttemptsRemaining);
265 if (ikAttemptsRemaining == 0 && discontinuityJointIndex != -1)
271 "[CpJointSpaceTrajectoryPlanner] Joint discontinuity at waypoint %lu: joint '%s' "
273 k, jointNames[discontinuityJointIndex].c_str(), discontinuityDelta);
279 "[CpJointSpaceTrajectoryPlanner] Initial posture discontinuity detected");
284 ikAttemptsRemaining = options.ikAttempts;
287 trajectory.push_back(jointPositions);
288 rclcpp::Duration durationFromStart = rclcpp::Time(pose.header.stamp) - referenceTime;
289 trajectoryTimeStamps.push_back(durationFromStart);
294 result.
trajectory.joint_trajectory.joint_names = jointNames;
297 for (
size_t i = 1; i < trajectory.size(); i++)
299 trajectory_msgs::msg::JointTrajectoryPoint jp;
300 jp.positions = trajectory[i];
301 jp.time_from_start = trajectoryTimeStamps[i];
302 result.
trajectory.joint_trajectory.points.push_back(jp);
316 result.
errorMessage =
"Joint trajectory discontinuity detected";
327 "[CpJointSpaceTrajectoryPlanner] Successfully computed trajectory with %lu points",
328 result.
trajectory.joint_trajectory.points.size());
331 catch (
const std::exception & e)
334 result.
errorMessage = std::string(
"Exception during trajectory planning: ") + e.what();