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 #include <ros/ros.h>
00031 #include <geometry_msgs/Twist.h>
00032 #include <signal.h>
00033 #include <termios.h>
00034 #include <stdio.h>
00035 #include "boost/thread/mutex.hpp"
00036 #include "boost/thread/thread.hpp"
00037
00038 #define KEYCODE_R 0x43
00039 #define KEYCODE_L 0x44
00040 #define KEYCODE_U 0x41
00041 #define KEYCODE_D 0x42
00042 #define KEYCODE_Q 0x71
00043
00044 class TurtlebotTeleop
00045 {
00046 public:
00047 TurtlebotTeleop();
00048 void keyLoop();
00049 void watchdog();
00050
00051 private:
00052
00053
00054 ros::NodeHandle nh_,ph_;
00055 double linear_, angular_;
00056 ros::Time first_publish_;
00057 ros::Time last_publish_;
00058 double l_scale_, a_scale_;
00059 ros::Publisher vel_pub_;
00060 void publish(double, double);
00061 boost::mutex publish_mutex_;
00062
00063 };
00064
00065 TurtlebotTeleop::TurtlebotTeleop():
00066 ph_("~"),
00067 linear_(0),
00068 angular_(0),
00069 l_scale_(1.0),
00070 a_scale_(1.0)
00071 {
00072 ph_.param("scale_angular", a_scale_, a_scale_);
00073 ph_.param("scale_linear", l_scale_, l_scale_);
00074
00075 vel_pub_ = nh_.advertise<geometry_msgs::Twist>("cmd_vel", 1);
00076 }
00077
00078 int kfd = 0;
00079 struct termios cooked, raw;
00080
00081 void quit(int sig)
00082 {
00083 tcsetattr(kfd, TCSANOW, &cooked);
00084 ros::shutdown();
00085 exit(0);
00086 }
00087
00088
00089 int main(int argc, char** argv)
00090 {
00091 ros::init(argc, argv, "turtlebot_teleop");
00092 TurtlebotTeleop turtlebot_teleop;
00093 ros::NodeHandle n;
00094
00095 signal(SIGINT,quit);
00096
00097 boost::thread my_thread(boost::bind(&TurtlebotTeleop::keyLoop, &turtlebot_teleop));
00098
00099
00100 ros::Timer timer = n.createTimer(ros::Duration(0.1), boost::bind(&TurtlebotTeleop::watchdog, &turtlebot_teleop));
00101
00102 ros::spin();
00103
00104 my_thread.interrupt() ;
00105 my_thread.join() ;
00106
00107 return(0);
00108 }
00109
00110
00111 void TurtlebotTeleop::watchdog()
00112 {
00113 boost::mutex::scoped_lock lock(publish_mutex_);
00114 if ((ros::Time::now() > last_publish_ + ros::Duration(0.15)) &&
00115 (ros::Time::now() > first_publish_ + ros::Duration(0.50)))
00116 publish(0, 0);
00117 }
00118
00119 void TurtlebotTeleop::keyLoop()
00120 {
00121 char c;
00122
00123
00124
00125 tcgetattr(kfd, &cooked);
00126 memcpy(&raw, &cooked, sizeof(struct termios));
00127 raw.c_lflag &=~ (ICANON | ECHO);
00128
00129 raw.c_cc[VEOL] = 1;
00130 raw.c_cc[VEOF] = 2;
00131 tcsetattr(kfd, TCSANOW, &raw);
00132
00133 puts("Reading from keyboard");
00134 puts("---------------------------");
00135 puts("Use arrow keys to move the turtlebot.");
00136
00137
00138 while (ros::ok())
00139 {
00140
00141 if(read(kfd, &c, 1) < 0)
00142 {
00143 perror("read():");
00144 exit(-1);
00145 }
00146
00147
00148 linear_=angular_=0;
00149 ROS_DEBUG("value: 0x%02X\n", c);
00150
00151 switch(c)
00152 {
00153 case KEYCODE_L:
00154 ROS_DEBUG("LEFT");
00155 angular_ = 1.0;
00156 break;
00157 case KEYCODE_R:
00158 ROS_DEBUG("RIGHT");
00159 angular_ = -1.0;
00160 break;
00161 case KEYCODE_U:
00162 ROS_DEBUG("UP");
00163 linear_ = 1.0;
00164 break;
00165 case KEYCODE_D:
00166 ROS_DEBUG("DOWN");
00167 linear_ = -1.0;
00168 break;
00169 }
00170 boost::mutex::scoped_lock lock(publish_mutex_);
00171 if (ros::Time::now() > last_publish_ + ros::Duration(1.0)) {
00172 first_publish_ = ros::Time::now();
00173 }
00174 last_publish_ = ros::Time::now();
00175 publish(angular_, linear_);
00176 }
00177
00178 return;
00179 }
00180
00181 void TurtlebotTeleop::publish(double angular, double linear)
00182 {
00183 geometry_msgs::Twist vel;
00184 vel.angular.z = a_scale_*angular;
00185 vel.linear.x = l_scale_*linear;
00186
00187 vel_pub_.publish(vel);
00188
00189
00190 return;
00191 }