00001 #include <ros/ros.h>
00002 #include <urdf/model.h>
00003
00004 #include <actionlib/server/simple_action_server.h>
00005
00006
00007 #include <sensor_msgs/JointState.h>
00008 #include <brics_actuator/JointPositions.h>
00009 #include <brics_actuator/JointVelocities.h>
00010 #include <diagnostic_msgs/DiagnosticArray.h>
00011 #include <control_msgs/FollowJointTrajectoryAction.h>
00012
00013
00014 #include <cob_srvs/Trigger.h>
00015 #include <cob_srvs/SetOperationMode.h>
00016
00017
00018 #include <cob_3d_mapping_demonstrator/demonstrator_params.h>
00019 #include <cob_3d_mapping_demonstrator/demonstrator_control.h>
00020 #include <cob_3d_mapping_demonstrator/demonstrator_control_maestro.h>
00021
00022
00023
00024
00025 class DemonstratorNode
00026 {
00027 public:
00029 ros::NodeHandle n_;
00030
00032 ros::Publisher topic_pub_joint_state_;
00033
00034 ros::Publisher topic_pub_diagnostic_;
00035
00037 ros::Subscriber topic_sub_command_pos_;
00038
00039
00041 ros::ServiceServer srv_server_init_;
00042 ros::ServiceServer srv_server_stop_;
00043 ros::ServiceServer srv_server_recover_;
00044
00045
00046 actionlib::SimpleActionServer<control_msgs::FollowJointTrajectoryAction> as_;
00047
00049 MapDemonCtrlMaestro* md_ctrl_;
00050
00052 DemonstratorParams* md_params_;
00053
00055
00056
00058 bool initialized_;
00059 bool stopped_;
00060 bool error_;
00061 bool auto_init_;
00062 std::string error_msg_;
00063 ros::Time last_publish_time_;
00064
00066 DemonstratorNode()
00067 :n_("~"),
00068 as_(n_, "follow_joint_trajectory", boost::bind(&DemonstratorNode::executeTrajectory, this, _1), false)
00069 {
00070
00071
00072
00073 md_params_ = new DemonstratorParams();
00074 md_ctrl_ = new MapDemonCtrlMaestro(md_params_);
00075
00077 topic_pub_joint_state_ = n_.advertise<sensor_msgs::JointState> ("joint_states", 1);
00078
00079 topic_pub_diagnostic_ = n_.advertise<diagnostic_msgs::DiagnosticArray>("diagnostics", 1);
00080
00082 topic_sub_command_pos_ = n_.subscribe("command_pos", 1, &DemonstratorNode::topicCallbackCommandPos, this);
00083
00084
00086 srv_server_init_ = n_.advertiseService("init", &DemonstratorNode::srvCallbackInit, this);
00087 srv_server_stop_ = n_.advertiseService("stop", &DemonstratorNode::srvCallbackStop, this);
00088 srv_server_recover_ = n_.advertiseService("recover", &DemonstratorNode::srvCallbackRecover, this);
00089
00090
00091 as_.start();
00092
00093 initialized_ = false;
00094 stopped_ = true;
00095 error_ = false;
00096 last_publish_time_ = ros::Time::now();
00097 }
00098
00100 ~DemonstratorNode()
00101 {
00102 delete md_ctrl_;
00103 }
00104
00106 bool getROSParameters()
00107 {
00109 std::string serial_device = "ttyUSB0";
00110 if(n_.hasParam("serial_device"))
00111 {
00112 n_.getParam("serial_device", serial_device);
00113 }
00114 ROS_INFO("Serial device set to:\t\t%s", serial_device.c_str());
00115
00117 int serial_baud_rate = 57600;
00118 if(n_.hasParam("serial_baudrate"))
00119 {
00120 n_.getParam("serial_baudrate", serial_baud_rate);
00121 }
00122 ROS_INFO("Serial baudrate set to:\t\t%d bps.", serial_baud_rate);
00124 md_params_->init(serial_device, serial_baud_rate);
00125
00127 XmlRpc::XmlRpcValue joint_names_xml_rpc;
00128 std::vector<std::string> joint_names;
00129 if (n_.hasParam("joint_names"))
00130 {
00131 n_.getParam("joint_names", joint_names_xml_rpc);
00132 joint_names.resize(joint_names_xml_rpc.size());
00133 for (int i = 0; i < joint_names_xml_rpc.size(); i++)
00134 {
00135 joint_names[i] = (std::string)joint_names_xml_rpc[i];
00136 }
00137 md_params_->setJointNames(joint_names);
00138 }
00139 else
00140 {
00141 ROS_ERROR("Parameter joint_names not set, shutting down node...");
00142 return false;
00143 }
00144
00146
00147
00148
00149
00150
00151
00152
00153
00154 XmlRpc::XmlRpcValue velocities_xml_rpc;
00155 std::vector<double> velocities;
00156 if(n_.hasParam("velocities"))
00157 {
00158 n_.getParam("velocities", velocities_xml_rpc);
00159 velocities.resize(velocities_xml_rpc.size());
00160 for (int i = 0; i < velocities_xml_rpc.size(); i++)
00161 {
00162 velocities[i] = (double)velocities_xml_rpc[i];
00163 }
00164 md_params_->setVels(velocities);
00165 }
00166 ROS_INFO("Loaded position velocities");
00167
00168 XmlRpc::XmlRpcValue accels_xml_rpc;
00169 std::vector<double> accelerations;
00170 if(n_.hasParam("accelerations"))
00171 {
00172 n_.getParam("accelerations", accels_xml_rpc);
00173 accelerations.resize(accels_xml_rpc.size());
00174 for (int i = 0; i < accels_xml_rpc.size(); i++)
00175 {
00176 accelerations[i] = (double)accels_xml_rpc[i];
00177 }
00178 md_params_->setAccels(accelerations);
00179 }
00180 ROS_INFO("Loaded position accelerations");
00181
00182 joint_names.resize(joint_names_xml_rpc.size());
00183 for (int i = 0; i < joint_names_xml_rpc.size(); i++)
00184 {
00185 joint_names[i] = (std::string)joint_names_xml_rpc[i];
00186 }
00187
00188 auto_init_ = true;
00189 if(n_.hasParam("auto_initialize"))
00190 {
00191 n_.getParam("auto_initialize", auto_init_);
00192 }
00193 ROS_INFO("Auto initialize set to: %d", auto_init_);
00194
00195 ROS_INFO("Parameters initialisation successful.");
00196 }
00197
00198 void getRobotDescriptionParameters()
00199 {
00200 std::vector<std::string> joint_names = md_params_->getJointNames();
00201 unsigned int dof = joint_names.size();
00202 md_params_->setDOF(dof);
00203
00204 urdf::Model model;
00205 ROS_DEBUG("Loading urdf");
00206
00207 std::string param_descr = "/robot_description";
00208 if (n_.hasParam(param_descr))
00209 {
00210 model.initParam(param_descr);
00211 ROS_INFO("Successfuly loaded URDF description.");
00212 }
00213 else
00214 {
00215 ROS_ERROR("URDF not found, shutting down node...");
00216 n_.shutdown();
00217 }
00218
00221 std::vector<double> max_velocities(dof);
00222 for (unsigned int i = 0; i < dof; i++)
00223 {
00224 max_velocities[i] = model.getJoint(joint_names[i].c_str())->limits->velocity;
00225 }
00227 std::vector<double> lower_limits(dof);
00228 for (unsigned int i = 0; i < dof; i++)
00229 {
00230 lower_limits[i] = model.getJoint(joint_names[i].c_str())->limits->lower;
00231 }
00232
00233
00234 std::vector<double> upper_limits(dof);
00235 for (unsigned int i = 0; i < dof; i++)
00236 {
00237 upper_limits[i] = model.getJoint(joint_names[i].c_str())->limits->upper;
00238 }
00239
00241 std::vector<double> offsets(dof);
00242 for (unsigned int i = 0; i < dof; i++)
00243 {
00244 offsets[i] = model.getJoint(joint_names[i].c_str())->calibration->rising.get()[0];
00245 }
00246
00248 md_params_->setMaxVel(max_velocities);
00249 md_params_->setLowerLimits(lower_limits);
00250 md_params_->setUpperLimits(upper_limits);
00251 md_params_->setOffsets(offsets);
00252
00253 ROS_DEBUG("Loading complete");
00254 }
00255
00256 void runAutoInit()
00257 {
00258 if (md_ctrl_->init(md_params_))
00259 {
00260 initialized_ = true;
00261 ROS_INFO("...initializing COB3DMD successful");
00262 }
00263 else
00264 {
00265 error_ = true;
00266 error_msg_ = md_ctrl_->getErrorMessage();
00267 ROS_ERROR("...initializing COB3DMD unsuccessful. Error: %s", error_msg_.c_str());
00268 }
00269
00270 }
00271
00272 void executeTrajectory(const control_msgs::FollowJointTrajectoryGoalConstPtr &goal)
00273 {
00274
00275 stopped_ = false;
00276 trajectory_msgs::JointTrajectory traj = goal->trajectory;
00277 for( unsigned int j = 0; j <traj.points.size(); j++)
00278 {
00279 brics_actuator::JointPositions::Ptr joint_pos(new brics_actuator::JointPositions());
00280 for(unsigned int i=0; i<traj.joint_names.size(); i++)
00281 {
00282 brics_actuator::JointValue jv;
00283 jv.joint_uri = traj.joint_names[i];
00284 jv.unit = "rad";
00285 jv.value = traj.points[j].positions[i];
00286 joint_pos->positions.push_back(jv);
00287 }
00288 topicCallbackCommandPos(joint_pos);
00289 while(!md_ctrl_->is_moving_ && !stopped_) usleep(1000);
00290 while(md_ctrl_->is_moving_ && !stopped_)
00291 {
00292
00293 usleep(10000);
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 }
00309 as_.setSucceeded();
00310 }
00311
00312
00313 void topicCallbackCommandPos(const brics_actuator::JointPositions::ConstPtr& msg)
00314 {
00315 ROS_DEBUG("Received new position command.");
00316 if(!initialized_)
00317 {
00318 ROS_WARN("Skipping command: mapping_demonstrator is not initialized");
00319 return;
00320 }
00321 if(stopped_) return;
00322
00323 unsigned int DOF = md_params_->getDOF();
00324 std::vector<std::string> joint_names = md_params_->getJointNames();
00325 std::vector<double> cmd_pos(DOF);
00326
00327
00328
00329 std::string unit = "rad";
00330
00332 if (msg->positions.size() != DOF)
00333 {
00334 ROS_ERROR("Skipping command: Commanded positions and DOF are not same dimension.");
00335 return;
00336 }
00337
00339 for (unsigned int i = 0; i < DOF; i++)
00340 {
00342 if (msg->positions[i].joint_uri != joint_names[i])
00343 {
00344 ROS_ERROR("Skipping command: Received joint name %s doesn't match expected joint name %s for joint %d.", msg->positions[i].joint_uri.c_str(), joint_names[i].c_str(), i);
00345 return;
00346 }
00347
00349 if (msg->positions[i].unit != unit)
00350 {
00351 ROS_ERROR("Skipping command: Received unit %s doesn't match expected unit %s.", msg->positions[i].unit.c_str(), unit.c_str());
00352 return;
00353 }
00354
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00369 ROS_DEBUG("Parsing of position %f for joint %s successful.", msg->positions[i].value, joint_names[i].c_str());
00370 cmd_pos[i] = msg->positions[i].value;
00371
00372 }
00373
00374 if( !md_ctrl_->movePos(cmd_pos) )
00375 {
00376 error_ = true;
00377 error_msg_ = md_ctrl_->getErrorMessage();
00378 ROS_ERROR("Joint reposition error: %s", md_ctrl_->getErrorMessage().c_str());
00379 return;
00380 }
00381
00382 ROS_INFO("Successfully executed position command");
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00398
00399
00400
00401
00402
00403
00405
00406
00408
00409
00410
00411
00412
00413
00415
00416
00417
00418
00419
00420
00422
00423
00424
00425
00426
00427
00428
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 bool srvCallbackInit(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res)
00452 {
00453 if (!initialized_)
00454 {
00455 ROS_INFO("Initializing COB3DMD...");
00456
00458 if (md_ctrl_->init(md_params_))
00459 {
00460 initialized_ = true;
00461 res.success.data = true;
00462 ROS_INFO("...initializing COB3DMD successful");
00463 }
00464 else
00465 {
00466 error_ = true;
00467 error_msg_ = md_ctrl_->getErrorMessage();
00468 res.success.data = false;
00469 res.error_message.data = md_ctrl_->getErrorMessage();
00470 ROS_ERROR("...initializing COB3DMD unsuccessful. Error: %s", res.error_message.data.c_str());
00471 }
00472 }
00473 else
00474 {
00475 error_ = false;
00476 res.success.data = false;
00477 res.error_message.data = "COB3DMD already initialized";
00478 ROS_WARN("...initializing COB3DMD unsuccessful. Warn: %s", res.error_message.data.c_str());
00479 }
00480
00481 return true;
00482 }
00486 bool srvCallbackStop(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res)
00487 {
00488 if( initialized_ )
00489 {
00490 stopped_ = true;
00491 if( md_ctrl_->stop() )
00492 {
00493 ROS_INFO("Stopping COB3DMD successful");
00494 res.success.data = true;
00495
00496 }
00497 else
00498 {
00499 res.success.data = false;
00500 md_ctrl_->getErrorMessage();
00501 ROS_ERROR("!!...stopping COB3DMD unsuccessful. Error: %s", res.error_message.data.c_str());
00502 }
00503 }
00504 else
00505 {
00506 res.success.data = false;
00507 res.error_message.data = "Not initialized";
00508 ROS_WARN("...stopping COB3DMD unsuccessful. Warn: %s", res.error_message.data.c_str());
00509 }
00510 return true;
00511 }
00512
00513 bool srvCallbackRecover(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res)
00514 {
00515 ROS_WARN("Attempting to recover...");
00516
00517 if (!initialized_)
00518 {
00519 error_msg_ = "Not Initialized";
00520 res.success.data = false;
00521 res.error_message.data = error_msg_;
00522 ROS_ERROR("...recovering COB3DMD unsuccessful. Error: %s", error_msg_.c_str());
00523 return false;
00524 }
00525 else
00526 {
00527 ROS_WARN("Recalibrating COB3DMD now...");
00528 if( !md_ctrl_->recover() )
00529 {
00530 error_ = true;
00531 error_msg_ = md_ctrl_->getErrorMessage();
00532 res.success.data = false;
00533 res.error_message.data = md_ctrl_->getErrorMessage();
00534 ROS_ERROR("...recovering COB3DMD unsuccessful. Error: %s", res.error_message.data.c_str());
00535 return false;
00536 }
00537 else
00538 {
00539 error_ = false;
00540 error_msg_ = "";
00541 res.success.data = true;
00542 res.error_message.data = error_msg_;
00543 ROS_INFO("...recovering COB3DMD successful");
00544 return true;
00545 }
00546 }
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 bool publishStates()
00571 {
00572 last_publish_time_ = ros::Time::now();
00573
00574 if(initialized_)
00575 {
00576 if( md_ctrl_->updatePositions() )
00577 {
00579 sensor_msgs::JointState joint_state_msg;
00580 joint_state_msg.header.stamp = ros::Time::now();
00581 joint_state_msg.header.frame_id = "COB3DMD";
00582 joint_state_msg.name = md_params_->getJointNames();
00583 joint_state_msg.position = md_ctrl_->getPositions();
00584 joint_state_msg.velocity = md_ctrl_->getVelocities();
00585
00586 ROS_DEBUG("Publishing COB3DMD state");
00587 topic_pub_joint_state_.publish(joint_state_msg);
00588 }
00589 else
00590 {
00591 ROS_ERROR("Pan reported position incongruency. Run recal");
00592 error_ = true;
00593 }
00594 }
00595
00597
00598
00599
00600
00601
00602 diagnostic_msgs::DiagnosticArray diagnostics;
00603 diagnostics.status.resize(1);
00604
00605
00606 if(error_)
00607 {
00608 diagnostics.status[0].level = 2;
00609 diagnostics.status[0].name = n_.getNamespace();;
00610 diagnostics.status[0].message = md_ctrl_->getErrorMessage();
00611 }
00612 else
00613 {
00614 if (initialized_)
00615 {
00616 diagnostics.status[0].level = 0;
00617 diagnostics.status[0].name = n_.getNamespace();
00618 diagnostics.status[0].message = "cob_3d_mapping_demonstrator is running";
00619 }
00620 else
00621 {
00622 diagnostics.status[0].level = 1;
00623 diagnostics.status[0].name = n_.getNamespace();
00624 diagnostics.status[0].message = "cob_3d_mapping_demonstrator not initialized";
00625 }
00626 }
00627
00628 topic_pub_diagnostic_.publish(diagnostics);
00629
00630 return true;
00631 }
00632 };
00633
00634
00635 int main(int argc, char **argv)
00636 {
00637
00638
00640 ros::init(argc, argv, "cob_3d_mapping_demonstrator_node");
00641
00642 DemonstratorNode md_node;
00643
00644 if(!md_node.getROSParameters()) return 0;
00645 md_node.getRobotDescriptionParameters();
00646 if( md_node.auto_init_ )
00647 md_node.runAutoInit();
00648
00650 double frequency;
00651 if (md_node.n_.hasParam("frequency"))
00652 {
00653 md_node.n_.getParam("frequency", frequency);
00654 ROS_INFO("Parameter frequency set to %f Hz", frequency);
00655 }
00656 else
00657 {
00658 frequency = 50 ;
00659 ROS_WARN("Parameter frequency not defined, setting to %f Hz", frequency);
00660 }
00661
00663 ros::Duration min_publish_duration;
00664 if (md_node.n_.hasParam("min_publish_duration"))
00665 {
00666 double sec;
00667 md_node.n_.getParam("min_publish_duration", sec);
00668 ROS_INFO("Parameter min publish duration set to %f seconds", sec);
00669 min_publish_duration.fromSec(sec);
00670 }
00671 else
00672 {
00673 min_publish_duration.fromSec(1 / frequency);
00674 ROS_WARN("Parameter min_publish_duration not defined, setting to %f sec", min_publish_duration.toSec());
00675 }
00676
00678 ros::Rate loop_rate(frequency);
00679
00680 while (md_node.n_.ok())
00681 {
00682
00683 {
00684 md_node.publishStates();
00685 }
00686
00688 ros::spinOnce();
00689 loop_rate.sleep();
00690 }
00691
00692 return 0;
00693 }