VelocityWidget.h
Go to the documentation of this file.
00001 
00029 #ifndef VELOCITYWIDGET_H_
00030 #define VELOCITYWIDGET_H_
00031 
00032 #include <iostream>
00033 #include <math.h>
00034 #include <ros/ros.h>
00035 #include <boost/bind.hpp>
00036 #include <boost/thread.hpp>
00037 #include <QWidget>
00038 #include <QPainter>
00039 #include <QMouseEvent>
00040 
00041 using namespace std;
00042 
00043 typedef boost::function<void (double, double)> VelocityCallback;
00044 
00045 namespace mr_rqt {
00046 
00047 class VelocityWidget : public QWidget {
00048 
00049 Q_OBJECT
00050 
00051 public:
00052         VelocityWidget(QWidget* parent)
00053                 : QWidget(parent),
00054                   _linear(0),
00055                   _angular(0),
00056                   _maxLinear(1),
00057                   _maxAngular(1),
00058                   _linearPercent(0),
00059                   _angularPercent(0),
00060                   _minAngular(-1),
00061                   _minLinear(-1),
00062                   _visibleLinear(0),
00063                   _visibleAngular(0),
00064                   _mouseEnabled(false),
00065                   _feedbackEnabled(true),
00066                   _mouseDown(false),
00067                   _zeroVelocityCounter(0),
00068                   _inputTicks(0),
00069                   _updateThread(boost::bind(&VelocityWidget::updateThread, this))
00070         {
00071 
00072                 connect(this, SIGNAL(redrawSignal()), this, SLOT(redraw()), Qt::QueuedConnection);
00073         }
00074 
00075         ~VelocityWidget() {
00076                 _updateThread.interrupt();
00077                 _updateThread.join();
00078         }
00079 
00080         void resetLimits() {
00081                 _maxLinear = 0.1;
00082                 _maxAngular = 0.1;
00083         }
00084 
00085         void setLinear(double linear) {
00086 
00087                 if (_mouseEnabled && !_feedbackEnabled)
00088                         return;
00089 
00090                 if (linear > _maxLinear)
00091                         _maxLinear = (linear);
00092 
00093                 if (linear < _minLinear)
00094                         _minLinear = linear;
00095 
00096                 _linear = linear;
00097 
00098                 if (linear >= 0)
00099                         _linearPercent = _linear / _maxLinear * 100.0;
00100                 else
00101                         _linearPercent = -_linear / _minLinear * 100.0;
00102         }
00103 
00104         void setAngular(double angular) {
00105 
00106                 if (_mouseEnabled && !_feedbackEnabled)
00107                         return;
00108 
00109                 if (angular > _maxAngular)
00110                         _maxAngular = (angular);
00111 
00112                 if (angular < _minAngular)
00113                         _minAngular = angular;
00114 
00115                 _angular = angular;
00116 
00117                 if (angular >= 0)
00118                         _angularPercent = _angular / _maxAngular * 100.0;
00119                 else
00120                         _angularPercent = -_angular / _minAngular * 100.0;
00121         }
00122 
00123         void setVelocity(double linear, double angular) {
00124 
00125                 if (!_feedbackEnabled)
00126                         return;
00127 
00128                 setLinear(linear);
00129                 setAngular(angular);
00130 
00131 //              cout << "Setting l/a: " << _linearPercent << ", " << _angularPercent << endl;
00132         }
00133 
00134         void setCallback(VelocityCallback callback) {
00135                 _callback = callback;
00136         }
00137 
00138         void enableMouseControl() {
00139                 _mouseEnabled = true;
00140         }
00141 
00142         void disableMouseControl() {
00143                 _mouseEnabled = false;
00144         }
00145 
00146 public slots:
00147 
00148         void redraw() {
00149                 update();
00150         }
00151 
00152 signals:
00153 
00154         void redrawSignal();
00155 
00156 private:
00157 
00158         volatile double _linear;
00159         volatile double _angular;
00160 
00161         volatile double _maxLinear;
00162         volatile double _minLinear;
00163         volatile double _maxAngular;
00164         volatile double _minAngular;
00165 
00166         volatile double _linearPercent;
00167         volatile double _angularPercent;
00168 
00169         volatile double _visibleLinear;
00170         volatile double _visibleAngular;
00171 
00172         bool _mouseEnabled;
00173         bool _feedbackEnabled;
00174         bool _mouseDown;
00175         int _zeroVelocityCounter;
00176         volatile long _inputTicks;
00177 
00178         VelocityCallback _callback;
00179 
00180         boost::thread _updateThread;
00181 
00182         void updateThread() {
00183 
00184                 while(ros::ok() && !_updateThread.interruption_requested()) {
00185 
00186 //                      cout << _linearPercent << ", " << _angularPercent << endl;
00187 
00188                         _visibleLinear += (_linearPercent - _visibleLinear)/ 2.0;
00189                         _visibleAngular += (_angularPercent - _visibleAngular) / 2.0;
00190 
00191 
00192                         if (fabs(_visibleLinear) < 0.0001)
00193                                 _visibleLinear = 0;
00194 
00195                         if (fabs(_visibleAngular) < 0.0001)
00196                                 _visibleAngular = 0;
00197 
00198                         emit redrawSignal();
00199 
00200                         if (!_mouseDown &&_inputTicks++ > 60)
00201                                 _feedbackEnabled = true;
00202                         else
00203                                 _feedbackEnabled = false;
00204 
00205                         boost::this_thread::sleep(boost::posix_time::milliseconds(1000.0 / 60.0));
00206                 }
00207         }
00208 
00209         void limitVector(double& x, double& y, double maxRadius) {
00210                 if (sqrt(x * x + y * y) > maxRadius) {
00211                         double angle = atan2(y, x);
00212                         x = cos(angle) * maxRadius;
00213                         y = sin(angle) * maxRadius;
00214                 }
00215         }
00216 
00217         void drawBackground(QPainter& p, int width, int height) {
00218                 QBrush brush(QColor::fromRgb(255, 255, 255, 255));
00219                 p.setBrush(brush);
00220 
00221                 p.fillRect(0, 0, width, height, brush);
00222         }
00223 
00224         void drawBorder(QPainter& p, int width, int height) {
00225                 QPen pen(QColor::fromRgb(100, 100, 100, 0));
00226                 p.setPen(pen);
00227 
00228                 // Horizontal
00229                 p.drawLine(0, 0, width, 0);
00230                 p.drawLine(0, height - 1, width, height - 1);
00231 
00232                 // Vertical
00233                 p.drawLine(0, 0, 0, height);
00234                 p.drawLine(width - 1, 0, width - 1, height);
00235         }
00236 
00237         void drawAxis(QPainter& p, int width, int height) {
00238                 QPen pen(QColor::fromRgb(0, 0, 0, 30));
00239                 pen.setDashOffset(3);
00240 
00241                 p.setPen(pen);
00242 
00243                 // Horizontal
00244                 p.drawLine(0, height / 2, width, height / 2);
00245 
00246                 // Vertical
00247                 p.drawLine(width / 2, 0, width / 2, height);
00248         }
00249 
00250         void drawCircles(QPainter& p, int width, int height) {
00251                 QLinearGradient grad(0, 0, width, height);
00252                 grad.setColorAt(1.0, QColor::fromRgb(180, 180, 180, 255));
00253                 grad.setColorAt(0.0, QColor::fromRgb(220, 220, 220, 255));
00254 
00255                 QPen pen(QColor::fromRgb(50, 50, 50, 255));
00256                 QBrush brush(grad);
00257                 brush.setStyle(Qt::LinearGradientPattern);
00258                 p.setBrush(brush);
00259                 p.setPen(pen);
00260 
00261                 p.drawEllipse(0, 0, width - 1, height - 1);
00262 
00263 
00264                 grad.setColorAt(0.0, QColor::fromRgb(180, 180, 180, 255));
00265                 grad.setColorAt(1.0, QColor::fromRgb(220, 220, 220, 255));
00266                 brush = QBrush(grad);
00267 
00268                 p.setPen(Qt::NoPen);
00269                 p.setBrush(brush);
00270 
00271                 p.drawEllipse(20, 20, width - 1 - 20 * 2, height - 1 - 20 * 2);
00272         }
00273 
00274         void drawPointer(QPainter& p, int x, int y, int width, int height, int size) {
00275 
00276                 int circleWidth = size * width / 100;
00277                 int circleHeight = size * height / 100;
00278 
00279                 int circleX = x * width / 200 + width / 2;
00280                 int circleY = y * height / 200 + height / 2;
00281 
00282                 circleX = circleX - circleWidth / 2;
00283                 circleY = circleY - circleHeight / 2;
00284 
00285 
00286                 QLinearGradient gradLine(width / 2, height / 2, circleX + circleWidth / 2, circleY + circleHeight / 2);
00287                 gradLine.setColorAt(0.0, QColor(30, 30, 30));
00288                 gradLine.setColorAt(0.5, QColor(100, 100, 100));
00289                 gradLine.setColorAt(1.0, QColor(0, 0, 0));
00290                 p.setPen(QPen(QBrush(gradLine), size / 1.1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin));
00291                 p.drawLine(width / 2, height / 2, circleX + circleWidth / 2, circleY + circleHeight / 2);
00292 
00293 
00294                 QLinearGradient grad(circleX, circleY, circleX + circleWidth, circleY + circleHeight);
00295                 grad.setColorAt(0.0, QColor::fromRgb(220, 0, 0, 255));
00296                 grad.setColorAt(1.0, QColor::fromRgb(100, 0, 0, 255));
00297                 QBrush brush(grad);
00298 
00299                 p.setPen(Qt::NoPen);
00300                 p.setBrush(brush);
00301 
00302                 p.drawEllipse(circleX, circleY, circleWidth, circleHeight);
00303 
00304 
00305                 grad.setColorAt(1.0, QColor::fromRgb(220, 0, 0, 255));
00306                 grad.setColorAt(0.0, QColor::fromRgb(100, 0, 0, 255));
00307                 brush = QBrush(grad);
00308 
00309                 p.setPen(Qt::NoPen);
00310                 p.setBrush(brush);
00311 
00312                 p.drawEllipse(circleX + 5, circleY + 5, circleWidth - 10, circleHeight - 10);
00313         }
00314 
00315         void drawJoystick(int linearPercent, int angularPercent) {
00316                 QPainter painter(this);
00317 
00318                 double w = width();
00319                 double h = height();
00320 
00321                 double linear = -linearPercent;
00322                 double angular = -angularPercent;
00323 
00324                 limitVector(linear, angular, 70);
00325 
00326                 drawCircles(painter, w, h);
00327                 drawPointer(painter, angular, linear, w, h, 30);
00328         }
00329 
00330         void paintEvent(QPaintEvent *e)
00331         {
00332                 drawJoystick(_visibleLinear, _visibleAngular);
00333         }
00334 
00335         void mousePressEvent(QMouseEvent* e) {
00336                 _mouseDown = true;
00337                 _inputTicks = 0;
00338 
00339                 if (!_mouseEnabled)
00340                         return;
00341 
00342                 mouseMoveEvent(e);
00343         }
00344 
00345         void mouseMoveEvent(QMouseEvent* e) {
00346 
00347                 _inputTicks = 0;
00348 
00349                 if (!_mouseEnabled)
00350                         return;
00351 
00352                 _linearPercent = (-e->pos().y() + width() / 2);
00353                 _angularPercent = (-e->pos().x() + width() / 2);
00354 
00355                 if (!_callback.empty())
00356                         _callback(_linearPercent, _angularPercent);
00357         }
00358 
00359         void mouseReleaseEvent(QMouseEvent* e) {
00360 
00361                 _mouseDown = false;
00362                 _inputTicks = 0;
00363 
00364                 if (!_mouseEnabled)
00365                         return;
00366 
00367                 _linearPercent = (0);
00368                 _angularPercent = (0);
00369 
00370                 if (!_callback.empty())
00371                         _callback(_linearPercent, _angularPercent);
00372         }
00373 
00374         void keyPressEvent(QKeyEvent* e) {
00375 //              cout << "Key pressed = " << e->key() << endl;
00376         }
00377 };
00378 
00379 }
00380 
00381 #endif /* VELOCITYWIDGET_H_ */


mr_rqt
Author(s): Igor Makhtes
autogenerated on Fri Aug 28 2015 11:35:38