00001 #include "unlatching.h"
00002
00003 #include <ee_cart_imped_action/ee_cart_imped_arm.hh>
00004 #include <cmath>
00005 #include "switch_controller.h"
00006
00007
00008 DoorOpener::DoorOpener(unsigned char side):
00009 serviceServer(n.advertiseService("unlatch_door", &DoorOpener::listen, this)),
00010 pregrasp_sub(n, "pregrasp", 5),
00011 grasp_sub(n, "grasp", 5),
00012 postgrasp_sub(n, "postgrasp", 5),
00013 sync(MySyncPolicy(10), pregrasp_sub, grasp_sub, postgrasp_sub),
00014 side_(side),
00015 tool_frame_name_("/r_gripper_tool_frame"),
00016 fixed_frame_name_("/torso_lift_link"),
00017 listening_(false),
00018 started_(false)
00019 {
00020 cmd_vel_pub_= n.advertise<geometry_msgs::Twist>("/base_controller/command", 12);
00021 base_cmd.linear.x = base_cmd.linear.y = base_cmd.angular.z = 0;
00022
00023 tflistener_ = new tf::TransformListener;
00024
00025 std::string gac_name("/r_gripper_controller/gripper_action");
00026 if(side_ == 'l') gac_name[1] = side_;
00027 gripperClient = new gripActClient(gac_name.c_str(), true);
00028
00029
00030 std::string contr_name("/r_arm_cart_imped_controller");
00031 if(side_ == 'l') contr_name[1] = side_;
00032 std::cout << contr_name;
00033 arm_ = new EECartImpedArm(contr_name.c_str());
00034
00035 if(side_ == 'l') tool_frame_name_[1] = side_;
00036
00037 }
00038
00039 bool DoorOpener::listen(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
00040 {
00041 started_ = true;
00042 if(!listening_){
00043 success_ = false;
00044 listening_ = true;
00045 sync.registerCallback(boost::bind(&DoorOpener::grasp_handle, this, _1, _2, _3));
00046 }
00047 ROS_INFO("Waiting for unlatching to finish");
00048 while(ros::ok() && started_){
00049 ros::Duration(0.5).sleep();
00050 ROS_INFO_THROTTLE(30,"Still waiting for unlatching to finish");
00051 }
00052 return true;
00053 }
00054
00055 DoorOpener::~DoorOpener(){
00056 delete gripperClient;
00057 delete arm_;
00058 delete tflistener_;
00059 }
00060
00061 void DoorOpener::use_gripper(float position, float effort)
00062 {
00063 while(!gripperClient->waitForServer(ros::Duration(5.0)) && ros::ok())
00064 ROS_INFO("Should use gripper, but I am waiting for the gripper action server to come up");
00065
00066 pr2_controllers_msgs::Pr2GripperCommandGoal goal;
00067 goal.command.position = position;
00068 goal.command.max_effort = effort;
00069
00070 gripperClient->sendGoal(goal);
00071 }
00072 bool DoorOpener::wait_for_gripper(){
00073 gripperClient->waitForResult();
00074
00075 if(gripperClient->getState() == actionlib::SimpleClientGoalState::SUCCEEDED){
00076 ROS_INFO("Successfully used gripper!");
00077 return true;
00078 } else {
00079 ROS_WARN("Failed to bring gripper to desired state");
00080 return false;
00081 }
00082 }
00083
00084
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 void DoorOpener::drive_base(const ros::TimerEvent& event)
00111 {
00112 if(base_cmd.linear.x == 0 && base_cmd.linear.y == 0 && base_cmd.angular.z == 0) return;
00113
00114 cmd_vel_pub_.publish(base_cmd);
00115 }
00116
00117
00118 void DoorOpener::push_door()
00119 {
00120 float base_speed = -0.05;
00121
00122
00123 tf::Transform gripper_transform, last_gripper_transform,
00124 init_gripper_global_tf, odom_to_torso_tf ;
00125
00126
00127 last_gripper_transform = getTransform(fixed_frame_name_, tool_frame_name_);
00128
00129
00130 init_gripper_global_tf = getTransform("/odom_combined", tool_frame_name_);
00131
00132 float px,py = 0.0,pz,rx,ry,rz,rw;
00133 px = last_gripper_transform.getOrigin().getX();
00134
00135 while(fabs(py) < 0.45){
00136
00137 gripper_transform = getTransform(fixed_frame_name_, tool_frame_name_);
00138 odom_to_torso_tf = getTransform("/odom_combined",fixed_frame_name_);
00139 tf::Transform first_gripper_pose = odom_to_torso_tf.inverseTimes(init_gripper_global_tf);
00140 tf::Transform delta = first_gripper_pose.inverseTimes(gripper_transform);
00141 printTransform(first_gripper_pose, "gripper init pose in torso frame");
00142 printTransform(delta, "global delta in torso_lift");
00143
00144
00145 py = gripper_transform.getOrigin().getY();
00146 pz = gripper_transform.getOrigin().getZ();
00147 rx = gripper_transform.getRotation().getX();
00148 ry = gripper_transform.getRotation().getY();
00149 rz = gripper_transform.getRotation().getZ();
00150 rw = gripper_transform.getRotation().getW();
00151
00152
00153 tf::Transform gripper_delta_tf = last_gripper_transform.inverseTimes(gripper_transform);
00154 printTransform(gripper_delta_tf, "Linear Delta");
00155 py += gripper_delta_tf.getOrigin().getY()*23;
00156 if(gripper_delta_tf.getOrigin().getX() < 0.0001) ROS_WARN("Door not moving further");
00157
00158
00159 ee_cart_imped_msgs::EECartImpedGoal pushDoor;
00160 EECartImpedArm::addTrajectoryPoint(pushDoor, px,py,pz, rx, ry, rz, rw,
00161 1000, 550, 1000,
00162 30, 30, 1,
00163 false, true, false, false, false,false,
00164 0.50,fixed_frame_name_);
00165
00166 base_cmd.linear.x = base_speed;
00167
00168 arm_->startTrajectory(pushDoor);
00169 last_gripper_transform = gripper_transform;
00170 py = gripper_transform.getOrigin().getY();
00171 }
00172 base_cmd.linear.x = 0.0;
00173
00174
00175
00176
00177
00178
00179
00180 ROS_INFO("Gripper is outside of robot footprint" );
00181 }
00182
00183
00184 void DoorOpener::home_position()
00185 {
00186 ee_cart_imped_msgs::EECartImpedGoal homePos;
00187
00188 tf::Quaternion r(tf::Vector3(1,0,0), -M_PI/2.0);
00189 float y = side_ == 'l'? 0.2 : -0.4;
00190 EECartImpedArm::addTrajectoryPoint(homePos, 0.35, y,-0.10, r.getX(), r.getY(), r.getZ(), r.getW(),
00191 100, 1000, 100, 3, 3, 3,
00192 false, false, false, false, false,false,
00193 2,fixed_frame_name_);
00194 arm_->startTrajectory(homePos);
00195 }
00196
00197
00198 void DoorOpener::withdraw(float meters)
00199 {
00200 tf::StampedTransform gripper_transform(getTransform(fixed_frame_name_, tool_frame_name_));
00201 tf::Vector3 gripperBackward(-meters, 0,0);
00202 gripperBackward = gripper_transform * gripperBackward;
00203
00204 float px,py,pz,rx,ry,rz,rw;
00205 px = gripperBackward.getX();
00206 py = gripperBackward.getY();
00207 pz = gripperBackward.getZ();
00208
00209 rx = gripper_transform.getRotation().getX();
00210 ry = gripper_transform.getRotation().getY();
00211 rz = gripper_transform.getRotation().getZ();
00212 rw = gripper_transform.getRotation().getW();
00213
00214 ee_cart_imped_msgs::EECartImpedGoal withdrawTraj;
00215 EECartImpedArm::addTrajectoryPoint(withdrawTraj, px,py,pz, rx, ry, rz, rw,
00216 1000, 1000, 1000, 1, 1, 1,
00217 false, false, false, false, false,false,
00218 1.5,fixed_frame_name_);
00219 arm_->startTrajectory(withdrawTraj);
00220 }
00221
00222
00223 void DoorOpener::grasp_handle(const geometry_msgs::PoseStamped::ConstPtr a_pregrasp,
00224 const geometry_msgs::PoseStamped::ConstPtr a_grasp,
00225 const geometry_msgs::PoseStamped::ConstPtr a_postgrasp)
00226 {
00227 if(!started_) return;
00228 ROS_INFO("Got grasping poses");
00229 geometry_msgs::Pose postgrasp = (*a_postgrasp).pose;
00230 geometry_msgs::Pose pregrasp = (*a_pregrasp).pose;
00231 geometry_msgs::Pose grasp = (*a_grasp).pose;
00232
00233 std::string desired_controller("x_arm_cart_imped_controller");
00234 desired_controller[0] = side_;
00235 std::string undesired_controller("x_arm_controller");
00236 undesired_controller[0] = side_;
00237 ROS_WARN_COND(!load_controller(desired_controller), "Could not load %s, May already be loaded.", desired_controller.c_str());
00238 int failure_count = 0;
00239 while(!switch_controller(desired_controller, undesired_controller))
00240 {
00241 failure_count++;
00242 if(failure_count > 10){
00243 success_ = false;
00244 return;
00245 }
00246
00247 ROS_ERROR("Could not switch to %s. Waiting 2 sec before retrying. (%d/10 times)", desired_controller.c_str(), failure_count);
00248 ros::Duration(2).sleep();
00249 if(!load_controller(desired_controller)){
00250 ROS_DEBUG("Could not (re-)load %s, May already be loaded.", desired_controller.c_str());
00251 }
00252
00253 }
00254
00255 ee_cart_imped_msgs::EECartImpedGoal toPregrasp, toGrasp, toPostgrasp, backToGrasp;
00256
00257 ROS_INFO("opening right gripper");
00258 use_gripper(0.08, -1.0 );
00259
00260 EECartImpedArm::addTrajectoryPoint(toPregrasp, pregrasp.position.x,pregrasp.position.y,pregrasp.position.z,
00261 pregrasp.orientation.x, pregrasp.orientation.y, pregrasp.orientation.z, pregrasp.orientation.w,
00262 1000, 1000, 1000,
00263 30, 30, 30,
00264 false, false, false,
00265 false, false,false,
00266 4,fixed_frame_name_);
00267 {
00268 EECartImpedClient* traj_client = arm_->startTrajectory(toPregrasp);
00269 actionlib::SimpleClientGoalState state = traj_client->getState();
00270 if (state != actionlib::SimpleClientGoalState::SUCCEEDED)
00271 return;
00272 }
00273 if( !wait_for_gripper()) return;
00274
00275 EECartImpedArm::addTrajectoryPoint(toGrasp, grasp.position.x,grasp.position.y,grasp.position.z,
00276 grasp.orientation.x, grasp.orientation.y, grasp.orientation.z, grasp.orientation.w,
00277 1000, 1000, 1000,
00278 30, 30, 30,
00279 false, false, false,
00280 false, false,false,
00281 1,fixed_frame_name_);
00282 {
00283 EECartImpedClient* traj_client = arm_->startTrajectory(toGrasp);
00284 actionlib::SimpleClientGoalState state = traj_client->getState();
00285 if (state != actionlib::SimpleClientGoalState::SUCCEEDED)
00286 return;
00287 }
00288
00289 ROS_INFO("closing right gripper");
00290 use_gripper(0.005, 50.0 );
00291 if(wait_for_gripper()){
00292 ROS_WARN("Closed completely. Missed handle?");
00293 }
00294
00295 EECartImpedArm::addTrajectoryPoint(toPostgrasp, postgrasp.position.x,postgrasp.position.y,postgrasp.position.z,
00296 postgrasp.orientation.x, postgrasp.orientation.y, postgrasp.orientation.z, postgrasp.orientation.w,
00297 500, 100, 100,
00298 70, 70, 70,
00299 false, false, false,
00300 false, false,false,
00301 2,fixed_frame_name_);
00302 {
00303 EECartImpedClient* traj_client = arm_->startTrajectory(toPostgrasp);
00304 actionlib::SimpleClientGoalState state = traj_client->getState();
00305 if (state == actionlib::SimpleClientGoalState::SUCCEEDED)
00306 success_ = true;
00307 }
00308 use_gripper(0.08, -1 );
00309
00310 EECartImpedArm::addTrajectoryPoint(backToGrasp, grasp.position.x,grasp.position.y,grasp.position.z,
00311 grasp.orientation.x, grasp.orientation.y, grasp.orientation.z, grasp.orientation.w,
00312 500, 500, 500,
00313 20, 20, 20,
00314 false, false, false,
00315 false, false,false,
00316 2,fixed_frame_name_);
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 {
00327 EECartImpedClient* traj_client = arm_->startTrajectory(backToGrasp);
00328 actionlib::SimpleClientGoalState state = traj_client->getState();
00329 }
00330 wait_for_gripper();
00331
00332
00333
00334
00335
00336
00337 swing_door(*a_grasp);
00338 started_ = false;
00339 }
00340
00341 tf::StampedTransform DoorOpener::getTransform(const std::string& from, const std::string& to){
00342 tf::StampedTransform transform;
00343 ros::Time now = ros::Time::now();
00344 while(!tflistener_->waitForTransform(from, to,now, ros::Duration(6.0/30.0))){
00345 ROS_WARN_STREAM("No tranform from "<<from<<" to "<<to<<" available, when getting initial gripper position");
00346 }
00347 tflistener_->lookupTransform(from, to, now, transform);
00348 return transform;
00349 }
00350
00351 void DoorOpener::addTrajectoryPoint(ee_cart_imped_msgs::EECartImpedGoal& msg, tf::Transform pose, float fx, float fy, float fz, float tx, float ty, float tz, float time, std::string frame_id)
00352 {
00353 EECartImpedArm::addTrajectoryPoint(msg,
00354 pose.getOrigin().getX(), pose.getOrigin().getY(), pose.getOrigin().getZ(),
00355 pose.getRotation().getX(), pose.getRotation().getY(), pose.getRotation().getZ(), pose.getRotation().getW(),
00356 fx, fy, fz,
00357 tx, ty, tz,
00358 false, false, false,
00359 false, false,false,
00360 time, frame_id);
00361
00362 }
00363
00364 bool DoorOpener::swing_door(geometry_msgs::PoseStamped start_pose)
00365 {
00366 tf::Stamped<tf::Transform> tf_start_pose_stamped;
00367 tf::Transform tf_start_pose;
00368 tf::poseStampedMsgToTF(start_pose, tf_start_pose_stamped);
00369 tf::Transform tf_centerwards(tf::Quaternion(0,0,0,1), tf::Vector3(0,0,0.20));
00370 tf_start_pose = tf_start_pose_stamped * tf_centerwards;
00371 tf::Transform tf_forward(tf::Quaternion(0,0,0,1), tf::Vector3(0.1,0,0));
00372 tf::Transform tf_touch_pose = tf_start_pose * tf_forward;
00373 tf::Transform tf_fast_forward(tf::Quaternion(0,0,0,1), tf::Vector3(0.24,0,0));
00374 tf::Transform tf_swing_pose = tf_start_pose * tf_fast_forward;
00375
00376 ee_cart_imped_msgs::EECartImpedGoal door;
00377
00378
00379 tf::Quaternion r(tf::Vector3(0,1,0), -M_PI/2.0);
00380 addTrajectoryPoint(door, tf_start_pose, 1000, 1000, 1000, 30, 30, 30, 2, start_pose.header.frame_id);
00381 addTrajectoryPoint(door, tf_touch_pose, 100, 100, 100, 30, 30, 30, 6, start_pose.header.frame_id);
00382 addTrajectoryPoint(door, tf_swing_pose, 1000, 1000, 1000, 30, 30, 30, 7, start_pose.header.frame_id);
00383 addTrajectoryPoint(door, tf_start_pose, 1000, 1000, 1000, 30, 30, 30, 10, start_pose.header.frame_id);
00384
00385
00386 EECartImpedClient* traj_client = arm_->startTrajectory(door);
00387 actionlib::SimpleClientGoalState state = traj_client->getState();
00388 return true;
00389 }
00390 void printTransform(const tf::Transform& t, const std::string& name){
00391 float px = t.getOrigin().getX();
00392 float py = t.getOrigin().getY();
00393 float pz = t.getOrigin().getZ();
00394 float rx = t.getRotation().getX();
00395 float ry = t.getRotation().getY();
00396 float rz = t.getRotation().getZ();
00397 float rw = t.getRotation().getW();
00398 ROS_INFO_STREAM("Transformation "<<name<<": ("<<px<<", "<<py<<", "<<pz<<") ["<<rx<<", "<<ry<<", "<<rz<<", "<<rw<<"]");
00399 }