jaco_comm.cpp
Go to the documentation of this file.
00001 
00046 #include <ros/ros.h>
00047 #include "jaco_driver/jaco_comm.h"
00048 #include <string>
00049 #include <vector>
00050 
00051 
00052 namespace jaco
00053 {
00054 
00055 JacoComm::JacoComm(const ros::NodeHandle& node_handle,
00056                    boost::recursive_mutex &api_mutex,
00057                    const bool is_movement_on_start)
00058     : is_software_stop_(false), api_mutex_(api_mutex)
00059 {
00060     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00061 
00062     // Get the serial number parameter for the arm we wish to connec to
00063     std::string serial_number = "";
00064     node_handle.getParam("serial_number", serial_number);
00065 
00066     std::vector<int> api_version;
00067     int result = jaco_api_.getAPIVersion(api_version);
00068     if (result != NO_ERROR_KINOVA)
00069     {
00070         throw JacoCommException("Could not get the Kinova API version", result);
00071     }
00072 
00073     ROS_INFO_STREAM("Initializing Kinova API (header version: " << COMMAND_LAYER_VERSION << ", library version: "
00074                     << api_version[0] << "." << api_version[1] << "." << api_version[2] << ")");
00075 
00076     result = jaco_api_.initAPI();
00077     if (result != NO_ERROR_KINOVA)
00078     {
00079         throw JacoCommException("Could not initialize Kinova API", result);
00080     }
00081 
00082     std::vector<KinovaDevice> devices_list;
00083     result = NO_ERROR_KINOVA;
00084     jaco_api_.getDevices(devices_list, result);
00085     if (result != NO_ERROR_KINOVA)
00086     {
00087         throw JacoCommException("Could not get devices list", result);
00088     }
00089 
00090     bool found_arm = false;
00091     for (int device_i = 0; device_i < devices_list.size(); device_i++)
00092     {
00093         // If no device is specified, just use the first available device
00094         if ((serial_number == "")
00095             || (std::strcmp(serial_number.c_str(), devices_list[device_i].SerialNumber) == 0))
00096         {
00097             result = jaco_api_.setActiveDevice(devices_list[device_i]);
00098             if (result != NO_ERROR_KINOVA)
00099             {
00100                 throw JacoCommException("Could not set the active device", result);
00101             }
00102 
00103             GeneralInformations general_info;
00104             result = jaco_api_.getGeneralInformations(general_info);
00105             if (result != NO_ERROR_KINOVA)
00106             {
00107                 throw JacoCommException("Could not get general information about the device", result);
00108             }
00109 
00110             ClientConfigurations configuration;
00111             getConfig(configuration);
00112 
00113             QuickStatus quick_status;
00114             getQuickStatus(quick_status);
00115 
00116             if ((quick_status.RobotType != 0) && (quick_status.RobotType != 1))
00117             {
00118                 ROS_ERROR("Could not get the type of the arm from the quick status, expected "
00119                           "either type 0 (JACO), or type 1 (MICO), got %d", quick_status.RobotType);
00120                 throw JacoCommException("Could not get the type of the arm", quick_status.RobotType);
00121             }
00122 
00123             num_fingers_ = quick_status.RobotType == 0 ? 3 : 2;
00124 
00125             ROS_INFO_STREAM("Found " << devices_list.size() << " device(s), using device at index " << device_i
00126                             << " (model: " << configuration.Model
00127                             << ", serial number: " << devices_list[device_i].SerialNumber
00128                             << ", code version: " << general_info.CodeVersion
00129                             << ", code revision: " << general_info.CodeRevision << ")");
00130 
00131             found_arm = true;
00132             break;
00133         }
00134     }
00135 
00136     if (!found_arm)
00137     {
00138         ROS_ERROR("Could not find the specified arm (serial: %s) among the %d attached devices",
00139                   serial_number.c_str(), static_cast<int>(devices_list.size()));
00140         throw JacoCommException("Could not find the specified arm", 0);
00141     }
00142 
00143     // On a cold boot the arm may not respond to commands from the API right away.
00144     // This kick-starts the Control API so that it's ready to go.
00145     startAPI();
00146     stopAPI();
00147     startAPI();
00148 
00149     // Set the angular velocity of each of the joints to zero
00150     TrajectoryPoint jaco_velocity;
00151     memset(&jaco_velocity, 0, sizeof(jaco_velocity));
00152     setCartesianVelocities(jaco_velocity.Position.CartesianPosition);
00153 
00154     if (is_movement_on_start)
00155     {
00156         initFingers();
00157     }
00158     else
00159     {
00160         ROS_WARN("Movement on connection to the arm has been suppressed on initialization. You may "
00161                  "have to home the arm (through the home service) before movement is possible");
00162     }
00163 }
00164 
00165 
00166 JacoComm::~JacoComm()
00167 {
00168     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00169     jaco_api_.closeAPI();
00170 }
00171 
00172 
00179 bool JacoComm::isHomed(void)
00180 {
00181     QuickStatus quick_status;
00182     getQuickStatus(quick_status);
00183 
00184     if (quick_status.RetractType == 1)
00185     {
00186         return true;
00187     }
00188     else
00189     {
00190         return false;
00191     }
00192 }
00193 
00194 
00205 void JacoComm::homeArm(void)
00206 {
00207     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00208 
00209     if (isStopped())
00210     {
00211         ROS_INFO("Arm is stopped, cannot home");
00212         return;
00213     }
00214     else if (isHomed())
00215     {
00216         ROS_INFO("Arm is already in \"home\" position");
00217         return;
00218     }
00219 
00220     stopAPI();
00221     ros::Duration(1.0).sleep();
00222     startAPI();
00223 
00224     ROS_INFO("Homing the arm");
00225     int result = jaco_api_.moveHome();
00226     if (result != NO_ERROR_KINOVA)
00227     {
00228         throw JacoCommException("Move home failed", result);
00229     }
00230 }
00231 
00232 
00239 void JacoComm::initFingers(void)
00240 {
00241     ROS_INFO("Initializing fingers...this will take a few seconds and the fingers should open completely");
00242     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00243     int result = jaco_api_.initFingers();
00244     if (result != NO_ERROR_KINOVA)
00245     {
00246         throw JacoCommException("Could not init fingers", result);
00247     }
00248     return;
00249 }
00250 
00251 
00257 void JacoComm::setJointAngles(const JacoAngles &angles, int timeout, bool push)
00258 {
00259     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00260 
00261     if (isStopped())
00262     {
00263         ROS_INFO("The angles could not be set because the arm is stopped");
00264         return;
00265     }
00266 
00267     int result = NO_ERROR_KINOVA;
00268     TrajectoryPoint jaco_position;
00269     jaco_position.InitStruct();
00270     memset(&jaco_position, 0, sizeof(jaco_position));  // zero structure
00271 
00272     if (push)
00273     {
00274         result = jaco_api_.eraseAllTrajectories();
00275         if (result != NO_ERROR_KINOVA)
00276         {
00277             throw JacoCommException("Could not erase trajectories", result);
00278         }
00279     }
00280 
00281     startAPI();
00282 
00283     result = jaco_api_.setAngularControl();
00284     if (result != NO_ERROR_KINOVA)
00285     {
00286         throw JacoCommException("Could not set angular control", result);
00287     }
00288 
00289     jaco_position.Position.Delay = 0.0;
00290     jaco_position.Position.Type = ANGULAR_POSITION;
00291     jaco_position.Position.Actuators = angles;
00292 
00293     result = jaco_api_.sendAdvanceTrajectory(jaco_position);
00294     if (result != NO_ERROR_KINOVA)
00295     {
00296         throw JacoCommException("Could not send advanced joint angle trajectory", result);
00297     }
00298 }
00299 
00300 
00306 void JacoComm::setCartesianPosition(const JacoPose &position, int timeout, bool push)
00307 {
00308     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00309 
00310     if (isStopped())
00311     {
00312         ROS_INFO("The position could not be set because the arm is stopped");
00313         return;
00314     }
00315 
00316     int result = NO_ERROR_KINOVA;
00317     TrajectoryPoint jaco_position;
00318     jaco_position.InitStruct();
00319     memset(&jaco_position, 0, sizeof(jaco_position));  // zero structure
00320 
00321     if (push)
00322     {
00323         result = jaco_api_.eraseAllTrajectories();
00324         if (result != NO_ERROR_KINOVA)
00325         {
00326             throw JacoCommException("Could not erase trajectories", result);
00327         }
00328     }
00329 
00330     startAPI();
00331 
00332     result = jaco_api_.setCartesianControl();
00333     if (result != NO_ERROR_KINOVA)
00334     {
00335         throw JacoCommException("Could not set Cartesian control", result);
00336     }
00337 
00338     jaco_position.Position.Delay = 0.0;
00339     jaco_position.Position.Type = CARTESIAN_POSITION;
00340     jaco_position.Position.HandMode = HAND_NOMOVEMENT;
00341 
00342     // These values will not be used but are initialized anyway.
00343     jaco_position.Position.Actuators.Actuator1 = 0.0f;
00344     jaco_position.Position.Actuators.Actuator2 = 0.0f;
00345     jaco_position.Position.Actuators.Actuator3 = 0.0f;
00346     jaco_position.Position.Actuators.Actuator4 = 0.0f;
00347     jaco_position.Position.Actuators.Actuator5 = 0.0f;
00348     jaco_position.Position.Actuators.Actuator6 = 0.0f;
00349 
00350     jaco_position.Position.CartesianPosition = position;
00351 
00352     result = jaco_api_.sendBasicTrajectory(jaco_position);
00353     if (result != NO_ERROR_KINOVA)
00354     {
00355         throw JacoCommException("Could not send basic trajectory", result);
00356     }
00357 }
00358 
00359 
00363 void JacoComm::setFingerPositions(const FingerAngles &fingers, int timeout, bool push)
00364 {
00365     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00366 
00367     if (isStopped())
00368     {
00369         ROS_INFO("The fingers could not be set because the arm is stopped");
00370         return;
00371     }
00372 
00373     int result = NO_ERROR_KINOVA;
00374     TrajectoryPoint jaco_position;
00375     jaco_position.InitStruct();
00376     memset(&jaco_position, 0, sizeof(jaco_position));  // zero structure
00377 
00378     if (push)
00379     {
00380         result = jaco_api_.eraseAllTrajectories();
00381         if (result != NO_ERROR_KINOVA)
00382         {
00383             throw JacoCommException("Could not erase trajectories", result);
00384         }
00385     }
00386 
00387     startAPI();
00388 
00389     result = jaco_api_.setCartesianControl();
00390     if (result != NO_ERROR_KINOVA)
00391     {
00392         throw JacoCommException("Could not set Cartesian control", result);
00393     }
00394 
00395     // Initialize Cartesian control of the fingers
00396     jaco_position.Position.HandMode = POSITION_MODE;
00397     jaco_position.Position.Type = CARTESIAN_POSITION;
00398     jaco_position.Position.Fingers = fingers;
00399     jaco_position.Position.Delay = 0.0;
00400     jaco_position.LimitationsActive = 0;
00401 
00402     // These values will not be used but are initialized anyway.
00403     JacoAngles angles;
00404     getJointAngles(angles);
00405     jaco_position.Position.Actuators = angles;
00406 
00407     // When loading a cartesian position for the fingers, values are required for the arm joints
00408     // as well or the arm goes nuts.  Grab the current position and feed it back to the arm.
00409     JacoPose pose;
00410     getCartesianPosition(pose);
00411     jaco_position.Position.CartesianPosition = pose;
00412 
00413     result = jaco_api_.sendAdvanceTrajectory(jaco_position);
00414     if (result != NO_ERROR_KINOVA)
00415     {
00416         throw JacoCommException("Could not send advanced finger trajectory", result);
00417     }
00418 }
00419 
00420 
00424 void JacoComm::setJointVelocities(const AngularInfo &joint_vel)
00425 {
00426     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00427 
00428     if (isStopped())
00429     {
00430         ROS_INFO("The velocities could not be set because the arm is stopped");
00431         return;
00432     }
00433 
00434     TrajectoryPoint jaco_velocity;
00435     jaco_velocity.InitStruct();
00436 
00437     memset(&jaco_velocity, 0, sizeof(jaco_velocity));  // zero structure
00438 
00439     startAPI();
00440     jaco_velocity.Position.Type = ANGULAR_VELOCITY;
00441 
00442     // confusingly, velocity is passed in the position struct
00443     jaco_velocity.Position.Actuators = joint_vel;
00444 
00445     int result = jaco_api_.sendAdvanceTrajectory(jaco_velocity);
00446     if (result != NO_ERROR_KINOVA)
00447     {
00448         throw JacoCommException("Could not send advanced joint velocity trajectory", result);
00449     }
00450 }
00451 
00452 
00456 void JacoComm::setCartesianVelocities(const CartesianInfo &velocities)
00457 {
00458     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00459 
00460     if (isStopped())
00461     {
00462         ROS_INFO("The cartesian velocities could not be set because the arm is stopped");
00463         jaco_api_.eraseAllTrajectories();
00464         return;
00465     }
00466 
00467     TrajectoryPoint jaco_velocity;
00468     jaco_velocity.InitStruct();
00469 
00470     memset(&jaco_velocity, 0, sizeof(jaco_velocity));  // zero structure
00471 
00472     startAPI();
00473     jaco_velocity.Position.Type = CARTESIAN_VELOCITY;
00474 
00475     // confusingly, velocity is passed in the position struct
00476     jaco_velocity.Position.CartesianPosition = velocities;
00477 
00478     int result = jaco_api_.sendAdvanceTrajectory(jaco_velocity);
00479     if (result != NO_ERROR_KINOVA)
00480     {
00481         throw JacoCommException("Could not send advanced Cartesian velocity trajectory", result);
00482     }
00483 }
00484 
00485 
00492 void JacoComm::setConfig(const ClientConfigurations &config)
00493 {
00494     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00495     int result = jaco_api_.setClientConfigurations(config);
00496     if (result != NO_ERROR_KINOVA)
00497     {
00498         throw JacoCommException("Could not set the client configuration", result);
00499     }
00500 }
00501 
00502 
00506 void JacoComm::getJointAngles(JacoAngles &angles)
00507 {
00508     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00509     AngularPosition jaco_angles;
00510     memset(&jaco_angles, 0, sizeof(jaco_angles));  // zero structure
00511 
00512     int result = jaco_api_.getAngularPosition(jaco_angles);
00513     if (result != NO_ERROR_KINOVA)
00514     {
00515         throw JacoCommException("Could not get the angular position", result);
00516     }
00517 
00518     angles = JacoAngles(jaco_angles.Actuators);
00519 }
00520 
00521 
00525 void JacoComm::getCartesianPosition(JacoPose &position)
00526 {
00527     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00528     CartesianPosition jaco_cartesian_position;
00529     memset(&jaco_cartesian_position, 0, sizeof(jaco_cartesian_position));  // zero structure
00530 
00531     int result = jaco_api_.getCartesianPosition(jaco_cartesian_position);
00532     if (result != NO_ERROR_KINOVA)
00533     {
00534         throw JacoCommException("Could not get the Cartesian position", result);
00535     }
00536 
00537     position = JacoPose(jaco_cartesian_position.Coordinates);
00538 }
00539 
00540 
00544 void JacoComm::getFingerPositions(FingerAngles &fingers)
00545 {
00546     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00547     CartesianPosition jaco_cartesian_position;
00548     memset(&jaco_cartesian_position, 0, sizeof(jaco_cartesian_position));  // zero structure
00549 
00550     int result = jaco_api_.getCartesianPosition(jaco_cartesian_position);
00551     if (result != NO_ERROR_KINOVA)
00552     {
00553         throw JacoCommException("Could not get Cartesian finger position", result);
00554     }
00555 
00556     if (num_fingers_ == 2)
00557     {
00558         jaco_cartesian_position.Fingers.Finger3 = 0.0;
00559     }
00560 
00561     fingers = FingerAngles(jaco_cartesian_position.Fingers);
00562 }
00563 
00564 
00568 void JacoComm::getConfig(ClientConfigurations &config)
00569 {
00570     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00571     memset(&config, 0, sizeof(config));  // zero structure
00572 
00573     int result = jaco_api_.getClientConfigurations(config);
00574     if (result != NO_ERROR_KINOVA)
00575     {
00576         throw JacoCommException("Could not get client configuration", result);
00577     }
00578 }
00579 
00580 
00584 void JacoComm::getQuickStatus(QuickStatus &quick_status)
00585 {
00586     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00587     memset(&quick_status, 0, sizeof(quick_status));  // zero structure
00588     int result = jaco_api_.getQuickStatus(quick_status);
00589     if (result != NO_ERROR_KINOVA)
00590     {
00591         throw JacoCommException("Could not get quick status", result);
00592     }
00593 }
00594 
00595 
00596 void JacoComm::stopAPI()
00597 {
00598     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00599     is_software_stop_ = true;
00600 
00601     int result = jaco_api_.stopControlAPI();
00602     if (result != NO_ERROR_KINOVA)
00603     {
00604         throw JacoCommException("Could not stop the control API", result);
00605     }
00606 
00607     result = jaco_api_.eraseAllTrajectories();
00608     if (result != NO_ERROR_KINOVA)
00609     {
00610         throw JacoCommException("Could not erase all trajectories", result);
00611     }
00612 }
00613 
00614 
00615 void JacoComm::startAPI()
00616 {
00617     boost::recursive_mutex::scoped_lock lock(api_mutex_);
00618     if (is_software_stop_)
00619     {
00620         is_software_stop_ = false;
00621         jaco_api_.stopControlAPI();
00622         ros::Duration(0.05).sleep();
00623     }
00624 
00625     int result = jaco_api_.startControlAPI();
00626     if (result != NO_ERROR_KINOVA)
00627     {
00628         throw JacoCommException("Could not start the control API", result);
00629     }
00630 }
00631 
00632 
00633 int JacoComm::numFingers()
00634 {
00635     return num_fingers_;
00636 }
00637 
00638 
00642 void JacoComm::printAngles(const JacoAngles &angles)
00643 {
00644     ROS_INFO("Joint angles (deg) -- J1: %f, J2: %f J3: %f, J4: %f, J5: %f, J6: %f",
00645              angles.Actuator1, angles.Actuator2, angles.Actuator3,
00646              angles.Actuator4, angles.Actuator5, angles.Actuator6);
00647 }
00648 
00649 
00653 void JacoComm::printPosition(const JacoPose &position)
00654 {
00655     ROS_INFO("Arm position\n"
00656              "\tposition (m) -- x: %f, y: %f z: %f\n"
00657              "\trotation (rad) -- theta_x: %f, theta_y: %f, theta_z: %f",
00658              position.X, position.Y, position.Z,
00659              position.ThetaX, position.ThetaY, position.ThetaZ);
00660 }
00661 
00662 
00666 void JacoComm::printFingers(const FingersPosition &fingers)
00667 {
00668     ROS_INFO("Finger positions -- F1: %f, F2: %f, F3: %f",
00669              fingers.Finger1, fingers.Finger2, fingers.Finger3);
00670 }
00671 
00672 
00676 void JacoComm::printConfig(const ClientConfigurations &config)
00677 {
00678     ROS_INFO_STREAM("Arm configuration:\n"
00679                     "\tClientID: " << config.ClientID <<
00680                     "\n\tClientName: " << config.ClientName <<
00681                     "\n\tOrganization: " << config.Organization <<
00682                     "\n\tSerial:" << config.Serial <<
00683                     "\n\tModel: " << config.Model <<
00684                     "\n\tMaxForce: " << config.MaxForce <<
00685                     "\n\tSensibility: " <<  config.Sensibility <<
00686                     "\n\tDrinkingHeight: " << config.DrinkingHeight <<
00687                     "\n\tComplexRetractActive: " << config.ComplexRetractActive <<
00688                     "\n\tRetractedPositionAngle: " << config.RetractedPositionAngle <<
00689                     "\n\tRetractedPositionCount: " << config.RetractedPositionCount <<
00690                     "\n\tDrinkingDistance: " << config.DrinkingDistance <<
00691                     "\n\tFingers2and3Inverted: " << config.Fingers2and3Inverted <<
00692                     "\n\tDrinkingLength: " << config.DrinkingLenght <<
00693                     "\n\tDeletePreProgrammedPositionsAtRetract: " <<
00694                     config.DeletePreProgrammedPositionsAtRetract <<
00695                     "\n\tEnableFlashErrorLog: " << config.EnableFlashErrorLog <<
00696                     "\n\tEnableFlashPositionLog: " << config.EnableFlashPositionLog);
00697 }
00698 
00699 
00700 bool JacoComm::isStopped()
00701 {
00702     return is_software_stop_;
00703 }
00704 
00705 
00706 }  // namespace jaco


jaco_driver
Author(s): Ilia Baranov (Clearpath) , Jeff Schmidt (Clearpath) , Alex Bencz (Clearpath) , Matt DeDonato (WPI), Braden Stenning
autogenerated on Mon Mar 2 2015 16:21:03