jaco_arm_trajectory_node.cpp
Go to the documentation of this file.
00001 #include <wpi_jaco_wrapper/jaco_arm_trajectory_node.h>
00002 
00003 using namespace std;
00004 
00005 namespace jaco
00006 {
00007 JacoArmTrajectoryController::JacoArmTrajectoryController(ros::NodeHandle nh, ros::NodeHandle pnh)
00008   : arm_initialized (false)
00009 {
00010   pnh.param("kinova_gripper", kinova_gripper_, true);
00011   loadParameters(nh);
00012 
00013   // Create actionlib servers and clients
00014   trajectory_server_              = new TrajectoryServer( nh, topic_prefix_ + "_arm/arm_controller/trajectory", boost::bind(&JacoArmTrajectoryController::execute_trajectory, this, _1), true);
00015   smooth_joint_trajectory_server_ = new TrajectoryServer( nh, topic_prefix_ + "_arm/joint_velocity_controller/trajectory", boost::bind(&JacoArmTrajectoryController::execute_joint_trajectory, this, _1), true);
00016   smooth_trajectory_server_       = new TrajectoryServer( nh, topic_prefix_ + "_arm/smooth_arm_controller/trajectory", boost::bind(&JacoArmTrajectoryController::execute_smooth_trajectory, this, _1), false);
00017   home_arm_server_                = new HomeArmServer( nh, topic_prefix_ + "_arm/home_arm", boost::bind(&JacoArmTrajectoryController::home_arm, this, _1), false);
00018 
00019   if (kinova_gripper_)
00020   {
00021     gripper_server_                 = new GripperServer( nh, topic_prefix_ + "_arm/fingers_controller/gripper", boost::bind(&JacoArmTrajectoryController::execute_gripper, this, _1), false);
00022     gripper_server_radian_          = new GripperServer( nh, topic_prefix_ + "_arm/fingers_controller_radian/gripper", boost::bind(&JacoArmTrajectoryController::execute_gripper_radian, this, _1), false);
00023 
00024     gripper_client_                 = new GripperClient( topic_prefix_ + "_arm/fingers_controller/gripper");
00025   }
00026 
00027   boost::recursive_mutex::scoped_lock lock(api_mutex);
00028 
00029   // ROS_INFO("Trying to initialize JACO API...");
00030   while ( InitAPI() != NO_ERROR )
00031   {
00032     ROS_ERROR("Could not initialize Kinova API. Is the arm connected?");
00033     ROS_INFO("Retrying in 5 seconds..");
00034     ros::Duration(5.0).sleep();
00035   }
00036   ros::Duration(1.0).sleep();
00037   StartControlAPI();
00038   ros::Duration(3.0).sleep();
00039   StopControlAPI();
00040 
00041   // Initialize arm
00042   bool home_arm = true;
00043   pnh.getParam("home_arm_on_init", home_arm);
00044   if (home_arm)
00045     MoveHome();
00046   InitFingers();
00047   SetFrameType(0); //set end effector to move with respect to the fixed frame
00048 
00049   ROS_INFO("Arm initialized.");
00050 
00051   // Initialize joint names
00052   if (arm_name_ == "jaco2")
00053   {
00054     joint_names.push_back("jaco_shoulder_pan_joint");
00055     joint_names.push_back("jaco_shoulder_lift_joint");
00056     joint_names.push_back("jaco_elbow_joint");
00057     joint_names.push_back("jaco_wrist_1_joint");
00058     joint_names.push_back("jaco_wrist_2_joint");
00059     joint_names.push_back("jaco_wrist_3_joint");
00060   }
00061   else
00062   {
00063     for (int joint_id = 0; joint_id < NUM_JACO_JOINTS; ++joint_id)
00064     {
00065       stringstream joint_name_stream;
00066       joint_name_stream << arm_name_ << "_joint_" << (joint_id + 1);
00067       string joint_name = joint_name_stream.str();
00068       joint_names.push_back(joint_name);
00069     }
00070   }
00071   if (kinova_gripper_)
00072   {
00073     for (int finger_id = 0; finger_id < num_fingers_; ++finger_id)
00074     {
00075       stringstream finger_name_stream;
00076       finger_name_stream << arm_name_ << "_joint_finger_" << (finger_id + 1);
00077       string finger_name = finger_name_stream.str();
00078       joint_names.push_back(finger_name);
00079     }
00080   }
00081 
00082   StartControlAPI();
00083   SetAngularControl();
00084   controlType = ANGULAR_CONTROL;
00085   eStopEnabled = false;
00086 
00087   // Messages
00088   joint_state_pub_ = nh.advertise<sensor_msgs::JointState>(topic_prefix_ + "_arm/joint_states", 1);
00089   cartesianCmdPublisher = nh.advertise<wpi_jaco_msgs::CartesianCommand>(topic_prefix_+"_arm/cartesian_cmd", 1);
00090   angularCmdPublisher = nh.advertise<wpi_jaco_msgs::AngularCommand>(topic_prefix_+"_arm/angular_cmd", 1);
00091   update_joint_states();
00092   armHomedPublisher = nh.advertise<std_msgs::Bool>(topic_prefix_ + "_arm/arm_homed", 1);
00093 
00094   cartesianCmdSubscriber = nh.subscribe(topic_prefix_+"_arm/cartesian_cmd", 1, &JacoArmTrajectoryController::cartesianCmdCallback,
00095                                         this);
00096   angularCmdSubscriber = nh.subscribe(topic_prefix_+"_arm/angular_cmd", 1, &JacoArmTrajectoryController::angularCmdCallback,
00097                                       this);
00098 
00099   // Services
00100   jaco_fk_client = nh.serviceClient<wpi_jaco_msgs::JacoFK>(topic_prefix_+"_arm/kinematics/fk");
00101   qe_client = nh.serviceClient<wpi_jaco_msgs::QuaternionToEuler>("jaco_conversions/quaternion_to_euler");
00102   angularPositionServer = nh.advertiseService(topic_prefix_+"_arm/get_angular_position", &JacoArmTrajectoryController::getAngularPosition, this);
00103   cartesianPositionServer = nh.advertiseService(topic_prefix_+"_arm/get_cartesian_position",
00104                                                 &JacoArmTrajectoryController::getCartesianPosition, this);
00105   eStopServer = nh.advertiseService(topic_prefix_+"_arm/software_estop", &JacoArmTrajectoryController::eStopCallback, this);
00106   eraseTrajectoriesServer = nh.advertiseService(topic_prefix_+"_arm/erase_trajectories", &JacoArmTrajectoryController::eraseTrajectoriesCallback, this);
00107 
00108   // Action servers
00109   trajectory_server_->start();
00110   smooth_trajectory_server_->start();
00111   smooth_joint_trajectory_server_->start();
00112   home_arm_server_->start();
00113   if (kinova_gripper_)
00114   {
00115     gripper_server_->start();
00116     gripper_server_radian_->start();
00117   }
00118 
00119   joint_state_timer_ = nh.createTimer(ros::Duration(0.0333),
00120                                       boost::bind(&JacoArmTrajectoryController::update_joint_states, this));
00121 
00122   if (home_arm)
00123   {
00124     //publish to arm_homed because the arm is initialized
00125     std_msgs::Bool msg;
00126     msg.data = true;
00127     armHomedPublisher.publish(msg);
00128   }
00129 
00130   arm_initialized = true;
00131 }
00132 
00133 JacoArmTrajectoryController::~JacoArmTrajectoryController()
00134 {
00135   StopControlAPI();
00136   CloseAPI();
00137 }
00138 
00143 static inline double simplify_angle(double angle)
00144 {
00145   double previous_rev = floor(angle / (2.0 * M_PI)) * 2.0 * M_PI;
00146   double next_rev = ceil(angle / (2.0 * M_PI)) * 2.0 * M_PI;
00147   double current_rev;
00148   if (fabs(angle - previous_rev) < fabs(angle - next_rev))
00149     return angle - previous_rev;
00150   return angle - next_rev;
00151 }
00152 
00153 void JacoArmTrajectoryController::update_joint_states()
00154 {
00155   {
00156     boost::recursive_mutex::scoped_lock lock(api_mutex);
00157     AngularPosition force_data;
00158     GetAngularForce(force_data);
00159     joint_eff_[0] = force_data.Actuators.Actuator1;
00160     joint_eff_[1] = force_data.Actuators.Actuator2;
00161     joint_eff_[2] = force_data.Actuators.Actuator3;
00162     joint_eff_[3] = force_data.Actuators.Actuator4;
00163     joint_eff_[4] = force_data.Actuators.Actuator5;
00164     joint_eff_[5] = force_data.Actuators.Actuator6;
00165     if (kinova_gripper_)
00166     {
00167       joint_eff_[6] = force_data.Fingers.Finger1;
00168       joint_eff_[7] = force_data.Fingers.Finger2;
00169       joint_eff_[8] = force_data.Fingers.Finger3;
00170     }
00171 
00172     AngularPosition velocity_data;
00173     GetAngularVelocity(velocity_data);
00174     joint_vel_[0] = velocity_data.Actuators.Actuator1 * DEG_TO_RAD;
00175     joint_vel_[1] = velocity_data.Actuators.Actuator2 * DEG_TO_RAD;
00176     joint_vel_[2] = velocity_data.Actuators.Actuator3 * DEG_TO_RAD;
00177     joint_vel_[3] = velocity_data.Actuators.Actuator4 * DEG_TO_RAD;
00178     joint_vel_[4] = velocity_data.Actuators.Actuator5 * DEG_TO_RAD;
00179     joint_vel_[5] = velocity_data.Actuators.Actuator6 * DEG_TO_RAD;
00180     if (kinova_gripper_)
00181     {
00182       //NOTE: the finger units are arbitrary, but converting them as if they were in degrees provides an approximately correct visualization
00183       joint_vel_[6] = velocity_data.Fingers.Finger1 * DEG_TO_RAD * finger_scale_;
00184       joint_vel_[7] = velocity_data.Fingers.Finger2 * DEG_TO_RAD * finger_scale_;
00185       joint_vel_[8] = velocity_data.Fingers.Finger3 * DEG_TO_RAD * finger_scale_;
00186     }
00187 
00188     AngularPosition position_data;
00189     GetAngularPosition(position_data);
00190     joint_pos_[0] = simplify_angle(position_data.Actuators.Actuator1 * DEG_TO_RAD);
00191     joint_pos_[1] = position_data.Actuators.Actuator2 * DEG_TO_RAD;
00192     joint_pos_[2] = position_data.Actuators.Actuator3 * DEG_TO_RAD;
00193     joint_pos_[3] = simplify_angle(position_data.Actuators.Actuator4 * DEG_TO_RAD);
00194     joint_pos_[4] = simplify_angle(position_data.Actuators.Actuator5 * DEG_TO_RAD);
00195     joint_pos_[5] = simplify_angle(position_data.Actuators.Actuator6 * DEG_TO_RAD);
00196     if (kinova_gripper_)
00197     {
00198       joint_pos_[6] = position_data.Fingers.Finger1 * DEG_TO_RAD * finger_scale_;
00199       joint_pos_[7] = position_data.Fingers.Finger2 * DEG_TO_RAD * finger_scale_;
00200       joint_pos_[8] = position_data.Fingers.Finger3 * DEG_TO_RAD * finger_scale_;
00201     }
00202   }
00203 
00204   sensor_msgs::JointState state;
00205   state.header.stamp = ros::Time::now();
00206   state.name = joint_names;
00207   state.position.assign(joint_pos_.begin(), joint_pos_.end());
00208   state.velocity.assign(joint_vel_.begin(), joint_vel_.end());
00209   state.effort.assign(joint_eff_.begin(), joint_eff_.end());
00210   joint_state_pub_.publish(state);
00211 }
00212 
00218 static inline double nearest_equivalent(double desired, double current)
00219 {
00220   //calculate current number of revolutions
00221   double previous_rev = floor(current / (2 * M_PI));
00222   double next_rev = ceil(current / (2 * M_PI));
00223   double current_rev;
00224   if (fabs(current - previous_rev * 2 * M_PI) < fabs(current - next_rev * 2 * M_PI))
00225     current_rev = previous_rev;
00226   else
00227     current_rev = next_rev;
00228 
00229   //determine closest angle
00230   double lowVal = (current_rev - 1) * 2 * M_PI + desired;
00231   double medVal = current_rev * 2 * M_PI + desired;
00232   double highVal = (current_rev + 1) * 2 * M_PI + desired;
00233   if (fabs(current - lowVal) <= fabs(current - medVal) && fabs(current - lowVal) <= fabs(current - highVal))
00234     return lowVal;
00235   if (fabs(current - medVal) <= fabs(current - lowVal) && fabs(current - medVal) <= fabs(current - highVal))
00236     return medVal;
00237   return highVal;
00238 }
00239 
00240 /*****************************************/
00241 /**********  Trajectory Control **********/
00242 /*****************************************/
00243 
00244 void JacoArmTrajectoryController::execute_trajectory(const control_msgs::FollowJointTrajectoryGoalConstPtr &goal)
00245 {
00246   if ( not arm_initialized )
00247   {
00248     return; // The arm is not fully initialized yet
00249   }
00250   //cancel check
00251   if (eStopEnabled)
00252   {
00253     control_msgs::FollowJointTrajectoryResult result;
00254     result.error_code = control_msgs::FollowJointTrajectoryResult::PATH_TOLERANCE_VIOLATED;
00255     trajectory_server_->setSucceeded(result);
00256     return;
00257   }
00258 
00259   {
00260     boost::recursive_mutex::scoped_lock lock(api_mutex);
00261     EraseAllTrajectories();
00262   }
00263 
00264   update_joint_states();
00265   double current_joint_pos[NUM_JACO_JOINTS];
00266 
00267   AngularPosition position_data;
00268   {
00269     boost::recursive_mutex::scoped_lock lock(api_mutex);
00270     GetAngularPosition(position_data);
00271   }
00272   current_joint_pos[0] = position_data.Actuators.Actuator1 * DEG_TO_RAD;
00273   current_joint_pos[1] = position_data.Actuators.Actuator2 * DEG_TO_RAD;
00274   current_joint_pos[2] = position_data.Actuators.Actuator3 * DEG_TO_RAD;
00275   current_joint_pos[3] = position_data.Actuators.Actuator4 * DEG_TO_RAD;
00276   current_joint_pos[4] = position_data.Actuators.Actuator5 * DEG_TO_RAD;
00277   current_joint_pos[5] = position_data.Actuators.Actuator6 * DEG_TO_RAD;
00278 
00279   //initialize trajectory point
00280   TrajectoryPoint trajPoint;
00281   trajPoint.InitStruct();
00282   trajPoint.Position.Type = ANGULAR_POSITION;
00283   trajPoint.Position.HandMode = HAND_NOMOVEMENT;
00284   BOOST_FOREACH(trajectory_msgs::JointTrajectoryPoint point, goal->trajectory.points)
00285   {
00286     ROS_INFO("Trajectory Point");
00287     double joint_cmd[NUM_JACO_JOINTS];
00288     for (int trajectory_index = 0; trajectory_index < goal->trajectory.joint_names.size(); ++trajectory_index)
00289     {
00290       string joint_name = goal->trajectory.joint_names[trajectory_index];
00291       int joint_index = distance(joint_names.begin(), find(joint_names.begin(), joint_names.end(), joint_name));
00292       if (joint_index >= 0 && joint_index < NUM_JACO_JOINTS)
00293       {
00294         //ROS_INFO("Before: %s: (%d -> %d) = %f", joint_name.c_str(), trajectory_index, joint_index, point.positions[trajectory_index]);
00295         if (joint_index != 1 && joint_index != 2)
00296           joint_cmd[joint_index] = nearest_equivalent(simplify_angle(point.positions[trajectory_index]),
00297                                                       current_joint_pos[joint_index]);
00298         else
00299           joint_cmd[joint_index] = point.positions[trajectory_index];
00300         //ROS_INFO("After:  %s: (%d -> %d) = %f", joint_name.c_str(), trajectory_index, joint_index, joint_cmd[joint_index]);
00301       }
00302     }
00303     for (int i = 0; i < NUM_JACO_JOINTS; i++)
00304       current_joint_pos[i] = joint_cmd[i];
00305 
00306     AngularInfo angles;
00307     angles.Actuator1 = joint_cmd[0] * RAD_TO_DEG;
00308     angles.Actuator2 = joint_cmd[1] * RAD_TO_DEG;
00309     angles.Actuator3 = joint_cmd[2] * RAD_TO_DEG;
00310     angles.Actuator4 = joint_cmd[3] * RAD_TO_DEG;
00311     angles.Actuator5 = joint_cmd[4] * RAD_TO_DEG;
00312     angles.Actuator6 = joint_cmd[5] * RAD_TO_DEG;
00313 
00314     trajPoint.Position.Actuators = angles;
00315 
00316     executeAngularTrajectoryPoint(trajPoint, false);
00317   }
00318 
00319   ros::Rate rate(10);
00320   int trajectory_size;
00321   while (trajectory_size > 0)
00322   {
00323     //cancel check
00324     if (eStopEnabled)
00325     {
00326       control_msgs::FollowJointTrajectoryResult result;
00327       result.error_code = control_msgs::FollowJointTrajectoryResult::PATH_TOLERANCE_VIOLATED;
00328       trajectory_server_->setSucceeded(result);
00329       return;
00330     }
00331 
00332     //check for preempt requests from clients
00333     if (trajectory_server_->isPreemptRequested() || !ros::ok())
00334     {
00335       //stop gripper control
00336       trajPoint.Position.Type = ANGULAR_VELOCITY;
00337       trajPoint.Position.Actuators.Actuator1 = 0.0;
00338       trajPoint.Position.Actuators.Actuator2 = 0.0;
00339       trajPoint.Position.Actuators.Actuator3 = 0.0;
00340       trajPoint.Position.Actuators.Actuator4 = 0.0;
00341       trajPoint.Position.Actuators.Actuator5 = 0.0;
00342       trajPoint.Position.Actuators.Actuator6 = 0.0;
00343       executeAngularTrajectoryPoint(trajPoint, true);
00344 
00345       //preempt action server
00346       trajectory_server_->setPreempted();
00347       ROS_INFO("Joint trajectory server preempted by client");
00348 
00349       return;
00350     }
00351 
00352     {
00353       boost::recursive_mutex::scoped_lock lock(api_mutex);
00354 
00355       TrajectoryFIFO Trajectory_Info;
00356       memset(&Trajectory_Info, 0, sizeof(Trajectory_Info));
00357       GetGlobalTrajectoryInfo(Trajectory_Info);
00358       trajectory_size = Trajectory_Info.TrajectoryCount;
00359     }
00360     //ROS_INFO("%f, %f, %f, %f, %f, %f", joint_pos[0], joint_pos[1], joint_pos[2], joint_pos[3], joint_pos[4], joint_pos[5]);
00361     rate.sleep();
00362   }
00363 
00364   //stop gripper control
00365   trajPoint.Position.Type = ANGULAR_VELOCITY;
00366   trajPoint.Position.Actuators.Actuator1 = 0.0;
00367   trajPoint.Position.Actuators.Actuator2 = 0.0;
00368   trajPoint.Position.Actuators.Actuator3 = 0.0;
00369   trajPoint.Position.Actuators.Actuator4 = 0.0;
00370   trajPoint.Position.Actuators.Actuator5 = 0.0;
00371   trajPoint.Position.Actuators.Actuator6 = 0.0;
00372   executeAngularTrajectoryPoint(trajPoint, true);
00373 
00374   ROS_INFO("Trajectory Control Complete.");
00375   control_msgs::FollowJointTrajectoryResult result;
00376   result.error_code = control_msgs::FollowJointTrajectoryResult::SUCCESSFUL;
00377   trajectory_server_->setSucceeded(result);
00378 }
00379 
00380 /*****************************************/
00381 /*****  Smoothed Trajectory Control ******/
00382 /*****************************************/
00383 
00384 void JacoArmTrajectoryController::execute_smooth_trajectory(const control_msgs::FollowJointTrajectoryGoalConstPtr &goal)
00385 {
00386   //cancel check
00387   if (eStopEnabled)
00388   {
00389     control_msgs::FollowJointTrajectoryResult result;
00390     result.error_code = control_msgs::FollowJointTrajectoryResult::PATH_TOLERANCE_VIOLATED;
00391     smooth_trajectory_server_->setSucceeded(result);
00392     return;
00393   }
00394 
00395   {
00396     boost::recursive_mutex::scoped_lock lock(api_mutex);
00397     EraseAllTrajectories();
00398   }
00399 
00400   update_joint_states();
00401   double current_joint_pos[NUM_JACO_JOINTS];
00402 
00403   AngularPosition position_data;
00404   {
00405     boost::recursive_mutex::scoped_lock lock(api_mutex);
00406     GetAngularPosition(position_data);
00407   }
00408   current_joint_pos[0] = position_data.Actuators.Actuator1 * DEG_TO_RAD;
00409   current_joint_pos[1] = position_data.Actuators.Actuator2 * DEG_TO_RAD;
00410   current_joint_pos[2] = position_data.Actuators.Actuator3 * DEG_TO_RAD;
00411   current_joint_pos[3] = position_data.Actuators.Actuator4 * DEG_TO_RAD;
00412   current_joint_pos[4] = position_data.Actuators.Actuator5 * DEG_TO_RAD;
00413   current_joint_pos[5] = position_data.Actuators.Actuator6 * DEG_TO_RAD;
00414 
00415   TrajectoryPoint trajPoint;
00416   trajPoint.InitStruct();
00417   trajPoint.Position.Type = CARTESIAN_POSITION;
00418   trajPoint.Position.HandMode = HAND_NOMOVEMENT;
00419 
00420   BOOST_FOREACH(trajectory_msgs::JointTrajectoryPoint point, goal->trajectory.points)
00421   {
00422     double joint_cmd[NUM_JACO_JOINTS];
00423     for (int trajectory_index = 0; trajectory_index < goal->trajectory.joint_names.size(); ++trajectory_index)
00424     {
00425       string joint_name = goal->trajectory.joint_names[trajectory_index];
00426       int joint_index = distance(joint_names.begin(), find(joint_names.begin(), joint_names.end(), joint_name));
00427       if (joint_index >= 0 && joint_index < NUM_JACO_JOINTS)
00428       {
00429         //convert angles from continuous joints to be correct for the arm API
00430         if (joint_index != 1 && joint_index != 2)
00431           joint_cmd[joint_index] = nearest_equivalent(simplify_angle(point.positions[trajectory_index]),
00432                                                       current_joint_pos[joint_index]);
00433         else
00434           joint_cmd[joint_index] = point.positions[trajectory_index];
00435       }
00436     }
00437 
00438     for (int i = 0; i < NUM_JACO_JOINTS; i++)
00439       current_joint_pos[i] = joint_cmd[i];
00440 
00441     //convert joint angles to end effector pose
00442     wpi_jaco_msgs::JacoFK fkSrv;
00443     for (unsigned int i = 0; i < NUM_JACO_JOINTS; i++)
00444     {
00445       fkSrv.request.joints.push_back(joint_cmd[i]);
00446     }
00447     if (jaco_fk_client.call(fkSrv))
00448     {
00449       //conversion to rpy
00450       wpi_jaco_msgs::QuaternionToEuler qeSrv;
00451       qeSrv.request.orientation = fkSrv.response.handPose.pose.orientation;
00452       if (qe_client.call(qeSrv))
00453       {
00454         trajPoint.Position.CartesianPosition.X = fkSrv.response.handPose.pose.position.x;
00455         trajPoint.Position.CartesianPosition.Y = fkSrv.response.handPose.pose.position.y;
00456         trajPoint.Position.CartesianPosition.Z = fkSrv.response.handPose.pose.position.z;
00457         trajPoint.Position.CartesianPosition.ThetaX = qeSrv.response.roll;
00458         trajPoint.Position.CartesianPosition.ThetaY = qeSrv.response.pitch;
00459         trajPoint.Position.CartesianPosition.ThetaZ = qeSrv.response.yaw;
00460 
00461         // for debugging:
00462         ROS_INFO("Trajectory point: (%f, %f, %f); (%f, %f, %f)", trajPoint.Position.CartesianPosition.X, trajPoint.Position.CartesianPosition.Y, trajPoint.Position.CartesianPosition.Z, trajPoint.Position.CartesianPosition.ThetaX, trajPoint.Position.CartesianPosition.ThetaY, trajPoint.Position.CartesianPosition.ThetaZ);
00463 
00464         //send point to arm trajectory
00465         executeCartesianTrajectoryPoint(trajPoint, false);
00466       }
00467       else
00468       {
00469         ROS_INFO("Quaternion to Euler Angle conversion service failed");
00470 
00471         trajPoint.Position.Type = ANGULAR_VELOCITY;
00472         trajPoint.Position.Actuators.Actuator1 = 0.0;
00473         trajPoint.Position.Actuators.Actuator2 = 0.0;
00474         trajPoint.Position.Actuators.Actuator3 = 0.0;
00475         trajPoint.Position.Actuators.Actuator4 = 0.0;
00476         trajPoint.Position.Actuators.Actuator5 = 0.0;
00477         trajPoint.Position.Actuators.Actuator6 = 0.0;
00478         executeAngularTrajectoryPoint(trajPoint, true);
00479 
00480         control_msgs::FollowJointTrajectoryResult result;
00481         result.error_code = control_msgs::FollowJointTrajectoryResult::INVALID_JOINTS;
00482         smooth_trajectory_server_->setSucceeded(result);
00483         return;
00484       }
00485     }
00486     else
00487     {
00488       ROS_INFO("Failed to call forward kinematics service");
00489 
00490       trajPoint.Position.Type = ANGULAR_VELOCITY;
00491       trajPoint.Position.Actuators.Actuator1 = 0.0;
00492       trajPoint.Position.Actuators.Actuator2 = 0.0;
00493       trajPoint.Position.Actuators.Actuator3 = 0.0;
00494       trajPoint.Position.Actuators.Actuator4 = 0.0;
00495       trajPoint.Position.Actuators.Actuator5 = 0.0;
00496       trajPoint.Position.Actuators.Actuator6 = 0.0;
00497       executeAngularTrajectoryPoint(trajPoint, true);
00498 
00499       control_msgs::FollowJointTrajectoryResult result;
00500       result.error_code = control_msgs::FollowJointTrajectoryResult::INVALID_JOINTS;
00501       smooth_trajectory_server_->setSucceeded(result);
00502       return;
00503     }
00504   }
00505 
00506   //wait for trajectory to complete execution
00507   ros::Rate rate(10);
00508   int trajectory_size;
00509   int initialTrajectorySize;
00510   TrajectoryFIFO Trajectory_Info;
00511   memset(&Trajectory_Info, 0, sizeof(Trajectory_Info));
00512   {
00513     boost::recursive_mutex::scoped_lock lock(api_mutex);
00514     GetGlobalTrajectoryInfo(Trajectory_Info);
00515   }
00516   trajectory_size = Trajectory_Info.TrajectoryCount;
00517   initialTrajectorySize = trajectory_size;
00518   while (trajectory_size > 0)
00519   {
00520     //cancel check
00521     if (eStopEnabled)
00522     {
00523       control_msgs::FollowJointTrajectoryResult result;
00524       result.error_code = control_msgs::FollowJointTrajectoryResult::PATH_TOLERANCE_VIOLATED;
00525       smooth_trajectory_server_->setSucceeded(result);
00526       return;
00527     }
00528 
00529     //check for preempt requests from clients
00530     if (smooth_trajectory_server_->isPreemptRequested() || !ros::ok())
00531     {
00532       //stop gripper control
00533       trajPoint.Position.Type = ANGULAR_VELOCITY;
00534       trajPoint.Position.Actuators.Actuator1 = 0.0;
00535       trajPoint.Position.Actuators.Actuator2 = 0.0;
00536       trajPoint.Position.Actuators.Actuator3 = 0.0;
00537       trajPoint.Position.Actuators.Actuator4 = 0.0;
00538       trajPoint.Position.Actuators.Actuator5 = 0.0;
00539       trajPoint.Position.Actuators.Actuator6 = 0.0;
00540       executeAngularTrajectoryPoint(trajPoint, true);
00541 
00542       //preempt action server
00543       smooth_trajectory_server_->setPreempted();
00544       ROS_INFO("Smooth trajectory server preempted by client");
00545 
00546       return;
00547     }
00548 
00549     {
00550       boost::recursive_mutex::scoped_lock lock(api_mutex);
00551       GetGlobalTrajectoryInfo(Trajectory_Info);
00552     }
00553     trajectory_size = Trajectory_Info.TrajectoryCount;
00554 
00555     ROS_INFO("%f, %f, %f, %f, %f, %f", joint_pos_[0], joint_pos_[1], joint_pos_[2], joint_pos_[3], joint_pos_[4], joint_pos_[5]);
00556     ROS_INFO("Trajectory points complete: %d; remaining: %d", initialTrajectorySize - trajectory_size, trajectory_size);
00557     rate.sleep();
00558   }
00559   ROS_INFO("Trajectory Control Complete.");
00560   control_msgs::FollowJointTrajectoryResult result;
00561   result.error_code = control_msgs::FollowJointTrajectoryResult::SUCCESSFUL;
00562   smooth_trajectory_server_->setSucceeded(result);
00563 }
00564 
00565 void JacoArmTrajectoryController::execute_joint_trajectory(const control_msgs::FollowJointTrajectoryGoalConstPtr &goal)
00566 {
00567   //check for cancel
00568   if (eStopEnabled)
00569   {
00570     control_msgs::FollowJointTrajectoryResult result;
00571     result.error_code = control_msgs::FollowJointTrajectoryResult::PATH_TOLERANCE_VIOLATED;
00572     smooth_joint_trajectory_server_->setSucceeded(result);
00573     return;
00574   }
00575 
00576   float trajectoryPoints[NUM_JACO_JOINTS][goal->trajectory.points.size()];
00577   int numPoints = goal->trajectory.points.size();
00578 
00579   //get trajectory data
00580   for (unsigned int i = 0; i < numPoints; i++)
00581   {
00582 
00583     //TEST
00584     for (int trajectory_index = 0; trajectory_index < goal->trajectory.joint_names.size(); trajectory_index++)
00585     {
00586       string joint_name = goal->trajectory.joint_names[trajectory_index];
00587       int joint_index = distance(joint_names.begin(), find(joint_names.begin(), joint_names.end(), joint_name));
00588       if (joint_index >= 0 && joint_index < NUM_JACO_JOINTS)
00589       {
00590         trajectoryPoints[joint_index][i] = goal->trajectory.points.at(i).positions.at(trajectory_index);
00591       }
00592     }
00593     //END TEST
00594 
00595     /*
00596     for (unsigned int j = 0; j < NUM_JACO_JOINTS; j++)
00597     {
00598       trajectoryPoints[j][i] = goal->trajectory.points.at(i).positions.at(j);
00599     }
00600     */
00601   }
00602 
00603   //initialize arrays needed to fit a smooth trajectory to the given points
00604   ecl::Array<double> timePoints(numPoints);
00605   timePoints[0] = 0.0;
00606   vector<ecl::Array<double> > jointPoints;
00607   jointPoints.resize(NUM_JACO_JOINTS);
00608   float prevPoint[NUM_JACO_JOINTS];
00609   for (unsigned int i = 0; i < NUM_JACO_JOINTS; i++)
00610   {
00611     jointPoints[i].resize(numPoints);
00612     jointPoints[i][0] = trajectoryPoints[i][0];
00613     prevPoint[i] = trajectoryPoints[i][0];
00614   }
00615 
00616   //determine time component of trajectories for each joint
00617   for (unsigned int i = 1; i < numPoints; i++)
00618   {
00619     float maxTime = 0.0;
00620     for (unsigned int j = 0; j < NUM_JACO_JOINTS; j++)
00621     {
00622       //calculate approximate time required to move to the next position
00623       float time = fabs(trajectoryPoints[j][i] - prevPoint[j]);
00624       if (j <= 2)
00625         time /= LARGE_ACTUATOR_VELOCITY;
00626       else
00627         time /= SMALL_ACTUATOR_VELOCITY;
00628 
00629       if (time > maxTime)
00630         maxTime = time;
00631 
00632       jointPoints[j][i] = trajectoryPoints[j][i];
00633       prevPoint[j] = trajectoryPoints[j][i];
00634     }
00635 
00636     timePoints[i] = timePoints[i - 1] + maxTime * TIME_SCALING_FACTOR;
00637   }
00638 
00639   vector<ecl::SmoothLinearSpline> splines;
00640   splines.resize(6);
00641   for (unsigned int i = 0; i < NUM_JACO_JOINTS; i++)
00642   {
00643     ecl::SmoothLinearSpline tempSpline(timePoints, jointPoints[i], max_curvature_);
00644     splines.at(i) = tempSpline;
00645   }
00646 
00647   //control loop
00648   bool trajectoryComplete = false;
00649   double startTime = ros::Time::now().toSec();
00650   double t = 0;
00651   float error[NUM_JACO_JOINTS];
00652   float totalError;
00653   float prevError[NUM_JACO_JOINTS] = {0};
00654   float currentPoint;
00655   double current_joint_pos[NUM_JACO_JOINTS];
00656   AngularPosition position_data;
00657   TrajectoryPoint trajPoint;
00658   trajPoint.InitStruct();
00659   trajPoint.Position.Type = ANGULAR_VELOCITY;
00660   trajPoint.Position.HandMode = HAND_NOMOVEMENT;
00661 
00662   ros::Rate rate(600);
00663 
00664   while (!trajectoryComplete)
00665   {
00666     if (eStopEnabled)
00667     {
00668       control_msgs::FollowJointTrajectoryResult result;
00669       result.error_code = control_msgs::FollowJointTrajectoryResult::PATH_TOLERANCE_VIOLATED;
00670       smooth_joint_trajectory_server_->setSucceeded(result);
00671       return;
00672     }
00673 
00674     //check for preempt requests from clients
00675     if (smooth_joint_trajectory_server_->isPreemptRequested())
00676     {
00677       //stop gripper control
00678       trajPoint.Position.Actuators.Actuator1 = 0.0;
00679       trajPoint.Position.Actuators.Actuator2 = 0.0;
00680       trajPoint.Position.Actuators.Actuator3 = 0.0;
00681       trajPoint.Position.Actuators.Actuator4 = 0.0;
00682       trajPoint.Position.Actuators.Actuator5 = 0.0;
00683       trajPoint.Position.Actuators.Actuator6 = 0.0;
00684       executeAngularTrajectoryPoint(trajPoint, true);
00685 
00686       //preempt action server
00687       smooth_joint_trajectory_server_->setPreempted();
00688       ROS_INFO("Joint trajectory server preempted by client");
00689 
00690       return;
00691     }
00692 
00693     //get time for trajectory
00694     t = ros::Time::now().toSec() - startTime;
00695     if (t > timePoints.at(timePoints.size() - 1))
00696     {
00697       //use final trajectory point as the goal to calculate error until the error
00698       //is small enough to be considered successful
00699       {
00700         boost::recursive_mutex::scoped_lock lock(api_mutex);
00701         GetAngularPosition(position_data);
00702       }
00703       current_joint_pos[0] = position_data.Actuators.Actuator1 * DEG_TO_RAD;
00704       current_joint_pos[1] = position_data.Actuators.Actuator2 * DEG_TO_RAD;
00705       current_joint_pos[2] = position_data.Actuators.Actuator3 * DEG_TO_RAD;
00706       current_joint_pos[3] = position_data.Actuators.Actuator4 * DEG_TO_RAD;
00707       current_joint_pos[4] = position_data.Actuators.Actuator5 * DEG_TO_RAD;
00708       current_joint_pos[5] = position_data.Actuators.Actuator6 * DEG_TO_RAD;
00709 
00710       totalError = 0;
00711       for (unsigned int i = 0; i < NUM_JACO_JOINTS; i++)
00712       {
00713         currentPoint = simplify_angle(current_joint_pos[i]);
00714         error[i] = nearest_equivalent(simplify_angle((splines.at(i))(timePoints.at(timePoints.size() - 1))),
00715                                       currentPoint) - currentPoint;
00716         totalError += fabs(error[i]);
00717       }
00718 
00719       if (totalError < .03)
00720       {
00721         trajPoint.Position.Actuators.Actuator1 = 0.0;
00722         trajPoint.Position.Actuators.Actuator2 = 0.0;
00723         trajPoint.Position.Actuators.Actuator3 = 0.0;
00724         trajPoint.Position.Actuators.Actuator4 = 0.0;
00725         trajPoint.Position.Actuators.Actuator5 = 0.0;
00726         trajPoint.Position.Actuators.Actuator6 = 0.0;
00727         executeAngularTrajectoryPoint(trajPoint, true);
00728         trajectoryComplete = true;
00729         ROS_INFO("Trajectory complete!");
00730         break;
00731       }
00732     }
00733     else
00734     {
00735       //calculate error
00736       {
00737         boost::recursive_mutex::scoped_lock lock(api_mutex);
00738         GetAngularPosition(position_data);
00739       }
00740       current_joint_pos[0] = position_data.Actuators.Actuator1 * DEG_TO_RAD;
00741       current_joint_pos[1] = position_data.Actuators.Actuator2 * DEG_TO_RAD;
00742       current_joint_pos[2] = position_data.Actuators.Actuator3 * DEG_TO_RAD;
00743       current_joint_pos[3] = position_data.Actuators.Actuator4 * DEG_TO_RAD;
00744       current_joint_pos[4] = position_data.Actuators.Actuator5 * DEG_TO_RAD;
00745       current_joint_pos[5] = position_data.Actuators.Actuator6 * DEG_TO_RAD;
00746       for (unsigned int i = 0; i < NUM_JACO_JOINTS; i++)
00747       {
00748         currentPoint = simplify_angle(current_joint_pos[i]);
00749         error[i] = nearest_equivalent(simplify_angle((splines.at(i))(t)), currentPoint) - currentPoint;
00750       }
00751     }
00752 
00753     //calculate control input
00754     //populate the velocity command
00755     trajPoint.Position.Actuators.Actuator1 = (KP * error[0] + KV * (error[0] - prevError[0]) * RAD_TO_DEG);
00756     trajPoint.Position.Actuators.Actuator2 = (KP * error[1] + KV * (error[1] - prevError[1]) * RAD_TO_DEG);
00757     trajPoint.Position.Actuators.Actuator3 = (KP * error[2] + KV * (error[2] - prevError[2]) * RAD_TO_DEG);
00758     trajPoint.Position.Actuators.Actuator4 = (KP * error[3] + KV * (error[3] - prevError[3]) * RAD_TO_DEG);
00759     trajPoint.Position.Actuators.Actuator5 = (KP * error[4] + KV * (error[4] - prevError[4]) * RAD_TO_DEG);
00760     trajPoint.Position.Actuators.Actuator6 = (KP * error[5] + KV * (error[5] - prevError[5]) * RAD_TO_DEG);
00761 
00762     //for debugging:
00763     // cout << "Errors: " << error[0] << ", " << error[1] << ", " << error[2] << ", " << error[3] << ", " << error[4] << ", " << error[5] << endl;
00764 
00765     //send the velocity command
00766     executeAngularTrajectoryPoint(trajPoint, true);
00767 
00768     for (unsigned int i = 0; i < NUM_JACO_JOINTS; i++)
00769     {
00770       prevError[i] = error[i];
00771     }
00772 
00773     rate.sleep();
00774   }
00775 
00776   control_msgs::FollowJointTrajectoryResult result;
00777   result.error_code = control_msgs::FollowJointTrajectoryResult::SUCCESSFUL;
00778   smooth_joint_trajectory_server_->setSucceeded(result);
00779 }
00780 
00781 /*****************************************/
00782 /***********  Gripper Control ************/
00783 /*****************************************/
00784 
00785 void JacoArmTrajectoryController::execute_gripper(const control_msgs::GripperCommandGoalConstPtr &goal)
00786 {
00787   //check for cancel
00788   if (eStopEnabled)
00789   {
00790     control_msgs::GripperCommandResult result;
00791     result.reached_goal = false;
00792     gripper_server_->setSucceeded(result);
00793     return;
00794   }
00795   wpi_jaco_msgs::AngularCommand cmd;
00796   cmd.position = true;
00797   cmd.armCommand = false;
00798   cmd.fingerCommand = true;
00799   cmd.repeat = false;
00800   cmd.fingers.resize(num_fingers_);
00801   for (int i = 0 ; i < num_fingers_ ; i++)
00802     cmd.fingers[i] = goal->command.position;
00803 
00804   angularCmdPublisher.publish(cmd);
00805 
00806   //give the fingers sufficient time to start moving, this prevents early termination if a command is slow to reach arm
00807   ros::Rate startupRate(1);
00808   startupRate.sleep();
00809 
00810   ros::Rate rate(10);
00811   bool gripperMoving = true;
00812   while (gripperMoving)
00813   {
00814     //check for cancel
00815     if (eStopEnabled)
00816     {
00817       control_msgs::GripperCommandResult result;
00818       result.reached_goal = false;
00819       gripper_server_->setSucceeded(result);
00820       return;
00821     }
00822 
00823     rate.sleep();
00824     //check for preempt requests from clients
00825     if (gripper_server_->isPreemptRequested() || !ros::ok())
00826     {
00827       //stop gripper control
00828       cmd.position = false;
00829       for (int i = 0 ; i < num_fingers_ ; i++)
00830         cmd.fingers[i] = 0.0;
00831 
00832       angularCmdPublisher.publish(cmd);
00833 
00834       //preempt action server
00835       ROS_INFO("Gripper action server preempted by client");
00836       gripper_server_->setPreempted();
00837 
00838       return;
00839     }
00840 
00841     //see if fingers are still moving
00842     AngularPosition velocity_data;
00843     {
00844       boost::recursive_mutex::scoped_lock lock(api_mutex);
00845       GetAngularVelocity(velocity_data);
00846     }
00847 
00848     float totalSpeed = fabs(velocity_data.Fingers.Finger1) 
00849                      + fabs(velocity_data.Fingers.Finger2);
00850     if ( num_fingers_ == 3 )
00851       totalSpeed += fabs(velocity_data.Fingers.Finger3);
00852 
00853     if (totalSpeed <= 0.01)
00854       gripperMoving = false;
00855   }
00856 
00857   //stop gripper control
00858   {
00859     boost::recursive_mutex::scoped_lock lock(api_mutex);
00860     EraseAllTrajectories();
00861   }
00862 
00863   cmd.position = false;
00864   for (int i = 0 ; i < num_fingers_ ; i++)
00865     cmd.fingers[i] = 0.0;
00866 
00867   angularCmdPublisher.publish(cmd);
00868 
00869   control_msgs::GripperCommandResult result;
00870   AngularPosition force_data;
00871   AngularPosition position_data;
00872   {
00873     boost::recursive_mutex::scoped_lock lock(api_mutex);
00874     GetAngularPosition(position_data);
00875     GetAngularForce(force_data);
00876   }
00877   float finalError    = fabs(goal->command.position - position_data.Fingers.Finger1) 
00878                       + fabs(goal->command.position - position_data.Fingers.Finger2);
00879   if ( num_fingers_ == 3 )
00880     finalError += fabs(goal->command.position - position_data.Fingers.Finger3);
00881 
00882   ROS_INFO("Final error: %f", finalError);
00883   result.reached_goal = (finalError <= finger_error_threshold_);
00884   result.position     = position_data.Fingers.Finger1;
00885   result.effort       = force_data.Fingers.Finger1;
00886   result.stalled      = false;
00887   gripper_server_->setSucceeded(result);
00888 }
00889 
00890 void JacoArmTrajectoryController::execute_gripper_radian(const control_msgs::GripperCommandGoalConstPtr &goal)
00891 {
00892   control_msgs::GripperCommandGoal convertedGoal;
00893   convertedGoal.command.max_effort = goal->command.max_effort;
00894   convertedGoal.command.position = (gripper_closed_/.93)*goal->command.position;
00895 
00896   gripper_client_->sendGoal(convertedGoal);
00897   gripper_client_->waitForResult(ros::Duration(5.0));
00898 
00899   actionlib::SimpleClientGoalState state = gripper_client_->getState();
00900   if (state == actionlib::SimpleClientGoalState::SUCCEEDED)
00901   {
00902     //get result
00903     control_msgs::GripperCommandResultConstPtr res = gripper_client_->getResult();
00904 
00905     //convert resulting position to a radian position
00906     control_msgs::GripperCommandResult result = *res;
00907     result.position = result.position * DEG_TO_RAD * finger_scale_;
00908 
00909     gripper_server_radian_->setSucceeded(result);
00910   }
00911   else if (state == actionlib::SimpleClientGoalState::PREEMPTED)
00912     gripper_server_radian_->setPreempted();
00913   else
00914     gripper_server_radian_->setAborted();
00915 }
00916 
00917 /*****************************************/
00918 /**********  Other Arm Actions  **********/
00919 /*****************************************/
00920 
00921 void JacoArmTrajectoryController::home_arm(const wpi_jaco_msgs::HomeArmGoalConstPtr &goal)
00922 {
00923   //check for cancel
00924   if (eStopEnabled)
00925   {
00926     wpi_jaco_msgs::HomeArmResult result;
00927     result.success = false;
00928     home_arm_server_->setSucceeded(result);
00929     return;
00930   }
00931 
00932   {
00933     boost::recursive_mutex::scoped_lock lock(api_mutex);
00934     StopControlAPI();
00935     MoveHome();
00936     StartControlAPI();
00937     std_msgs::Bool msg;
00938     msg.data = true;
00939     armHomedPublisher.publish(msg);
00940   }
00941 
00942   if (goal->retract)
00943   {
00944     //check for cancel
00945     if (eStopEnabled)
00946     {
00947       wpi_jaco_msgs::HomeArmResult result;
00948       result.success = false;
00949       home_arm_server_->setSucceeded(result);
00950       return;
00951     }
00952 
00953     {
00954       boost::recursive_mutex::scoped_lock lock(api_mutex);
00955       //retract to given position
00956       controlType = ANGULAR_CONTROL;
00957       SetAngularControl();
00958     }
00959 
00960     angularCmdPublisher.publish(goal->retractPosition);
00961 
00962     ros::Rate rate(10);
00963     int trajectory_size = 1;
00964     while (trajectory_size > 0)
00965     {
00966       //check for cancel
00967       if (eStopEnabled)
00968       {
00969         wpi_jaco_msgs::HomeArmResult result;
00970         result.success = false;
00971         home_arm_server_->setSucceeded(result);
00972         return;
00973       }
00974 
00975       //check for preempt requests from clients
00976       if (home_arm_server_->isPreemptRequested() || !ros::ok())
00977       {
00978         //preempt action server
00979         ROS_INFO("Home arm server action server preempted by client");
00980         home_arm_server_->setPreempted();
00981 
00982         return;
00983       }
00984 
00985       TrajectoryFIFO Trajectory_Info;
00986       memset(&Trajectory_Info, 0, sizeof(Trajectory_Info));
00987       {
00988         boost::recursive_mutex::scoped_lock lock(api_mutex);
00989         GetGlobalTrajectoryInfo(Trajectory_Info);
00990       }
00991       trajectory_size = Trajectory_Info.TrajectoryCount;
00992       rate.sleep();
00993     }
00994 
00995     std_msgs::Bool msg;
00996     msg.data = true;
00997     armHomedPublisher.publish(msg);
00998   }
00999   else
01000   {
01001     boost::recursive_mutex::scoped_lock lock(api_mutex);
01002     //set control type to previous value
01003     if (controlType == ANGULAR_CONTROL)
01004       SetAngularControl();
01005     else
01006       SetCartesianControl();
01007   }
01008 
01009   wpi_jaco_msgs::HomeArmResult result;
01010   result.success = true;
01011   home_arm_server_->setSucceeded(result);
01012 }
01013 
01014 bool JacoArmTrajectoryController::loadParameters(const ros::NodeHandle n)
01015 {
01016     ROS_DEBUG("Loading parameters");
01017 
01018     n.param("wpi_jaco/arm_name",                arm_name_,              std::string("jaco"));
01019     n.param("wpi_jaco/finger_scale",            finger_scale_,          1.0);
01020     n.param("wpi_jaco/finger_error_threshold",  finger_error_threshold_,1.0);
01021     n.param("wpi_jaco/gripper_open",            gripper_open_,          0.0);
01022     n.param("wpi_jaco/gripper_closed",          gripper_closed_,        65.0);
01023     n.param("wpi_jaco/max_curvature",           max_curvature_,         20.0);
01024     n.param("wpi_jaco/max_speed_finger",        max_speed_finger_,      30.0);
01025     n.param("wpi_jaco/num_fingers",             num_fingers_,           3);
01026 
01027     ROS_INFO("arm_name: %s",                arm_name_.c_str());
01028     ROS_INFO("finger_scale: %f",            finger_scale_);
01029     ROS_INFO("finger_error_threshold_: %f", finger_error_threshold_);
01030     ROS_INFO("gripper_open_: %f",           gripper_open_);
01031     ROS_INFO("gripper_closed_: %f",         gripper_closed_);
01032     ROS_INFO("max_curvature: %f",           max_curvature_);
01033     ROS_INFO("max_speed_finger: %f",        max_speed_finger_);
01034     ROS_INFO("num_fingers: %d",             num_fingers_);
01035 
01036     // Update topic prefix
01037     if (arm_name_ == "jaco2")
01038       topic_prefix_ = "jaco";
01039     else
01040       topic_prefix_ = arm_name_;
01041 
01042     // Update total number of joints
01043     if (kinova_gripper_)
01044       num_joints_ = num_fingers_ + NUM_JACO_JOINTS;
01045     else
01046       num_joints_ = NUM_JACO_JOINTS;
01047 
01048     joint_pos_.resize(num_joints_);
01049     joint_vel_.resize(num_joints_);
01050     joint_eff_.resize(num_joints_);
01051     ROS_INFO("Parameters loaded.");
01052 
01054     return true;
01055 }
01056 
01057 /*****************************************/
01058 /**********  Basic Arm Commands **********/
01059 /*****************************************/
01060 
01061 void JacoArmTrajectoryController::angularCmdCallback(const wpi_jaco_msgs::AngularCommand& msg)
01062 {
01063   if (eStopEnabled)
01064     return;
01065 
01066   //take control of the arm
01067   {
01068     boost::recursive_mutex::scoped_lock lock(api_mutex);
01069     EraseAllTrajectories();
01070 
01071     if (controlType != ANGULAR_CONTROL)
01072     {
01073       SetAngularControl();
01074       controlType = ANGULAR_CONTROL;
01075     }
01076   }
01077 
01078   TrajectoryPoint jacoPoint;
01079   jacoPoint.InitStruct();
01080 
01081   //populate arm command
01082   if (msg.armCommand)
01083   {
01084     if (msg.position)
01085     {
01086       jacoPoint.Position.Type = ANGULAR_POSITION;
01087       AngularPosition position_data;
01088 
01089       float current_joint_pos[6];
01090       {
01091         boost::recursive_mutex::scoped_lock lock(api_mutex);
01092         GetAngularPosition(position_data);
01093       }
01094       current_joint_pos[0] = position_data.Actuators.Actuator1 * DEG_TO_RAD;
01095       current_joint_pos[1] = position_data.Actuators.Actuator2 * DEG_TO_RAD;
01096       current_joint_pos[2] = position_data.Actuators.Actuator3 * DEG_TO_RAD;
01097       current_joint_pos[3] = position_data.Actuators.Actuator4 * DEG_TO_RAD;
01098       current_joint_pos[4] = position_data.Actuators.Actuator5 * DEG_TO_RAD;
01099       current_joint_pos[5] = position_data.Actuators.Actuator6 * DEG_TO_RAD;
01100 
01101       jacoPoint.Position.Actuators.Actuator1 = nearest_equivalent(simplify_angle(msg.joints[0]),
01102                                                                   current_joint_pos[0]) * RAD_TO_DEG;
01103       jacoPoint.Position.Actuators.Actuator2 = nearest_equivalent(simplify_angle(msg.joints[1]),
01104                                                                   current_joint_pos[1]) * RAD_TO_DEG;
01105       jacoPoint.Position.Actuators.Actuator3 = nearest_equivalent(simplify_angle(msg.joints[2]),
01106                                                                   current_joint_pos[2]) * RAD_TO_DEG;
01107       jacoPoint.Position.Actuators.Actuator4 = nearest_equivalent(simplify_angle(msg.joints[3]),
01108                                                                   current_joint_pos[3]) * RAD_TO_DEG;
01109       jacoPoint.Position.Actuators.Actuator5 = nearest_equivalent(simplify_angle(msg.joints[4]),
01110                                                                   current_joint_pos[4]) * RAD_TO_DEG;
01111       jacoPoint.Position.Actuators.Actuator6 = nearest_equivalent(simplify_angle(msg.joints[5]),
01112                                                                   current_joint_pos[5]) * RAD_TO_DEG;
01113     }
01114     else
01115     {
01116       jacoPoint.Position.Type = ANGULAR_VELOCITY;
01117       jacoPoint.Position.Actuators.Actuator1 = msg.joints[0] * RAD_TO_DEG;
01118       jacoPoint.Position.Actuators.Actuator2 = msg.joints[1] * RAD_TO_DEG;
01119       jacoPoint.Position.Actuators.Actuator3 = msg.joints[2] * RAD_TO_DEG;
01120       jacoPoint.Position.Actuators.Actuator4 = msg.joints[3] * RAD_TO_DEG;
01121       jacoPoint.Position.Actuators.Actuator5 = msg.joints[4] * RAD_TO_DEG;
01122       jacoPoint.Position.Actuators.Actuator6 = msg.joints[5] * RAD_TO_DEG;
01123     }
01124 
01125   }
01126   else
01127   {
01128     if (msg.position)
01129     {
01130       fingerPositionControl(msg.fingers[0], msg.fingers[1], msg.fingers[2]);
01131       return;
01132     }
01133     else
01134     {
01135       jacoPoint.Position.Type = ANGULAR_VELOCITY;
01136       jacoPoint.Position.Actuators.Actuator1 = 0.0;
01137       jacoPoint.Position.Actuators.Actuator2 = 0.0;
01138       jacoPoint.Position.Actuators.Actuator3 = 0.0;
01139       jacoPoint.Position.Actuators.Actuator4 = 0.0;
01140       jacoPoint.Position.Actuators.Actuator5 = 0.0;
01141       jacoPoint.Position.Actuators.Actuator6 = 0.0;
01142     }
01143   }
01144 
01145   //populate finger command
01146   if (msg.fingerCommand)
01147   {
01148     if (msg.position)
01149       jacoPoint.Position.HandMode = POSITION_MODE;
01150     else
01151       jacoPoint.Position.HandMode = VELOCITY_MODE;
01152 
01153     jacoPoint.Position.Fingers.Finger1 = msg.fingers[0];
01154     jacoPoint.Position.Fingers.Finger2 = msg.fingers[1];
01155     jacoPoint.Position.Fingers.Finger3 = msg.fingers[2];
01156   }
01157   else
01158     jacoPoint.Position.HandMode = HAND_NOMOVEMENT;
01159 
01160   //send command
01161   if (msg.position)
01162   {
01163     boost::recursive_mutex::scoped_lock lock(api_mutex);
01164     SendBasicTrajectory(jacoPoint);
01165   }
01166   else
01167   {
01168     boost::recursive_mutex::scoped_lock lock(api_mutex);
01169     if (msg.repeat)
01170     {
01171       //send the command repeatedly for ~1/60th of a second
01172       //(this is sometimes necessary for velocity commands to work correctly)
01173       ros::Rate rate(600);
01174       for (int i = 0; i < 10; i++)
01175       {
01176         SendBasicTrajectory(jacoPoint);
01177         rate.sleep();
01178       }
01179     }
01180     else
01181       SendBasicTrajectory(jacoPoint);
01182   }
01183 }
01184 
01185 void JacoArmTrajectoryController::cartesianCmdCallback(const wpi_jaco_msgs::CartesianCommand& msg)
01186 {
01187   if (eStopEnabled)
01188     return;
01189 
01190   //take control of the arm
01191   {
01192     boost::recursive_mutex::scoped_lock lock(api_mutex);
01193     EraseAllTrajectories();
01194 
01195     if (controlType != CARTESIAN_CONTROL)
01196     {
01197       SetCartesianControl();
01198       controlType = CARTESIAN_CONTROL;
01199     }
01200   }
01201 
01202   TrajectoryPoint jacoPoint;
01203   jacoPoint.InitStruct();
01204 
01205   //populate arm command
01206   if (msg.armCommand)
01207   {
01208     if (msg.position)
01209       jacoPoint.Position.Type = CARTESIAN_POSITION;
01210     else
01211       jacoPoint.Position.Type = CARTESIAN_VELOCITY;
01212     jacoPoint.Position.CartesianPosition.X = msg.arm.linear.x;
01213     jacoPoint.Position.CartesianPosition.Y = msg.arm.linear.y;
01214     jacoPoint.Position.CartesianPosition.Z = msg.arm.linear.z;
01215     jacoPoint.Position.CartesianPosition.ThetaX = msg.arm.angular.x;
01216     jacoPoint.Position.CartesianPosition.ThetaY = msg.arm.angular.y;
01217     jacoPoint.Position.CartesianPosition.ThetaZ = msg.arm.angular.z;
01218   }
01219   else
01220   {
01221     if (msg.position)
01222     {
01223       fingerPositionControl(msg.fingers[0], msg.fingers[1], msg.fingers[2]);
01224       return;
01225     }
01226     else
01227     {
01228       jacoPoint.Position.Type = ANGULAR_VELOCITY;
01229       jacoPoint.Position.Actuators.Actuator1 = 0.0;
01230       jacoPoint.Position.Actuators.Actuator2 = 0.0;
01231       jacoPoint.Position.Actuators.Actuator3 = 0.0;
01232       jacoPoint.Position.Actuators.Actuator4 = 0.0;
01233       jacoPoint.Position.Actuators.Actuator5 = 0.0;
01234       jacoPoint.Position.Actuators.Actuator6 = 0.0;
01235     }
01236   }
01237 
01238   //populate finger command
01239   if (msg.fingerCommand)
01240   {
01241     if (msg.position)
01242       jacoPoint.Position.HandMode = POSITION_MODE;
01243     else
01244       jacoPoint.Position.HandMode = VELOCITY_MODE;
01245     jacoPoint.Position.Fingers.Finger1 = msg.fingers[0];
01246     jacoPoint.Position.Fingers.Finger2 = msg.fingers[1];
01247     jacoPoint.Position.Fingers.Finger3 = msg.fingers[2];
01248   }
01249   else
01250     jacoPoint.Position.HandMode = HAND_NOMOVEMENT;
01251 
01252   //send command
01253   if (msg.position)
01254   {
01255     boost::recursive_mutex::scoped_lock lock(api_mutex);
01256     SendBasicTrajectory(jacoPoint);
01257   }
01258   else
01259   {
01260     boost::recursive_mutex::scoped_lock lock(api_mutex);
01261     SendBasicTrajectory(jacoPoint);
01262     if (msg.repeat)
01263     {
01264       //send the command repeatedly for ~1/60th of a second
01265       //(this is sometimes necessary for velocity commands to work correctly)
01266       ros::Rate rate(600);
01267       for (int i = 0; i < 10; i++)
01268       {
01269         SendBasicTrajectory(jacoPoint);
01270         rate.sleep();
01271       }
01272     }
01273   }
01274 }
01275 
01276 void JacoArmTrajectoryController::fingerPositionControl(float f1, float f2, float f3)
01277 {
01278   if (eStopEnabled)
01279     return;
01280 
01281   f1 = max(f1, .02f);
01282   f2 = max(f2, .02f);
01283   f3 = max(f3, .02f);
01284 
01285   TrajectoryPoint jacoPoint;
01286   jacoPoint.InitStruct();
01287   jacoPoint.Position.Type = ANGULAR_VELOCITY;
01288   jacoPoint.Position.Actuators.Actuator1 = 0.0;
01289   jacoPoint.Position.Actuators.Actuator2 = 0.0;
01290   jacoPoint.Position.Actuators.Actuator3 = 0.0;
01291   jacoPoint.Position.Actuators.Actuator4 = 0.0;
01292   jacoPoint.Position.Actuators.Actuator5 = 0.0;
01293   jacoPoint.Position.Actuators.Actuator6 = 0.0;
01294   jacoPoint.Position.HandMode = VELOCITY_MODE;
01295 
01296   bool goalReached = false;
01297   AngularPosition position_data;
01298   float error[3];
01299   float prevTotalError;
01300   int counter = 0; //check if error is unchanging, this likely means a finger is blocked by something so the controller should terminate
01301   vector<float> errorFinger1;
01302   vector<float> errorFinger2;
01303   vector<float> errorFinger3;
01304   errorFinger1.resize(10);
01305   errorFinger2.resize(10);
01306   errorFinger3.resize(10);
01307   for (unsigned int i = 0; i < errorFinger1.size(); i++)
01308   {
01309     errorFinger1[i] = 0.0;
01310     errorFinger2[i] = 0.0;
01311     errorFinger3[i] = 0.0;
01312   }
01313   ros::Rate rate(600);
01314   while (!goalReached)
01315   {
01316     {
01317       boost::recursive_mutex::scoped_lock lock(api_mutex);
01318 
01319       //get current finger position
01320       GetAngularPosition(position_data);
01321       error[0] = f1 - position_data.Fingers.Finger1;
01322       error[1] = f2 - position_data.Fingers.Finger2;
01323       if (num_fingers_ == 3)
01324         error[2] = f3 - position_data.Fingers.Finger3;
01325       else
01326         error[2] = 0.0;
01327 
01328       float totalError = fabs(error[0]) + fabs(error[1]) + fabs(error[2]);
01329       if (totalError == prevTotalError)
01330       {
01331         counter++;
01332       }
01333       else
01334       {
01335         counter = 0;
01336         prevTotalError = totalError;
01337       }
01338 
01339       // ROS_INFO("Current error: %f, previous error: %f", totalError, prevTotalError);
01340 
01341       if (totalError < finger_error_threshold_ || counter > 40)
01342       {
01343         goalReached = true;
01344         jacoPoint.Position.Fingers.Finger1 = 0.0;
01345         jacoPoint.Position.Fingers.Finger2 = 0.0;
01346         jacoPoint.Position.Fingers.Finger3 = 0.0;
01347       }
01348       else
01349       {
01350         float errorSum[3] = {0};
01351         for (unsigned int i = 0; i < errorFinger1.size(); i ++)
01352         {
01353           errorSum[0] += errorFinger1[i];
01354           errorSum[1] += errorFinger2[i];
01355           errorSum[2] += errorFinger3[i];
01356         }
01357         jacoPoint.Position.Fingers.Finger1 = max(min(KP_F*error[0] + KV_F*(error[0] - errorFinger1.front()) + KI_F*errorSum[0], max_speed_finger_), -max_speed_finger_);
01358         jacoPoint.Position.Fingers.Finger2 = max(min(KP_F*error[1] + KV_F*(error[1] - errorFinger2.front()) + KI_F*errorSum[1], max_speed_finger_), -max_speed_finger_);
01359         jacoPoint.Position.Fingers.Finger3 = max(min(KP_F*error[2] + KV_F*(error[2] - errorFinger3.front()) + KI_F*errorSum[2], max_speed_finger_), -max_speed_finger_);
01360 
01361         errorFinger1.insert(errorFinger1.begin(), error[0]);
01362         errorFinger2.insert(errorFinger2.begin(), error[1]);
01363         errorFinger3.insert(errorFinger3.begin(), error[2]);
01364 
01365         errorFinger1.resize(10);
01366         errorFinger2.resize(10);
01367         errorFinger3.resize(10);
01368       }
01369       
01370       EraseAllTrajectories();
01371       SendBasicTrajectory(jacoPoint);
01372     }
01373 
01374     //check for cancel requests
01375     if (eStopEnabled)
01376       return;
01377 
01378     rate.sleep();
01379   }
01380 
01381   //ROS_INFO("Goal reached, counter: %d, total error: %f", counter, prevTotalError);
01382 }
01383 
01384 void JacoArmTrajectoryController::executeAngularTrajectoryPoint(TrajectoryPoint point, bool erase)
01385 {
01386   if (eStopEnabled)
01387     return;
01388 
01389   boost::recursive_mutex::scoped_lock lock(api_mutex);
01390 
01391   if (controlType != ANGULAR_CONTROL)
01392   {
01393     SetAngularControl();
01394     controlType = ANGULAR_CONTROL;
01395   }
01396 
01397   if (erase)
01398     EraseAllTrajectories();
01399 
01400   SendBasicTrajectory(point);
01401 }
01402 
01403 void JacoArmTrajectoryController::executeCartesianTrajectoryPoint(TrajectoryPoint point, bool erase)
01404 {
01405   if (eStopEnabled)
01406     return;
01407 
01408   boost::recursive_mutex::scoped_lock lock(api_mutex);
01409 
01410   if (controlType != CARTESIAN_CONTROL)
01411   {
01412     SetCartesianControl();
01413     controlType = CARTESIAN_CONTROL;
01414   }
01415 
01416   if (erase)
01417     EraseAllTrajectories();
01418 
01419   SendBasicTrajectory(point);
01420 }
01421 
01422 bool JacoArmTrajectoryController::getAngularPosition(wpi_jaco_msgs::GetAngularPosition::Request &req, wpi_jaco_msgs::GetAngularPosition::Response &res)
01423 {
01424   res.pos.resize(num_joints_);
01425   for (unsigned int i = 0; i < num_joints_; i ++)
01426   {
01427     res.pos[i] = joint_pos_[i];
01428   }
01429 
01430   return true;
01431 }
01432 
01433 bool JacoArmTrajectoryController::getCartesianPosition(wpi_jaco_msgs::GetCartesianPosition::Request &req,
01434                                                        wpi_jaco_msgs::GetCartesianPosition::Response &res)
01435 {
01436   CartesianPosition pos;
01437   {
01438     boost::recursive_mutex::scoped_lock lock(api_mutex);
01439     GetCartesianPosition(pos);
01440   }
01441   res.pos.linear.x = pos.Coordinates.X;
01442   res.pos.linear.y = pos.Coordinates.Y;
01443   res.pos.linear.z = pos.Coordinates.Z;
01444   res.pos.angular.x = pos.Coordinates.ThetaX;
01445   res.pos.angular.y = pos.Coordinates.ThetaY;
01446   res.pos.angular.z = pos.Coordinates.ThetaZ;
01447 
01448   return true;
01449 }
01450 
01451 bool JacoArmTrajectoryController::eStopCallback(wpi_jaco_msgs::EStop::Request &req, wpi_jaco_msgs::EStop::Response &res)
01452 {
01453   res.success = true;
01454   if (req.enableEStop)
01455   {
01456     boost::recursive_mutex::scoped_lock lock(api_mutex);
01457     ROS_INFO("Software emergency stop request received.");
01458     if (!eStopEnabled)
01459     {
01460       int stopResult = StopControlAPI();
01461       if (stopResult != NO_ERROR)
01462       {
01463         ROS_INFO("Error stopping arm control.");
01464         res.success = false;
01465       }
01466       stopResult = EraseAllTrajectories();
01467       if (stopResult != NO_ERROR)
01468       {
01469         ROS_INFO("Error stopping arm trajectories.");
01470         res.success = false;
01471       }
01472       eStopEnabled = true;
01473     }
01474   }
01475   else
01476   {
01477     boost::recursive_mutex::scoped_lock lock(api_mutex);
01478     ROS_INFO("Turning off software emergency stop.");
01479     if (eStopEnabled)
01480     {
01481       StopControlAPI();
01482       ros::Duration(0.05).sleep();
01483       StartControlAPI();
01484       if (controlType == ANGULAR_CONTROL)
01485         SetAngularControl();
01486       else
01487         SetCartesianControl();
01488       eStopEnabled = false;
01489     }
01490   }
01491 
01492   return true;
01493 }
01494 
01495 bool JacoArmTrajectoryController::eraseTrajectoriesCallback(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res)
01496 {
01497   if (EraseAllTrajectories() != NO_ERROR)
01498   {
01499     ROS_INFO("Error stopping arm trajectories.");
01500     return false;
01501   }
01502   return true;
01503 }
01504 }
01505 
01506 int main(int argc, char** argv)
01507 {
01508   ros::init(argc, argv, "jaco_arm_trajectory_node");
01509   ros::NodeHandle nh;
01510   ros::NodeHandle pnh("~");
01511 
01512   jaco::JacoArmTrajectoryController robot(nh, pnh);
01513   ros::spin();
01514 }


wpi_jaco_wrapper
Author(s): David Kent
autogenerated on Thu Jun 6 2019 19:43:31