ee_cart_imped_action.cpp
Go to the documentation of this file.
00001 //For function comments, see ee_cart_imped_action.hh
00002 //Written by heavily borrowing from joint_trajectory_action.
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   //pick up all the constraints from the parameter server
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   //this is published by the controller
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   //is the controller started?
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     //sub_controller_state_.shutdown();
00079     watchdog_timer_.stop();
00080 }
00081 
00082 void EECartImpedExecuter::watchdog(const ros::TimerEvent &e) {
00083   ros::Time now = ros::Time::now();
00084   
00085   // Aborts the active goal if the controller does not appear to be active.
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       // Stops the controller.
00100       ee_cart_imped_msgs::EECartImpedGoal empty;
00101       pub_controller_command_.publish(empty);
00102       
00103       // Marks the current goal as aborted.
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 //a new goal! so exciting
00117 void EECartImpedExecuter::goalCB(GoalHandle gh) {
00118 
00119   //should probably do sqome checking to make sure
00120   //this is a reasonable goal
00121   
00122   // Cancels the currently active goal.
00123   if (has_active_goal_) {
00124     // Stops the controller.
00125     ee_cart_imped_msgs::EECartImpedGoal empty;
00126     pub_controller_command_.publish(empty);
00127     // Marks the current goal as canceled.
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   //re-interpret this in the frame of the root name
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   // Sends the trajectory along to the controller
00187   pub_controller_command_.publish(current_traj_);
00188 }
00189 
00190 void EECartImpedExecuter::cancelCB(GoalHandle gh) {
00191   if (active_goal_ == gh) {
00192     // Stops the controller.
00193     ee_cart_imped_msgs::EECartImpedGoal empty;
00194     pub_controller_command_.publish(empty);
00195     
00196     // Marks the current goal as canceled.
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   //check to make sure we're within constraints
00223   if (!checkConstraints(msg, trajectory_constraints_, 
00224                         trajectory_effort_constraint_)) {
00225     //stop the controller
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     //are we at the goal?
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   //since the quaternion is the same negative and positive
00291   //we check both
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   //check the forces
00361   //if we care about them
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 }


ee_cart_imped_action
Author(s): Jenny Barry, Mario Bollini, and Huan Liu
autogenerated on Sun Jan 5 2014 11:14:46