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 }
00192 
00193 
00194