cartesian_controller.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *   http://www.apache.org/licenses/LICENSE-2.0
00009 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 
00018 #include <math.h>
00019 #include <algorithm>
00020 #include <string>
00021 #include <boost/lexical_cast.hpp>
00022 
00023 #include <ros/ros.h>
00024 #include <std_srvs/Trigger.h>
00025 #include <cob_srvs/SetString.h>
00026 
00027 #include <cob_cartesian_controller/cartesian_controller.h>
00028 
00029 bool CartesianController::initialize()
00030 {
00031     ros::NodeHandle nh_private("~");
00032 
00033     if (!nh_.getParam("chain_tip_link", chain_tip_link_))
00034     {
00035         ROS_ERROR("Parameter 'chain_tip_link' not set");
00036         return false;
00037     }
00038 
00039     if (!nh_.getParam("root_frame", root_frame_))
00040     {
00041         ROS_ERROR("Parameter 'reference_frame' not set");
00042         return false;
00043     }
00044 
00045     if (!nh_.getParam("update_rate", update_rate_))
00046     {
00047         update_rate_ = 50.0;  // hz
00048     }
00049 
00051     if (!nh_private.getParam("target_frame", target_frame_))
00052     {
00053         ROS_WARN("Parameter 'target_frame' not set. Using default 'cartesian_target'");
00054         target_frame_ = DEFAULT_CARTESIAN_TARGET;
00055     }
00056 
00057     ROS_WARN("Waiting for Services...");
00058     start_tracking_ = nh_.serviceClient<cob_srvs::SetString>("frame_tracker/start_tracking");
00059     stop_tracking_ = nh_.serviceClient<std_srvs::Trigger>("frame_tracker/stop");
00060     start_tracking_.waitForExistence();
00061     stop_tracking_.waitForExistence();
00062     tracking_ = false;
00063 
00064     trajectory_interpolator_.reset(new TrajectoryInterpolator(root_frame_, update_rate_));
00065 
00066     action_name_ = "cartesian_trajectory_action";
00067     as_.reset(new SAS_CartesianControllerAction_t(nh_, action_name_, false));
00068     as_->registerGoalCallback(boost::bind(&CartesianController::goalCallback, this));
00069     as_->registerPreemptCallback(boost::bind(&CartesianController::preemptCallback, this));
00070     as_->start();
00071 
00072     ROS_INFO("Cartesian Controller running");
00073     return true;
00074 }
00075 
00076 // ToDo: Use the ActionInterface of the FrameTracker instead in order to be able to consider TrackingConstraints
00077 bool CartesianController::startTracking()
00078 {
00079     bool success = false;
00080     cob_srvs::SetString start;
00081     start.request.data = target_frame_;
00082     if (!tracking_)
00083     {
00084         success = start_tracking_.call(start);
00085 
00086         if (success)
00087         {
00088             success = start.response.success;
00089             if (success)
00090             {
00091                 ROS_INFO("Response 'start_tracking': succeded");
00092                 tracking_ = true;
00093             }
00094             else
00095             {
00096                 ROS_ERROR("Response 'start_tracking': failed");
00097             }
00098         }
00099         else
00100         {
00101             ROS_ERROR("Failed to call service 'start_tracking'");
00102         }
00103     }
00104     else
00105     {
00106         ROS_WARN("Already tracking");
00107     }
00108 
00109     return success;
00110 }
00111 
00112 // ToDo:: If we use the ActionInterface of the FrameTracker, here that action should be cancled()
00113 bool CartesianController::stopTracking()
00114 {
00115     bool success = false;
00116     std_srvs::Trigger stop;
00117     if (tracking_)
00118     {
00119         success = stop_tracking_.call(stop);
00120 
00121         if (success)
00122         {
00123             ROS_INFO("Service 'stop' succeded!");
00124             tracking_ = false;
00125         }
00126         else
00127         {
00128             ROS_ERROR("Failed to call service 'stop_tracking'");
00129         }
00130     }
00131     else
00132     {
00133         ROS_WARN("Have not been tracking");
00134     }
00135 
00136     return success;
00137 }
00138 
00139 // Broadcasting interpolated Cartesian path
00140 bool CartesianController::posePathBroadcaster(const geometry_msgs::PoseArray& cartesian_path)
00141 {
00142     bool success = true;
00143     ros::Rate rate(update_rate_);
00144     tf::Transform transform;
00145 
00146     for (unsigned int i = 0; i < cartesian_path.poses.size(); i++)
00147     {
00148         if (!as_->isActive())
00149         {
00150             success = false;
00151             break;
00152         }
00153 
00154         // Send/Refresh target Frame
00155         transform.setOrigin(tf::Vector3(cartesian_path.poses.at(i).position.x,
00156                                         cartesian_path.poses.at(i).position.y,
00157                                         cartesian_path.poses.at(i).position.z));
00158         transform.setRotation(tf::Quaternion(cartesian_path.poses.at(i).orientation.x,
00159                                              cartesian_path.poses.at(i).orientation.y,
00160                                              cartesian_path.poses.at(i).orientation.z,
00161                                              cartesian_path.poses.at(i).orientation.w));
00162 
00163         tf_broadcaster_.sendTransform(tf::StampedTransform(transform, ros::Time::now(), cartesian_path.header.frame_id, target_frame_));
00164 
00165         ros::spinOnce();
00166         rate.sleep();
00167     }
00168 
00169     return success;
00170 }
00171 
00172 
00173 void CartesianController::goalCallback()
00174 {
00175     geometry_msgs::PoseArray cartesian_path;
00176     cob_cartesian_controller::CartesianActionStruct action_struct;
00177 
00178     action_struct = acceptGoal(as_->acceptNewGoal());
00179 
00180     if (action_struct.move_type == cob_cartesian_controller::CartesianControllerGoal::LIN)
00181     {
00182         // Interpolate path
00183         if (!trajectory_interpolator_->linearInterpolation(cartesian_path, action_struct))
00184         {
00185             actionAbort(false, "Failed to do interpolation for 'move_lin'");
00186             return;
00187         }
00188 
00189         // Publish Preview
00190         utils_.previewPath(cartesian_path);
00191         
00192         // initially broadcast target_frame
00193         tf::Transform identity = tf::Transform();
00194         identity.setIdentity();
00195         tf_broadcaster_.sendTransform(tf::StampedTransform(identity, ros::Time::now(), chain_tip_link_, target_frame_));
00196 
00197         // Activate Tracking
00198         if (!startTracking())
00199         {
00200             actionAbort(false, "Failed to start tracking");
00201             return;
00202         }
00203 
00204         // Execute path
00205         if (!posePathBroadcaster(cartesian_path))
00206         {
00207             actionAbort(false, "Failed to execute path for 'move_lin'");
00208             return;
00209         }
00210 
00211         // De-Activate Tracking
00212         if (!stopTracking())
00213         {
00214             actionAbort(false, "Failed to stop tracking");
00215             return;
00216         }
00217 
00218         actionSuccess(true, "move_lin succeeded!");
00219     }
00220     else if (action_struct.move_type == cob_cartesian_controller::CartesianControllerGoal::CIRC)
00221     {
00222         if (!trajectory_interpolator_->circularInterpolation(cartesian_path, action_struct))
00223         {
00224             actionAbort(false, "Failed to do interpolation for 'move_circ'");
00225             return;
00226         }
00227 
00228         // Publish Preview
00229         utils_.previewPath(cartesian_path);
00230 
00231         // Activate Tracking
00232         if (!startTracking())
00233         {
00234             actionAbort(false, "Failed to start tracking");
00235             return;
00236         }
00237 
00238         // Execute path
00239         if (!posePathBroadcaster(cartesian_path))
00240         {
00241             actionAbort(false, "Failed to execute path for 'move_circ'");
00242             return;
00243         }
00244 
00245         // De-Activate Tracking
00246         if (!stopTracking())
00247         {
00248             actionAbort(false, "Failed to stop tracking");
00249             return;
00250         }
00251 
00252         actionSuccess(true, "move_circ succeeded!");
00253     }
00254     else
00255     {
00256         actionAbort(false, "Unknown trajectory action");
00257         return;
00258     }
00259 }
00260 
00261 cob_cartesian_controller::MoveLinStruct CartesianController::convertMoveLin(const cob_cartesian_controller::MoveLin& move_lin_msg)
00262 {
00263     geometry_msgs::Pose start, end;
00264     start = utils_.getPose(root_frame_, chain_tip_link_);   // current tcp pose
00265     utils_.transformPose(move_lin_msg.frame_id, root_frame_, move_lin_msg.pose_goal, end);
00266 
00267     cob_cartesian_controller::MoveLinStruct move_lin;
00268 
00269     move_lin.start = start;
00270     move_lin.end = end;
00271 
00272     return move_lin;
00273 }
00274 
00275 cob_cartesian_controller::MoveCircStruct CartesianController::convertMoveCirc(const cob_cartesian_controller::MoveCirc& move_circ_msg)
00276 {
00277     geometry_msgs::Pose center;
00278     utils_.transformPose(move_circ_msg.frame_id, root_frame_, move_circ_msg.pose_center, center);
00279 
00280     cob_cartesian_controller::MoveCircStruct move_circ;
00281     move_circ.start_angle           = move_circ_msg.start_angle;
00282     move_circ.end_angle             = move_circ_msg.end_angle;
00283     move_circ.radius                = move_circ_msg.radius;
00284 
00285     move_circ.pose_center = center;
00286 
00287     return move_circ;
00288 }
00289 
00290 cob_cartesian_controller::CartesianActionStruct CartesianController::acceptGoal(boost::shared_ptr<const cob_cartesian_controller::CartesianControllerGoal> goal)
00291 {
00292     cob_cartesian_controller::CartesianActionStruct action_struct;
00293     action_struct.move_type = goal->move_type;
00294 
00295     action_struct.profile.vel           = goal->profile.vel;
00296     action_struct.profile.accl          = goal->profile.accl;
00297     action_struct.profile.profile_type  = goal->profile.profile_type;
00298     action_struct.profile.t_ipo         = 1/update_rate_;
00299 
00300 
00301     if (action_struct.move_type == cob_cartesian_controller::CartesianControllerGoal::LIN)
00302     {
00303         action_struct.move_lin = convertMoveLin(goal->move_lin);
00304     }
00305     else if (action_struct.move_type == cob_cartesian_controller::CartesianControllerGoal::CIRC)
00306     {
00307         action_struct.move_circ = convertMoveCirc(goal->move_circ);
00308     }
00309     else
00310     {
00311         actionAbort(false, "Unknown trajectory action " + boost::lexical_cast<std::string>(action_struct.move_type));
00312     }
00313 
00314     return action_struct;
00315 }
00316 
00317 void CartesianController::preemptCallback()
00318 {
00319     // De-Activate Tracking
00320     stopTracking();
00321     actionPreempt(true, "action preempted!");
00322 }
00323 
00324 void CartesianController::actionSuccess(const bool success, const std::string& message)
00325 {
00326     ROS_INFO_STREAM("Goal succeeded: " << message);
00327     action_result_.success = success;
00328     action_result_.message = message;
00329     as_->setSucceeded(action_result_, action_result_.message);
00330 }
00331 
00332 void CartesianController::actionPreempt(const bool success, const std::string& message)
00333 {
00334     ROS_WARN_STREAM("Goal preempted: " << message);
00335     action_result_.success = success;
00336     action_result_.message = message;
00337     as_->setPreempted(action_result_, action_result_.message);
00338 }
00339 
00340 void CartesianController::actionAbort(const bool success, const std::string& message)
00341 {
00342     ROS_ERROR_STREAM("Goal aborted: "  << message);
00343     action_result_.success = success;
00344     action_result_.message = message;
00345     as_->setAborted(action_result_, action_result_.message);
00346     stopTracking();
00347 }


cob_cartesian_controller
Author(s): Christoph Mark
autogenerated on Thu Jun 6 2019 21:19:40