00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
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
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
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
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
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
00158 diff = btVector3(diff.x(), diff.y(), 0);
00159 double dist = diff.length();
00160 ROS_INFO("DISTANCE TO TRAVEL %f", dist);
00161
00162
00163
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
00200
00201
00202
00203
00204 listener_.waitForTransform("base_footprint", "odom_combined",
00205 ros::Time(0), ros::Duration(10.0));
00206
00207
00208 tf::StampedTransform start_transform;
00209 tf::StampedTransform current_transform;
00210
00211
00212 listener_.lookupTransform("base_footprint", "odom_combined",
00213 ros::Time(0), start_transform);
00214
00215
00216 geometry_msgs::Twist base_cmd;
00217
00218
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
00242
00243 scale = fabs(scale);
00244
00245
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
00255
00256 ros::Rate rate(10.0);
00257
00258
00259 double distToTarg = sqrt(targetPoseBase.getOrigin().x() * targetPoseBase.getOrigin().x() + targetPoseBase.getOrigin().y() * targetPoseBase.getOrigin().y());
00260
00261
00262
00263 if ((distToTarg < 0.02) && (targetPoseBase.getRotation().getAngle() < 0.05))
00264 done = true;
00265
00266
00267
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
00275 double approach_dist = 0.125;
00276
00277
00278 if (used > approach_dist)
00279 {
00280
00281
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
00286 base_cmd.linear.x *= dscale;
00287 base_cmd.linear.y *= dscale;
00288 base_cmd.angular.z *= dscale;
00289 }
00290 else
00291 {
00292
00293 }
00294
00295
00296
00297
00298
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
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
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
00327
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
00344 }
00345
00346
00347 tf::Stamped<tf::Pose> actPose;
00348 getRobotPose(actPose);
00349 double travelled = (actPose.getOrigin() - startPose.getOrigin()).length();
00350
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
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
00423
00424
00425
00426
00427
00429
00430
00431
00432 MoveBaseClient ac("move_base", true);
00433
00434
00435
00436
00437
00438
00439 move_base_msgs::MoveBaseGoal goal;
00440
00441
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
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
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 tf::Pose relative_transform_left;
00529 tf::Pose relative_transform_right;
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