katana_teleop_key.cpp
Go to the documentation of this file.
00001 /*
00002  * UOS-ROS packages - Robot Operating System code by the University of Osnabrück
00003  * Copyright (C) 2011  University of Osnabrück
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018  *
00019  * katana_teleop_key.cpp
00020  *
00021  *  Created on: 21.04.2011
00022  *  Author: Henning Deeken <hdeeken@uos.de>
00023  *
00024  * based on a pr2 teleop by Kevin Watts
00025  */
00026 
00027 #include <katana_teleop/katana_teleop_key.h>
00028 
00029 namespace katana
00030 {
00031 
00032 KatanaTeleopKey::KatanaTeleopKey() :
00033   action_client("katana_arm_controller/joint_movement_action", true), gripper_("gripper_grasp_posture_controller", true)
00034 {
00035   ROS_INFO("KatanaTeleopKey starting...");
00036   ros::NodeHandle n_;
00037   ros::NodeHandle n_private("~");
00038 
00039   n_.param("increment", increment, 0.017453293); // default increment = 1°
00040   n_.param("increment_step", increment_step, 0.017453293); // default step_increment = 1°
00041   n_.param("increment_step_scaling", increment_step_scaling, 1.0); // default scaling = 1
00042 
00043   js_sub_ = n_.subscribe("joint_states", 1000, &KatanaTeleopKey::jointStateCallback, this);
00044 
00045   got_joint_states_ = false;
00046 
00047   jointIndex = 0;
00048 
00049   action_client.waitForServer();
00050   gripper_.waitForServer();
00051 
00052   // Gets all of the joints
00053   XmlRpc::XmlRpcValue joint_names;
00054 
00055   // Gets all of the joints
00056   if (!n_.getParam("katana_joints", joint_names))
00057   {
00058     ROS_ERROR("No joints given. (namespace: %s)", n_.getNamespace().c_str());
00059   }
00060   joint_names_.resize(joint_names.size());
00061 
00062   if (joint_names.getType() != XmlRpc::XmlRpcValue::TypeArray)
00063   {
00064     ROS_ERROR("Malformed joint specification.  (namespace: %s)", n_.getNamespace().c_str());
00065   }
00066 
00067   for (size_t i = 0; (int)i < joint_names.size(); ++i)
00068   {
00069     XmlRpc::XmlRpcValue &name_value = joint_names[i];
00070 
00071     if (name_value.getType() != XmlRpc::XmlRpcValue::TypeString)
00072     {
00073       ROS_ERROR("Array of joint names should contain all strings.  (namespace: %s)",
00074           n_.getNamespace().c_str());
00075     }
00076 
00077     joint_names_[i] = (std::string)name_value;
00078   }
00079 
00080   // Gets all of the gripper joints
00081   XmlRpc::XmlRpcValue gripper_joint_names;
00082 
00083   // Gets all of the joints
00084   if (!n_.getParam("katana_gripper_joints", gripper_joint_names))
00085   {
00086     ROS_ERROR("No gripper joints given. (namespace: %s)", n_.getNamespace().c_str());
00087   }
00088 
00089   gripper_joint_names_.resize(gripper_joint_names.size());
00090 
00091   if (gripper_joint_names.getType() != XmlRpc::XmlRpcValue::TypeArray)
00092   {
00093     ROS_ERROR("Malformed gripper joint specification.  (namespace: %s)", n_.getNamespace().c_str());
00094   }
00095   for (size_t i = 0; (int)i < gripper_joint_names.size(); ++i)
00096   {
00097     XmlRpc::XmlRpcValue &name_value = gripper_joint_names[i];
00098     if (name_value.getType() != XmlRpc::XmlRpcValue::TypeString)
00099     {
00100       ROS_ERROR("Array of gripper joint names should contain all strings.  (namespace: %s)",
00101           n_.getNamespace().c_str());
00102     }
00103 
00104     gripper_joint_names_[i] = (std::string)name_value;
00105   }
00106 
00107   combined_joints_.resize(joint_names_.size() + gripper_joint_names_.size());
00108 
00109   for (unsigned int i = 0; i < joint_names_.size(); i++)
00110   {
00111     combined_joints_[i] = joint_names_[i];
00112   }
00113 
00114   for (unsigned int i = 0; i < gripper_joint_names_.size(); i++)
00115   {
00116     combined_joints_[joint_names_.size() + i] = gripper_joint_names_[i];
00117   }
00118 
00119   giveInfo();
00120 
00121 }
00122 
00123 void KatanaTeleopKey::giveInfo()
00124 {
00125   ROS_INFO("---------------------------");
00126   ROS_INFO("Use 'WS' to increase/decrease the joint position about one increment");
00127   ROS_INFO("Current increment is set to: %f", increment);
00128   ROS_INFO("Use '+#' to alter the increment by a increment/decrement of: %f", increment_step);
00129   ROS_INFO("Use ',.' to alter the increment_step_size altering the scaling factor by -/+ 1.0");
00130   ROS_INFO("Current scaling is set to: %f" , increment_step_scaling);
00131   ROS_INFO("---------------------------");
00132   ROS_INFO("Use 'R' to return to the arm's initial pose");
00133   ROS_INFO("Use 'I' to display this manual and the current joint state");
00134   ROS_INFO("---------------------------");
00135   ROS_INFO("Use 'AD' to switch to the next/previous joint");
00136   ROS_INFO("Use '0-9' to select a joint by number");
00137   ROS_INFO("---------------------------");
00138   ROS_INFO("Use 'OC' to open/close gripper");
00139 
00140   for (unsigned int i = 0; i < joint_names_.size(); i++)
00141   {
00142     ROS_INFO("Use '%d' to switch to Joint: '%s'",i, joint_names_[i].c_str());
00143   }
00144 
00145   for (unsigned int i = 0; i < gripper_joint_names_.size(); i++)
00146   {
00147     ROS_INFO("Use '%zu' to switch to Gripper Joint: '%s'",i + joint_names_.size(), gripper_joint_names_[i].c_str());
00148   }
00149 
00150   if (!current_pose_.name.empty())
00151   {
00152     ROS_INFO("---------------------------");
00153     ROS_INFO("Current Joint Positions:");
00154 
00155     for (unsigned int i = 0; i < current_pose_.position.size(); i++)
00156     {
00157       ROS_INFO("Joint %d - %s: %f", i, current_pose_.name[i].c_str(), current_pose_.position[i]);
00158     }
00159   }
00160 }
00161 
00162 void KatanaTeleopKey::jointStateCallback(const sensor_msgs::JointState::ConstPtr& js)
00163 {
00164   // ROS_INFO("KatanaTeleopKeyboard received a new JointState");
00165 
00166   current_pose_.name = js->name;
00167   current_pose_.position = js->position;
00168 
00169   if (!got_joint_states_)
00170   {
00171     // ROS_INFO("KatanaTeleopKeyboard received initial JointState");
00172     initial_pose_.name = js->name;
00173     initial_pose_.position = js->position;
00174     got_joint_states_ = true;
00175   }
00176 }
00177 
00178 bool KatanaTeleopKey::matchJointGoalRequest(double increment)
00179 {
00180   bool found_match = false;
00181 
00182   for (unsigned int i = 0; i < current_pose_.name.size(); i++)
00183   {
00184     if (current_pose_.name[i] == combined_joints_[jointIndex])
00185     {
00186       //ROS_DEBUG("incoming inc: %f - curren_pose: %f - resulting pose: %f ",increment, current_pose_.position[i], current_pose_.position[i] + increment);
00187       movement_goal_.position.push_back(current_pose_.position[i] + increment);
00188       found_match = true;
00189       break;
00190 
00191     }
00192   }
00193 
00194   return found_match;
00195 }
00196 
00197 void KatanaTeleopKey::keyboardLoop()
00198 {
00199 
00200   char c;
00201   bool dirty = true;
00202   bool shutdown = false;
00203 
00204   // get the console in raw mode
00205   tcgetattr(kfd, &cooked);
00206   memcpy(&raw, &cooked, sizeof(struct termios));
00207   raw.c_lflag &= ~(ICANON | ECHO);
00208   // Setting a new line, then end of file
00209   raw.c_cc[VEOL] = 1;
00210   raw.c_cc[VEOF] = 2;
00211   tcsetattr(kfd, TCSANOW, &raw);
00212 
00213   ros::Rate r(50.0); // 50 Hz
00214 
00215   while (ros::ok() && !shutdown)
00216   {
00217     r.sleep();
00218     ros::spinOnce();
00219 
00220     if (!got_joint_states_)
00221       continue;
00222 
00223     dirty = false;
00224 
00225     // get the next event from the keyboard
00226     if (read(kfd, &c, 1) < 0)
00227     {
00228       perror("read():");
00229       exit(-1);
00230     }
00231 
00232     size_t selected_joint_index;
00233     switch (c)
00234     {
00235       // Increasing/Decreasing JointPosition
00236       case KEYCODE_W:
00237         if (matchJointGoalRequest(increment))
00238         {
00239           movement_goal_.name.push_back(combined_joints_[jointIndex]);
00240           dirty = true;
00241         }
00242         else
00243         {
00244           ROS_WARN("movement with the desired joint: %s failed due to a mismatch with the current joint state", combined_joints_[jointIndex].c_str());
00245         }
00246 
00247         break;
00248 
00249       case KEYCODE_S:
00250         if (matchJointGoalRequest(-increment))
00251         {
00252           movement_goal_.name.push_back(combined_joints_[jointIndex]);
00253           dirty = true;
00254         }
00255         else
00256         {
00257           ROS_WARN("movement with the desired joint: %s failed due to a mismatch with the current joint state", combined_joints_[jointIndex].c_str());
00258         }
00259 
00260         break;
00261 
00262         // Switching active Joint
00263       case KEYCODE_D:
00264         // use this line if you want to use "the gripper" instead of the single gripper joints
00265         jointIndex = (jointIndex + 1) % (joint_names_.size() + 1);
00266 
00267         // use this line if you want to select specific gripper joints
00268         //jointIndex = (jointIndex + 1) % combined_joints_.size();
00269         break;
00270 
00271       case KEYCODE_A:
00272         // use this line if you want to use "the gripper" instead of the single gripper joints
00273         jointIndex = (jointIndex - 1) % (joint_names_.size() + 1);
00274 
00275         // use this line if you want to select specific gripper joints
00276         //jointIndex = (jointIndex - 1) % combined_joints_.size();
00277 
00278         break;
00279 
00280       case KEYCODE_R:
00281         ROS_INFO("Resetting arm to its initial pose..");
00282 
00283         movement_goal_.name = initial_pose_.name;
00284         movement_goal_.position = initial_pose_.position;
00285         dirty = true;
00286         break;
00287 
00288       case KEYCODE_Q:
00289         // in case of shutting down the teleop node the arm is moved back into it's initial pose
00290         // assuming that this is a proper resting pose for the arm
00291 
00292         ROS_INFO("Shutting down the Katana Teleoperation node...");
00293         shutdown = true;
00294         break;
00295 
00296       case KEYCODE_I:
00297         giveInfo();
00298         break;
00299 
00300       case KEYCODE_0:
00301       case KEYCODE_1:
00302       case KEYCODE_2:
00303       case KEYCODE_3:
00304       case KEYCODE_4:
00305       case KEYCODE_5:
00306       case KEYCODE_6:
00307       case KEYCODE_7:
00308       case KEYCODE_8:
00309       case KEYCODE_9:
00310         selected_joint_index = c - KEYCODE_0;
00311 
00312         if (combined_joints_.size() > jointIndex)
00313         {
00314           ROS_DEBUG("You choose to adress joint no. %zu: %s", selected_joint_index, combined_joints_[9].c_str());
00315           jointIndex = selected_joint_index;
00316         }
00317         else
00318         {
00319           ROS_WARN("Joint Index No. %zu can not be adressed!", jointIndex);
00320         }
00321         break;
00322 
00323       case KEYCODE_PLUS:
00324         increment += (increment_step * increment_step_scaling);
00325         ROS_DEBUG("Increment increased to: %f",increment);
00326         break;
00327 
00328       case KEYCODE_NUMBER:
00329         increment -= (increment_step * increment_step_scaling);
00330         if (increment < 0)
00331         {
00332           increment = 0.0;
00333         }
00334         ROS_DEBUG("Increment decreased to: %f",increment);
00335         break;
00336 
00337       case KEYCODE_POINT:
00338         increment_step_scaling += 1.0;
00339         ROS_DEBUG("Increment_Scaling increased to: %f",increment_step_scaling);
00340         break;
00341 
00342       case KEYCODE_COMMA:
00343         increment_step_scaling -= 1.0;
00344         ROS_DEBUG("Increment_Scaling decreased to: %f",increment_step_scaling);
00345         break;
00346 
00347       case KEYCODE_C:
00348         send_gripper_action(GHPEG::GRASP);
00349         break;
00350 
00351       case KEYCODE_O:
00352         send_gripper_action(GHPEG::RELEASE);
00353         break;
00354     } // end switch case
00355 
00356     if (dirty)
00357     {
00358       ROS_INFO("Sending new JointMovementActionGoal..");
00359 
00360       katana_msgs::JointMovementGoal goal;
00361       goal.jointGoal = movement_goal_;
00362 
00363       for (size_t i = 0; i < goal.jointGoal.name.size(); i++)
00364       {
00365         ROS_DEBUG("Joint: %s to %f rad", goal.jointGoal.name[i].c_str(), goal.jointGoal.position[i]);
00366       }
00367 
00368       action_client.sendGoal(goal);
00369       bool finished_within_time = action_client.waitForResult(ros::Duration(10.0));
00370       if (!finished_within_time)
00371       {
00372         action_client.cancelGoal();
00373         ROS_INFO("Timed out achieving goal!");
00374       }
00375       else
00376       {
00377         actionlib::SimpleClientGoalState state = action_client.getState();
00378         if (state == actionlib::SimpleClientGoalState::SUCCEEDED)
00379           ROS_INFO("Action finished: %s",state.toString().c_str());
00380         else
00381           ROS_INFO("Action failed: %s", state.toString().c_str());
00382 
00383       }
00384 
00385       movement_goal_.name.clear();
00386       movement_goal_.position.clear();
00387 
00388     } // end if dirty
00389   }
00390 }
00391 
00392 bool KatanaTeleopKey::send_gripper_action(int32_t goal_type)
00393 {
00394   GHPEG goal;
00395 
00396   switch (goal_type)
00397   {
00398     case GHPEG::GRASP:
00399       goal.grasp.grasp_posture.name.push_back("dummy_name");
00400       goal.grasp.grasp_posture.position.push_back(0.0); // angle is ignored
00401       // leave velocity and effort empty
00402       break;
00403 
00404     case GHPEG::PRE_GRASP:
00405       goal.grasp.pre_grasp_posture.name.push_back("dummy_name");
00406       goal.grasp.pre_grasp_posture.position.push_back(0.0);
00407       // leave velocity and effort empty
00408       break;
00409 
00410     case GHPEG::RELEASE:
00411       break;
00412 
00413     default:
00414       ROS_ERROR("unknown goal code (%d)", goal_type);
00415       return false;
00416   }
00417 
00418   goal.goal = goal_type;
00419 
00420   bool finished_within_time = false;
00421   gripper_.sendGoal(goal);
00422   finished_within_time = gripper_.waitForResult(ros::Duration(10.0));
00423   if (!finished_within_time)
00424   {
00425     gripper_.cancelGoal();
00426     ROS_WARN("Timed out achieving goal!");
00427     return false;
00428   }
00429   else
00430   {
00431     actionlib::SimpleClientGoalState state = gripper_.getState();
00432     bool success = (state == actionlib::SimpleClientGoalState::SUCCEEDED);
00433     if (success)
00434       ROS_INFO("Action finished: %s",state.toString().c_str());
00435     else
00436       ROS_WARN("Action failed: %s",state.toString().c_str());
00437 
00438     return success;
00439   }
00440 
00441 }
00442 }// end namespace "katana"
00443 
00444 void quit(int sig)
00445 {
00446   tcsetattr(kfd, TCSANOW, &cooked);
00447   exit(0);
00448 }
00449 
00450 int main(int argc, char** argv)
00451 {
00452   ros::init(argc, argv, "katana_teleop_key");
00453 
00454   katana::KatanaTeleopKey ktk;
00455 
00456   signal(SIGINT, quit);
00457 
00458   ktk.keyboardLoop();
00459 
00460   return 0;
00461 }
00462 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends Defines


katana_teleop
Author(s): Henning Deeken
autogenerated on Tue May 28 2013 14:50:45