cartesian_controller.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 #include <math.h>
19 #include <algorithm>
20 #include <string>
21 #include <boost/lexical_cast.hpp>
22 
23 #include <ros/ros.h>
24 #include <std_srvs/Trigger.h>
25 #include <cob_srvs/SetString.h>
26 
28 
30 {
31  ros::NodeHandle nh_private("~");
32 
33  if (!nh_.getParam("chain_tip_link", chain_tip_link_))
34  {
35  ROS_ERROR("Parameter 'chain_tip_link' not set");
36  return false;
37  }
38 
39  if (!nh_.getParam("root_frame", root_frame_))
40  {
41  ROS_ERROR("Parameter 'reference_frame' not set");
42  return false;
43  }
44 
45  if (!nh_.getParam("update_rate", update_rate_))
46  {
47  update_rate_ = 50.0; // hz
48  }
49 
51  if (!nh_private.getParam("target_frame", target_frame_))
52  {
53  ROS_WARN("Parameter 'target_frame' not set. Using default 'cartesian_target'");
55  }
56 
57  ROS_WARN("Waiting for Services...");
58  start_tracking_ = nh_.serviceClient<cob_srvs::SetString>("frame_tracker/start_tracking");
59  stop_tracking_ = nh_.serviceClient<std_srvs::Trigger>("frame_tracker/stop");
61  stop_tracking_.waitForExistence();
62  tracking_ = false;
63 
65 
66  action_name_ = "cartesian_trajectory_action";
68  as_->registerGoalCallback(boost::bind(&CartesianController::goalCallback, this));
69  as_->registerPreemptCallback(boost::bind(&CartesianController::preemptCallback, this));
70  as_->start();
71 
72  ROS_INFO("Cartesian Controller running");
73  return true;
74 }
75 
76 // ToDo: Use the ActionInterface of the FrameTracker instead in order to be able to consider TrackingConstraints
78 {
79  bool success = false;
80  cob_srvs::SetString start;
81  start.request.data = target_frame_;
82  if (!tracking_)
83  {
84  success = start_tracking_.call(start);
85 
86  if (success)
87  {
88  success = start.response.success;
89  if (success)
90  {
91  ROS_INFO("Response 'start_tracking': succeded");
92  tracking_ = true;
93  }
94  else
95  {
96  ROS_ERROR("Response 'start_tracking': failed");
97  }
98  }
99  else
100  {
101  ROS_ERROR("Failed to call service 'start_tracking'");
102  }
103  }
104  else
105  {
106  ROS_WARN("Already tracking");
107  }
108 
109  return success;
110 }
111 
112 // ToDo:: If we use the ActionInterface of the FrameTracker, here that action should be cancled()
114 {
115  bool success = false;
116  std_srvs::Trigger stop;
117  if (tracking_)
118  {
119  success = stop_tracking_.call(stop);
120 
121  if (success)
122  {
123  ROS_INFO("Service 'stop' succeded!");
124  tracking_ = false;
125  }
126  else
127  {
128  ROS_ERROR("Failed to call service 'stop_tracking'");
129  }
130  }
131  else
132  {
133  ROS_WARN("Have not been tracking");
134  }
135 
136  return success;
137 }
138 
139 // Broadcasting interpolated Cartesian path
140 bool CartesianController::posePathBroadcaster(const geometry_msgs::PoseArray& cartesian_path)
141 {
142  bool success = true;
144  tf::Transform transform;
145 
146  for (unsigned int i = 0; i < cartesian_path.poses.size(); i++)
147  {
148  if (!as_->isActive())
149  {
150  success = false;
151  break;
152  }
153 
154  // Send/Refresh target Frame
155  transform.setOrigin(tf::Vector3(cartesian_path.poses.at(i).position.x,
156  cartesian_path.poses.at(i).position.y,
157  cartesian_path.poses.at(i).position.z));
158  transform.setRotation(tf::Quaternion(cartesian_path.poses.at(i).orientation.x,
159  cartesian_path.poses.at(i).orientation.y,
160  cartesian_path.poses.at(i).orientation.z,
161  cartesian_path.poses.at(i).orientation.w));
162 
163  tf_broadcaster_.sendTransform(tf::StampedTransform(transform, ros::Time::now(), cartesian_path.header.frame_id, target_frame_));
164 
165  ros::spinOnce();
166  rate.sleep();
167  }
168 
169  return success;
170 }
171 
172 
174 {
175  geometry_msgs::PoseArray cartesian_path;
177 
178  action_struct = acceptGoal(as_->acceptNewGoal());
179 
180  if (action_struct.move_type == cob_cartesian_controller::CartesianControllerGoal::LIN)
181  {
182  // Interpolate path
183  if (!trajectory_interpolator_->linearInterpolation(cartesian_path, action_struct))
184  {
185  actionAbort(false, "Failed to do interpolation for 'move_lin'");
186  return;
187  }
188 
189  // Publish Preview
190  utils_.previewPath(cartesian_path);
191 
192  // initially broadcast target_frame
193  tf::Transform identity = tf::Transform();
194  identity.setIdentity();
196 
197  // Activate Tracking
198  if (!startTracking())
199  {
200  actionAbort(false, "Failed to start tracking");
201  return;
202  }
203 
204  // Execute path
205  if (!posePathBroadcaster(cartesian_path))
206  {
207  actionAbort(false, "Failed to execute path for 'move_lin'");
208  return;
209  }
210 
211  // De-Activate Tracking
212  if (!stopTracking())
213  {
214  actionAbort(false, "Failed to stop tracking");
215  return;
216  }
217 
218  actionSuccess(true, "move_lin succeeded!");
219  }
220  else if (action_struct.move_type == cob_cartesian_controller::CartesianControllerGoal::CIRC)
221  {
222  if (!trajectory_interpolator_->circularInterpolation(cartesian_path, action_struct))
223  {
224  actionAbort(false, "Failed to do interpolation for 'move_circ'");
225  return;
226  }
227 
228  // Publish Preview
229  utils_.previewPath(cartesian_path);
230 
231  // Activate Tracking
232  if (!startTracking())
233  {
234  actionAbort(false, "Failed to start tracking");
235  return;
236  }
237 
238  // Execute path
239  if (!posePathBroadcaster(cartesian_path))
240  {
241  actionAbort(false, "Failed to execute path for 'move_circ'");
242  return;
243  }
244 
245  // De-Activate Tracking
246  if (!stopTracking())
247  {
248  actionAbort(false, "Failed to stop tracking");
249  return;
250  }
251 
252  actionSuccess(true, "move_circ succeeded!");
253  }
254  else
255  {
256  actionAbort(false, "Unknown trajectory action");
257  return;
258  }
259 }
260 
261 cob_cartesian_controller::MoveLinStruct CartesianController::convertMoveLin(const cob_cartesian_controller::MoveLin& move_lin_msg)
262 {
263  geometry_msgs::Pose start, end;
264  start = utils_.getPose(root_frame_, chain_tip_link_); // current tcp pose
265  utils_.transformPose(move_lin_msg.frame_id, root_frame_, move_lin_msg.pose_goal, end);
266 
268 
269  move_lin.start = start;
270  move_lin.end = end;
271 
272  return move_lin;
273 }
274 
275 cob_cartesian_controller::MoveCircStruct CartesianController::convertMoveCirc(const cob_cartesian_controller::MoveCirc& move_circ_msg)
276 {
277  geometry_msgs::Pose center;
278  utils_.transformPose(move_circ_msg.frame_id, root_frame_, move_circ_msg.pose_center, center);
279 
281  move_circ.start_angle = move_circ_msg.start_angle;
282  move_circ.end_angle = move_circ_msg.end_angle;
283  move_circ.radius = move_circ_msg.radius;
284 
285  move_circ.pose_center = center;
286 
287  return move_circ;
288 }
289 
291 {
293  action_struct.move_type = goal->move_type;
294 
295  action_struct.profile.vel = goal->profile.vel;
296  action_struct.profile.accl = goal->profile.accl;
297  action_struct.profile.profile_type = goal->profile.profile_type;
298  action_struct.profile.t_ipo = 1/update_rate_;
299 
300 
301  if (action_struct.move_type == cob_cartesian_controller::CartesianControllerGoal::LIN)
302  {
303  action_struct.move_lin = convertMoveLin(goal->move_lin);
304  }
305  else if (action_struct.move_type == cob_cartesian_controller::CartesianControllerGoal::CIRC)
306  {
307  action_struct.move_circ = convertMoveCirc(goal->move_circ);
308  }
309  else
310  {
311  actionAbort(false, "Unknown trajectory action " + boost::lexical_cast<std::string>(action_struct.move_type));
312  }
313 
314  return action_struct;
315 }
316 
318 {
319  // De-Activate Tracking
320  stopTracking();
321  actionPreempt(true, "action preempted!");
322 }
323 
324 void CartesianController::actionSuccess(const bool success, const std::string& message)
325 {
326  ROS_INFO_STREAM("Goal succeeded: " << message);
327  action_result_.success = success;
328  action_result_.message = message;
329  as_->setSucceeded(action_result_, action_result_.message);
330 }
331 
332 void CartesianController::actionPreempt(const bool success, const std::string& message)
333 {
334  ROS_WARN_STREAM("Goal preempted: " << message);
335  action_result_.success = success;
336  action_result_.message = message;
337  as_->setPreempted(action_result_, action_result_.message);
338 }
339 
340 void CartesianController::actionAbort(const bool success, const std::string& message)
341 {
342  ROS_ERROR_STREAM("Goal aborted: " << message);
343  action_result_.success = success;
344  action_result_.message = message;
345  as_->setAborted(action_result_, action_result_.message);
346  stopTracking();
347 }
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
boost::shared_ptr< TrajectoryInterpolator > trajectory_interpolator_
ros::ServiceClient start_tracking_
TFSIMD_FORCE_INLINE void setRotation(const Quaternion &q)
std::string action_name_
Action interface.
rate
void previewPath(const geometry_msgs::PoseArray pose_array)
cob_cartesian_controller::CartesianActionStruct acceptGoal(boost::shared_ptr< const cob_cartesian_controller::CartesianControllerGoal > goal)
bool call(MReq &req, MRes &res)
actionlib::SimpleActionServer< cob_cartesian_controller::CartesianControllerAction > SAS_CartesianControllerAction_t
#define ROS_WARN(...)
void actionPreempt(const bool success, const std::string &message)
cob_cartesian_controller::MoveLinStruct convertMoveLin(const cob_cartesian_controller::MoveLin &move_lin_msg)
void setIdentity()
CartesianControllerUtils utils_
tf::TransformBroadcaster tf_broadcaster_
def move_circ(pose_center, frame_id, start_angle, end_angle, radius, profile)
bool waitForExistence(ros::Duration timeout=ros::Duration(-1))
#define ROS_INFO(...)
void sendTransform(const StampedTransform &transform)
#define ROS_WARN_STREAM(args)
#define DEFAULT_CARTESIAN_TARGET
void transformPose(const std::string source_frame, const std::string target_frame, const geometry_msgs::Pose pose_in, geometry_msgs::Pose &pose_out)
bool sleep()
geometry_msgs::Pose getPose(const std::string &target_frame, const std::string &source_frame)
bool posePathBroadcaster(const geometry_msgs::PoseArray &cartesian_path)
#define ROS_INFO_STREAM(args)
bool getParam(const std::string &key, std::string &s) const
ros::ServiceClient stop_tracking_
boost::shared_ptr< SAS_CartesianControllerAction_t > as_
static Time now()
void goalCallback()
Action interface.
#define ROS_ERROR_STREAM(args)
cob_cartesian_controller::CartesianControllerResult action_result_
ROSCPP_DECL void spinOnce()
#define ROS_ERROR(...)
TFSIMD_FORCE_INLINE void setOrigin(const Vector3 &origin)
cob_cartesian_controller::MoveCircStruct convertMoveCirc(const cob_cartesian_controller::MoveCirc &move_circ_msg)
void actionSuccess(const bool success, const std::string &message)
void actionAbort(const bool success, const std::string &message)


cob_cartesian_controller
Author(s): Christoph Mark
autogenerated on Thu Apr 8 2021 02:40:13