21#include <tf2/transform_datatypes.h>
22#include <tf2_ros/transform_listener.h>
27#include <moveit_msgs/srv/get_position_ik.hpp>
29#include <visualization_msgs/msg/marker_array.hpp>
31using namespace std::chrono_literals;
36: tipLink_(tipLink), markersInitialized_(false)
40CbMoveEndEffectorTrajectory::CbMoveEndEffectorTrajectory(
41 const std::vector<geometry_msgs::msg::PoseStamped> & endEffectorTrajectory,
42 std::optional<std::string> tipLink)
43: tipLink_(tipLink), endEffectorTrajectory_(endEffectorTrajectory), markersInitialized_(false)
48void CbMoveEndEffectorTrajectory::initializeROS()
50 RCLCPP_INFO_STREAM(getLogger(),
"[" << getName() <<
"] initializing ros");
52 auto nh = this->getNode();
53 markersPub_ = nh->create_publisher<visualization_msgs::msg::MarkerArray>(
54 "trajectory_markers", rclcpp::QoS(1));
55 iksrv_ = nh->create_client<moveit_msgs::srv::GetPositionIK>(
"/compute_ik");
59 moveit_msgs::msg::RobotTrajectory & computedJointTrajectory)
61 RCLCPP_INFO_STREAM(getLogger(),
"[" << getName() <<
"] getting current state.. waiting");
64 auto currentState = movegroupClient_->moveGroupClientInterface->getCurrentState(100);
67 auto groupname = movegroupClient_->moveGroupClientInterface->getName();
69 RCLCPP_INFO_STREAM(getLogger(),
"[" << getName() <<
"] getting joint names");
70 auto currentjointnames = currentState->getJointModelGroup(groupname)->getActiveJointModelNames();
72 if (!tipLink_ || *tipLink_ ==
"")
74 tipLink_ = movegroupClient_->moveGroupClientInterface->getEndEffectorLink();
77 std::vector<double> jointPositions;
78 currentState->copyJointGroupPositions(groupname, jointPositions);
80 std::vector<std::vector<double>> trajectory;
81 std::vector<rclcpp::Duration> trajectoryTimeStamps;
83 trajectory.push_back(jointPositions);
84 trajectoryTimeStamps.push_back(rclcpp::Duration(0s));
86 auto & first = endEffectorTrajectory_.front();
87 rclcpp::Time referenceTime(first.header.stamp);
89 std::vector<int> discontinuityIndexes;
92 for (
size_t k = 0; k < this->endEffectorTrajectory_.size(); k++)
94 auto & pose = this->endEffectorTrajectory_[k];
95 auto req = std::make_shared<moveit_msgs::srv::GetPositionIK::Request>();
98 req->ik_request.ik_link_name = *tipLink_;
99 req->ik_request.robot_state.joint_state.name = currentjointnames;
100 req->ik_request.robot_state.joint_state.position = jointPositions;
102 req->ik_request.group_name = groupname;
103 req->ik_request.avoid_collisions =
true;
106 req->ik_request.pose_stamped = pose;
108 RCLCPP_INFO_STREAM(getLogger(),
"[" << getName() <<
"] IK request: " << k <<
" " << *req);
110 auto resfut = iksrv_->async_send_request(req);
112 auto status = resfut.wait_for(3s);
113 if (status == std::future_status::ready)
117 auto & prevtrajpoint = trajectory.back();
120 auto res = resfut.get();
121 std::stringstream ss;
122 for (
size_t j = 0; j < res->solution.joint_state.position.size(); j++)
124 auto & jointname = res->solution.joint_state.name[j];
125 auto it = std::find(currentjointnames.begin(), currentjointnames.end(), jointname);
126 if (it != currentjointnames.end())
128 int index = std::distance(currentjointnames.begin(), it);
129 jointPositions[index] = res->solution.joint_state.position[j];
130 ss << jointname <<
"(" << index <<
"): " << jointPositions[index] << std::endl;
135 size_t jointindex = 0;
136 int discontinuityJointIndex = -1;
137 double discontinuityDeltaJointIndex = -1;
140 bool check = k > 0 || !allowInitialTrajectoryStateJointDiscontinuity_ ||
141 (allowInitialTrajectoryStateJointDiscontinuity_ &&
142 !(*allowInitialTrajectoryStateJointDiscontinuity_));
145 for (jointindex = 0; jointindex < jointPositions.size(); jointindex++)
147 deltajoint = jointPositions[jointindex] - prevtrajpoint[jointindex];
149 if (fabs(deltajoint) > 0.3 )
151 discontinuityDeltaJointIndex = deltajoint;
152 discontinuityJointIndex = jointindex;
157 if (ikAttempts > 0 && discontinuityJointIndex != -1)
165 bool discontinuity =
false;
168 discontinuityIndexes.push_back(k);
169 discontinuity =
true;
174 if (discontinuity && discontinuityJointIndex != -1)
177 std::stringstream ss;
178 ss <<
"Traj[" << k <<
"/" << endEffectorTrajectory_.size() <<
"] "
179 << currentjointnames[discontinuityJointIndex]
180 <<
" IK discontinuity : " << discontinuityDeltaJointIndex << std::endl
181 <<
"prev joint value: " << prevtrajpoint[discontinuityJointIndex] << std::endl
182 <<
"current joint value: " << jointPositions[discontinuityJointIndex] << std::endl;
185 for (
size_t ji = 0; ji < jointPositions.size(); ji++)
187 ss << currentjointnames[ji] <<
": " << jointPositions[ji] << std::endl;
190 for (
size_t kindex = 0; kindex < trajectory.size(); kindex++)
192 ss <<
"[" << kindex <<
"]: " << trajectory[kindex][discontinuityJointIndex]
198 ss <<
"This is the first posture of the trajectory. Maybe the robot initial posture is "
199 "not coincident to the initial posture of the generated joint trajectory."
203 RCLCPP_ERROR_STREAM(getLogger(), ss.str());
205 trajectory.push_back(jointPositions);
206 rclcpp::Duration durationFromStart = rclcpp::Time(pose.header.stamp) - referenceTime;
207 trajectoryTimeStamps.push_back(durationFromStart);
213 trajectory.push_back(jointPositions);
214 rclcpp::Duration durationFromStart = rclcpp::Time(pose.header.stamp) - referenceTime;
215 trajectoryTimeStamps.push_back(durationFromStart);
217 RCLCPP_DEBUG_STREAM(getLogger(),
"IK solution: " << res->solution.joint_state);
218 RCLCPP_DEBUG_STREAM(getLogger(),
"trajpoint: " << std::endl << ss.str());
224 RCLCPP_ERROR_STREAM(getLogger(),
"[" << getName() <<
"] wrong IK call");
238 computedJointTrajectory.joint_trajectory.joint_names = currentjointnames;
240 for (
auto & p : trajectory)
250 trajectory_msgs::msg::JointTrajectoryPoint jp;
252 jp.time_from_start = trajectoryTimeStamps[i];
253 computedJointTrajectory.joint_trajectory.points.push_back(jp);
257 if (discontinuityIndexes.size())
259 if (discontinuityIndexes[0] == 0)
260 return ComputeJointTrajectoryErrorCode::INCORRECT_INITIAL_STATE;
262 return ComputeJointTrajectoryErrorCode::JOINT_TRAJECTORY_DISCONTINUITY;
265 return ComputeJointTrajectoryErrorCode::SUCCESS;
268void CbMoveEndEffectorTrajectory::executeJointSpaceTrajectory(
269 const moveit_msgs::msg::RobotTrajectory & computedJointTrajectory)
271 RCLCPP_INFO_STREAM(getLogger(),
"[" << this->getName() <<
"] Executing joint trajectory");
273 auto executionResult =
274 this->movegroupClient_->moveGroupClientInterface->execute(computedJointTrajectory);
276 if (executionResult == moveit_msgs::msg::MoveItErrorCodes::SUCCESS)
278 RCLCPP_INFO_STREAM(getLogger(),
"[" << this->getName() <<
"] motion execution succeeded");
279 movegroupClient_->postEventMotionExecutionSucceded();
280 this->postSuccessEvent();
284 this->postMotionExecutionFailureEvents();
285 this->postFailureEvent();
289void CbMoveEndEffectorTrajectory::onEntry()
291 this->requiresClient(movegroupClient_);
293 RCLCPP_INFO_STREAM(getLogger(),
"[" << getName() <<
"] Generating end effector trajectory");
295 this->generateTrajectory();
297 if (this->endEffectorTrajectory_.size() == 0)
301 <<
"] No points in the trajectory. Skipping behavior.");
305 RCLCPP_INFO_STREAM(getLogger(),
"[" << getName() <<
"] Creating markers.");
307 this->createMarkers();
308 markersInitialized_ =
true;
309 moveit_msgs::msg::RobotTrajectory computedTrajectory;
311 RCLCPP_INFO_STREAM(getLogger(),
"[" << getName() <<
"] Computing joint space trajectory.");
313 auto errorcode = computeJointSpaceTrajectory(computedTrajectory);
315 bool trajectoryGenerationSuccess = errorcode == ComputeJointTrajectoryErrorCode::SUCCESS;
317 CpTrajectoryHistory * trajectoryHistory;
318 this->requiresComponent(trajectoryHistory);
320 if (!trajectoryGenerationSuccess)
323 getLogger(),
"[" << this->getName() <<
"] Incorrect trajectory. Posting failure event.");
324 if (trajectoryHistory !=
nullptr)
326 moveit_msgs::msg::MoveItErrorCodes error;
327 error.val = moveit_msgs::msg::MoveItErrorCodes::NO_IK_SOLUTION;
328 trajectoryHistory->pushTrajectory(this->getName(), computedTrajectory, error);
331 movegroupClient_->postEventMotionExecutionFailed();
332 this->postFailureEvent();
334 if (errorcode == ComputeJointTrajectoryErrorCode::JOINT_TRAJECTORY_DISCONTINUITY)
336 this->postJointDiscontinuityEvent(computedTrajectory);
338 else if (errorcode == ComputeJointTrajectoryErrorCode::INCORRECT_INITIAL_STATE)
340 this->postIncorrectInitialStateEvent(computedTrajectory);
346 if (trajectoryHistory !=
nullptr)
348 moveit_msgs::msg::MoveItErrorCodes error;
349 error.val = moveit_msgs::msg::MoveItErrorCodes::SUCCESS;
350 trajectoryHistory->pushTrajectory(this->getName(), computedTrajectory, error);
353 this->executeJointSpaceTrajectory(computedTrajectory);
359void CbMoveEndEffectorTrajectory::update()
361 if (markersInitialized_)
363 std::lock_guard<std::mutex> guard(m_mutex_);
364 markersPub_->publish(beahiorMarkers_);
368void CbMoveEndEffectorTrajectory::onExit()
370 markersInitialized_ =
false;
372 if (autocleanmarkers)
374 std::lock_guard<std::mutex> guard(m_mutex_);
375 for (
auto & marker : this->beahiorMarkers_.markers)
377 marker.header.stamp = getNode()->now();
378 marker.action = visualization_msgs::msg::Marker::DELETE;
381 markersPub_->publish(beahiorMarkers_);
385void CbMoveEndEffectorTrajectory::createMarkers()
387 tf2::Transform localdirection;
388 localdirection.setIdentity();
389 localdirection.setOrigin(tf2::Vector3(0.05, 0, 0));
390 auto frameid = this->endEffectorTrajectory_.front().header.frame_id;
392 for (
auto & pose : this->endEffectorTrajectory_)
394 visualization_msgs::msg::Marker marker;
395 marker.header.frame_id =
frameid;
396 marker.header.stamp = getNode()->now();
397 marker.ns =
"trajectory";
398 marker.id = this->beahiorMarkers_.markers.size();
399 marker.type = visualization_msgs::msg::Marker::ARROW;
400 marker.action = visualization_msgs::msg::Marker::ADD;
401 marker.scale.x = 0.005;
402 marker.scale.y = 0.01;
403 marker.scale.z = 0.01;
404 marker.color.a = 0.8;
405 marker.color.r = 1.0;
409 geometry_msgs::msg::Point start, end;
414 tf2::Transform basetransform;
415 tf2::fromMsg(pose.pose, basetransform);
418 end.x = localdirection.getOrigin().x();
419 end.y = localdirection.getOrigin().y();
420 end.z = localdirection.getOrigin().z();
422 marker.pose.position = pose.pose.position;
423 marker.pose.orientation = pose.pose.orientation;
424 marker.points.push_back(start);
425 marker.points.push_back(end);
427 beahiorMarkers_.markers.push_back(marker);
431void CbMoveEndEffectorTrajectory::generateTrajectory()
437void CbMoveEndEffectorTrajectory::getCurrentEndEffectorPose(
438 std::string globalFrame, tf2::Stamped<tf2::Transform> & currentEndEffectorTransform)
440 tf2_ros::Buffer tfBuffer(getNode()->get_clock());
441 tf2_ros::TransformListener tfListener(tfBuffer);
445 if (!tipLink_ || *tipLink_ ==
"")
447 tipLink_ = this->movegroupClient_->moveGroupClientInterface->getEndEffectorLink();
451 tfBuffer.lookupTransform(globalFrame, *tipLink_, rclcpp::Time(0), rclcpp::Duration(10s)),
452 currentEndEffectorTransform);
460 catch (
const std::exception & e)
462 std::cerr << e.what() << std::endl;
CbMoveEndEffectorTrajectory(std::optional< std::string > tipLink=std::nullopt)
ComputeJointTrajectoryErrorCode
const std::string frameid
std::string demangleSymbol()