40 template <
class TrajectoryInterface>
45 if (!controller_nh.
getParam(
"joints", joint_names_))
52 trajectory_interface_ = hw->
get<TrajectoryInterface>();
53 if (!trajectory_interface_)
59 trajectory_interface_->setResources(joint_names_);
63 if (!speed_scaling_interface)
66 "without this feature.");
67 speed_scaling_ =
nullptr;
71 speed_scaling_ = std::make_unique<scaled_controllers::SpeedScalingHandle>(speed_scaling_interface->getHandle(
"speed"
81 std::is_same<TrajectoryInterface, hardware_interface::JointTrajectoryInterface>::value ?
"follow_joint_"
94 action_server_->start();
99 template <
class TrajectoryInterface>
105 template <
class TrajectoryInterface>
108 if (action_server_->isActive())
111 trajectory_interface_->setCancel();
113 typename Base::FollowTrajectoryResult result;
114 result.error_string =
"Controller stopped.";
115 result.error_code = Base::FollowTrajectoryResult::PATH_TOLERANCE_VIOLATED;
116 action_server_->setAborted(result);
121 template <
class TrajectoryInterface>
124 if (action_server_->isActive() && !done_)
127 const double factor = (speed_scaling_) ? *speed_scaling_->getScalingFactor() : 1.0;
128 action_duration_.current += period * factor;
130 typename Base::TrajectoryFeedback
f = trajectory_interface_->getFeedback();
131 action_server_->publishFeedback(
f);
139 if (action_duration_.current >= action_duration_.target)
144 "Something might be wrong with the robot. "
145 "You might want to cancel this goal.");
151 template <
class TrajectoryInterface>
157 if (!this->isRunning())
159 ROS_ERROR(
"Can't accept new action goals. Controller is not running.");
160 typename Base::FollowTrajectoryResult result;
161 result.error_code = Base::FollowTrajectoryResult::INVALID_GOAL;
162 action_server_->setAborted(result);
171 path_tolerances_ = goal->path_tolerance;
172 goal_tolerances_ = goal->goal_tolerance;
175 if (!trajectory_interface_->setGoal(*goal))
177 ROS_ERROR(
"Trajectory goal is invalid.");
178 typename Base::FollowTrajectoryResult result;
179 result.error_code = Base::FollowTrajectoryResult::INVALID_GOAL;
180 action_server_->setAborted(result);
186 action_duration_.target = goal->trajectory.points.back().time_from_start + goal->goal_time_tolerance;
200 template <
class TrajectoryInterface>
203 if (action_server_->isActive())
206 trajectory_interface_->setCancel();
210 template <
class TrajectoryInterface>
214 if (!withinTolerances(feedback.error, path_tolerances_))
216 trajectory_interface_->setCancel();
222 const Tolerance& tolerances)
227 for (
size_t i = 0; i < tolerances.size(); ++i)
229 if (tolerances[i].position > 0.0)
231 if (error.positions.size() == tolerances.size())
233 return std::abs(error.positions[i]) <= tolerances[i].position;
235 ROS_WARN(
"Position tolerances specified, but not fully supported by the driver implementation.");
239 if (tolerances[i].velocity > 0.0)
241 if (error.velocities.size() == tolerances.size())
243 return std::abs(error.velocities[i]) <= tolerances[i].velocity;
245 ROS_WARN(
"Velocity tolerances specified, but not fully supported by the driver implementation.");
249 if (tolerances[i].acceleration > 0.0)
251 if (error.accelerations.size() == tolerances.size())
253 return std::abs(error.accelerations[i]) <= tolerances[i].acceleration;
255 ROS_WARN(
"Acceleration tolerances specified, but not fully supported by the driver implementation.");
266 const typename Base::TrajectoryPoint& error,
const typename Base::Tolerance& tolerances)
269 Base::Tolerance uninitialized;
270 std::stringstream str_1;
271 std::stringstream str_2;
273 str_2 << uninitialized;
275 if (str_1.str() == str_2.str())
280 auto not_within_limits = [](
auto& a,
auto& b) {
return a.x > b.x || a.y > b.y || a.z > b.z; };
283 if (not_within_limits(error.pose.position, tolerances.position_error) ||
284 not_within_limits(error.pose.orientation, tolerances.orientation_error) ||
285 not_within_limits(error.twist.linear, tolerances.twist_error.linear) ||
286 not_within_limits(error.twist.angular, tolerances.twist_error.angular) ||
287 not_within_limits(error.acceleration.linear, tolerances.acceleration_error.linear) ||
288 not_within_limits(error.acceleration.angular, tolerances.acceleration_error.angular))
298 const typename Base::GoalConstPtr& goal)
301 if ((!goal->path_tolerance.empty() && goal->path_tolerance.size() != joint_names_.size()) ||
302 (!goal->goal_tolerance.empty() && goal->goal_tolerance.size() != joint_names_.size()))
304 ROS_ERROR(
"Given tolerances must match the number of joints");
305 typename Base::FollowTrajectoryResult result;
306 result.error_code = Base::FollowTrajectoryResult::INVALID_GOAL;
307 action_server_->setAborted(result);
315 const typename Base::GoalConstPtr& goal)
321 template <
class TrajectoryInterface>
324 typename Base::FollowTrajectoryResult result;
326 if (!action_server_->isActive())
334 result.error_string =
"Trajectory aborted by the robot. Something unexpected happened.";
335 result.error_code = Base::FollowTrajectoryResult::PATH_TOLERANCE_VIOLATED;
336 action_server_->setAborted(result);
341 result.error_string =
"Trajectory preempted. Possible reasons: user request | path tolerances fail.";
342 result.error_code = Base::FollowTrajectoryResult::PATH_TOLERANCE_VIOLATED;
343 action_server_->setPreempted(result);
350 typename Base::TrajectoryPoint p = trajectory_interface_->getFeedback().error;
351 if (!withinTolerances(p, goal_tolerances_))
353 result.error_string =
"Trajectory finished execution but failed goal tolerances";
354 result.error_code = Base::FollowTrajectoryResult::GOAL_TOLERANCE_VIOLATED;
355 action_server_->setAborted(result);
359 result.error_string =
"Trajectory execution successful";
360 result.error_code = Base::FollowTrajectoryResult::SUCCESSFUL;
361 action_server_->setSucceeded(result);
367 result.error_string =
"Trajectory finished in unknown state.";
368 result.error_code = Base::FollowTrajectoryResult::PATH_TOLERANCE_VIOLATED;
369 action_server_->setAborted(result);