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
00029
00030
00031 #include <termios.h>
00032 #include <signal.h>
00033 #include <math.h>
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <sys/poll.h>
00037
00038 #include <boost/thread/thread.hpp>
00039 #include <ros/ros.h>
00040 #include <geometry_msgs/Twist.h>
00041
00042
00043
00044 #define KEYCODE_W 0x77
00045 #define KEYCODE_A 0x61
00046 #define KEYCODE_S 0x73
00047 #define KEYCODE_D 0x64
00048
00049
00050
00051 #define KEYCODE_A_CAP 0x41
00052 #define KEYCODE_D_CAP 0x44
00053 #define KEYCODE_S_CAP 0x53
00054 #define KEYCODE_W_CAP 0x57
00055
00056
00057
00058 class ErraticKeyboardTeleopNode
00059 {
00060 private:
00061 double walk_vel_;
00062 double run_vel_;
00063 double yaw_rate_;
00064 double yaw_rate_run_;
00065
00066 geometry_msgs::Twist cmdvel_;
00067 ros::NodeHandle n_;
00068 ros::Publisher pub_;
00069
00070 public:
00071 ErraticKeyboardTeleopNode() {
00072 pub_ = n_.advertise<geometry_msgs::Twist> ("cmd_vel", 1);
00073
00074 ros::NodeHandle n_private ("~");
00075 n_private.param ("walk_vel", walk_vel_, 0.4);
00076 n_private.param ("run_vel", run_vel_, 0.7);
00077 n_private.param ("yaw_rate", yaw_rate_, 0.4);
00078 n_private.param ("yaw_rate_run", yaw_rate_run_, 0.8);
00079 }
00080
00081 ~ErraticKeyboardTeleopNode() { }
00082 void keyboardLoop();
00083
00084 void stopRobot() {
00085 cmdvel_.linear.x = 0.0;
00086 cmdvel_.angular.z = 0.0;
00087 pub_.publish (cmdvel_);
00088 }
00089 };
00090
00091
00092
00093 ErraticKeyboardTeleopNode* tbk;
00094 int kfd = 0;
00095 struct termios cooked, raw;
00096 bool done;
00097
00098
00099
00100 int main (int argc, char** argv)
00101 {
00102 ros::init (argc, argv, "teleop_keyboard");
00103 ErraticKeyboardTeleopNode tbk;
00104
00105 boost::thread t = boost::thread (boost::bind (&ErraticKeyboardTeleopNode::keyboardLoop, &tbk));
00106
00107 ros::spin();
00108
00109 t.interrupt();
00110 t.join();
00111 tbk.stopRobot();
00112 tcsetattr (kfd, TCSANOW, &cooked);
00113
00114 return (0);
00115 }
00116
00117
00118
00119 void ErraticKeyboardTeleopNode::keyboardLoop()
00120 {
00121 char c;
00122 double max_tv = walk_vel_;
00123 double max_rv = yaw_rate_;
00124 bool dirty = false;
00125 int speed = 0;
00126 int turn = 0;
00127
00128
00129 tcgetattr (kfd, &cooked);
00130 memcpy (&raw, &cooked, sizeof (struct termios));
00131 raw.c_lflag &= ~ (ICANON | ECHO);
00132 raw.c_cc[VEOL] = 1;
00133 raw.c_cc[VEOF] = 2;
00134 tcsetattr (kfd, TCSANOW, &raw);
00135
00136 puts ("Reading from keyboard");
00137 puts ("Use WASD keys to control the robot");
00138 puts ("Press Shift to move faster");
00139
00140 struct pollfd ufd;
00141 ufd.fd = kfd;
00142 ufd.events = POLLIN;
00143
00144 for (;;) {
00145 boost::this_thread::interruption_point();
00146
00147
00148 int num;
00149
00150 if ( (num = poll (&ufd, 1, 250)) < 0) {
00151 perror ("poll():");
00152 return;
00153 }
00154 else if (num > 0) {
00155 if (read (kfd, &c, 1) < 0) {
00156 perror ("read():");
00157 return;
00158 }
00159 }
00160 else {
00161 if (dirty == true) {
00162 stopRobot();
00163 dirty = false;
00164 }
00165
00166 continue;
00167 }
00168
00169 switch (c) {
00170 case KEYCODE_W:
00171 max_tv = walk_vel_;
00172 speed = 1;
00173 turn = 0;
00174 dirty = true;
00175 break;
00176 case KEYCODE_S:
00177 max_tv = walk_vel_;
00178 speed = -1;
00179 turn = 0;
00180 dirty = true;
00181 break;
00182 case KEYCODE_A:
00183 max_rv = yaw_rate_;
00184 speed = 0;
00185 turn = 1;
00186 dirty = true;
00187 break;
00188 case KEYCODE_D:
00189 max_rv = yaw_rate_;
00190 speed = 0;
00191 turn = -1;
00192 dirty = true;
00193 break;
00194
00195 case KEYCODE_W_CAP:
00196 max_tv = run_vel_;
00197 speed = 1;
00198 turn = 0;
00199 dirty = true;
00200 break;
00201 case KEYCODE_S_CAP:
00202 max_tv = run_vel_;
00203 speed = -1;
00204 turn = 0;
00205 dirty = true;
00206 break;
00207 case KEYCODE_A_CAP:
00208 max_rv = yaw_rate_run_;
00209 speed = 0;
00210 turn = 1;
00211 dirty = true;
00212 break;
00213 case KEYCODE_D_CAP:
00214 max_rv = yaw_rate_run_;
00215 speed = 0;
00216 turn = -1;
00217 dirty = true;
00218 break;
00219
00220 default:
00221 max_tv = walk_vel_;
00222 max_rv = yaw_rate_;
00223 speed = 0;
00224 turn = 0;
00225 dirty = false;
00226 }
00227
00228 cmdvel_.linear.x = speed * max_tv;
00229 cmdvel_.angular.z = turn * max_rv;
00230 pub_.publish (cmdvel_);
00231 }
00232 }