Go to the documentation of this file.00001
00029 #ifndef KEYBOARDTELEOP_H_
00030 #define KEYBOARDTELEOP_H_
00031
00032 #include <iostream>
00033
00034 #include <boost/thread.hpp>
00035
00036 #include <ros/ros.h>
00037
00038 #include <QWidget>
00039 #include <QEvent>
00040 #include <QKeyEvent>
00041
00042 using namespace std;
00043
00044 typedef boost::function<void (double, double)> VelocityCallback;
00045
00046 namespace mr_rqt {
00047
00048 class KeyboardTeleop : public QWidget {
00049 Q_OBJECT
00050
00051 public:
00052
00053 explicit KeyboardTeleop()
00054 : _updateThread(boost::bind(&KeyboardTeleop::updateThread, this))
00055 {
00056 _linear = 0;
00057 _angular = 0;
00058 _angularDown = false;
00059 _linearDown = false;
00060 }
00061
00062 virtual ~KeyboardTeleop() { }
00063
00064 void setCallback(VelocityCallback callback) {
00065 _callback = callback;
00066 }
00067
00068 bool eventFilter(QObject* obj, QEvent *event)
00069 {
00070 if (event->type() == QEvent::KeyPress)
00071 {
00072 QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
00073
00074 switch (keyEvent->key()) {
00075 case Qt::Key_Left:
00076 _angularDown = true;
00077 _angularDirectionSign = 1;
00078 break;
00079 case Qt::Key_Right:
00080 _angularDown = true;
00081 _angularDirectionSign = -1;
00082 break;
00083 case Qt::Key_Up:
00084 _linearDown = true;
00085 _linearDirectionSign = 1;
00086 break;
00087 case Qt::Key_Down:
00088 _linearDown = true;
00089 _linearDirectionSign = -1;
00090 break;
00091 default:
00092 break;
00093 }
00094
00095
00096
00097 return true;
00098 }
00099
00100 if (event->type() == QEvent::KeyRelease)
00101 {
00102 QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
00103
00104 switch (keyEvent->key()) {
00105 case Qt::Key_Left:
00106 case Qt::Key_Right:
00107 _angularDown = false;
00108 break;
00109 case Qt::Key_Up:
00110 case Qt::Key_Down:
00111 _linearDown = false;
00112 break;
00113 }
00114
00115 return true;
00116 }
00117
00118 return false;
00119 }
00120
00121 private:
00122
00123 boost::thread _updateThread;
00124 double _linear;
00125 double _angular;
00126 volatile bool _linearDown;
00127 volatile bool _angularDown;
00128 int _linearDirectionSign;
00129 int _angularDirectionSign;
00130 VelocityCallback _callback;
00131
00132 void updateThread() {
00133 while (ros::ok()) {
00134
00135 double linearStep = 0.2;
00136 double angularStep = 0.2;
00137
00138 double decayFactor = 0.7;
00139
00140 if (_linearDown) {
00141 _linear += linearStep * _linearDirectionSign;
00142 } else {
00143 _linear *= decayFactor;
00144
00145 if (fabs(_linear) < 0.001)
00146 _linear = 0;
00147 }
00148
00149 if (_angularDown) {
00150 _angular += angularStep * _angularDirectionSign;
00151 } else {
00152 _angular *= decayFactor;
00153
00154 if (fabs(_angular) < 0.001)
00155 _angular = 0;
00156 }
00157
00158 _linear = fmax(fmin(2.0, _linear), -2.0);
00159 _angular = fmax(fmin(2.0, _angular), -2.0);
00160
00161
00162
00163 if (!_callback.empty())
00164 _callback(_linear, _angular);
00165
00166 boost::this_thread::sleep(boost::posix_time::milliseconds(50));
00167 }
00168 }
00169
00170
00171 };
00172
00173 }
00174
00175 #endif