00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00056
00057
00058
00059
00060 #include <stdlib.h>
00061 #include <unistd.h>
00062 #include <stdio.h>
00063 #include <string.h>
00064 #include <string>
00065 #include <map>
00066
00067
00068
00069
00070 #include <boost/bind.hpp>
00071
00072
00073
00074
00075 #include "ros/ros.h"
00076 #include "actionlib/server/simple_action_server.h"
00077
00078
00079
00080
00081 #include "trajectory_msgs/JointTrajectory.h"
00082 #include "sensor_msgs/JointState.h"
00083 #include "industrial_msgs/RobotStatus.h"
00084 #include "hekateros_control/HekJointStateExtended.h"
00085 #include "hekateros_control/HekRobotStatusExtended.h"
00086
00087
00088
00089
00090 #include "hekateros_control/Calibrate.h"
00091 #include "hekateros_control/ClearAlarms.h"
00092 #include "hekateros_control/CloseGripper.h"
00093 #include "hekateros_control/EStop.h"
00094 #include "hekateros_control/Freeze.h"
00095 #include "hekateros_control/GetProductInfo.h"
00096 #include "hekateros_control/GotoBalancedPos.h"
00097 #include "hekateros_control/GotoParkedPos.h"
00098 #include "hekateros_control/GotoZeroPt.h"
00099 #include "hekateros_control/IsAlarmed.h"
00100 #include "hekateros_control/IsCalibrated.h"
00101 #include "hekateros_control/IsDescLoaded.h"
00102 #include "hekateros_control/OpenGripper.h"
00103 #include "hekateros_control/Release.h"
00104 #include "hekateros_control/ResetEStop.h"
00105 #include "hekateros_control/SetRobotMode.h"
00106 #include "hekateros_control/Stop.h"
00107
00108
00109
00110
00111 #include "hekateros_control/CalibrateAction.h"
00112
00113
00114
00115
00116 #include "rnr/rnrconfig.h"
00117 #include "rnr/log.h"
00118
00119
00120
00121
00122 #include "Hekateros/hekateros.h"
00123 #include "Hekateros/hekXmlCfg.h"
00124 #include "Hekateros/hekRobot.h"
00125 #include "Hekateros/hekUtils.h"
00126
00127
00128
00129
00130 #include "hekateros_control.h"
00131
00132
00133 using namespace std;
00134 using namespace hekateros;
00135 using namespace hekateros_control;
00136
00137
00138
00139
00140
00141
00142 HekaterosControl::HekaterosControl(ros::NodeHandle &nh, double hz) :
00143 m_nh(nh), m_hz(hz)
00144 {
00145 }
00146
00147 HekaterosControl::~HekaterosControl()
00148 {
00149 disconnect();
00150 }
00151
00152 int HekaterosControl::configure(const string &strCfgFile)
00153 {
00154 HekXmlCfg xml;
00155 int rc;
00156
00157 if( (rc = xml.loadFile(strCfgFile)) < 0 )
00158 {
00159 ROS_ERROR("Loading XML file '%s' failed.", strCfgFile.c_str());
00160 }
00161
00162 else if( (rc = xml.setHekDescFromDOM(*m_robot.getHekDesc())) < 0 )
00163 {
00164 ROS_ERROR("Setting robot description failed.");
00165 }
00166
00167 else if( (rc = m_robot.getHekDesc()->markAsDescribed()) < 0 )
00168 {
00169 ROS_ERROR("Failed to finalize descriptions.");
00170 }
00171
00172 else
00173 {
00174 ROS_INFO("Hekateros description loaded:\n\t %s",
00175 m_robot.getHekDesc()->getFullProdBrief().c_str());
00176 rc = HEK_OK;
00177 }
00178
00179 return rc;
00180 }
00181
00182
00183
00184
00185
00186
00187 void HekaterosControl::advertiseServices()
00188 {
00189 string strSvc;
00190
00191 strSvc = "calibrate";
00192 m_services[strSvc] = m_nh.advertiseService(strSvc,
00193 &HekaterosControl::calibrate,
00194 &(*this));
00195
00196 strSvc = "clear_alarms";
00197 m_services[strSvc] = m_nh.advertiseService(strSvc,
00198 &HekaterosControl::clearAlarms,
00199 &(*this));
00200
00201 strSvc = "close_gripper";
00202 m_services[strSvc] = m_nh.advertiseService(strSvc,
00203 &HekaterosControl::closeGripper,
00204 &(*this));
00205
00206 strSvc = "estop";
00207 m_services[strSvc] = m_nh.advertiseService(strSvc,
00208 &HekaterosControl::estop,
00209 &(*this));
00210
00211 strSvc = "freeze";
00212 m_services[strSvc] = m_nh.advertiseService(strSvc,
00213 &HekaterosControl::freeze,
00214 &(*this));
00215
00216 strSvc = "get_product_info";
00217 m_services[strSvc] = m_nh.advertiseService(strSvc,
00218 &HekaterosControl::getProductInfo,
00219 &(*this));
00220
00221 strSvc = "goto_balanced";
00222 m_services[strSvc] = m_nh.advertiseService(strSvc,
00223 &HekaterosControl::gotoBalancedPos,
00224 &(*this));
00225
00226 strSvc = "goto_parked";
00227 m_services[strSvc] = m_nh.advertiseService(strSvc,
00228 &HekaterosControl::gotoParkedPos,
00229 &(*this));
00230
00231 strSvc = "goto_zero";
00232 m_services[strSvc] = m_nh.advertiseService(strSvc,
00233 &HekaterosControl::gotoZeroPt,
00234 &(*this));
00235
00236 strSvc = "is_alarmed";
00237 m_services[strSvc] = m_nh.advertiseService(strSvc,
00238 &HekaterosControl::isAlarmed,
00239 &(*this));
00240
00241 strSvc = "is_calibrated";
00242 m_services[strSvc] = m_nh.advertiseService(strSvc,
00243 &HekaterosControl::isCalibrated,
00244 &(*this));
00245
00246 strSvc = "is_desc_loaded";
00247 m_services[strSvc] = m_nh.advertiseService(strSvc,
00248 &HekaterosControl::isDescLoaded,
00249 &(*this));
00250
00251 strSvc = "open_gripper";
00252 m_services[strSvc] = m_nh.advertiseService(strSvc,
00253 &HekaterosControl::openGripper,
00254 &(*this));
00255
00256 strSvc = "release";
00257 m_services[strSvc] = m_nh.advertiseService(strSvc,
00258 &HekaterosControl::release,
00259 &(*this));
00260
00261 strSvc = "reset_estop";
00262 m_services[strSvc] = m_nh.advertiseService(strSvc,
00263 &HekaterosControl::resetEStop,
00264 &(*this));
00265
00266 strSvc = "set_robot_mode";
00267 m_services[strSvc] = m_nh.advertiseService(strSvc,
00268 &HekaterosControl::setRobotMode,
00269 &(*this));
00270
00271 strSvc = "stop";
00272 m_services[strSvc] = m_nh.advertiseService(strSvc,
00273 &HekaterosControl::stop,
00274 &(*this));
00275 }
00276
00277 bool HekaterosControl::calibrate(Calibrate::Request &req,
00278 Calibrate::Response &rsp)
00279 {
00280 const char *svc = "calibrate";
00281
00282 ROS_DEBUG("%s", svc);
00283
00284 rsp.rc = m_robot.calibrate(req.force_recalib);
00285
00286 if( rsp.rc == HEK_OK )
00287 {
00288 ROS_INFO("Robot calibrated.");
00289 return true;
00290 }
00291 else
00292 {
00293 ROS_ERROR("%s failed. %s(rc=%d).", svc, getStrError(rsp.rc), rsp.rc);
00294 return false;
00295 }
00296 }
00297
00298 bool HekaterosControl::clearAlarms(ClearAlarms::Request &req,
00299 ClearAlarms::Response &rsp)
00300 {
00301 const char *svc = "clear_alarms";
00302
00303 ROS_DEBUG("%s", svc);
00304
00305 m_robot.clearAlarms();
00306
00307 return true;
00308 }
00309
00310 bool HekaterosControl::closeGripper(CloseGripper::Request &req,
00311 CloseGripper::Response &rsp)
00312 {
00313 const char *svc = "close_gripper";
00314 int rc;
00315
00316 ROS_DEBUG("%s", svc);
00317
00318 rc = m_robot.closeGripper();
00319
00320 if( rc == HEK_OK )
00321 {
00322 ROS_INFO("Closing gripper.");
00323 return true;
00324 }
00325 else
00326 {
00327 ROS_ERROR("%s failed. %s(rc=%d).", svc, getStrError(rc), rc);
00328 return false;
00329 }
00330 }
00331
00332 bool HekaterosControl::estop(EStop::Request &req,
00333 EStop::Response &rsp)
00334 {
00335 const char *svc = "estop";
00336
00337 ROS_DEBUG("%s", svc);
00338
00339 m_robot.estop();
00340
00341 ROS_INFO("ESTOPPED! You must issue a \"reset_estop\" to continue.");
00342
00343 return true;
00344 }
00345
00346 bool HekaterosControl::freeze(Freeze::Request &req,
00347 Freeze::Response &rsp)
00348 {
00349 const char *svc = "freeze";
00350
00351 ROS_DEBUG("%s", svc);
00352
00353 m_robot.freeze();
00354
00355 ROS_INFO("Robot position frozen.");
00356
00357 return true;
00358 }
00359
00360 bool HekaterosControl::getProductInfo(GetProductInfo::Request &req,
00361 GetProductInfo::Response &rsp)
00362 {
00363 const char *svc = "get_product_info";
00364
00365 int nMajor, nMinor, nRev;
00366
00367 ROS_DEBUG("%s", svc);
00368
00369 if( !m_robot.isDescribed() )
00370 {
00371 ROS_ERROR("%s failed: "
00372 "Robot description not loaded - unable to determine info.",
00373 svc);
00374 return false;
00375 }
00376
00377 m_robot.getVersion(nMajor, nMinor, nRev);
00378
00379 rsp.i.maj = nMajor;
00380 rsp.i.min = nMinor;
00381 rsp.i.rev = nRev;
00382 rsp.i.version_string = m_robot.getVersion();
00383 rsp.i.product_id = m_robot.getProdId();
00384 rsp.i.product_name = m_robot.getProdName();
00385 rsp.i.desc = m_robot.getFullProdBrief();
00386
00387 return true;
00388 }
00389
00390 bool HekaterosControl::gotoBalancedPos(GotoBalancedPos::Request &req,
00391 GotoBalancedPos::Response &rsp)
00392 {
00393 const char *svc = "goto_balanced";
00394
00395 ROS_DEBUG("%s", svc);
00396
00397 rsp.rc = m_robot.gotoBalancedPos();
00398
00399 if( rsp.rc == HEK_OK )
00400 {
00401 ROS_INFO("Moving Hekateros to balanced position.");
00402 return true;
00403 }
00404 else
00405 {
00406 ROS_ERROR("%s failed. %s(rc=%d).", svc, getStrError(rsp.rc), rsp.rc);
00407 return false;
00408 }
00409 }
00410
00411 bool HekaterosControl::gotoParkedPos(GotoParkedPos::Request &req,
00412 GotoParkedPos::Response &rsp)
00413 {
00414 const char *svc = "goto_zero";
00415
00416 ROS_DEBUG("%s", svc);
00417
00418 rsp.rc = m_robot.gotoParkedPos();
00419
00420 if( rsp.rc == HEK_OK )
00421 {
00422 ROS_INFO("Moving Hekateros to parked position.");
00423 return true;
00424 }
00425 else
00426 {
00427 ROS_ERROR("%s failed. %s(rc=%d).", svc, getStrError(rsp.rc), rsp.rc);
00428 return false;
00429 }
00430 }
00431
00432 bool HekaterosControl::gotoZeroPt(GotoZeroPt::Request &req,
00433 GotoZeroPt::Response &rsp)
00434 {
00435 const char *svc = "goto_zero";
00436
00437 ROS_DEBUG("%s", svc);
00438
00439 rsp.rc = m_robot.gotoZeroPtPos();
00440
00441 if( rsp.rc == HEK_OK )
00442 {
00443 ROS_INFO("Moving Hekateros to calibrated zero point.");
00444 return true;
00445 }
00446 else
00447 {
00448 ROS_ERROR("%s failed. %s(rc=%d).", svc, getStrError(rsp.rc), rsp.rc);
00449 return false;
00450 }
00451 }
00452
00453 bool HekaterosControl::isAlarmed(IsAlarmed::Request &req,
00454 IsAlarmed::Response &rsp)
00455 {
00456 const char *svc = "is_alarmed";
00457
00458 ROS_DEBUG("%s", svc);
00459
00460 rsp.is_alarmed = m_robot.isAlarmed();
00461
00462 if( rsp.is_alarmed )
00463 {
00464 ROS_WARN("Hekateros is alarmed.");
00465 }
00466
00467 return true;
00468 }
00469
00470 bool HekaterosControl::isCalibrated(IsCalibrated::Request &req,
00471 IsCalibrated::Response &rsp)
00472 {
00473 const char *svc = "is_calibrated";
00474
00475 ROS_DEBUG("%s", svc);
00476
00477 rsp.is_calibrated = m_robot.isCalibrated();
00478
00479 if( !rsp.is_calibrated )
00480 {
00481 ROS_WARN("Hekateros is not calibrated.");
00482 }
00483
00484 return true;
00485 }
00486
00487 bool HekaterosControl::isDescLoaded(IsDescLoaded::Request &req,
00488 IsDescLoaded::Response &rsp)
00489 {
00490 const char *svc = "is_desc_loaded";
00491
00492 ROS_DEBUG("%s", svc);
00493
00494 rsp.is_desc_loaded = m_robot.isCalibrated();
00495
00496 if( !rsp.is_desc_loaded )
00497 {
00498 ROS_WARN("Hekateros description file not loaded.");
00499 }
00500
00501 return true;
00502 }
00503
00504 bool HekaterosControl::openGripper(OpenGripper::Request &req,
00505 OpenGripper::Response &rsp)
00506 {
00507 const char *svc = "open_gripper";
00508 int rc;
00509
00510 ROS_DEBUG("%s", svc);
00511
00512 rc = m_robot.openGripper();
00513
00514 if( rc == HEK_OK )
00515 {
00516 ROS_INFO("Opening gripper.");
00517 return true;
00518 }
00519 else
00520 {
00521 ROS_ERROR("%s failed. %s(rc=%d).", svc, getStrError(rc), rc);
00522 return false;
00523 }
00524 }
00525
00526 bool HekaterosControl::release(Release::Request &req,
00527 Release::Response &rsp)
00528 {
00529 const char *svc = "release";
00530
00531 ROS_DEBUG("%s", svc);
00532
00533 m_robot.release();
00534
00535 ROS_INFO("Robot released, motors are undriven.");
00536
00537 return true;
00538 }
00539
00540 bool HekaterosControl::resetEStop(ResetEStop::Request &req,
00541 ResetEStop::Response &rsp)
00542 {
00543 const char *svc = "reset_estop";
00544
00545 ROS_DEBUG("%s", svc);
00546
00547 m_robot.resetEStop();
00548
00549 ROS_INFO("EStop reset.");
00550
00551 return true;
00552 }
00553
00554 bool HekaterosControl::setRobotMode(SetRobotMode::Request &req,
00555 SetRobotMode::Response &rsp)
00556 {
00557 const char *svc = "set_robot_mode";
00558
00559 ROS_DEBUG("%s", svc);
00560
00561 m_robot.setRobotMode((HekRobotMode)req.mode.val);
00562
00563 ROS_INFO("Robot mode set to %d.", req.mode.val);
00564
00565 return true;
00566 }
00567
00568 bool HekaterosControl::stop(Stop::Request &req,
00569 Stop::Response &rsp)
00570 {
00571 const char *svc = "stop";
00572
00573 int n;
00574
00575 ROS_DEBUG("%s", svc);
00576
00577 n = m_robot.stop(req.joint_names);
00578
00579 ROS_INFO("Stopped %d joints.", n);
00580
00581 return true;
00582 }
00583
00584
00585
00586
00587
00588
00589 void HekaterosControl::advertisePublishers(int nQueueDepth)
00590 {
00591 string strPub;
00592
00593 strPub = "joint_states";
00594 m_publishers[strPub] =
00595 m_nh.advertise<sensor_msgs::JointState>(strPub, nQueueDepth);
00596
00597 strPub = "joint_states_ex";
00598 m_publishers[strPub] =
00599 m_nh.advertise<HekJointStateExtended>(strPub,nQueueDepth);
00600
00601 strPub = "robot_status";
00602 m_publishers[strPub] =
00603 m_nh.advertise<industrial_msgs::RobotStatus>(strPub, nQueueDepth);
00604
00605 strPub = "robot_status_ex";
00606 m_publishers[strPub] =
00607 m_nh.advertise<HekRobotStatusExtended>(strPub, nQueueDepth);
00608 }
00609
00610 void HekaterosControl::publish()
00611 {
00612 publishJointState();
00613 publishRobotStatus();
00614 }
00615
00616 void HekaterosControl::publishJointState()
00617 {
00618 HekJointStatePoint state;
00619
00620
00621 m_robot.getJointState(state);
00622
00623
00624 updateJointStateMsg(state, m_msgJointState);
00625
00626
00627 m_publishers["joint_states"].publish(m_msgJointState);
00628
00629
00630 updateExtendedJointStateMsg(state, m_msgJointStateEx);
00631
00632
00633 m_publishers["joint_states_ex"].publish(m_msgJointStateEx);
00634 }
00635
00636 void HekaterosControl::publishRobotStatus()
00637 {
00638 HekRobotState status;
00639
00640
00641 m_robot.getRobotState(status);
00642
00643
00644 updateRobotStatusMsg(status, m_msgRobotStatus);
00645
00646
00647 m_publishers["robot_status"].publish(m_msgRobotStatus);
00648
00649
00650 updateExtendedRobotStatusMsg(status, m_msgRobotStatusEx);
00651
00652
00653 m_publishers["robot_status_ex"].publish(m_msgRobotStatusEx);
00654 }
00655
00656 void HekaterosControl::updateJointStateMsg(HekJointStatePoint &state,
00657 sensor_msgs::JointState &msg)
00658 {
00659
00660
00661
00662 msg.name.clear();
00663 msg.position.clear();
00664 msg.velocity.clear();
00665 msg.effort.clear();
00666
00667
00668
00669
00670 msg.header.stamp = ros::Time::now();
00671 msg.header.frame_id = "0";
00672 msg.header.seq++;
00673
00674
00675
00676
00677 for(int n=0; n<state.getNumPoints(); ++n)
00678 {
00679
00680 msg.name.push_back(state[n].m_strName);
00681 msg.position.push_back(state[n].m_fPosition);
00682 msg.velocity.push_back(state[n].m_fVelocity);
00683 msg.effort.push_back(state[n].m_fEffort);
00684 }
00685 }
00686
00687 void HekaterosControl::updateExtendedJointStateMsg(HekJointStatePoint &state,
00688 HekJointStateExtended &msg)
00689 {
00690 HekOpState opstate;
00691
00692
00693
00694
00695 msg.name.clear();
00696 msg.position.clear();
00697 msg.velocity.clear();
00698 msg.effort.clear();
00699 msg.master_servo_id.clear();
00700 msg.slave_servo_id.clear();
00701 msg.odometer_pos.clear();
00702 msg.encoder_pos.clear();
00703 msg.raw_speed.clear();
00704 msg.op_state.clear();
00705
00706
00707
00708
00709 msg.header.stamp = ros::Time::now();
00710 msg.header.frame_id = "0";
00711 msg.header.seq++;
00712
00713
00714
00715
00716 for(int n=0; n<state.getNumPoints(); ++n)
00717 {
00718 msg.name.push_back(state[n].m_strName);
00719 msg.position.push_back(state[n].m_fPosition);
00720 msg.velocity.push_back(state[n].m_fVelocity);
00721 msg.effort.push_back(state[n].m_fEffort);
00722 msg.master_servo_id.push_back(state[n].m_nMasterServoId);
00723 msg.slave_servo_id.push_back(state[n].m_nSlaveServoId);
00724 msg.odometer_pos.push_back(state[n].m_nOdPos);
00725 msg.encoder_pos.push_back(state[n].m_nEncPos);
00726 msg.raw_speed.push_back(state[n].m_nSpeed);
00727
00728 opstate.calib_state = state[n].m_eOpState;
00729 msg.op_state.push_back(opstate);
00730 }
00731 }
00732
00733 void HekaterosControl::updateRobotStatusMsg(HekRobotState &status,
00734 industrial_msgs::RobotStatus &msg)
00735 {
00736
00737
00738
00739 msg.header.stamp = ros::Time::now();
00740 msg.header.frame_id = "0";
00741 msg.header.seq++;
00742
00743
00744
00745
00746 msg.mode.val = status.m_eRobotMode;
00747 msg.e_stopped.val = status.m_eIsEStopped;
00748 msg.drives_powered.val = status.m_eAreDrivesPowered;
00749 msg.motion_possible.val = status.m_eIsMotionPossible;
00750 msg.in_motion.val = status.m_eIsInMotion;
00751 msg.in_error.val = status.m_eIsInError;
00752 msg.error_code = status.m_nErrorCode;
00753
00754 }
00755
00756 void HekaterosControl::updateExtendedRobotStatusMsg(HekRobotState &status,
00757 HekRobotStatusExtended &msg)
00758 {
00759 ServoHealth sh;
00760 int i;
00761
00762
00763
00764
00765 msg.header.stamp = ros::Time::now();
00766 msg.header.frame_id = "0";
00767 msg.header.seq++;
00768
00769
00770
00771
00772 msg.mode.val = status.m_eRobotMode;
00773 msg.e_stopped.val = status.m_eIsEStopped;
00774 msg.drives_powered.val = status.m_eAreDrivesPowered;
00775 msg.motion_possible.val = status.m_eIsMotionPossible;
00776 msg.in_motion.val = status.m_eIsInMotion;
00777 msg.in_error.val = status.m_eIsInError;
00778 msg.error_code = status.m_nErrorCode;
00779 msg.is_calibrated.val = status.m_eIsCalibrated;
00780
00781
00782 msg.servo_health.clear();
00783
00784 for(i=0; i<status.m_vecServoHealth.size(); ++i)
00785 {
00786 sh.servo_id = (s8_t)status.m_vecServoHealth[i].m_nServoId;
00787 sh.temp = status.m_vecServoHealth[i].m_fTemperature;
00788 sh.voltage = status.m_vecServoHealth[i].m_fVoltage;
00789 sh.alarm = (u8_t)status.m_vecServoHealth[i].m_uAlarms;
00790
00791 msg.servo_health.push_back(sh);
00792 }
00793 }
00794
00795
00796
00797
00798
00799
00800 void HekaterosControl::subscribeToTopics(int nQueueDepth)
00801 {
00802 string strSub;
00803
00804 strSub = "joint_command";
00805 m_subscriptions[strSub] = m_nh.subscribe(strSub, nQueueDepth,
00806 &HekaterosControl::execJointCmd,
00807 &(*this));
00808 }
00809
00810 void HekaterosControl::execJointCmd(const trajectory_msgs::JointTrajectory &jt)
00811 {
00812 ROS_DEBUG("Executing joint_command.");
00813
00814 HekJointTrajectoryPoint pt;
00815
00816
00817 for(int j=0; j<jt.joint_names.size(); ++j)
00818 {
00819 pt.append(jt.joint_names[j],
00820 jt.points[0].positions[j],
00821 jt.points[0].velocities[j]);
00822 ROS_INFO("%s: pos=%5.3f speed=%2.1f", jt.joint_names[j].c_str(),
00823 jt.points[0].positions[j],
00824 jt.points[0].velocities[j]);
00825 }
00826
00827 m_robot.moveArm(pt);
00828 }