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 <sys/types.h>
00061 #include <stdlib.h>
00062 #include <unistd.h>
00063 #include <stdio.h>
00064 #include <math.h>
00065 #include <string.h>
00066 #include <string>
00067 #include <map>
00068
00069
00070
00071
00072 #include <boost/bind.hpp>
00073 #include "boost/assign.hpp"
00074
00075
00076
00077
00078 #include "ros/ros.h"
00079 #include "actionlib/server/simple_action_server.h"
00080
00081
00082
00083
00084 #include "trajectory_msgs/JointTrajectory.h"
00085 #include "sensor_msgs/JointState.h"
00086 #include "industrial_msgs/RobotStatus.h"
00087 #include "hekateros_control/HekJointStateExtended.h"
00088 #include "hekateros_control/HekRobotStatusExtended.h"
00089
00090
00091
00092
00093 #include "hekateros_control/Calibrate.h"
00094 #include "hekateros_control/ClearAlarms.h"
00095 #include "hekateros_control/CloseGripper.h"
00096 #include "hekateros_control/EStop.h"
00097 #include "hekateros_control/Freeze.h"
00098 #include "hekateros_control/GetProductInfo.h"
00099 #include "hekateros_control/GotoBalancedPos.h"
00100 #include "hekateros_control/GotoParkedPos.h"
00101 #include "hekateros_control/GotoZeroPt.h"
00102 #include "hekateros_control/IsAlarmed.h"
00103 #include "hekateros_control/IsCalibrated.h"
00104 #include "hekateros_control/IsDescLoaded.h"
00105 #include "hekateros_control/OpenGripper.h"
00106 #include "hekateros_control/Release.h"
00107 #include "hekateros_control/ResetEStop.h"
00108 #include "hekateros_control/SetRobotMode.h"
00109 #include "hekateros_control/Stop.h"
00110
00111
00112
00113
00114
00115
00116
00117
00118 #include "hid/ConnStatus.h"
00119 #include "hid/Controller360State.h"
00120 #include "hid/LEDPattern.h"
00121 #include "hid/RumbleCmd.h"
00122
00123
00124
00125
00126 #include "hid/SetLED.h"
00127 #include "hid/SetRumble.h"
00128
00129
00130
00131
00132 #include "rnr/rnrconfig.h"
00133 #include "rnr/log.h"
00134 #include "rnr/hid/HIDXbox360.h"
00135
00136
00137
00138
00139 #include "Hekateros/hekateros.h"
00140 #include "Hekateros/hekXmlCfg.h"
00141 #include "Hekateros/hekRobot.h"
00142 #include "Hekateros/hekUtils.h"
00143
00144
00145
00146
00147 #include "hek_teleop.h"
00148
00149 using namespace std;
00150 using namespace boost::assign;
00151 using namespace hid;
00152 using namespace hekateros;
00153 using namespace trajectory_msgs;
00154 using namespace industrial_msgs;
00155 using namespace hekateros_control;
00156
00157
00158
00159
00160 static string JointNameBaseRot("base_rot");
00161 static string JointNameShoulder("shoulder");
00162 static string JointNameElbow("elbow");
00163 static string JointNameWristPitch("wrist_pitch");
00164 static string JointNameWristRot("wrist_rot");
00165 static string JointNameGrip("grip");
00166
00167
00168
00169
00170
00171
00172 HekTeleop::HekTeleop(ros::NodeHandle &nh, double hz) : m_nh(nh), m_hz(hz)
00173 {
00174 m_eState = TeleopStateUninit;
00175 m_eMode = TeleopModeFirstPerson;
00176 m_bHasXboxComm = false;
00177 m_nWdXboxCounter = 0;
00178 m_nWdXboxTimeout = countsPerSecond(3.0);
00179 m_bRcvdRobotStatus = false;
00180 m_bRcvdJointState = false;
00181 m_bHasRobotComm = false;
00182 m_nWdRobotCounter = 0;
00183 m_nWdRobotTimeout = countsPerSecond(5.0);
00184 m_bHasFullComm = false;
00185
00186 m_buttonState = map_list_of
00187 (ButtonIdGotoBalPos, 0)
00188 (ButtonIdEStop, 0)
00189 (ButtonIdGotoParkedPos, 0)
00190 (ButtonIdGotoZeroPt, 0)
00191
00192 (ButtonIdPause, 0)
00193 (ButtonIdToggleMode, 0)
00194 (ButtonIdStart, 0)
00195
00196 (ButtonIdPrevJoint, 0)
00197 (ButtonIdNextJoint, 0)
00198
00199 (ButtonIdFineTune1, 0)
00200 (ButtonIdFineTune1, 0)
00201
00202 (ButtonIdMoveJoints, 0)
00203 (ButtonIdRotBase, 0)
00204 (ButtonIdPitchWrist, 0)
00205
00206 (ButtonIdRotWristCw, 0)
00207 (ButtonIdRotWristCcw, 0)
00208
00209 (ButtonIdOpenGripper, 0)
00210 (ButtonIdCloseGripper, 0);
00211
00212 m_rumbleLeft = 0;
00213 m_rumbleRight = 0;
00214
00215 m_fpState.m_bNewGoal = true;
00216 m_fpState.m_goalSign = 1.0;
00217 m_fpState.m_goalJoint.alpha = 0.0;
00218 m_fpState.m_goalJoint.beta = 0.0;
00219 m_fpState.m_goalJoint.gamma = 0.0;
00220 m_fpState.m_goalCart.x = 0.0;
00221 m_fpState.m_goalCart.y = 0.0;
00222
00223 m_bPreemptMove = false;
00224 m_fMoveTuning = 1.0;
00225 }
00226
00227 HekTeleop::~HekTeleop()
00228 {
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 void HekTeleop::clientServices()
00242 {
00243 string strSvc;
00244
00245 strSvc = "/xbox_360/set_led";
00246 m_clientServices[strSvc] = m_nh.serviceClient<hid::SetLED>(strSvc);
00247
00248 strSvc = "/xbox_360/set_rumble";
00249 m_clientServices[strSvc] = m_nh.serviceClient<hid::SetRumble>(strSvc);
00250
00251 strSvc = "/hekateros_control/estop";
00252 m_clientServices[strSvc] =
00253 m_nh.serviceClient<hekateros_control::EStop>(strSvc);
00254
00255 strSvc = "/hekateros_control/freeze";
00256 m_clientServices[strSvc] =
00257 m_nh.serviceClient<hekateros_control::Freeze>(strSvc);
00258
00259 strSvc = "/hekateros_control/stop";
00260 m_clientServices[strSvc] =
00261 m_nh.serviceClient<hekateros_control::Stop>(strSvc);
00262
00263 strSvc = "/hekateros_control/goto_balanced";
00264 m_clientServices[strSvc] =
00265 m_nh.serviceClient<hekateros_control::GotoBalancedPos>(strSvc);
00266
00267 strSvc = "/hekateros_control/goto_parked";
00268 m_clientServices[strSvc] =
00269 m_nh.serviceClient<hekateros_control::GotoParkedPos>(strSvc);
00270
00271 strSvc = "/hekateros_control/goto_zero";
00272 m_clientServices[strSvc] =
00273 m_nh.serviceClient<hekateros_control::GotoZeroPt>(strSvc);
00274
00275 strSvc = "/hekateros_control/reset_estop";
00276 m_clientServices[strSvc] =
00277 m_nh.serviceClient<hekateros_control::ResetEStop>(strSvc);
00278
00279 strSvc = "/hekateros_control/set_robot_mode";
00280 m_clientServices[strSvc] =
00281 m_nh.serviceClient<hekateros_control::SetRobotMode>(strSvc);
00282
00283 }
00284
00285 void HekTeleop::setLED(int pattern)
00286 {
00287 hid::SetLED svc;
00288
00289 svc.request.led_pattern.val = pattern;
00290
00291 if( m_clientServices["/xbox_360/set_led"].call(svc) )
00292 {
00293 ROS_DEBUG("Xbox360 LED set to pattern to %d.", pattern);
00294 }
00295 else
00296 {
00297 ROS_ERROR("Failed to set Xbox360 LED.");
00298 }
00299 }
00300
00301 void HekTeleop::setRumble(int motorLeft, int motorRight)
00302 {
00303 hid::SetRumble svc;
00304
00305
00306 if( (motorLeft == m_rumbleLeft) && (motorRight == m_rumbleRight) )
00307 {
00308 return;
00309 }
00310
00311 svc.request.left_rumble = motorLeft;
00312 svc.request.right_rumble = motorRight;
00313
00314 if( m_clientServices["/xbox_360/set_rumble"].call(svc) )
00315 {
00316 ROS_INFO("Xbox360 rumble motors set to %d, %d.", motorLeft, motorRight);
00317 m_rumbleLeft = motorLeft;
00318 m_rumbleRight = motorRight;
00319 }
00320 else
00321 {
00322 ROS_ERROR("Failed to set Xbox360 rumble motors.");
00323 }
00324 }
00325
00326 void HekTeleop::estop()
00327 {
00328 hekateros_control::EStop svc;
00329
00330 if( m_clientServices["/hekateros_control/estop"].call(svc) )
00331 {
00332 ROS_INFO("Robot emergency stopped.");
00333 }
00334 else
00335 {
00336 ROS_ERROR("Failed to estop robot.");
00337 }
00338 }
00339
00340 void HekTeleop::freeze()
00341 {
00342 hekateros_control::Freeze svc;
00343
00344 if( m_clientServices["/hekateros_control/freeze"].call(svc) )
00345 {
00346 ROS_INFO("Robot stopped.");
00347 }
00348 else
00349 {
00350 ROS_ERROR("Failed to freeze robot.");
00351 }
00352 }
00353
00354 void HekTeleop::gotoBalancedPos()
00355 {
00356 hekateros_control::GotoBalancedPos svc;
00357
00358 if( m_clientServices["/hekateros_control/goto_balanced"].call(svc) )
00359 {
00360 ROS_INFO("Moving to balanced position.");
00361 }
00362 else
00363 {
00364 ROS_ERROR("Failed to move.");
00365 }
00366 }
00367
00368 void HekTeleop::gotoParkedPos()
00369 {
00370 hekateros_control::GotoParkedPos svc;
00371
00372 if( m_clientServices["/hekateros_control/goto_parked"].call(svc) )
00373 {
00374 ROS_INFO("Moving to parked position.");
00375 }
00376 else
00377 {
00378 ROS_ERROR("Failed to move.");
00379 }
00380 }
00381
00382 void HekTeleop::gotoZeroPt()
00383 {
00384 hekateros_control::GotoZeroPt svc;
00385
00386 if( m_clientServices["/hekateros_control/goto_zero"].call(svc) )
00387 {
00388 ROS_INFO("Moving to zero point.");
00389 }
00390 else
00391 {
00392 ROS_ERROR("Failed to move.");
00393 }
00394 }
00395
00396 void HekTeleop::resetEStop()
00397 {
00398 hekateros_control::ResetEStop svc;
00399
00400 if( m_clientServices["/hekateros_control/reset_estop"].call(svc) )
00401 {
00402 ROS_INFO("Robot emergency stopped has been reset.");
00403 }
00404 else
00405 {
00406 ROS_ERROR("Failed to reset estop.");
00407 }
00408 }
00409
00410 void HekTeleop::setRobotMode(HekRobotMode mode)
00411 {
00412 hekateros_control::SetRobotMode svc;
00413
00414 svc.request.mode.val = mode;
00415
00416 if( m_clientServices["/hekateros_control/set_robot_mode"].call(svc) )
00417 {
00418 ROS_INFO("Robot mode set to %d.", mode);
00419 }
00420 else
00421 {
00422 ROS_ERROR("Failed to set robot mode.");
00423 }
00424 }
00425
00426 void HekTeleop::stop(const vector<string> &vecJointNames)
00427 {
00428 hekateros_control::Stop svc;
00429
00430 svc.request.joint_names = vecJointNames;
00431
00432 if( m_clientServices["/hekateros_control/stop"].call(svc) )
00433 {
00434 ROS_INFO("Robot joint(s) stopped.");
00435 }
00436 else
00437 {
00438 ROS_ERROR("Failed to call 'stop' robot service.");
00439 }
00440 }
00441
00442
00443
00444
00445
00446
00447 void HekTeleop::advertisePublishers(int nQueueDepth)
00448 {
00449 string strPub;
00450
00451 strPub = "/hekateros_control/joint_command";
00452 m_publishers[strPub] =
00453 m_nh.advertise<trajectory_msgs::JointTrajectory>(strPub, nQueueDepth);
00454
00455 strPub = "/xbox_360/rumble_command";
00456 m_publishers[strPub] =
00457 m_nh.advertise<hid::RumbleCmd>(strPub, nQueueDepth);
00458 }
00459
00460 void HekTeleop::publishJointCmd()
00461 {
00462 static bool bPubJointCmd = false;
00463
00464
00465 if( hasWorkingTrajectory() )
00466 {
00467 m_msgJointTraj.header.stamp = ros::Time::now();
00468 m_msgJointTraj.header.frame_id = "0";
00469 m_msgJointTraj.header.seq++;
00470 m_msgJointTraj.points.push_back(m_msgJointTrajPoint);
00471
00472
00473 m_publishers["/hekateros_control/joint_command"].publish(m_msgJointTraj);
00474
00475 bPubJointCmd = true;
00476 }
00477
00478
00479 else if( bPubJointCmd && !hasActiveTrajectory() )
00480 {
00481 if( m_msgRobotStatus.in_motion.val == TriState::FALSE )
00482 {
00483
00484 clearActiveTrajectory();
00485 bPubJointCmd = false;
00486 }
00487 }
00488 }
00489
00490 void HekTeleop::publishRumbleCmd(int motorLeft, int motorRight)
00491 {
00492 RumbleCmd msg;
00493
00494 msg.left_rumble = motorLeft;
00495 msg.right_rumble = motorRight;
00496
00497
00498 m_publishers["/xbox_360/rumble_command"].publish(msg);
00499 }
00500
00501
00502
00503
00504
00505
00506 void HekTeleop::subscribeToTopics(int nQueueDepth)
00507 {
00508 string strSub;
00509
00510 strSub = "/hekateros_control/robot_status_ex";
00511 m_subscriptions[strSub] = m_nh.subscribe(strSub, nQueueDepth,
00512 &HekTeleop::cbRobotStatus,
00513 &(*this));
00514
00515 strSub = "/hekateros_control/joint_states_ex";
00516 m_subscriptions[strSub] = m_nh.subscribe(strSub, nQueueDepth,
00517 &HekTeleop::cbJointState,
00518 &(*this));
00519
00520 strSub = "/xbox_360/conn_status";
00521 m_subscriptions[strSub] = m_nh.subscribe(strSub, nQueueDepth,
00522 &HekTeleop::cbXboxConnStatus,
00523 &(*this));
00524
00525 strSub = "/xbox_360/controller_360_state";
00526 m_subscriptions[strSub] = m_nh.subscribe(strSub, nQueueDepth,
00527 &HekTeleop::cbXboxBttnState,
00528 &(*this));
00529 }
00530
00531 void HekTeleop::cbRobotStatus(const HekRobotStatusExtended &msg)
00532 {
00533 ROS_DEBUG("Received robot status.");
00534
00535
00536
00537 m_msgRobotStatus = msg;
00538 m_bRcvdRobotStatus = true;
00539 m_bHasRobotComm = m_bRcvdJointState;
00540 m_nWdRobotCounter = 0;
00541 }
00542
00543 void HekTeleop::cbJointState(const HekJointStateExtended &msg)
00544 {
00545 static float DeadZone = 256.0;
00546 static float Scale = (float)XBOX360_RUMBLE_RIGHT_MAX/(1023.0 - DeadZone);
00547
00548
00549 ssize_t i;
00550 float effort;
00551 int rumbleRight;
00552
00553 ROS_DEBUG("Received joint state.");
00554
00555 m_nWdRobotCounter = 0;
00556 m_msgJointState = msg;
00557 m_bRcvdJointState = true;
00558
00559 m_mapCurPos.clear();
00560 m_mapCurVel.clear();
00561
00562 for(i=0; i<msg.name.size(); ++i)
00563 {
00564
00565 m_mapCurPos[msg.name[i]] = msg.position[i];
00566 m_mapCurVel[msg.name[i]] = msg.velocity[i];
00567
00568
00569
00570
00571 if( msg.name[i] == "grip" &&
00572 m_bHasFullComm &&
00573 (m_eState == TeleopStateReady) )
00574 {
00575 effort = fabs((float)msg.effort[i]);
00576
00577 if( effort > DeadZone )
00578 {
00579
00580
00581
00582 rumbleRight = XBOX360_RUMBLE_RIGHT_MAX/2;
00583 }
00584 else
00585 {
00586 rumbleRight = 0;
00587 }
00588
00589 setRumble(m_rumbleLeft, rumbleRight);
00590 }
00591 }
00592
00593
00594
00595
00596 if( msg.name.size() > m_mapTeleop.size() )
00597 {
00598 m_mapTeleop.clear();
00599
00600 for(i=0; i<msg.name.size(); ++i)
00601 {
00602 m_mapTeleop[msg.name[i]] = false;
00603 }
00604 }
00605 }
00606
00607 void HekTeleop::cbXboxConnStatus(const hid::ConnStatus &msg)
00608 {
00609 ROS_DEBUG("Received Xbox360 connectivity status.");
00610
00611 m_bHasXboxComm = msg.is_connected && msg.is_linked;
00612 m_nWdXboxCounter = 0;
00613
00614 m_msgConnStatus = msg;
00615 }
00616
00617 void HekTeleop::cbXboxBttnState(const hid::Controller360State &msg)
00618 {
00619 ButtonState buttonState;
00620
00621 ROS_DEBUG("Received Xbox360 button state.");
00622
00623 if( m_bHasFullComm )
00624 {
00625 msgToState(msg, buttonState);
00626
00627 switch( m_eState )
00628 {
00629 case TeleopStateReady:
00630 execAllButtonActions(buttonState);
00631 break;
00632 case TeleopStatePaused:
00633 buttonStart(buttonState);
00634 break;
00635 case TeleopStateUninit:
00636 default:
00637 pause();
00638 break;
00639 }
00640 }
00641
00642 m_buttonState = buttonState;
00643 }
00644
00645
00646
00647
00648
00649
00650 void HekTeleop::commCheck()
00651 {
00652 if( m_bHasXboxComm )
00653 {
00654 if( ++m_nWdXboxCounter >= m_nWdXboxTimeout )
00655 {
00656 m_bHasXboxComm = false;
00657 }
00658 }
00659
00660 if( m_bHasRobotComm )
00661 {
00662 if( ++m_nWdRobotCounter >= m_nWdRobotTimeout )
00663 {
00664 m_bHasRobotComm = false;
00665 }
00666 }
00667
00668 bool hasComm = m_bHasXboxComm && m_bHasRobotComm;
00669
00670
00671 if( m_bHasFullComm && !hasComm )
00672 {
00673 ROS_INFO("Lost communication with Xbox360 and/or Hek.");
00674 putRobotInSafeMode(m_msgConnStatus.is_connected);
00675 }
00676
00677 m_bHasFullComm = hasComm;
00678
00679
00680 if( m_eState == TeleopStatePaused )
00681 {
00682 driveLEDsFigure8Pattern();
00683 }
00684 }
00685
00686 void HekTeleop::putRobotInSafeMode(bool bHard)
00687 {
00688
00689 freeze();
00690
00691
00692 setRobotMode(HekRobotModeAuto);
00693
00694 if( bHard )
00695 {
00696
00697 }
00698
00699 m_eState = TeleopStateUninit;
00700
00701 setRumble(0, 0);
00702 setLED(LEDPatOn);
00703 }
00704
00705
00706
00707
00708
00709
00710 void HekTeleop::msgToState(const hid::Controller360State &msg,
00711 ButtonState &buttonState)
00712 {
00713 buttonState[ButtonIdGotoBalPos] = msg.a_button;
00714 buttonState[ButtonIdEStop] = msg.b_button;
00715 buttonState[ButtonIdGotoParkedPos] = msg.x_button;
00716 buttonState[ButtonIdGotoZeroPt] = msg.y_button;
00717
00718 buttonState[ButtonIdPause] = msg.back_button;
00719 buttonState[ButtonIdToggleMode] = msg.center_button;
00720 buttonState[ButtonIdStart] = msg.start_button;
00721
00722 buttonState[ButtonIdPrevJoint] = msg.dpad_down;
00723 buttonState[ButtonIdNextJoint] = msg.dpad_up;
00724
00725 buttonState[ButtonIdFineTune1] = msg.left_joy_click;
00726 buttonState[ButtonIdFineTune2] = msg.right_joy_click;
00727
00728 buttonState[ButtonIdMoveJoints] = msg.left_joy_y;
00729 buttonState[ButtonIdRotBase] = msg.left_joy_x;
00730 buttonState[ButtonIdPitchWrist] = msg.right_joy_y;
00731
00732 buttonState[ButtonIdRotWristCw] = msg.left_bump;
00733 buttonState[ButtonIdRotWristCcw] = msg.right_bump;
00734
00735 buttonState[ButtonIdOpenGripper] = msg.left_trig;
00736 buttonState[ButtonIdCloseGripper] = msg.right_trig;
00737 }
00738
00739 void HekTeleop::execAllButtonActions(ButtonState &buttonState)
00740 {
00741
00742
00743
00744 if( m_eState == TeleopStateReady )
00745 {
00746 buttonPause(buttonState);
00747 }
00748 else if( m_eState == TeleopStatePaused )
00749 {
00750 buttonStart(buttonState);
00751 }
00752
00753 if( m_eState != TeleopStateReady )
00754 {
00755 return;
00756 }
00757
00758
00759 buttonEStop(buttonState);
00760
00761
00762
00763
00764 buttonToggleMode(buttonState);
00765
00766 if( m_eMode != TeleopModeFirstPerson )
00767 {
00768 buttonPrevJoint(buttonState);
00769 buttonNextJoint(buttonState);
00770 }
00771
00772 buttonFineTune(buttonState);
00773
00774
00775
00776
00777 if( canMove() )
00778 {
00779 clearWorkingTrajectory();
00780 resetActiveTeleop();
00781
00782
00783 buttonGotoBalancedPos(buttonState);
00784 buttonGotoParkedPos(buttonState);
00785 buttonGotoZeroPt(buttonState);
00786
00787 if( m_bPreemptMove )
00788 {
00789 clearActiveTrajectory();
00790 }
00791
00792
00793 else
00794 {
00795 buttonCloseGripper(buttonState);
00796 buttonOpenGripper(buttonState);
00797 buttonPitchWrist(buttonState);
00798 buttonRotateWristCw(buttonState);
00799 buttonRotateWristCcw(buttonState);
00800 buttonRotateBase(buttonState);
00801 buttonMoveJoints(buttonState);
00802
00803 publishJointCmd();
00804 stopUnteleopJoints();
00805 }
00806 }
00807 }
00808
00809 void HekTeleop::buttonStart(ButtonState &buttonState)
00810 {
00811 if( buttonOffToOn(ButtonIdStart, buttonState) )
00812 {
00813 ROS_INFO("Manual operation active, auto mode disabled.");
00814
00815 setRobotMode(HekRobotModeManual);
00816
00817 if( m_msgRobotStatus.e_stopped.val == TriState::TRUE )
00818 {
00819 resetEStop();
00820 }
00821
00822 ready();
00823 }
00824 }
00825
00826 void HekTeleop::buttonPause(ButtonState &buttonState)
00827 {
00828 if( buttonOffToOn(ButtonIdPause, buttonState) )
00829 {
00830 ROS_INFO("Manual operation paused, auto mode enabled.");
00831
00832 setRobotMode(HekRobotModeAuto);
00833
00834 pause();
00835 }
00836 }
00837
00838 void HekTeleop::buttonToggleMode(ButtonState &buttonState)
00839 {
00840 if( buttonOffToOn(ButtonIdToggleMode, buttonState) )
00841 {
00842 if( m_eMode == TeleopModeFirstPerson )
00843 {
00844 m_eMode = TeleopModeShoulder;
00845 setLED(LEDPatShoulder);
00846 ROS_INFO("Move shoulder in isolation.");
00847 }
00848 else
00849 {
00850 m_eMode = TeleopModeFirstPerson;
00851 m_fpState.m_bNewGoal = true;
00852 setLED(LEDPatReady);
00853 ROS_INFO("First person mode.");
00854 }
00855 }
00856 }
00857
00858 void HekTeleop::buttonPrevJoint(ButtonState &buttonState)
00859 {
00860 if( buttonOffToOn(ButtonIdPrevJoint, buttonState) )
00861 {
00862 if( m_eMode == TeleopModeShoulder )
00863 {
00864 m_eMode = TeleopModeElbow;
00865 setLED(LEDPatElbow);
00866 ROS_INFO("Move elbow in isolation.");
00867 }
00868 else if( m_eMode == TeleopModeElbow )
00869 {
00870 m_eMode = TeleopModeShoulder;
00871 setLED(LEDPatShoulder);
00872 ROS_INFO("Move shoulder in isolation.");
00873 }
00874 }
00875 }
00876
00877 void HekTeleop::buttonNextJoint(ButtonState &buttonState)
00878 {
00879 if( buttonOffToOn(ButtonIdNextJoint, buttonState) )
00880 {
00881 if( m_eMode == TeleopModeShoulder )
00882 {
00883 m_eMode = TeleopModeElbow;
00884 setLED(LEDPatElbow);
00885 ROS_INFO("Move elbow in isolation.");
00886 }
00887 else if( m_eMode == TeleopModeElbow )
00888 {
00889 m_eMode = TeleopModeShoulder;
00890 setLED(LEDPatShoulder);
00891 ROS_INFO("Move shoulder in isolation.");
00892 }
00893 }
00894 }
00895
00896 void HekTeleop::buttonFineTune(ButtonState &buttonState)
00897 {
00898 if( buttonOffToOn(ButtonIdFineTune1, buttonState) ||
00899 buttonOffToOn(ButtonIdFineTune2, buttonState) )
00900 {
00901 if( m_fMoveTuning >= 1.0 )
00902 {
00903 m_fMoveTuning = 0.25;
00904 }
00905 else
00906 {
00907 m_fMoveTuning = 1.0;
00908 }
00909
00910 ROS_INFO("Manual movement scale set to %.1lf%%.", m_fMoveTuning * 100.0);
00911 }
00912 }
00913
00914 void HekTeleop::buttonEStop(ButtonState &buttonState)
00915 {
00916 static int clicks = 0;
00917 static int intvlCounter = 0;
00918 static int intvlTimeout = countsPerSecond(0.3);
00919
00920
00921
00922
00923
00924 if( m_msgRobotStatus.e_stopped.val == TriState::TRUE )
00925 {
00926 clicks = 0;
00927 intvlCounter = 0;
00928 return;
00929 }
00930
00931
00932 if( buttonOffToOn(ButtonIdEStop, buttonState) )
00933 {
00934 ++clicks;
00935 }
00936
00937 switch( clicks )
00938 {
00939 case 0:
00940 break;
00941 case 1:
00942 if( intvlCounter > intvlTimeout )
00943 {
00944 clicks = 0;
00945 intvlCounter = 0;
00946 }
00947 break;
00948 case 2:
00949 if( intvlCounter <= intvlTimeout )
00950 {
00951 estop();
00952 m_eState = TeleopStatePaused;
00953 setLED(LEDPatOn);
00954 setLED(LEDPatPaused);
00955 }
00956 clicks = 0;
00957 intvlCounter = 0;
00958 break;
00959 default:
00960 clicks = 0;
00961 intvlCounter = 0;
00962 break;
00963 }
00964 }
00965
00966 void HekTeleop::buttonCloseGripper(ButtonState &buttonState)
00967 {
00968 static int deadzone = 10;
00969 static double scale = 15.0;
00970
00971 int trigger = buttonState[ButtonIdCloseGripper];
00972 int i;
00973 double pos;
00974 double vel;
00975
00976
00977
00978
00979 if( trigger <= deadzone )
00980 {
00981 return;
00982 }
00983
00984
00985 if( m_mapCurPos.find(JointNameGrip) == m_mapCurPos.end() )
00986 {
00987 return;
00988 }
00989
00990
00991 pos = m_mapCurPos[JointNameGrip] - degToRad(40.0);
00992 vel = (double)(trigger-deadzone)/(double)(XBOX360_TRIGGER_MAX-deadzone) *
00993 scale;
00994 vel *= m_fMoveTuning;
00995
00996
00997 if( setJoint(JointNameGrip, pos, vel) >= 0 )
00998 {
00999 ROS_INFO_STREAM("Closing " << JointNameGrip << ".");
01000 }
01001 }
01002
01003 void HekTeleop::buttonOpenGripper(ButtonState &buttonState)
01004 {
01005 static int deadzone = 10;
01006 static double scale = 15.0;
01007
01008 int trigger = buttonState[ButtonIdOpenGripper];
01009 int i;
01010 double pos;
01011 double vel;
01012
01013
01014
01015
01016 if( trigger <= deadzone )
01017 {
01018 return;
01019 }
01020
01021
01022 if( m_mapCurPos.find(JointNameGrip) == m_mapCurPos.end() )
01023 {
01024 return;
01025 }
01026
01027
01028 pos = m_mapCurPos[JointNameGrip] + degToRad(40.0);
01029 vel = (double)(trigger-deadzone)/(double)(XBOX360_TRIGGER_MAX-deadzone) *
01030 scale;
01031 vel *= m_fMoveTuning;
01032
01033
01034 if( setJoint(JointNameGrip, pos, vel) >= 0 )
01035 {
01036 ROS_INFO_STREAM("Opening " << JointNameGrip << ".");
01037 }
01038 }
01039
01040 void HekTeleop::buttonMoveJoints(ButtonState &buttonState)
01041 {
01042 int joy = buttonState[ButtonIdMoveJoints];
01043
01044 switch( m_eMode )
01045 {
01046 case TeleopModeFirstPerson:
01047 buttonMoveFirstPerson(joy);
01048 break;
01049 case TeleopModeShoulder:
01050 buttonMoveShoulder(joy);
01051 break;
01052 case TeleopModeElbow:
01053 buttonMoveElbow(joy);
01054 break;
01055 default:
01056 break;
01057 }
01058 }
01059
01060 void HekTeleop::buttonMoveFirstPerson(int joy)
01061 {
01062
01063
01064
01065
01066
01067
01068
01069 static double UPPER_ARM = 406.27;
01070 static double LOWER_ARM = 401.60;
01071 static double V_MAX = 4.0;
01072 static double EPSILON = 0.7;
01073
01074 int i, j, k;
01075 double goal_sign;
01076 double A, B, C, D;
01077 double alpha, beta, gamma, theta;
01078 double dir;
01079 double x0, y0;
01080 double xp, yp;
01081 double b, c;
01082
01083 if( joy == 0 )
01084 {
01085 return;
01086 }
01087
01088
01089 if( (m_mapCurPos.find(JointNameShoulder) == m_mapCurPos.end()) ||
01090 (m_mapCurPos.find(JointNameElbow) == m_mapCurPos.end()) ||
01091 (m_mapCurPos.find(JointNameWristPitch) == m_mapCurPos.end()) )
01092 {
01093 return;
01094 }
01095
01096 goal_sign = joy < 0.0? -1.0: 1.0;
01097
01098 if( goal_sign != m_fpState.m_goalSign )
01099 {
01100 m_fpState.m_bNewGoal = true;
01101 }
01102
01103 alpha = m_mapCurPos[JointNameShoulder];
01104 beta = m_mapCurPos[JointNameElbow];
01105 gamma = m_mapTeleop[JointNameWristPitch]? m_mapGoalPos[JointNameWristPitch]:
01106 m_mapCurPos[JointNameWristPitch];
01107
01108
01109
01110
01111 if( m_fpState.m_bNewGoal )
01112 {
01113 m_fpState.m_goalSign = goal_sign;
01114
01115 A = UPPER_ARM;
01116 B = LOWER_ARM;
01117 D = goal_sign * 200.0;
01118
01119 dir = alpha + beta + gamma;
01120
01121 x0 = A * sin(alpha) + B * sin(alpha + beta);
01122 y0 = A * cos(alpha) + B * cos(alpha + beta);
01123 xp = x0 + D * sin(dir);
01124 yp = y0 + D * cos(dir);
01125
01126
01127 m_fpState.m_goalCart.x = xp;
01128 m_fpState.m_goalCart.y = yp;
01129
01130 C = sqrt(xp*xp + yp*yp);
01131 if( C > (A + B) )
01132 {
01133 C = A + B;
01134 }
01135
01136 theta = atan2(xp, yp);
01137 b = acos((A*A+C*C-B*B)/(2*A*C));
01138 c = acos((A*A+B*B-C*C)/(2*A*B));
01139
01140
01141 m_fpState.m_goalJoint.alpha = theta - b;
01142 m_fpState.m_goalJoint.beta = M_PI - c;
01143 m_fpState.m_goalJoint.gamma = dir -
01144 m_fpState.m_goalJoint.alpha -
01145 m_fpState.m_goalJoint.beta;
01146
01147
01148 setJoint(JointNameShoulder, m_fpState.m_goalJoint.alpha, 1.0);
01149 setJoint(JointNameElbow, m_fpState.m_goalJoint.beta, 1.0);
01150 setJoint(JointNameWristPitch, m_fpState.m_goalJoint.gamma, 2.0);
01151
01152 m_fpState.m_bNewGoal = false;
01153
01154 ROS_INFO_STREAM("Moving in first-person mode.");
01155 }
01156
01157
01158
01159
01160 else
01161 {
01162 A = UPPER_ARM;
01163 B = LOWER_ARM;
01164 D = 10.0;
01165
01166 double delta = abs(m_fpState.m_goalJoint.alpha - alpha) +
01167 abs(m_fpState.m_goalJoint.beta - beta) +
01168 abs(m_fpState.m_goalJoint.gamma - gamma);
01169
01170 if( delta < EPSILON )
01171 {
01172 m_fpState.m_bNewGoal = true;
01173 }
01174
01175
01176 x0 = A * sin(alpha) + B * sin(alpha + beta);
01177 y0 = A * cos(alpha) + B * cos(alpha + beta);
01178
01179
01180 double xdelta = m_fpState.m_goalCart.x - x0;
01181 double ydelta = m_fpState.m_goalCart.y - y0;
01182 if( ydelta == 0.0 )
01183 {
01184 dir = M_PI/2.0;
01185 }
01186 else
01187 {
01188 dir = atan2(xdelta, ydelta);
01189 }
01190
01191
01192 xp = x0 + D * sin(dir);
01193 yp = y0 + D * cos(dir);
01194
01195 C = sqrt(xp*xp + yp*yp);
01196 if( C > (A + B) )
01197 {
01198 C = A + B;
01199 }
01200
01201 theta = atan2(xp, yp);
01202 b = acos((A*A+C*C-B*B)/(2*A*C));
01203 c = acos((A*A+B*B-C*C)/(2*A*B));
01204
01205 double alpha_target = theta - b;
01206 double beta_target = M_PI - c;
01207
01208
01209 double alpha_delta = alpha_target - alpha;
01210 double beta_delta = beta_target - beta;
01211 if( abs(alpha_delta) > abs(beta_delta) )
01212 {
01213 beta_delta = beta_delta/alpha_delta;
01214 alpha_delta = 1.0;
01215 }
01216 else
01217 {
01218 alpha_delta = alpha_delta/beta_delta;
01219 beta_delta = 1.0;
01220 }
01221
01222 double scale = (double)joy/(double)(XBOX360_JOY_MAX) * V_MAX;
01223 double shoulder_vel = alpha_delta * scale * m_fMoveTuning;
01224 double elbow_vel = beta_delta * scale * m_fMoveTuning;
01225
01226 setJoint(JointNameShoulder, m_fpState.m_goalJoint.alpha,
01227 abs(shoulder_vel));
01228 setJoint(JointNameElbow, m_fpState.m_goalJoint.beta,
01229 abs(elbow_vel));
01230 setJoint(JointNameWristPitch, m_fpState.m_goalJoint.gamma,
01231 abs(shoulder_vel+elbow_vel));
01232
01233 ROS_INFO_STREAM("Moving in first-person mode.");
01234 }
01235 }
01236
01237 void HekTeleop::buttonMoveShoulder(int joy)
01238 {
01239 int i;
01240 double pos;
01241 double vel;
01242
01243 if( joy == 0 )
01244 {
01245 return;
01246 }
01247
01248
01249 if( m_mapCurPos.find(JointNameShoulder) == m_mapCurPos.end() )
01250 {
01251 return;
01252 }
01253
01254
01255 pos = degToRad(40.0);
01256 vel = (double)(joy) / XBOX360_JOY_MAX * 7.5;
01257 vel *= m_fMoveTuning;
01258
01259 if( vel < 0.0 )
01260 {
01261 pos = -pos;
01262 vel = -vel;
01263 }
01264
01265 pos = m_mapCurPos[JointNameShoulder] + pos;
01266
01267
01268 if( setJoint(JointNameShoulder, pos, vel) >= 0 )
01269 {
01270 m_fpState.m_bNewGoal = true;
01271 ROS_INFO_STREAM("Moving " << JointNameShoulder << ".");
01272 }
01273 }
01274
01275 void HekTeleop::buttonMoveElbow(int joy)
01276 {
01277 int i;
01278 double pos;
01279 double vel;
01280
01281 if( joy == 0 )
01282 {
01283 return;
01284 }
01285
01286
01287 if( m_mapCurPos.find(JointNameElbow) == m_mapCurPos.end() )
01288 {
01289 return;
01290 }
01291
01292
01293 pos = degToRad(40.0);
01294 vel = (double)(joy) / XBOX360_JOY_MAX * 7.5;
01295 vel *= m_fMoveTuning;
01296
01297 if( vel < 0.0 )
01298 {
01299 pos = -pos;
01300 vel = -vel;
01301 }
01302
01303 pos = m_mapCurPos[JointNameElbow] + pos;
01304
01305
01306 if( setJoint(JointNameElbow, pos, vel) >= 0 )
01307 {
01308 m_fpState.m_bNewGoal = true;
01309 ROS_INFO_STREAM("Moving " << JointNameElbow << ".");
01310 }
01311 }
01312
01313 void HekTeleop::buttonRotateBase(ButtonState &buttonState)
01314 {
01315 int joy = buttonState[ButtonIdRotBase];
01316 int i;
01317 double pos;
01318 double vel;
01319
01320 if( joy == 0 )
01321 {
01322 return;
01323 }
01324
01325
01326 if( m_mapCurPos.find(JointNameBaseRot) == m_mapCurPos.end() )
01327 {
01328 return;
01329 }
01330
01331
01332 pos = degToRad(45.0);
01333 vel = (double)(-joy) / XBOX360_JOY_MAX * 7.5;
01334 vel *= m_fMoveTuning;
01335
01336 if( vel < 0.0 )
01337 {
01338 pos = -pos;
01339 vel = -vel;
01340 }
01341
01342 pos = m_mapCurPos[JointNameBaseRot] + pos;
01343
01344
01345 if( setJoint(JointNameBaseRot, pos, vel) >= 0 )
01346 {
01347 ROS_INFO_STREAM("Rotating " << JointNameBaseRot << ".");
01348 }
01349 }
01350
01351 void HekTeleop::buttonPitchWrist(ButtonState &buttonState)
01352 {
01353 int joy = buttonState[ButtonIdPitchWrist];
01354 int i;
01355 double pos;
01356 double vel;
01357
01358 if( joy == 0 )
01359 {
01360 return;
01361 }
01362
01363
01364 if( m_mapCurPos.find(JointNameWristPitch) == m_mapCurPos.end() )
01365 {
01366 return;
01367 }
01368
01369
01370 pos = degToRad(45.0);
01371 vel = (double)(joy) / XBOX360_JOY_MAX * 15.0;
01372 vel *= m_fMoveTuning;
01373
01374 if( vel < 0.0 )
01375 {
01376 pos = -pos;
01377 vel = -vel;
01378 }
01379
01380 pos = m_mapCurPos[JointNameWristPitch] + pos;
01381
01382
01383 if( setJoint(JointNameWristPitch, pos, vel) >= 0 )
01384 {
01385 m_fpState.m_bNewGoal = true;
01386 ROS_INFO_STREAM("Pitching " << JointNameWristPitch << ".");
01387 }
01388 }
01389
01390 void HekTeleop::buttonRotateWristCw(ButtonState &buttonState)
01391 {
01392 int i;
01393 double pos;
01394 double vel;
01395
01396
01397
01398
01399 if( buttonState[ButtonIdRotWristCw] == 0 )
01400 {
01401 return;
01402 }
01403
01404
01405 if( m_mapCurPos.find(JointNameWristRot) == m_mapCurPos.end() )
01406 {
01407 return;
01408 }
01409
01410
01411 pos = m_mapCurPos[JointNameWristRot] - degToRad(360.0);
01412 vel = 20.0;
01413 vel *= m_fMoveTuning;
01414
01415
01416 if( setJoint(JointNameWristRot, pos, vel) >= 0 )
01417 {
01418 ROS_INFO_STREAM("Rotating " << JointNameWristRot << " CW.");
01419 }
01420 }
01421
01422 void HekTeleop::buttonRotateWristCcw(ButtonState &buttonState)
01423 {
01424 int i;
01425 double pos;
01426 double vel;
01427
01428
01429
01430
01431 if( buttonState[ButtonIdRotWristCcw] == 0 )
01432 {
01433 return;
01434 }
01435
01436
01437 if( m_mapCurPos.find(JointNameWristRot) == m_mapCurPos.end() )
01438 {
01439 return;
01440 }
01441
01442
01443 pos = m_mapCurPos[JointNameWristRot] + degToRad(360.0);
01444 vel = 20.0;
01445 vel *= m_fMoveTuning;
01446
01447
01448 if( setJoint(JointNameWristRot, pos, vel) >= 0 )
01449 {
01450 ROS_INFO_STREAM("Rotating " << JointNameWristRot << " CCW.");
01451 }
01452 }
01453
01454
01455
01456
01457
01458
01459 void HekTeleop::pause()
01460 {
01461 m_eState = TeleopStatePaused;
01462
01463 setRumble(0, 0);
01464 setLED(LEDPatPaused);
01465 }
01466
01467 void HekTeleop::ready()
01468 {
01469 m_eState = TeleopStateReady;
01470 m_fpState.m_bNewGoal = true;
01471
01472 setLED(LEDPatReady);
01473 }
01474
01475 void HekTeleop::driveLEDsFigure8Pattern()
01476 {
01477 static int nLEDTimeout = -1;
01478 static int nLEDCounter = 0;
01479 static int iLED = 0;
01480 static int LEDPat[] =
01481 {
01482 XBOX360_LED_PAT_1_ON, XBOX360_LED_PAT_2_ON,
01483 XBOX360_LED_PAT_3_ON, XBOX360_LED_PAT_4_ON
01484 };
01485
01486
01487 if( nLEDTimeout < 0 )
01488 {
01489 nLEDTimeout = countsPerSecond(0.50);
01490 }
01491
01492
01493 if( nLEDCounter++ >= nLEDTimeout )
01494 {
01495 iLED = (iLED + 1) % arraysize(LEDPat);
01496 setLED(LEDPat[iLED]);
01497 nLEDCounter = 0;
01498 }
01499 }
01500
01501 void HekTeleop::stopUnteleopJoints()
01502 {
01503 MapBool::iterator iter;
01504 MapDouble::iterator p;
01505 MapDouble::iterator q;
01506 vector<string> vecJointNames;
01507
01508 for(iter = m_mapTeleop.begin(); iter != m_mapTeleop.end(); ++iter)
01509 {
01510
01511 if( iter->second )
01512 {
01513 continue;
01514 }
01515
01516 p = m_mapGoalPos.find(iter->first);
01517 q = m_mapGoalVel.find(iter->first);
01518
01519
01520 if( (p != m_mapGoalPos.end()) && (q != m_mapGoalVel.end()) )
01521 {
01522
01523 if( q->second > 0.0 )
01524 {
01525 vecJointNames.push_back(iter->first);
01526 }
01527
01528 m_mapGoalPos.erase(p);
01529 m_mapGoalVel.erase(q);
01530 }
01531
01532 iter->second = false;
01533 }
01534
01535 if( vecJointNames.size() > 0 )
01536 {
01537 stop(vecJointNames);
01538 }
01539 }
01540
01541 ssize_t HekTeleop::setJoint(const string &strJointName, double pos, double vel)
01542 {
01543 MapDouble::iterator p = m_mapGoalPos.find(strJointName);
01544 MapDouble::iterator q = m_mapGoalVel.find(strJointName);
01545 ssize_t i = -1;
01546
01547
01548 if( (p != m_mapGoalPos.end()) && (q != m_mapGoalVel.end()) )
01549 {
01550
01551 if( (pos != p->second) || (vel != q->second) )
01552 {
01553 if( (i = addJointToTrajectoryPoint(strJointName)) >= 0 )
01554 {
01555 m_msgJointTrajPoint.positions[i] = pos;
01556 m_msgJointTrajPoint.velocities[i] = vel;
01557
01558 p->second = pos;
01559 q->second = vel;
01560 }
01561 }
01562
01563 m_mapTeleop[strJointName] = true;
01564 }
01565
01566
01567 else if( (i = addJointToTrajectoryPoint(strJointName)) >= 0 )
01568 {
01569 m_msgJointTrajPoint.positions[i] = pos;
01570 m_msgJointTrajPoint.velocities[i] = vel;
01571
01572 m_mapGoalPos[strJointName] = pos;
01573 m_mapGoalVel[strJointName] = vel;
01574
01575 m_mapTeleop[strJointName] = true;
01576 }
01577
01578 return i;
01579 }
01580
01581 ssize_t HekTeleop::addJointToTrajectoryPoint(const string &strJointName)
01582 {
01583 MapJointTraj::iterator p;
01584 MapDouble::iterator q;
01585 ssize_t i;
01586
01587
01588 if( (p = m_mapTraj.find(strJointName)) != m_mapTraj.end() )
01589 {
01590 return p->second;
01591 }
01592
01593
01594 else if( (q = m_mapCurPos.find(strJointName)) != m_mapCurPos.end() )
01595 {
01596 m_msgJointTraj.joint_names.push_back(strJointName);
01597 m_msgJointTrajPoint.positions.push_back(q->second);
01598 m_msgJointTrajPoint.velocities.push_back(m_mapCurVel[strJointName]);
01599 m_msgJointTrajPoint.accelerations.push_back(0.0);
01600 i = m_msgJointTraj.joint_names.size() - 1;
01601 m_mapTraj[strJointName] = (int)i;
01602 return i;
01603 }
01604
01605
01606 else
01607 {
01608 return -1;
01609 }
01610 }
01611
01612 void HekTeleop::clearWorkingTrajectory()
01613 {
01614 m_msgJointTraj.joint_names.clear();
01615 m_msgJointTraj.points.clear();
01616
01617 m_msgJointTrajPoint.positions.clear();
01618 m_msgJointTrajPoint.velocities.clear();
01619 m_msgJointTrajPoint.accelerations.clear();
01620
01621 m_mapTraj.clear();
01622 }
01623
01624 void HekTeleop::clearActiveTrajectory()
01625 {
01626 m_mapGoalPos.clear();
01627 m_mapGoalVel.clear();
01628 }
01629
01630 void HekTeleop::resetActiveTeleop()
01631 {
01632 MapBool::iterator iter;
01633
01634 for(iter = m_mapTeleop.begin(); iter != m_mapTeleop.end(); ++iter)
01635 {
01636 iter->second = false;
01637 }
01638
01639 m_bPreemptMove = false;
01640 }