hek_teleop.cpp
Go to the documentation of this file.
00001 
00002 //
00003 // Package:   RoadNarrows Robotics Hekateros Robotic Manipulator ROS Package
00004 //
00005 // Link:      https://github.com/roadnarrows-robotics/hekateros
00006 //
00007 // ROS Node:  hek_teleop
00008 //
00009 // File:      hek_teleop.cpp
00010 //
00026 /*
00027  * @EulaBegin@
00028  * 
00029  * Permission is hereby granted, without written agreement and without
00030  * license or royalty fees, to use, copy, modify, and distribute this
00031  * software and its documentation for any purpose, provided that
00032  * (1) The above copyright notice and the following two paragraphs
00033  * appear in all copies of the source code and (2) redistributions
00034  * including binaries reproduces these notices in the supporting
00035  * documentation.   Substantial modifications to this software may be
00036  * copyrighted by their authors and need not follow the licensing terms
00037  * described here, provided that the new terms are clearly indicated in
00038  * all files where they apply.
00039  * 
00040  * IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
00041  * OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
00042  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
00043  * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
00044  * EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
00045  * THE POSSIBILITY OF SUCH DAMAGE.
00046  * 
00047  * THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
00048  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
00049  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
00050  * "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
00051  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
00052  * 
00053  * @EulaEnd@
00054  */
00056 
00057 //
00058 // System
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 // Boost
00071 //
00072 #include <boost/bind.hpp>
00073 #include "boost/assign.hpp"
00074 
00075 //
00076 // ROS
00077 //
00078 #include "ros/ros.h"
00079 #include "actionlib/server/simple_action_server.h"
00080 
00081 //
00082 // ROS generated core, industrial, and hekateros messages.
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 // ROS generatated hekateros services.
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 // ROS generated action servers.
00113 //
00114 
00115 //
00116 // ROS generated HID messages.
00117 //
00118 #include "hid/ConnStatus.h"           // subscribe
00119 #include "hid/Controller360State.h"   // subscribe
00120 #include "hid/LEDPattern.h"           // service
00121 #include "hid/RumbleCmd.h"            // publish
00122 
00123 //
00124 // ROS generatated HID services.
00125 //
00126 #include "hid/SetLED.h"
00127 #include "hid/SetRumble.h"
00128 
00129 //
00130 // RoadNarrows
00131 //
00132 #include "rnr/rnrconfig.h"
00133 #include "rnr/log.h"
00134 #include "rnr/hid/HIDXbox360.h"
00135 
00136 //
00137 // RoadNarrows embedded hekateros library.
00138 //
00139 #include "Hekateros/hekateros.h"
00140 #include "Hekateros/hekXmlCfg.h"
00141 #include "Hekateros/hekRobot.h"
00142 #include "Hekateros/hekUtils.h"
00143 
00144 //
00145 // Node headers.
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 // All joints supported in current Hekaterors product line.
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 // HekTeleop Class
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 // Server Services
00234 //. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
00235 
00236 
00237 //. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
00238 // Client Services
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   // no change
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 // Topic Publishers
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   // new working trajectory
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     // publish
00473     m_publishers["/hekateros_control/joint_command"].publish(m_msgJointTraj);
00474 
00475     bPubJointCmd = true;
00476   }
00477 
00478   // transition to no active trajectory
00479   else if( bPubJointCmd && !hasActiveTrajectory() )
00480   {
00481     if( m_msgRobotStatus.in_motion.val == TriState::FALSE )
00482     {
00483       //freeze();
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   // publish
00498   m_publishers["/xbox_360/rumble_command"].publish(msg);
00499 }
00500 
00501 
00502 //. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
00503 // Subscribed Topics
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   // RDK might autoset pause/start here
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;    // no haptic feedback in this zone
00546   static float  Scale     = (float)XBOX360_RUMBLE_RIGHT_MAX/(1023.0 - DeadZone);
00547                                       // effort to rumble scale factor
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     // current joint position and velocity
00565     m_mapCurPos[msg.name[i]] = msg.position[i]; 
00566     m_mapCurVel[msg.name[i]] = msg.velocity[i]; 
00567 
00568     //
00569     // Gripper tactile feedback.
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         // Setting this often seems to slow down button response. So set at
00580         // one fixed value.
00581         //rumbleRight = (int)((effort - DeadZone) * Scale);
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   // Auto-discovery of all joints to keep joint teleoperation state.
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);    // only active button in pause state
00634         break;
00635       case TeleopStateUninit:
00636       default:
00637         pause();
00638         break;
00639     }
00640   }
00641 
00642   m_buttonState = buttonState;
00643 }
00644 
00645 
00646 //. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
00647 // Sanity
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   // had communitcation, but no more
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   // not really a communication check function, but convenient.
00680   if( m_eState == TeleopStatePaused )
00681   {
00682     driveLEDsFigure8Pattern();
00683   }
00684 }
00685 
00686 void HekTeleop::putRobotInSafeMode(bool bHard)
00687 {
00688   // stop robot
00689   freeze();
00690 
00691   // set robot mode
00692   setRobotMode(HekRobotModeAuto);
00693  
00694   if( bHard )
00695   {
00696     // nothing to do
00697   }
00698   
00699   m_eState = TeleopStateUninit;
00700 
00701   setRumble(0, 0);
00702   setLED(LEDPatOn);
00703 }
00704 
00705 
00706 //. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
00707 // Xbox Actions
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   // Teleoperation state.
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   // Emergency stop.
00759   buttonEStop(buttonState);
00760 
00761   //
00762   // Teleoperation Modes.
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   // Moves.
00776   //
00777   if( canMove() )
00778   {
00779     clearWorkingTrajectory();
00780     resetActiveTeleop();
00781 
00782     // preemptive canned moves
00783     buttonGotoBalancedPos(buttonState);
00784     buttonGotoParkedPos(buttonState);
00785     buttonGotoZeroPt(buttonState);
00786 
00787     if( m_bPreemptMove )
00788     {
00789       clearActiveTrajectory();
00790     }
00791 
00792     // manually controlled moves
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;            // number of button clicks
00917   static int  intvlCounter  = 0;            // intra-click interval counter
00918   static int  intvlTimeout  = countsPerSecond(0.3); // intra-click timeout
00919 
00920   //
00921   // Robot is estopped. This can come from a different node source. Make sure
00922   // counters are cleared.
00923   //
00924   if( m_msgRobotStatus.e_stopped.val == TriState::TRUE )
00925   {
00926     clicks = 0;
00927     intvlCounter = 0;
00928     return;
00929   }
00930 
00931   // button off to on
00932   if( buttonOffToOn(ButtonIdEStop, buttonState) )
00933   {
00934     ++clicks;
00935   }
00936 
00937   switch( clicks )
00938   {
00939     case 0:     // no click
00940       break;
00941     case 1:     // single click
00942       if( intvlCounter > intvlTimeout )
00943       {
00944         clicks = 0;
00945         intvlCounter = 0;
00946       }
00947       break;
00948     case 2:     // double click
00949       if( intvlCounter <= intvlTimeout )
00950       {
00951         estop();
00952         m_eState = TeleopStatePaused;
00953         setLED(LEDPatOn);       // see comment block in buttonPause()
00954         setLED(LEDPatPaused);
00955       }
00956       clicks = 0;
00957       intvlCounter = 0;
00958       break;
00959     default:    // multiple clicks
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   // Two buttons control gripper movement.
00978   //
00979   if( trigger <= deadzone )
00980   {
00981     return;
00982   }
00983 
00984   // no joint
00985   if( m_mapCurPos.find(JointNameGrip) == m_mapCurPos.end() )
00986   {
00987     return;
00988   }
00989 
00990   // goal position and velocity
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   // new joint trajectory point component
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   // Two buttons control gripper movement.
01015   //
01016   if( trigger <= deadzone )
01017   {
01018     return;
01019   }
01020 
01021   // no joint
01022   if( m_mapCurPos.find(JointNameGrip) == m_mapCurPos.end() )
01023   {
01024     return;
01025   }
01026 
01027   // goal position and velocity
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   // new joint trajectory point component
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   // Fixed tuned parameters.
01064   //
01065   // RDK TODO:
01066   // The Upper and lower arm lengths (mm) are for the large Hakateros.
01067   // Need to dynamically find these values from the robot.
01068   //
01069   static double UPPER_ARM = 406.27;   // upper arm (shoulder - elbow) 
01070   static double LOWER_ARM = 401.60;   // lower arm (elbow - wrist)
01071   static double V_MAX     = 4.0;      // maximum velocity scale
01072   static double EPSILON   = 0.7;      // tolerance in L1 angle space
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   // no joint state available
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   // New goal, calculate new targets.
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;  // distance to move in mm
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     // save cartesian target
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     // save joint targets
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     // minimum movement on new goal
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   // Same goal, calculate delta targets.
01159   //
01160   else
01161   {
01162     A = UPPER_ARM;
01163     B = LOWER_ARM;
01164     D = 10.0;       // distance used to calculate joint velocities (mm)
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     // current position
01176     x0 = A * sin(alpha) + B * sin(alpha + beta);
01177     y0 = A * cos(alpha) + B * cos(alpha + beta);
01178 
01179     // calculate direction towards target
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     // target for calculating joint velocities
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     // ok, calculate velocities
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;        // joint index
01240   double  pos;      // delta joint position
01241   double  vel;      // joint velocity
01242 
01243   if( joy == 0 )
01244   {
01245     return;
01246   }
01247 
01248   // no joint
01249   if( m_mapCurPos.find(JointNameShoulder) == m_mapCurPos.end() )
01250   {
01251     return;
01252   }
01253 
01254   // goal position and velocity
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   // new joint trajectory point component
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;        // joint index
01278   double  pos;      // delta joint position
01279   double  vel;      // joint velocity
01280 
01281   if( joy == 0 )
01282   {
01283     return;
01284   }
01285 
01286   // no joint
01287   if( m_mapCurPos.find(JointNameElbow) == m_mapCurPos.end() )
01288   {
01289     return;
01290   }
01291 
01292   // goal position and velocity
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   // new joint trajectory point component
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;        // joint index
01317   double  pos;      // delta joint position
01318   double  vel;      // joint velocity
01319 
01320   if( joy == 0 )
01321   {
01322     return;
01323   }
01324 
01325   // no joint
01326   if( m_mapCurPos.find(JointNameBaseRot) == m_mapCurPos.end() )
01327   {
01328     return;
01329   }
01330 
01331   // goal position and velocity
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   // new joint trajectory point component
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;        // joint index
01355   double  pos;      // delta joint position
01356   double  vel;      // joint velocity
01357 
01358   if( joy == 0 )
01359   {
01360     return;
01361   }
01362 
01363   // no joint
01364   if( m_mapCurPos.find(JointNameWristPitch) == m_mapCurPos.end() )
01365   {
01366     return;
01367   }
01368 
01369   // goal position and velocity
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   // new joint trajectory point component
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   // Two buttons control wrist rotation.
01398   //
01399   if( buttonState[ButtonIdRotWristCw] == 0 )
01400   {
01401     return;
01402   }
01403 
01404   // no joint
01405   if( m_mapCurPos.find(JointNameWristRot) == m_mapCurPos.end() )
01406   {
01407     return;
01408   }
01409 
01410   // goal position and velocity
01411   pos = m_mapCurPos[JointNameWristRot] - degToRad(360.0);
01412   vel = 20.0;
01413   vel *= m_fMoveTuning;
01414 
01415   // new joint trajectory point component
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   // Two buttons control wrist rotation.
01430   //
01431   if( buttonState[ButtonIdRotWristCcw] == 0 )
01432   {
01433     return;
01434   }
01435 
01436   // no joint
01437   if( m_mapCurPos.find(JointNameWristRot) == m_mapCurPos.end() )
01438   {
01439     return;
01440   }
01441 
01442   // goal position and velocity
01443   pos = m_mapCurPos[JointNameWristRot] + degToRad(360.0);
01444   vel = 20.0;
01445   vel *= m_fMoveTuning;
01446 
01447   // new joint trajectory point component
01448   if( setJoint(JointNameWristRot, pos, vel) >= 0 )
01449   {
01450     ROS_INFO_STREAM("Rotating " << JointNameWristRot << " CCW.");
01451   }
01452 }
01453 
01454 
01455 //. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
01456 // Support
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   // lazy init
01487   if( nLEDTimeout < 0 )
01488   {
01489     nLEDTimeout = countsPerSecond(0.50);
01490   }
01491 
01492   // switch pattern
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     // active
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     // previously teleoperated joint
01520     if( (p != m_mapGoalPos.end()) && (q != m_mapGoalVel.end()) )
01521     {
01522       // non-zero velocity
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   // there exists a previous joint trajectory point component
01548   if( (p != m_mapGoalPos.end()) && (q != m_mapGoalVel.end()) )
01549   {
01550     // previous joint trajectory point is different
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   // no active joint trajectory point component
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   // joint already added
01588   if( (p = m_mapTraj.find(strJointName)) != m_mapTraj.end() )
01589   {
01590     return p->second;
01591   }
01592 
01593   // add new joint with null trajectory
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   // unknown joint
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 }


hekateros_control
Author(s): Robin Knight , Daniel Packard
autogenerated on Mon Oct 6 2014 00:36:42