$search
00001 /* 00002 * Copyright (c) 2010, Thomas Ruehr <ruehr@cs.tum.edu> 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of Willow Garage, Inc. nor the names of its 00014 * contributors may be used to endorse or promote products derived from 00015 * this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 00030 #include <ias_drawer_executive/RobotDriver.h> 00031 #include <ias_drawer_executive/RobotArm.h> 00032 #include <ias_drawer_executive/Geometry.h> 00033 00034 #include <ias_drawer_executive/Poses.h> 00035 00036 #include <sensor_msgs/point_cloud_conversion.h> 00037 00038 RobotDriver::RobotDriver() 00039 { 00040 //set up the publisher for the cmd_vel topic 00041 cmd_vel_pub_ = nh_.advertise<geometry_msgs::Twist>("/navigation/cmd_vel", 1); 00042 subScan_ = nh_.subscribe("base_scan", 10, &RobotDriver::scanCallback, this); 00043 projector_ = 0; 00044 weHaveScan = false; 00045 } 00046 00047 RobotDriver *RobotDriver::getInstance() 00048 { 00049 if (!instance) 00050 instance = new RobotDriver(); 00051 return instance; 00052 } 00053 00054 void RobotDriver::scanCallback(const sensor_msgs::LaserScan::ConstPtr& scan_in) 00055 { 00056 if (!projector_) 00057 projector_ = new laser_geometry::LaserProjection(); 00058 00059 scan_mutex.lock(); 00060 sensor_msgs::PointCloud scan_cloud; 00061 projector_->projectLaser(*scan_in,scan_cloud); 00062 int step = 1; 00063 for (size_t k = 0; k < scan_cloud.points.size(); k += step) 00064 { 00065 scanPoints[k/step][0] = scan_cloud.points[k].x; 00066 scanPoints[k/step][1] = scan_cloud.points[k].y; 00067 numScanPoints = k / step; 00068 //ROS_INFO("SCAN POINTS : %i %f %f",numScanPoints, scanPoints[k/step][0], scanPoints[k/step][1]); 00069 } 00070 scan_mutex.unlock(); 00071 weHaveScan = true; 00072 } 00073 00074 bool RobotDriver::checkCollision(double relativePose[]) 00075 { 00076 ros::Rate rate(10); 00077 while (!weHaveScan) 00078 { 00079 rate.sleep(); 00080 ros::spinOnce(); 00081 } 00082 scan_mutex.lock(); 00083 ROS_INFO("SCAN POINTS : %zu POSE : %f %f",numScanPoints, relativePose[0], relativePose[1] ); 00084 bool good = true; 00085 double padding = 0.05; 00086 for (size_t k = 0; good && (k < numScanPoints); k += 1) 00087 { 00088 double x = scanPoints[k][0] + relativePose[0] + 0.275; 00089 double y = scanPoints[k][1] + relativePose[1]; 00090 if ((x < .325 + padding) && (x > -.325 - padding) && (y < .325 + padding) && (y > -.325 - padding)) 00091 { 00092 //ROS_INFO("POINT %f %f", scanPoints[k][0] , scanPoints[k][1]); 00093 good = false; 00094 } 00095 } 00096 scan_mutex.unlock(); 00097 return good; 00098 } 00099 00100 bool RobotDriver::checkCollision(tf::Stamped<tf::Pose> target) 00101 { 00102 tf::Stamped<tf::Pose> inBase = Geometry::getPoseIn("base_link",target); 00103 double relativePose[2]; 00104 relativePose[0] = -inBase.getOrigin().x(); 00105 relativePose[1] = -inBase.getOrigin().y(); 00106 return checkCollision(relativePose); 00107 } 00108 00109 void RobotDriver::getRobotPose(tf::Stamped<tf::Pose> &marker) 00110 { 00111 tf::StampedTransform transform; 00112 00113 listener_.waitForTransform("map", "base_link", 00114 ros::Time(0), ros::Duration(30.0)); 00115 try 00116 { 00117 listener_.lookupTransform("map", "base_link",ros::Time(0), transform); 00118 } 00119 catch (tf::TransformException ex) 00120 { 00121 ROS_ERROR("%s",ex.what()); 00122 } 00123 tf::Stamped<tf::Pose> ret; 00124 ret.frame_id_ = transform.frame_id_; 00125 ret.stamp_ = transform.stamp_; 00126 ret.setOrigin(transform.getOrigin()); 00127 ret.setRotation(transform.getRotation()); 00128 //marker = transform; 00129 marker = ret; 00130 } 00131 00132 void RobotDriver::QuaternionToEuler(const btQuaternion &TQuat, btVector3 &TEuler) 00133 { 00134 btScalar W = TQuat.getW(); 00135 btScalar X = TQuat.getX(); 00136 btScalar Y = TQuat.getY(); 00137 btScalar Z = TQuat.getZ(); 00138 double WSquared = W * W; 00139 double XSquared = X * X; 00140 double YSquared = Y * Y; 00141 double ZSquared = Z * Z; 00142 TEuler.setX(atan2f(2.0f * (Y * Z + X * W), -XSquared - YSquared + ZSquared + WSquared)); 00143 TEuler.setY(asinf(-2.0f * (X * Z - Y * W))); 00144 TEuler.setZ(atan2f(2.0f * (X * Y + Z * W), XSquared - YSquared - ZSquared + WSquared)); 00145 // TEuler *= RADTODEG; 00146 } 00147 00148 bool RobotDriver::driveInMap(tf::Stamped<tf::Pose> targetPoseMap,bool exitWhenStuck) 00149 { 00150 00151 tf::Stamped<tf::Pose> targetPoseBase; 00152 00153 tf::Stamped<tf::Pose> startPose; 00154 getRobotPose(startPose); 00155 00156 btVector3 diff = targetPoseMap.getOrigin() - startPose.getOrigin(); 00157 //we dont move in z 00158 diff = btVector3(diff.x(), diff.y(), 0); 00159 double dist = diff.length(); 00160 ROS_INFO("DISTANCE TO TRAVEL %f", dist); 00161 00162 //if (dist < 0.01) 00163 //return true; 00164 00165 ROS_INFO("diff unnorm %f %f %f ", diff.x(),diff.y(),diff.z()); 00166 if (dist != 0) 00167 diff = (diff * ( 1.0 / dist)) ; 00168 ROS_INFO("diff norm %f %f %f ", diff.x(),diff.y(),diff.z()); 00169 btVector3 rel = (dist + 0.05) * diff; 00170 ROS_INFO("new target in base %f %f", rel.x(), rel.y()); 00171 00172 ROS_INFO("TPM before adjust %f %f ", targetPoseMap.getOrigin().x(), targetPoseMap.getOrigin().y()); 00173 targetPoseMap.setOrigin(startPose.getOrigin() + (dist + 0.02) * diff); 00174 ROS_INFO("TPM after adjust %f %f", targetPoseMap.getOrigin().x(), targetPoseMap.getOrigin().y()); 00175 00176 bool done = false; 00177 bool doneBad = false; 00178 int cnt = 0; 00179 int cntbad = 0; 00180 double lastDistMoved = 0; 00181 00182 ROS_INFO("TARGET POSE IN MAP %f %f", targetPoseMap.getOrigin().x(), targetPoseMap.getOrigin().y()); 00183 00184 while (ros::ok() && !done) 00185 { 00186 cnt++; 00187 listener_.waitForTransform("base_link", "map", 00188 ros::Time(0), ros::Duration(30.0)); 00189 00190 targetPoseMap.stamp_ = ros::Time(); 00191 targetPoseBase.stamp_ = ros::Time(); 00192 00193 listener_.transformPose("base_link", targetPoseMap, targetPoseBase); 00194 00195 btVector3 euler; 00196 QuaternionToEuler(targetPoseBase.getRotation(),euler); 00197 00198 00199 //get the difference between the two poses 00200 //geometry_msgs::Twist diff = diff2D(target_pose, robot_pose); 00201 //tf_.transformPose(fixed_frame_, pose, fixed_pose); 00202 00203 //wait for the listener to get the first message 00204 listener_.waitForTransform("base_footprint", "odom_combined", 00205 ros::Time(0), ros::Duration(10.0)); 00206 00207 //we will record transforms here 00208 tf::StampedTransform start_transform; 00209 tf::StampedTransform current_transform; 00210 00211 //record the starting transform from the odometry to the base frame 00212 listener_.lookupTransform("base_footprint", "odom_combined", 00213 ros::Time(0), start_transform); 00214 00215 //we will be sending commands of type "twist" 00216 geometry_msgs::Twist base_cmd; 00217 00218 //calulate speeds for reaching goal in 1 second and then scale them down to reasonable speeds 00219 double theoretic_x = targetPoseBase.getOrigin().x(); 00220 double theoretic_y = targetPoseBase.getOrigin().y(); 00221 double theoretic_w = euler.z(); 00222 00223 00224 00225 double scale_x = 1; 00226 double scale_y = 1; 00227 double scale_w = 1; 00228 if (fabs(theoretic_x) > 0.05) 00229 scale_x = 0.05 / fabs(theoretic_x); 00230 if (fabs(theoretic_y) > 0.05) 00231 scale_y = 0.05 / fabs(theoretic_y); 00232 if (fabs(theoretic_w) > 0.25) 00233 scale_w = 0.25 / fabs(theoretic_w); 00234 00235 double scale = scale_x; 00236 if (scale_y < scale) 00237 scale = scale_y; 00238 if (scale_w < scale) 00239 scale = scale_w; 00240 00241 //ROS_INFO("scales %f %f %f", scale_x, scale_y, scale_w); 00242 00243 scale = fabs(scale); 00244 //if (scale > 1) 00245 // scale = 1; 00246 00247 base_cmd.linear.x = theoretic_x * scale; 00248 base_cmd.linear.y = theoretic_y * scale; 00249 base_cmd.angular.z = theoretic_w * scale; 00250 00251 if ((scale == scale_w) && (fabs(theoretic_w) < 0.05)) 00252 base_cmd.angular.z = theoretic_w * 0.05 / fabs(theoretic_w); 00253 00254 //ROS_INFO("COMMAND %f %f %f", base_cmd.linear.x, base_cmd.linear.y, base_cmd.angular.z); 00255 00256 ros::Rate rate(10.0); 00257 00258 // if ((base_cmd.angular.z == 0) && (base_cmd.linear.y == 0) && (base_cmd.linear.x == 0)) 00259 double distToTarg = sqrt(targetPoseBase.getOrigin().x() * targetPoseBase.getOrigin().x() + targetPoseBase.getOrigin().y() * targetPoseBase.getOrigin().y()); 00260 //ROS_INFO("dist %f target pose in base coords: %f %f %f %f ANGLE %f ", distToTarg, targetPoseBase.getOrigin().x(), targetPoseBase.getOrigin().y(), targetPoseBase.getRotation().z(), targetPoseBase.getRotation().w(),euler.z()); 00261 00262 //if ((fabs(targetPoseBase.getOrigin().x()) < 0.02) && (fabs(targetPoseBase.getOrigin().y()) < 0.05) && (fabs(euler.z()) < 0.01)) 00263 if ((distToTarg < 0.02) && (targetPoseBase.getRotation().getAngle() < 0.05)) 00264 done = true; 00265 // while (!done && nh_.ok()) 00266 00267 //if (distToTarg > 0.3f) { 00268 00269 tf::Stamped<tf::Pose> actPose; 00270 getRobotPose(actPose); 00271 double trav = (3 * (actPose.getOrigin() - startPose.getOrigin()).length()) + 0.2; 00272 double used = (distToTarg < trav) ? distToTarg : trav; 00273 //double used = distToTarg; 00275 double approach_dist = 0.125; // 0.25; 00276 //if (used > 0.25f) { 00277 // speed up when further away 00278 if (used > approach_dist) 00279 { 00280 //double used = (distToTarg < lastDistMoved) ? distToTarg : lastDistMoved; 00281 //double dscale = (distToTarg + .7) * (distToTarg + .7); 00282 double dscale = (used + (1-approach_dist)) * (used + (1-approach_dist)) * (used + (1-approach_dist)); 00283 if (dscale > 5.0) 00284 dscale = 5.0; 00285 //ROS_INFO("USED %f TRAV %f TOTARG %f SCALE %f", used, trav, distToTarg, dscale); 00286 base_cmd.linear.x *= dscale; 00287 base_cmd.linear.y *= dscale; 00288 base_cmd.angular.z *= dscale; 00289 } 00290 else 00291 { 00292 //ROS_INFO("USED %f TRAV %f TOTARG %f", used, trav, distToTarg); 00293 } 00294 00295 00296 //send the drive command after safety check 00297 //if ((fabs(base_cmd.linear.x) <= 0.051) && (fabs(base_cmd.linear.y) <= 0.051) && (fabs(base_cmd.angular.z) <= 0.26)) 00298 //if ((fabs(base_cmd.linear.x) <= 0.153) && (fabs(base_cmd.linear.y) <= 0.153) && (fabs(base_cmd.angular.z) <= 0.78)) 00299 00300 if (isnan(base_cmd.linear.x)) 00301 base_cmd.linear.x = 0; 00302 if (isnan(base_cmd.linear.y)) 00303 base_cmd.linear.y = 0; 00304 00305 if ((fabs(base_cmd.linear.x) <= 0.255) && (fabs(base_cmd.linear.y) <= 0.255) && (fabs(base_cmd.angular.z) <= 1.3)) 00306 cmd_vel_pub_.publish(base_cmd); 00307 else 00308 ROS_ERROR("COMMAND EXCEEDS MAXIMUM LIMITS (COMMAND %f %f %f)", base_cmd.linear.x, base_cmd.linear.y, base_cmd.angular.z); 00309 rate.sleep(); 00310 //get the current transform 00311 try 00312 { 00313 listener_.lookupTransform("base_footprint", "odom_combined", 00314 ros::Time(0), current_transform); 00315 } 00316 catch (tf::TransformException ex) 00317 { 00318 ROS_ERROR("%s",ex.what()); 00319 break; 00320 } 00321 //see how far we've traveled 00322 tf::Transform relative_transform = start_transform.inverse() * current_transform; 00323 00324 double dist_moved = relative_transform.getOrigin().length() + relative_transform.getRotation().getAngle() * 100.0f; 00325 lastDistMoved = dist_moved; 00326 //ROS_INFO("dist_moved %f", dist_moved); 00327 // if we didnt move much and tried sometimes already, get out, we're stuck 00328 if ((dist_moved < 0.005) && (cnt < 15)) 00329 cntbad++; 00330 else 00331 cntbad = 0; 00332 00333 if (cntbad > 10) 00334 { 00335 ROS_ERROR("RobotDriver: could not reach goal, stuck"); 00336 00337 if (exitWhenStuck) 00338 { 00339 done = true; 00340 doneBad = true; 00341 } 00342 } 00343 // if(dist_moved > distance) done = true; 00344 } 00345 00346 00347 tf::Stamped<tf::Pose> actPose; 00348 getRobotPose(actPose); 00349 double travelled = (actPose.getOrigin() - startPose.getOrigin()).length(); 00350 //ROS_ERROR("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); 00351 btVector3 euler; 00352 ROS_INFO("TRAVELLED %f", travelled); 00353 QuaternionToEuler(targetPoseMap.getRotation(),euler); 00354 ROS_INFO("Goal in Map: %f %f %f", targetPoseMap.getOrigin().x(), targetPoseMap.getOrigin().y(), euler.z()); 00355 QuaternionToEuler(actPose.getRotation(),euler); 00356 ROS_INFO("Curr in Map: %f %f %f", actPose.getOrigin().x(), actPose.getOrigin().y(), euler.z()); 00357 //if (done) return true; 00358 return true; 00359 } 00360 00361 00362 bool RobotDriver::driveInMap(const double targetPose[], bool exitWhenStuck) 00363 { 00364 tf::Stamped<tf::Pose> targetPoseMap; 00365 targetPoseMap.frame_id_ = "map"; 00366 targetPoseMap.stamp_ = ros::Time(); 00367 targetPoseMap.setOrigin(btVector3( targetPose[0], targetPose[1], 0)); 00368 targetPoseMap.setRotation(btQuaternion(0,0, targetPose[2], targetPose[3])); 00369 00370 return driveInMap(targetPoseMap,exitWhenStuck); 00371 } 00372 00373 bool RobotDriver::driveInOdom(const double targetPose[], bool exitWhenStuck) 00374 { 00375 00376 listener_.waitForTransform("base_link", "map", 00377 ros::Time(0), ros::Duration(10.0)); 00378 00379 tf::Stamped<tf::Pose> targetPoseMap; 00380 targetPoseMap.frame_id_ = "base_link"; 00381 targetPoseMap.stamp_ = ros::Time(); 00382 targetPoseMap.setOrigin(btVector3( targetPose[0], targetPose[1], 0)); 00383 targetPoseMap.setRotation(btQuaternion(0,0, targetPose[2], targetPose[3])); 00384 00385 tf::Stamped<tf::Pose> targetPoseBase; 00386 00387 targetPoseBase.stamp_ = ros::Time(); 00388 00389 listener_.transformPose("map", targetPoseMap, targetPoseBase); 00390 00391 double pose[4]; 00392 pose[0] = targetPoseBase.getOrigin().x(); 00393 pose[1] = targetPoseBase.getOrigin().y(); 00394 pose[2] = targetPoseBase.getRotation().z(); 00395 pose[3] = targetPoseBase.getRotation().w(); 00396 00397 return driveInMap(pose,exitWhenStuck); 00398 } 00399 00400 00401 00402 typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> MoveBaseClient; 00403 00404 void RobotDriver::moveBase4(double x, double y, double oz, double ow, bool useNavigation) 00405 { 00406 double p[4]; 00407 p[0] = x; 00408 p[1] = y; 00409 p[2] = oz; 00410 p[3] = ow; 00411 ROS_INFO("going to %f %f %f %f", p[0], p[1], p[2], p[3]); 00412 RobotDriver::getInstance()->moveBase(p); 00413 } 00414 00415 void RobotDriver::moveBase(const double pose[], bool useNavigation) 00416 { 00417 double x = pose[0]; 00418 double y = pose[1]; 00419 double oz = pose[2]; 00420 double ow = pose[3]; 00421 00422 //RobotArm *arm = RobotArm::getInstance(); 00423 // Start the trajectory 00424 00425 //if (!arm->isTucked()) 00426 //{ 00427 //arm->startTrajectory(arm->twoPointTrajectory(Poses::untuckPoseB, Poses::untuckPoseB)); 00429 //} 00430 00431 //tell the action client that we want to spin a thread by default 00432 MoveBaseClient ac("move_base", true); 00433 00434 //wait for the action server to come up 00435 //while(ros::ok() && !ac.waitForServer(ros::Duration(5.0))){ 00436 // ROS_INFO("Waiting for the move_base action server to come up"); 00437 //} 00438 00439 move_base_msgs::MoveBaseGoal goal; 00440 00441 //we'll send a goal to the robot to move 1 meter forward 00442 goal.target_pose.header.frame_id = "/map"; 00443 goal.target_pose.header.stamp = ros::Time::now(); 00444 00445 goal.target_pose.pose.position.x = x; 00446 goal.target_pose.pose.position.y = y; 00447 goal.target_pose.pose.orientation.z = oz; 00448 goal.target_pose.pose.orientation.w = ow; 00449 00450 bool use_move_base = useNavigation; 00451 00452 if (use_move_base) 00453 { 00454 ROS_INFO("Sending goal"); 00455 ac.sendGoal(goal); 00456 00457 //bool finished_before_timeout = 00458 ac.waitForResult(ros::Duration(30.0)); 00459 00460 if (ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED) 00461 ROS_INFO("Hooray, the base moved"); 00462 else 00463 ROS_INFO("The base failed to movefor some reason"); 00464 } 00465 00466 RobotDriver *driver = RobotDriver::getInstance(); 00467 00468 driver->driveInMap(pose); 00469 } 00470 00471 void RobotDriver::moveBaseP(double x, double y, double oz, double ow, bool useNavigation) 00472 { 00473 double p[4]; 00474 p[0] = x; 00475 p[1] = y; 00476 p[2] = oz; 00477 p[3] = ow; 00478 moveBase(p,useNavigation); 00479 } 00480 00481 void RobotDriver::driveToMatch(std::vector<tf::Stamped<tf::Pose> > targetPose, std::vector<std::string> frame_ids) 00482 { 00483 ros::Rate rate(5); 00484 while (ros::ok()) 00485 { 00486 00487 rate.sleep(); 00488 ros::spinOnce(); 00489 00490 RobotArm *right = RobotArm::getInstance(0); 00491 RobotArm *left = RobotArm::getInstance(1); 00492 tf::Stamped<tf::Pose> rightToolPose; 00493 right->getToolPose(rightToolPose, "base_link"); 00494 tf::Stamped<tf::Pose> leftToolPose; 00495 left->getToolPose(leftToolPose, "base_link"); 00496 00497 00498 tf::Stamped<tf::Pose> goalPoseRight; 00499 goalPoseRight.stamp_ = ros::Time::now(); 00500 goalPoseRight.frame_id_= "map"; 00501 goalPoseRight.setOrigin(btVector3(-1.657, 1.727, 0.982)); 00502 goalPoseRight.setRotation(btQuaternion(-0.618, -0.312, 0.674, 0.256)); 00503 goalPoseRight = Geometry::getPoseIn("base_link",goalPoseRight); 00504 00505 tf::Stamped<tf::Pose> goalPoseLeft; 00506 goalPoseLeft.stamp_ = ros::Time::now(); 00507 goalPoseLeft.frame_id_= "map"; 00508 goalPoseLeft.setOrigin(btVector3(-1.679, 1.987, 0.971)); 00509 goalPoseLeft.setRotation(btQuaternion(-0.285, 0.654, -0.282, 0.641)); 00510 goalPoseLeft = Geometry::getPoseIn("base_link",goalPoseLeft); 00511 00512 00513 /*- Translation: [-1.657, 1.727, 0.982] 00514 - Rotation: in Quaternion [-0.618, -0.312, 0.674, 0.256] 00515 in RPY [-1.516, 0.739, 1.713] 00516 ruehr@satie:~/sandbox/tumros-internal/highlevel/ias_drawer_executive$ rosrun tf tf_echo map r_gripper_tool_frame 00517 At time 1286556189.961 00518 - Translation: [-1.679, 1.987, 0.971] 00519 - Rotation: in Quaternion [-0.285, 0.654, -0.282, 0.641] 00520 in RPY [-1.597, 0.746, -1.592] 00521 At time 1286556191.008*/ 00522 00523 00524 //tf::Stamped<tf::Pose> rightTarget = targetPose[1]; 00525 //Stamped<tf::Pose> leftTarget = targetPose[1]; 00526 00527 //::Transform relative_transform = start_transform/inverse() * current_transform; 00528 tf::Pose relative_transform_left;// = goalPoseLeft.inverse() * rightToolPose; 00529 tf::Pose relative_transform_right;// = goalPoseRight.inverse() * leftToolPose; 00530 00531 relative_transform_right.setOrigin(rightToolPose.getOrigin() - goalPoseLeft.getOrigin()); 00532 relative_transform_left.setOrigin(leftToolPose.getOrigin() - goalPoseRight.getOrigin()); 00533 00534 btVector3 average = relative_transform_left.getOrigin() + relative_transform_right.getOrigin(); 00535 00536 ROS_INFO("RELATIVE LEFT %f %f %f %f %f %f %f", relative_transform_left.getOrigin().x(),relative_transform_left.getOrigin().y(),relative_transform_left.getOrigin().z(), 00537 relative_transform_left.getRotation().x(), relative_transform_left.getRotation().y(), relative_transform_left.getRotation().z(), relative_transform_left.getRotation().w()); 00538 ROS_INFO("RELATIVE RIGHT %f %f %f %f %f %f %f", relative_transform_right.getOrigin().x(),relative_transform_right.getOrigin().y(),relative_transform_right.getOrigin().z(), 00539 relative_transform_right.getRotation().x(), relative_transform_right.getRotation().y(), relative_transform_right.getRotation().z(), relative_transform_right.getRotation().w()); 00540 00541 ROS_INFO("AVERAGE %f %f", average.x(), average.y()); 00542 } 00543 00544 } 00545 00546 RobotDriver *RobotDriver::instance = 0; 00547 00548 00549