Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00030
00031 #include <jog_arm_server.h>
00032
00033 namespace jog_arm {
00034
00035 JogArmServer::JogArmServer(std::string move_group_name, std::string cmd_topic_name) :
00036 nh_("~"),
00037 arm_(move_group_name),
00038 spinner_(1)
00039 {
00041 joint_sub_ = nh_.subscribe("/joint_states", 1, &JogArmServer::jointStateCB, this);
00042
00043 cmd_sub_ = nh_.subscribe(cmd_topic_name, 1, &JogArmServer::commandCB, this);
00044
00046 robot_model_loader::RobotModelLoader model_loader("robot_description");
00047 robot_model::RobotModelPtr kinematic_model = model_loader.getModel();
00048
00049 kinematic_state_ = boost::shared_ptr<robot_state::RobotState>(new robot_state::RobotState(kinematic_model));
00050 kinematic_state_->setToDefaultValues();
00051
00052 joint_model_group_ = kinematic_model->getJointModelGroup(move_group_name);
00053
00054 arm_.setPlannerId( "RRTConnectkConfigDefault" );
00055 arm_.setMaxVelocityScalingFactor( 0.1 );
00056
00057 const std::vector<std::string> &joint_names = joint_model_group_->getJointModelNames();
00058 std::vector<double> dummy_joint_values;
00059 kinematic_state_ -> copyJointGroupPositions(joint_model_group_, dummy_joint_values);
00060
00061
00062 ros::topic::waitForMessage<sensor_msgs::JointState>("/joint_states");
00063
00064 joint_names_ = arm_.getJointNames();
00065
00066 spinner_.start();
00067 }
00068
00069 void JogArmServer::commandCB(geometry_msgs::TwistStampedConstPtr msg)
00070 {
00071
00072
00073
00074 const std::string planning_frame = arm_.getPlanningFrame();
00075
00076 try {
00077 listener_.waitForTransform( msg->header.frame_id, planning_frame, ros::Time::now(), ros::Duration(0.2) );
00078 } catch (tf::TransformException ex) {
00079 ROS_ERROR("JogArmServer::commandCB - Failed to transform command to planning frame.");
00080 return;
00081 }
00082
00083
00084 geometry_msgs::Vector3Stamped lin_vector;
00085 lin_vector.vector = msg->twist.linear;
00086 lin_vector.header.frame_id = msg->header.frame_id;
00087 listener_.transformVector(planning_frame, lin_vector, lin_vector);
00088
00089 geometry_msgs::Vector3Stamped rot_vector;
00090 rot_vector.vector = msg->twist.angular;
00091 rot_vector.header.frame_id = msg->header.frame_id;
00092 listener_.transformVector(planning_frame, rot_vector, rot_vector);
00093
00094
00095 geometry_msgs::TwistStamped twist_cmd;
00096 twist_cmd.twist.linear = lin_vector.vector;
00097 twist_cmd.twist.angular = rot_vector.vector;
00098
00099
00100 Vector6d scaling_factor;
00101 scaling_factor << 0.1, 0.1, 0.1, 0.1, 0.1, 0.1;
00102 const Vector6d delta_x = scaleCommand(twist_cmd, scaling_factor);
00103
00104 kinematic_state_->setVariableValues(current_joints_);
00105
00106
00107 Eigen::MatrixXd jacobian = kinematic_state_->getJacobian(joint_model_group_);
00108 const Eigen::VectorXd delta_theta = pseudoInverse(jacobian)*delta_x;
00109
00110
00111 sensor_msgs::JointState new_theta = current_joints_;
00112 if (!addJointIncrements(new_theta, delta_theta)) {
00113 return;
00114 }
00115
00116
00117 kinematic_state_->setVariableValues(new_theta);
00118 jacobian = kinematic_state_->getJacobian(joint_model_group_);
00119
00120
00121 kinematic_state_->setVariableValues(current_joints_);
00122
00123
00124 if (!checkConditionNumber(jacobian, 20)) {
00125 ROS_ERROR("JogArmServer::commandCB - Jacobian is ill-conditioned.");
00126 return;
00127 }
00128
00129
00130 if (!arm_.setJointValueTarget(new_theta)) {
00131 ROS_ERROR("JogArmServer::commandCB - Failed to set joint target.");
00132 return;
00133 }
00134
00135 if (!arm_.move()) {
00136 ROS_ERROR("JogArmServer::commandCB - Jogging movement failed.");
00137 return;
00138 }
00139 }
00140
00141 void JogArmServer::jointStateCB(sensor_msgs::JointStateConstPtr msg)
00142 {
00143
00144 if (msg->name.empty()) {
00145 return;
00146 }
00147
00148
00149 std::string joint = msg->name.front();
00150
00151 if (std::find(joint_names_.begin(), joint_names_.end(), joint) != joint_names_.end()) {
00152 current_joints_ = *msg;
00153 }
00154 }
00155
00156 JogArmServer::Vector6d JogArmServer::scaleCommand(const geometry_msgs::TwistStamped &command, const Vector6d& scalar) const
00157 {
00158 Vector6d result;
00159
00160 result(0) = scalar(0)*command.twist.linear.x;
00161 result(1) = scalar(1)*command.twist.linear.y;
00162 result(2) = scalar(2)*command.twist.linear.z;
00163 result(3) = scalar(3)*command.twist.angular.x;
00164 result(4) = scalar(4)*command.twist.angular.y;
00165 result(5) = scalar(5)*command.twist.angular.z;
00166
00167 return result;
00168 }
00169
00170 Eigen::MatrixXd JogArmServer::pseudoInverse(const Eigen::MatrixXd &J) const
00171 {
00172 Eigen::MatrixXd transpose = J.transpose();
00173 return transpose*(J*transpose).inverse();
00174 }
00175
00176 bool JogArmServer::addJointIncrements(sensor_msgs::JointState &output, const Eigen::VectorXd &increments) const
00177 {
00178 for (std::size_t i = 0, size = increments.size(); i < size; ++i) {
00179 try {
00180 output.position.at(i) += increments(i);
00181 } catch (std::out_of_range e) {
00182 ROS_ERROR("JogArmServer::addJointIncrements - Lengths of output and increments do not match.");
00183 return false;
00184 }
00185 }
00186
00187 return true;
00188 }
00189
00190 bool JogArmServer::checkConditionNumber(const Eigen::MatrixXd &matrix, double threshold) const
00191 {
00192
00193 Eigen::MatrixXd::EigenvaluesReturnType eigs = matrix.eigenvalues();
00194 Eigen::VectorXd eig_vector = eigs.cwiseAbs();
00195
00196
00197 double min = eig_vector.minCoeff();
00198 double max = eig_vector.maxCoeff();
00199
00200 double condition_number = max/min;
00201
00202 return (condition_number <= threshold);
00203 }
00204
00205
00206 }
00207
00208 int main(int argc, char **argv)
00209 {
00210 ros::init(argc, argv, "jog_arm_server");
00211
00212
00213 if( argc != 4 ) {
00214 ROS_FATAL("%s: Usage: rosrun jog_arm jog_arm_server [move_group_name] [cmd_topic_name] [loop_rate])",
00215 ros::this_node::getName().c_str() );
00216
00217 std::cout << "Args received:\n";
00218 for ( int i = 0; i < argc; i++ ) {
00219 std::cout << "argv[" << i << "]: " << argv[i] << std::endl;
00220 }
00221 return 1;
00222 }
00223
00224 std::string move_group_name(argv[1]);
00225 std::string cmd_topic_name(argv[2]);
00226 jog_arm::JogArmServer node(move_group_name, cmd_topic_name);
00227
00228 ros::Rate loop_rate( std::atoi( argv[3] ) );
00229 while ( ros::ok() )
00230 {
00231 ros::spinOnce();
00232 loop_rate.sleep();
00233 }
00234
00235 return 0;
00236 }