00001
00002
00003
00004 #include <ee_cart_imped_action/ee_cart_imped_action.hh>
00005
00006 EECartImpedExecuter::EECartImpedExecuter(ros::NodeHandle &n) :
00007 node_(n),
00008 action_server_(node_, "ee_cart_imped_action",
00009 boost::bind(&EECartImpedExecuter::goalCB, this, _1),
00010 boost::bind(&EECartImpedExecuter::cancelCB, this, _1),
00011 false),
00012 has_active_goal_(false) {
00013
00014 ros::NodeHandle pn("~");
00015
00016
00017 pn.param("constraints/goal/time", goal_time_constraint_, 0.0);
00018 pn.param("constraints/goal/position/x", goal_constraints_.position.x, -1.0);
00019 pn.param("constraints/goal/position/y", goal_constraints_.position.y, -1.0);
00020 pn.param("constraints/goal/position/z", goal_constraints_.position.z, -1.0);
00021 pn.param("constraints/goal/orientation/x", goal_constraints_.orientation.x,
00022 -1.0);
00023 pn.param("constraints/goal/orientation/y", goal_constraints_.orientation.y,
00024 -1.0);
00025 pn.param("constraints/goal/orientation/z", goal_constraints_.orientation.z,
00026 -1.0);
00027 pn.param("constraints/goal/orientation/w", goal_constraints_.orientation.w,
00028 -1.0);
00029 pn.param("constraints/goal/effort", goal_effort_constraint_, -1.0);
00030 pn.param("constraints/trajectory/position/x",
00031 trajectory_constraints_.position.x, -1.0);
00032 pn.param("constraints/trajectory/position/y",
00033 trajectory_constraints_.position.y, -1.0);
00034 pn.param("constraints/trajectory/position/z",
00035 trajectory_constraints_.position.z, -1.0);
00036 pn.param("constraints/trajectory/orientation/x",
00037 trajectory_constraints_.orientation.x, -1.0);
00038 pn.param("constraints/trajectory/orientation/y",
00039 trajectory_constraints_.orientation.y, -1.0);
00040 pn.param("constraints/trajectory/orientation/z",
00041 trajectory_constraints_.orientation.z, -1.0);
00042 pn.param("constraints/trajectory/orientation/w",
00043 trajectory_constraints_.orientation.w, -1.0);
00044 pn.param("constraints/trajectory/effort", trajectory_effort_constraint_,
00045 -1.0);
00046 pn.param("root_name", controller_frame_id_, std::string("/torso_lift_link"));
00047
00048 pub_controller_command_ =
00049 node_.advertise<ee_cart_imped_msgs::EECartImpedGoal>
00050 ("command", 1);
00051
00052 sub_controller_state_ =
00053 node_.subscribe("state", 1,
00054 &EECartImpedExecuter::controllerStateCB, this);
00055 watchdog_timer_ =
00056 node_.createTimer(ros::Duration(1.0), &EECartImpedExecuter::watchdog, this);
00057
00058
00059 ros::Time started_waiting_for_controller = ros::Time::now();
00060 while (ros::ok() && !last_controller_state_) {
00061 ros::spinOnce();
00062 if (started_waiting_for_controller != ros::Time(0) &&
00063 ros::Time::now() > started_waiting_for_controller +
00064 ros::Duration(30.0)) {
00065 ROS_WARN("Waited for the controller for 30 seconds, but it never showed up.");
00066 started_waiting_for_controller = ros::Time(0);
00067 }
00068 ros::Duration(0.1).sleep();
00069 }
00070
00071 action_server_.start();
00072 ROS_DEBUG("ee_cart_imped_action server started");
00073 }
00074
00075
00076 EECartImpedExecuter::~EECartImpedExecuter() {
00077 pub_controller_command_.shutdown();
00078
00079 watchdog_timer_.stop();
00080 }
00081
00082 void EECartImpedExecuter::watchdog(const ros::TimerEvent &e) {
00083 ros::Time now = ros::Time::now();
00084
00085
00086 if (has_active_goal_) {
00087 bool should_abort = false;
00088 if (!last_controller_state_) {
00089 should_abort = true;
00090 ROS_WARN("Aborting goal because we have never heard a controller state message.");
00091 } else if ((now - last_controller_state_->header.stamp) >
00092 ros::Duration(5.0)) {
00093 should_abort = true;
00094 ROS_WARN("Aborting goal because we haven't heard from the controller in %.3lf seconds",
00095 (now - last_controller_state_->header.stamp).toSec());
00096 }
00097
00098 if (should_abort) {
00099
00100 ee_cart_imped_msgs::EECartImpedGoal empty;
00101 pub_controller_command_.publish(empty);
00102
00103
00104 result_.success = false;
00105 if (last_controller_state_) {
00106 result_.desired = last_controller_state_->desired;
00107 result_.actual_pose = last_controller_state_->actual_pose.pose;
00108 result_.effort_sq_error = last_controller_state_->effort_sq_error;
00109 }
00110 active_goal_.setAborted(result_);
00111 has_active_goal_ = false;
00112 }
00113 }
00114 }
00115
00116
00117 void EECartImpedExecuter::goalCB(GoalHandle gh) {
00118
00119
00120
00121
00122
00123 if (has_active_goal_) {
00124
00125 ee_cart_imped_msgs::EECartImpedGoal empty;
00126 pub_controller_command_.publish(empty);
00127
00128 result_.success = false;
00129 if (last_controller_state_) {
00130 result_.desired = last_controller_state_->desired;
00131 result_.actual_pose = last_controller_state_->actual_pose.pose;
00132 result_.effort_sq_error = last_controller_state_->effort_sq_error;
00133 }
00134 active_goal_.setCanceled(result_);
00135 has_active_goal_ = false;
00136 }
00137
00138 current_traj_ = *(gh.getGoal());
00139
00140
00141 ROS_DEBUG("Checking header");
00142 ee_cart_imped_msgs::EECartImpedGoal transformed_traj;
00143 transformed_traj.header.frame_id = controller_frame_id_;
00144 transformed_traj.header.stamp = current_traj_.header.stamp;
00145 for (size_t i = 0; i < current_traj_.trajectory.size(); i++) {
00146 ee_cart_imped_msgs::StiffPoint &currpt = current_traj_.trajectory[i];
00147 if (currpt.header.frame_id.compare(controller_frame_id_) &&
00148 !currpt.header.frame_id.empty()) {
00149 ROS_DEBUG("Converting from %s to %s", currpt.header.frame_id.c_str(),
00150 controller_frame_id_.c_str());
00151 geometry_msgs::PoseStamped orig, trans;
00152 ee_cart_imped_msgs::StiffPoint transpt;
00153 transpt.header.stamp = orig.header.stamp;
00154 orig.header.frame_id = currpt.header.frame_id;
00155 orig.header.stamp = ros::Time(0);
00156 orig.pose = currpt.pose;
00157 trans.header.frame_id = controller_frame_id_;
00158 trans.header.stamp = ros::Time(0);
00159 try {
00160 tf_listener.transformPose(controller_frame_id_, orig, trans);
00161 } catch (tf::TransformException ex) {
00162 ROS_ERROR("ee_cart_imped_action could not transform point. Error was %s", ex.what());
00163 return;
00164 }
00165 transpt.header.frame_id = trans.header.frame_id;
00166 transpt.pose = trans.pose;
00167 transpt.wrench_or_stiffness = currpt.wrench_or_stiffness;
00168 transpt.isForceX = currpt.isForceX;
00169 transpt.isForceY = currpt.isForceY;
00170 transpt.isForceZ = currpt.isForceZ;
00171 transpt.isTorqueX = currpt.isTorqueX;
00172 transpt.isTorqueY = currpt.isTorqueY;
00173 transpt.isTorqueZ = currpt.isTorqueZ;
00174 transpt.time_from_start = currpt.time_from_start;
00175 transformed_traj.trajectory.push_back(transpt);
00176 } else {
00177 ROS_DEBUG("Point frame id was %s and controller frame id is %s. No need to transform", currpt.header.frame_id.c_str(), controller_frame_id_.c_str());
00178 transformed_traj.trajectory.push_back(currpt);
00179 }
00180 }
00181 current_traj_ = transformed_traj;
00182
00183 gh.setAccepted();
00184 active_goal_ = gh;
00185 has_active_goal_ = true;
00186
00187 pub_controller_command_.publish(current_traj_);
00188 }
00189
00190 void EECartImpedExecuter::cancelCB(GoalHandle gh) {
00191 if (active_goal_ == gh) {
00192
00193 ee_cart_imped_msgs::EECartImpedGoal empty;
00194 pub_controller_command_.publish(empty);
00195
00196
00197 result_.success = false;
00198 if (last_controller_state_) {
00199 result_.desired = last_controller_state_->desired;
00200 result_.actual_pose = last_controller_state_->actual_pose.pose;
00201 result_.effort_sq_error = last_controller_state_->effort_sq_error;
00202 }
00203 active_goal_.setCanceled(result_);
00204 has_active_goal_ = false;
00205 }
00206 }
00207
00208 void EECartImpedExecuter::controllerStateCB
00209 (const ee_cart_imped_msgs::EECartImpedFeedbackConstPtr &msg) {
00210 last_controller_state_ = msg;
00211 ros::Time now = ros::Time::now();
00212
00213 if (!has_active_goal_) {
00214 return;
00215 }
00216 if (current_traj_.trajectory.empty()) {
00217 return;
00218 }
00219
00220 active_goal_.publishFeedback(*msg);
00221
00222
00223 if (!checkConstraints(msg, trajectory_constraints_,
00224 trajectory_effort_constraint_)) {
00225
00226 ee_cart_imped_msgs::EECartImpedGoal empty;
00227 pub_controller_command_.publish(empty);
00228 result_.success = false;
00229 result_.desired = msg->desired;
00230 result_.actual_pose = msg->actual_pose.pose;
00231 result_.effort_sq_error = msg->effort_sq_error;
00232 active_goal_.setAborted(result_);
00233 has_active_goal_ = false;
00234 ROS_WARN("Trajectory constraints violated: aborting!");
00235 return;
00236 }
00237
00238 ros::Time end_time = current_traj_.header.stamp +
00239 current_traj_.trajectory[current_traj_.trajectory.size()-1].time_from_start;
00240 if (now >= end_time) {
00241
00242 if (checkConstraints(msg, goal_constraints_,
00243 goal_effort_constraint_)) {
00244 result_.success = true;
00245 result_.desired = msg->desired;
00246 result_.actual_pose = msg->actual_pose.pose;
00247 result_.effort_sq_error = msg->effort_sq_error;
00248 active_goal_.setSucceeded(result_);
00249 has_active_goal_ = false;
00250 } else if (now >= end_time + ros::Duration(goal_time_constraint_)) {
00251 ROS_WARN("Did not make goal position");
00252 result_.success = false;
00253 result_.desired = msg->desired;
00254 result_.actual_pose = msg->actual_pose.pose;
00255 result_.effort_sq_error = msg->effort_sq_error;
00256 active_goal_.setAborted(result_);
00257 has_active_goal_ = false;
00258 }
00259 }
00260 }
00261
00262 bool EECartImpedExecuter::checkConstraints
00263 (const ee_cart_imped_msgs::EECartImpedFeedbackConstPtr &msg,
00264 geometry_msgs::Pose pose_constraints, double effort_constraint) {
00265 if (!msg->desired.isForceX && pose_constraints.position.x >= 0 &&
00266 fabs(msg->actual_pose.pose.position.x - msg->desired.pose.position.x)
00267 > pose_constraints.position.x) {
00268 ROS_WARN("Violated constraint in x; actual %lf, desired %lf, constraint %lf",
00269 msg->actual_pose.pose.position.x, msg->desired.pose.position.x,
00270 pose_constraints.position.x);
00271 return false;
00272 }
00273 if (!msg->desired.isForceY && pose_constraints.position.y >= 0 &&
00274 fabs(msg->actual_pose.pose.position.y - msg->desired.pose.position.y)
00275 > pose_constraints.position.y) {
00276 ROS_WARN("Violated constraint in y; actual %lf, desired %lf, constraint %lf",
00277 msg->actual_pose.pose.position.y, msg->desired.pose.position.y,
00278 pose_constraints.position.y);
00279 return false;
00280 }
00281 if (!msg->desired.isForceZ && pose_constraints.position.z >= 0 &&
00282 fabs(msg->actual_pose.pose.position.z - msg->desired.pose.position.z)
00283 > pose_constraints.position.z) {
00284 ROS_WARN("Violated constraint in z; actual %lf, desired %lf, constraint %lf",
00285 msg->actual_pose.pose.position.z, msg->desired.pose.position.z,
00286 pose_constraints.position.z);
00287
00288 return false;
00289 }
00290
00291
00292 bool neg_close = true, pos_close = true;
00293 if (!msg->desired.isTorqueY && !msg->desired.isTorqueZ &&
00294 pose_constraints.orientation.x >= 0 &&
00295 fabs(msg->actual_pose.pose.orientation.x - msg->desired.pose.orientation.x)
00296 > pose_constraints.orientation.x) {
00297 pos_close = false;
00298 }
00299 if (!msg->desired.isTorqueY && !msg->desired.isTorqueZ &&
00300 pose_constraints.orientation.x >= 0 &&
00301 fabs(msg->actual_pose.pose.orientation.x + msg->desired.pose.orientation.x)
00302 > pose_constraints.orientation.x) {
00303 neg_close = false;
00304 }
00305 if (!msg->desired.isTorqueX && !msg->desired.isTorqueZ &&
00306 pose_constraints.orientation.y >= 0 &&
00307 fabs(msg->actual_pose.pose.orientation.y - msg->desired.pose.orientation.y)
00308 > pose_constraints.orientation.y) {
00309 pos_close = false;
00310 }
00311 if (!msg->desired.isTorqueX && !msg->desired.isTorqueZ &&
00312 pose_constraints.orientation.y >= 0 &&
00313 fabs(msg->actual_pose.pose.orientation.y + msg->desired.pose.orientation.y)
00314 > pose_constraints.orientation.y) {
00315 neg_close = false;
00316 }
00317 if (!msg->desired.isTorqueX && !msg->desired.isTorqueY &&
00318 pose_constraints.orientation.z >= 0 &&
00319 fabs(msg->actual_pose.pose.orientation.z - msg->desired.pose.orientation.z)
00320 > pose_constraints.orientation.z) {
00321 pos_close = false;
00322 }
00323 if (!msg->desired.isTorqueX && !msg->desired.isTorqueY &&
00324 pose_constraints.orientation.z >= 0 &&
00325 fabs(msg->actual_pose.pose.orientation.z + msg->desired.pose.orientation.z)
00326 > pose_constraints.orientation.z) {
00327 neg_close = false;
00328 }
00329 if (!msg->desired.isTorqueX && !msg->desired.isTorqueY &&
00330 !msg->desired.isTorqueZ &&
00331 pose_constraints.orientation.w >= 0 &&
00332 fabs(msg->actual_pose.pose.orientation.w - msg->desired.pose.orientation.w)
00333 > pose_constraints.orientation.w) {
00334 pos_close = false;
00335 }
00336 if (!msg->desired.isTorqueX && !msg->desired.isTorqueY &&
00337 !msg->desired.isTorqueZ &&
00338 pose_constraints.orientation.w >= 0 &&
00339 fabs(msg->actual_pose.pose.orientation.w + msg->desired.pose.orientation.w)
00340 > pose_constraints.orientation.w) {
00341 neg_close = false;
00342 }
00343 if (!neg_close && !pos_close) {
00344 ROS_WARN("Unable to achieve constraint in orientation. Desired: ox = %lf, oy = %lf, oz = %lf, ow = %lf. Actual: ox = %lf, oy = %lf, oz = %lf, ow = %lf. Pose_Constraints: ox = %lf, oy = %lf, oz = %lf, ow = %lf",
00345 msg->desired.pose.orientation.x,
00346 msg->desired.pose.orientation.y,
00347 msg->desired.pose.orientation.z,
00348 msg->desired.pose.orientation.w,
00349 msg->actual_pose.pose.orientation.x,
00350 msg->actual_pose.pose.orientation.y,
00351 msg->actual_pose.pose.orientation.z,
00352 msg->actual_pose.pose.orientation.w,
00353 pose_constraints.orientation.x,
00354 pose_constraints.orientation.y,
00355 pose_constraints.orientation.z,
00356 pose_constraints.orientation.w);
00357 return false;
00358 }
00359
00360
00361
00362 bool check_forces = (msg->desired.isForceX ||
00363 msg->desired.isForceY ||
00364 msg->desired.isForceZ ||
00365 msg->desired.isTorqueX ||
00366 msg->desired.isTorqueY ||
00367 msg->desired.isTorqueZ);
00368 if (check_forces && effort_constraint >= 0 &&
00369 (msg->effort_sq_error > effort_constraint)) {
00370 ROS_WARN("Violated effort constraint; error: %lf, constraint: %lf",
00371 msg->effort_sq_error, effort_constraint);
00372 return false;
00373 }
00374 return true;
00375 }
00376
00377 int main(int argc, char** argv) {
00378 ros::init(argc, argv, "ee_cart_imped_action");
00379 ros::NodeHandle node;
00380 EECartImpedExecuter ecie(node);
00381
00382 ros::spin();
00383
00384 return 0;
00385 }