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
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
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
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);
00048
00049 ROS_INFO("Arm initialized.");
00050
00051
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
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
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
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
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
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
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
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
00242
00243
00244 void JacoArmTrajectoryController::execute_trajectory(const control_msgs::FollowJointTrajectoryGoalConstPtr &goal)
00245 {
00246 if ( not arm_initialized )
00247 {
00248 return;
00249 }
00250
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
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
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
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
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
00333 if (trajectory_server_->isPreemptRequested() || !ros::ok())
00334 {
00335
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
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
00361 rate.sleep();
00362 }
00363
00364
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
00382
00383
00384 void JacoArmTrajectoryController::execute_smooth_trajectory(const control_msgs::FollowJointTrajectoryGoalConstPtr &goal)
00385 {
00386
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
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
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
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
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
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
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
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
00530 if (smooth_trajectory_server_->isPreemptRequested() || !ros::ok())
00531 {
00532
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
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
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
00580 for (unsigned int i = 0; i < numPoints; i++)
00581 {
00582
00583
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
00594
00595
00596
00597
00598
00599
00600
00601 }
00602
00603
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
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
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
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
00675 if (smooth_joint_trajectory_server_->isPreemptRequested())
00676 {
00677
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
00687 smooth_joint_trajectory_server_->setPreempted();
00688 ROS_INFO("Joint trajectory server preempted by client");
00689
00690 return;
00691 }
00692
00693
00694 t = ros::Time::now().toSec() - startTime;
00695 if (t > timePoints.at(timePoints.size() - 1))
00696 {
00697
00698
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
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
00754
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
00763
00764
00765
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
00783
00784
00785 void JacoArmTrajectoryController::execute_gripper(const control_msgs::GripperCommandGoalConstPtr &goal)
00786 {
00787
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
00807 ros::Rate startupRate(1);
00808 startupRate.sleep();
00809
00810 ros::Rate rate(10);
00811 bool gripperMoving = true;
00812 while (gripperMoving)
00813 {
00814
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
00825 if (gripper_server_->isPreemptRequested() || !ros::ok())
00826 {
00827
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
00835 ROS_INFO("Gripper action server preempted by client");
00836 gripper_server_->setPreempted();
00837
00838 return;
00839 }
00840
00841
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
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
00903 control_msgs::GripperCommandResultConstPtr res = gripper_client_->getResult();
00904
00905
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
00919
00920
00921 void JacoArmTrajectoryController::home_arm(const wpi_jaco_msgs::HomeArmGoalConstPtr &goal)
00922 {
00923
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
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
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
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
00976 if (home_arm_server_->isPreemptRequested() || !ros::ok())
00977 {
00978
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
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
01037 if (arm_name_ == "jaco2")
01038 topic_prefix_ = "jaco";
01039 else
01040 topic_prefix_ = arm_name_;
01041
01042
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
01059
01060
01061 void JacoArmTrajectoryController::angularCmdCallback(const wpi_jaco_msgs::AngularCommand& msg)
01062 {
01063 if (eStopEnabled)
01064 return;
01065
01066
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
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
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
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
01172
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
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
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
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
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
01265
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;
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
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
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
01375 if (eStopEnabled)
01376 return;
01377
01378 rate.sleep();
01379 }
01380
01381
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 }