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 #include <srs_assisted_grasping/reactive_grasping_node.h>
00029
00030 using namespace srs_assisted_grasping;
00031 using namespace srs_assisted_grasping_msgs;
00032
00033
00034 bool ReactiveGrasping::readParams() {
00035
00036
00037 double tmp;
00038 ros::param::param<double>("~default_time", tmp, 3.0);
00039
00040 params_.default_time = ros::Duration(tmp);
00041
00042 ros::param::param<double>("~max_force", params_.max_force, 1000.0);
00043 ros::param::param<double>("~max_velocity", params_.max_velocity, 1.5);
00044 ros::param::param<double>("~a_ramp", params_.a_ramp, 10.0);
00045 ros::param::param<double>("~d_ramp", params_.d_ramp, 20.0);
00046 ros::param::param<double>("~rate", params_.rate, 20.0);
00047
00048
00049
00050
00051 ros::NodeHandle nh("~");
00052 XmlRpc::XmlRpcValue joints_list;
00053
00054 joints_.num_of_tactile_pads = 0;
00055
00056
00057 if (nh.getParam("joints",joints_list)) {
00058
00059 ROS_ASSERT(joints_list.getType() == XmlRpc::XmlRpcValue::TypeArray);
00060
00061 for (int i=0; i < joints_list.size(); i++) {
00062
00063 XmlRpc::XmlRpcValue joint = joints_list[i];
00064
00065 if (joint.getType() != XmlRpc::XmlRpcValue::TypeStruct) {
00066
00067 ROS_ERROR("Wrong syntax in YAML config.");
00068 return false;
00069
00070 }
00071
00072 if (!joint.hasMember("joint")) {
00073
00074 ROS_ERROR("Joint doesn't have 'joint' property defined.");
00075 return false;
00076
00077 } else {
00078
00079 XmlRpc::XmlRpcValue joint_name = joint["joint"];
00080
00081 std::string tmp = static_cast<std::string>(joint_name);
00082
00083 joints_.joints.push_back(tmp);
00084
00085 std::cout << tmp << " ";
00086
00087 }
00088
00089 if (!joint.hasMember("static")) {
00090
00091 ROS_WARN("Joint doesn't have 'static' property defined. Supposing true.");
00092
00093 joints_.is_static.push_back(false);
00094
00095 } else {
00096
00097 XmlRpc::XmlRpcValue static_joint = joint["static"];
00098
00099 bool tmp = static_cast<bool>(static_joint);
00100
00101 joints_.is_static.push_back(tmp);
00102
00103 std::cout << "static: " << tmp << " ";
00104 }
00105
00106 if (!joint.hasMember("has_tactile_pad")) {
00107
00108 ROS_WARN("Joint doesn't have 'has_tactile_pad' property defined. Supposing false.");
00109
00110 joints_.has_tactile_pad.push_back(false);
00111
00112 } else {
00113
00114 XmlRpc::XmlRpcValue has_pad = joint["has_tactile_pad"];
00115
00116 bool tmp = static_cast<bool>(has_pad);
00117
00118 joints_.has_tactile_pad.push_back(tmp);
00119
00120 std::cout << "has_pad: " << tmp << std::endl;
00121
00122 }
00123
00124 }
00125
00126
00127 } else {
00128
00129 ROS_ERROR("Can't get list of joints!");
00130 return false;
00131
00132 }
00133
00134 for (unsigned char i=0; i < joints_.has_tactile_pad.size();i++) {
00135
00136 if (joints_.has_tactile_pad[i]) joints_.num_of_tactile_pads++;
00137
00138 }
00139
00140 return true;
00141
00142 }
00143
00144 ReactiveGrasping::~ReactiveGrasping(void) {
00145
00146 server_->shutdown();
00147 delete server_;
00148
00149 };
00150
00151
00152
00153 ReactiveGrasping::ReactiveGrasping(std::string name) {
00154
00155 fatal_error_ = false;
00156
00157 if (!readParams()) {
00158
00159 fatal_error_ = true;
00160
00161 } else {
00162
00163 ROS_INFO("Configured for %d joints with %d tactile pads",(int)joints_.joints.size(),joints_.num_of_tactile_pads);
00164
00165 feedback_data_.tactile_data.resize(joints_.num_of_tactile_pads);
00166 joints_.velocities.resize(joints_.joints.size());
00167 joints_.limits.resize(joints_.joints.size());
00168
00169 feedback_data_.sdh_data_stamp = ros::Time(0);
00170 feedback_data_.tactile_data_stamp = ros::Time(0);
00171 feedback_data_.sdh_data_checked = false;
00172
00173 server_ = new actionlib::SimpleActionServer<srs_assisted_grasping_msgs::ReactiveGraspingAction>(nh_, name, boost::bind(&ReactiveGrasping::execute, this, _1), false);
00174
00175 sdh_mode_client_ = nh_.serviceClient<cob_srvs::SetOperationMode>("set_mode_srv");
00176
00177 vel_publisher_ = nh_.advertise<brics_actuator::JointVelocities>("velocity_out", 10);
00178
00179 action_name_ = name;
00180
00181 time_to_stop_.resize(joints_.joints.size());
00182
00183 tact_sub_ = nh_.subscribe("tact_in", 10, &ReactiveGrasping::TactileDataCallback,this);
00184 state_sub_ = nh_.subscribe("state_in", 10, &ReactiveGrasping::SdhStateCallback,this);
00185
00186 urdf::Model model;
00187 model.initParam("robot_description");
00188
00189 for (unsigned int i=0; i < joints_.joints.size(); i++) {
00190
00191 joints_.limits[i].min = model.getJoint(joints_.joints[i])->limits->lower;
00192 joints_.limits[i].max = model.getJoint(joints_.joints[i])->limits->upper;
00193
00194 }
00195
00196
00197 server_->start();
00198
00199 ROS_INFO("Action server started");
00200
00201 }
00202
00203 }
00204
00205 void ReactiveGrasping::stop() {
00206
00207 ROS_INFO("Immediately stopping.");
00208
00209 std::vector<double> vel;
00210 vel.resize(joints_.joints.size());
00211
00212 for (unsigned int i=0; i < vel.size(); i++)
00213 vel[i];
00214
00215 publish(vel);
00216
00217 }
00218
00219 bool ReactiveGrasping::publish(std::vector<double> vel) {
00220
00221 if (vel.size()!= joints_.joints.size()) {
00222
00223 ROS_ERROR("Error on publishing velocities - vector size mismatch.");
00224 return false;
00225
00226 }
00227
00228
00229 ros::Time now = ros::Time::now();
00230
00231 brics_actuator::JointVelocities msg;
00232
00233 for (unsigned int i=0; i < vel.size(); i++) {
00234
00235 brics_actuator::JointValue jv;
00236
00237 jv.timeStamp = now;
00238 jv.joint_uri = joints_.joints[i];
00239 jv.value = vel[i];
00240 jv.unit = "rad/s";
00241
00242
00243
00244 msg.velocities.push_back(jv);
00245
00246 }
00247
00248
00249
00250 vel_publisher_.publish(msg);
00251
00252 return true;
00253
00254 }
00255
00256 void ReactiveGrasping::execute(const ReactiveGraspingGoalConstPtr &goal) {
00257
00258 ROS_INFO("Reactive grasping action triggered");
00259
00260 joints_.velocities.clear();
00261
00262 ReactiveGraspingResult res;
00263 ReactiveGraspingFeedback feedback;
00264
00265 ros::Rate r(params_.rate);
00266
00267
00268 bool data_received = false;
00269
00270 feedback_data_.data_mutex.lock();
00271
00272 if (feedback_data_.sdh_data_stamp > ros::Time(0) &&
00273 feedback_data_.tactile_data_stamp > ros::Time(0)) data_received = true;
00274
00275 feedback_data_.data_mutex.unlock();
00276
00277 if (!data_received) {
00278
00279 ROS_ERROR("SDH/tactile data not available! Could not perform action...");
00280
00281 server_->setAborted(res,"no data received, could not perform action");
00282 return;
00283
00284 }
00285
00286 if (fatal_error_) {
00287
00288 server_->setAborted(res,"Fatal error has occurred.");
00289 return;
00290
00291 }
00292
00293
00294
00295 bool limit_error = false;
00296
00297 for(unsigned int i=0; i < joints_.joints.size(); i++) {
00298
00299 if (joints_.is_static[i]) continue;
00300
00301 double g = goal->target_configuration.data[i];
00302
00303 if ( (g < joints_.limits[i].min) || (g > joints_.limits[i].max) ) {
00304
00305 ROS_ERROR("Target configuration for %s joint violates limits!",joints_.joints[i].c_str());
00306 limit_error = true;
00307
00308 }
00309
00310 }
00311
00312 if (limit_error) {
00313
00314 server_->setAborted(res,"Target configuration out of limits.");
00315 return;
00316
00317 }
00318
00319 if (vel_publisher_.getNumSubscribers() == 0) {
00320
00321 ROS_ERROR("No one is listening to our velocity commands!");
00322 server_->setAborted(res,"There is no listener.");
00323 return;
00324
00325 }
00326
00327 if (!setMode("velocity")) {
00328
00329 server_->setAborted(res,"Could not set SDH to velocity mode.");
00330 return;
00331
00332 }
00333
00334
00335
00336 for(unsigned int i=0; i < joints_.joints.size(); i++) {
00337
00338 if (joints_.is_static[i]) continue;
00339
00340 double g = goal->target_configuration.data[i];
00341
00342 if ( (g < joints_.limits[i].min) || (g > joints_.limits[i].max) ) {
00343
00344 ROS_ERROR("Target configuration for %s joint violates limits!",joints_.joints[i].c_str());
00345 limit_error = true;
00346
00347 }
00348
00349 }
00350
00351 if (limit_error) {
00352
00353 server_->setAborted(res,"Target configuration out of limits.");
00354 return;
00355
00356 }
00357
00358 if (vel_publisher_.getNumSubscribers() == 0) {
00359
00360 ROS_ERROR("No one is listening to our velocity commands!");
00361 server_->setAborted(res,"There is no listener.");
00362 return;
00363
00364 }
00365
00366 copyData();
00367
00368 double t1 = goal->time.toSec() * (params_.a_ramp / 100.0);
00369 double t3 = goal->time.toSec() * (params_.d_ramp / 100.0);
00370 double t2 = goal->time.toSec() - (t1 + t3);
00371
00372 ROS_INFO("t1=%f, t2=%f, t3=%f,tc=%f, rate=%f",t1,t2,t3,t1+t2+t3,params_.rate);
00373 ROS_INFO("Acc. will take %f %% of total time, dec. %f %%.",params_.a_ramp,params_.d_ramp);
00374
00375 unsigned int num_of_acc = (unsigned int)ceil(t1 * params_.rate) - 1;
00376 unsigned int num_of_vel = (unsigned int)ceil(t2 * params_.rate);
00377 unsigned int num_of_dec = (unsigned int)ceil(t3 * params_.rate) - 1;
00378
00379 bool velocity_limit_error = false;
00380
00381
00382 for (unsigned int i = 0; i < joints_.joints.size(); i++) {
00383
00384 if (joints_.is_static[i]) {
00385
00386 joints_.velocities[i].clear();
00387 continue;
00388
00389 } else {
00390
00391
00392 double p1 = goal->target_configuration.data[i];
00393 double p2 = sdh_data_act_.positions[i];
00394
00395 double pos_diff = (p1-p2);
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 double vel = (pos_diff / (0.5*t1 + t2 + 0.5*t3));
00406 double acc = (vel / t1) * (1.0 / params_.rate);
00407 double dec = (vel / t3) * (1.0 / params_.rate);
00408
00409 if (fabs(vel) >= params_.max_velocity) {
00410
00411 ROS_WARN("Joint %s will violate max. velocity limit (%f, limit %f).",joints_.joints[i].c_str(),vel,params_.max_velocity);
00412
00413 velocity_limit_error = true;
00414
00415 }
00416
00417 ROS_INFO("Joint %d, dv1=%f (%u), v2=%f (%u), dv3=%f (%u), pos_diff: %f",i,acc,num_of_acc,vel,num_of_vel,dec,num_of_dec,pos_diff);
00418
00419 joints_.velocities[i].resize(num_of_acc + num_of_vel + num_of_dec);
00420
00421 joints_.velocities[i][0] = 0.0;
00422
00423
00424 for (unsigned int j=1; j < (num_of_acc + num_of_vel + num_of_dec); j++) {
00425
00426 if (j < num_of_acc) {
00427
00428
00429 joints_.velocities[i][j] = joints_.velocities[i][j-1] + acc;
00430
00431 if (fabs(joints_.velocities[i][j]) > fabs(vel)) joints_.velocities[i][j] = vel;
00432
00433
00434
00435 } else if ( (j >= num_of_acc) && (j <= (num_of_acc + num_of_vel)) ) {
00436
00437
00438 joints_.velocities[i][j] = vel;
00439
00440 } else {
00441
00442
00443 if ( fabs(joints_.velocities[i][j-1]) > fabs(dec) ) {
00444
00445 joints_.velocities[i][j] = joints_.velocities[i][j-1] - dec;
00446
00447 } else {
00448
00449 joints_.velocities[i][j] = 0.0;
00450
00451 }
00452
00453 }
00454
00455
00456
00457 }
00458
00459 }
00460
00461
00462
00463 }
00464
00465 if (velocity_limit_error) {
00466
00467 server_->setAborted(res,"Some joint hit velocity limit.");
00468 return;
00469
00470 }
00471
00472 for(unsigned int i=0; i < joints_.joints.size(); i++) {
00473
00474 time_to_stop_[i] = -1.0;
00475
00476 }
00477
00478 ros::Time start_time = ros::Time::now();
00479 ros::Time max_time = ros::Time(0);
00480
00481 if ( goal->time > ros::Duration(0) ) max_time = start_time + goal->time;
00482 else max_time = start_time + params_.default_time;
00483
00484 unsigned int iter = 0;
00485
00486 while(ros::ok()) {
00487
00488
00489 if (server_->isPreemptRequested()) {
00490
00491 ros::Duration time_elapsed = ros::Time::now() - start_time;
00492 double time_elapsed_d = time_elapsed.toSec();
00493
00494 ROS_INFO("%s: Preempted, elapsed time: %f", action_name_.c_str(),time_elapsed_d);
00495
00496 server_->setPreempted(res,std::string("preempted"));
00497
00498 stop();
00499
00500 setMode("position");
00501
00502 return;
00503
00504 }
00505
00506
00507 if ((ros::Time::now() >= max_time) || iter >= (num_of_acc + num_of_vel + num_of_dec) ) {
00508
00509 ros::Duration time_elapsed = ros::Time::now() - start_time;
00510 double time_elapsed_d = time_elapsed.toSec();
00511
00512 ROS_INFO("Max. time condition reached (%fs, iter: %u)!",time_elapsed_d,iter);
00513
00514 res.actual_forces.data = tactile_data_;
00515
00516
00517 res.actual_joint_values.data.resize(sdh_data_act_.positions.size());
00518 for (unsigned int i=0; i < sdh_data_act_.positions.size(); i++) {
00519
00520 res.actual_joint_values.data[i] = (float)sdh_data_act_.positions[i];
00521
00522 }
00523
00524 ros::Duration d = ros::Time::now() - start_time;
00525
00526 for (unsigned int i=0; i < time_to_stop_.size(); i++) {
00527
00528 if (time_to_stop_[i] == -1.0) time_to_stop_[i] = d.toSec();
00529
00530 }
00531
00532 res.time_to_stop.data = time_to_stop_;
00533
00534 server_->setSucceeded(res,"Max. time condition reached.");
00535
00536 stop();
00537
00538 setMode("position");
00539
00540 return;
00541
00542 }
00543
00544 copyData();
00545
00546
00547 std::vector<double> vel;
00548 vel.resize(joints_.joints.size());
00549
00550
00551 if (iter++ < (num_of_acc + num_of_vel + num_of_dec) ) {
00552
00553
00554 for(unsigned int i=0; i < joints_.joints.size(); i++) {
00555
00556 vel[i] = 0.0;
00557
00558
00559 if (joints_.is_static[i]) continue;
00560
00561
00562 if (fabs(sdh_data_act_.positions[i] - goal->target_configuration.data[i]) < 0.02) {
00563
00564 if (time_to_stop_[i] == -1.0) {
00565
00566 ros::Duration d = ros::Time::now() - start_time;
00567 time_to_stop_[i] = d.toSec();
00568
00569 ROS_INFO("Joint %s (%u) reached target configuration in %f secs.",joints_.joints[i].c_str(),i,time_to_stop_[i]);
00570
00571 }
00572
00573 continue;
00574
00575 }
00576
00577
00578 if (joints_.has_tactile_pad[i]) {
00579
00580 if (tactile_data_[i] >= goal->max_force.data[i]) {
00581
00582 if (time_to_stop_[i] == -1.0) {
00583
00584 ros::Duration d = ros::Time::now() - start_time;
00585 time_to_stop_[i] = d.toSec();
00586
00587 ROS_INFO("Joint %s (%u) reached max. force (%d) in %f secs.",joints_.joints[i].c_str(),i,tactile_data_[i],time_to_stop_[i]);
00588
00589 }
00590
00591 continue;
00592
00593 } else vel[i] = joints_.velocities[i][iter];
00594
00595
00596 } else vel[i] = joints_.velocities[i][iter];
00597
00598
00599
00600 }
00601
00602
00603
00604 }
00605
00606
00607 publish(vel);
00608
00609 r.sleep();
00610
00611 }
00612
00613
00614 }
00615
00616 void ReactiveGrasping::copyData() {
00617
00618
00619 feedback_data_.data_mutex.lock();
00620
00621 sdh_data_act_ = feedback_data_.sdh_data.actual;
00622 tactile_data_ = feedback_data_.tactile_data;
00623
00624 feedback_data_.data_mutex.unlock();
00625
00626 }
00627
00628 void ReactiveGrasping::SdhStateCallback(const pr2_controllers_msgs::JointTrajectoryControllerState::ConstPtr & msg) {
00629
00630 if (fatal_error_) return;
00631
00632 boost::mutex::scoped_lock(feedback_data_.data_mutex);
00633
00634 feedback_data_.sdh_data = *msg;
00635
00636 feedback_data_.sdh_data_stamp = ros::Time::now();
00637
00638 if (!feedback_data_.sdh_data_checked) {
00639
00640
00641 if (feedback_data_.sdh_data.joint_names.size() != joints_.joints.size()) {
00642
00643 ROS_ERROR_ONCE("Received data for more/less joints than configured!");
00644 fatal_error_ = true;
00645 return;
00646
00647 }
00648
00649
00650 for (unsigned int i=0; i<joints_.joints.size(); i++) {
00651
00652 if (joints_.joints[i] != feedback_data_.sdh_data.joint_names[i]) {
00653
00654 ROS_ERROR_ONCE("Order or names of joint differs in config and received data!");
00655 fatal_error_ = true;
00656 return;
00657
00658 }
00659
00660 }
00661
00662 feedback_data_.sdh_data_checked = true;
00663
00664 }
00665
00666 }
00667
00668
00669 void ReactiveGrasping::TactileDataCallback(const schunk_sdh::TactileSensor::ConstPtr& msg) {
00670
00671 if (fatal_error_) return;
00672
00673 boost::mutex::scoped_lock(feedback_data_.data_mutex);
00674
00675
00676
00677 feedback_data_.tactile_data_stamp = ros::Time::now();
00678
00679 if (! feedback_data_.tactile_data_checked) {
00680
00681 if (msg->tactile_matrix.size() != (unsigned int)joints_.num_of_tactile_pads) {
00682
00683 ROS_ERROR("Received amount of tactile matrixes (%u) differs from configuration (%u)!",
00684 (unsigned int)joints_.num_of_tactile_pads,
00685 (unsigned int)feedback_data_.tactile_data.size());
00686
00687 fatal_error_ = true;
00688 return;
00689
00690 }
00691
00692 feedback_data_.tactile_data_checked = true;
00693 }
00694
00695
00696 for(unsigned int i=0; i < feedback_data_.tactile_data.size(); i++) {
00697
00698 int16_t max = 0;
00699
00700 for (unsigned int j=0; j < (unsigned int)(msg->tactile_matrix[i].cells_x*msg->tactile_matrix[i].cells_y); j++) {
00701
00702 if ( (msg->tactile_matrix[i].tactile_array[j] > max) && (msg->tactile_matrix[i].tactile_array[j] < 20000) ) max = msg->tactile_matrix[i].tactile_array[j];
00703
00704 }
00705
00706 feedback_data_.tactile_data[i] = max;
00707
00708 }
00709
00710 }
00711
00712
00713 bool ReactiveGrasping::setMode(std::string mode) {
00714
00715
00716 cob_srvs::SetOperationMode srv;
00717
00718 srv.request.operation_mode.data = mode;
00719
00720 if (sdh_mode_client_.call(srv)) {
00721
00722 if (srv.response.success.data) {
00723
00724 ROS_INFO("SDH should be in %s mode",mode.c_str());
00725 return true;
00726
00727 } else {
00728
00729 ROS_ERROR("Failed to set SDH to %s mode, error: %s",mode.c_str(),srv.response.error_message.data.c_str());
00730 return false;
00731
00732 }
00733
00734 } else {
00735
00736 ROS_ERROR("Failed to call SDH mode service");
00737 return false;
00738
00739 }
00740
00741 }
00742
00743 int main(int argc, char** argv)
00744 {
00745
00746
00747 ROS_INFO("Starting reactive grasping node");
00748 ros::init(argc, argv, "but_reactive_grasping_node");
00749
00750 std::string tmp = ACT_GRASP;
00751
00752 ReactiveGrasping mg(tmp);
00753
00754
00755 ROS_INFO("Spinning...");
00756
00757 ros::spin();
00758 ros::shutdown();
00759
00760 }