JoystickControlWidget.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  *
19  * @package ArmarX::RobotAPI
20  * @author Raphael Grimm <raphael dot grimm at kit dot edu>
21  * @date 2014
22  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
23  * GNU General Public License
24  */
25 
26 #include "JoystickControlWidget.h"
27 
28 //qt
29 #include <QBrush>
30 #include <QColor>
31 #include <QPen>
32 #include <QSizePolicy>
33 #include <QVBoxLayout>
34 
35 //std
36 #include <cmath>
37 #include <iostream>
38 #include <memory>
39 
40 namespace armarx
41 {
42 
44  QWidget* parent) :
45  QGraphicsView{scene, parent}
46  {
47  }
48 
50 
51  void
53  {
54  emit positionChanged(mapToScene(event->pos()));
55  emit pressed();
56  }
57 
58  void
60  {
61  emit positionChanged(mapToScene(event->pos()));
62  }
63 
64  void
66  {
67  emit positionChanged({0, 0});
68  emit released();
69  }
70 
71  JoystickControlWidget::JoystickControlWidget(bool useQuadrant3and4, QWidget* parent) :
72  QWidget{parent}, onlyQuadrant2and1{!useQuadrant3and4}, nibble{}, steps{0}
73  {
74  //build scene + use explicit pens (on some platforms the default ones dont have the desired default values)
75  std::unique_ptr<QGraphicsScene> scene{new QGraphicsScene{}};
76  QPen pen{Qt::black, 0};
77  //bounding circle
78  scene->addEllipse(-1, -1, 2, 2, pen);
79  //inner circle
80  scene->addEllipse(-0.13, -0.13, 0.26, 0.26, pen);
81  //cross
82  scene->addLine(0, -1, 0, 1, pen);
83  scene->addLine(-1, 0, 1, 0, pen);
84  //nibble
85  QPen penRed{Qt::darkRed};
86  penRed.setCosmetic(true);
87  nibble = scene->addEllipse(-0.1, -0.1, 0.2, 0.2, penRed, QBrush{Qt::darkRed});
88 
89  //build view
90  std::unique_ptr<JoystickControlWidgetQGraphicsView> viewPtr{
91  new JoystickControlWidgetQGraphicsView{scene.release()}};
92  view = viewPtr.get();
93 
94  view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
95  view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
96  view->setSceneRect(-1, -1, 2, (onlyQuadrant2and1 ? 1 : 2));
97 
98  //connect
99  connect(viewPtr.get(), SIGNAL(positionChanged(QPointF)), this, SLOT(setNibble(QPointF)));
100  connect(viewPtr.get(), SIGNAL(released()), this, SLOT(mouseReleased()));
101  connect(viewPtr.get(), SIGNAL(pressed()), this, SIGNAL(pressed()));
102 
103  //set gui
104  std::unique_ptr<QVBoxLayout> layout{new QVBoxLayout{}};
105  layout->setSpacing(0);
106  layout->setContentsMargins(0, 0, 0, 0);
107  layout->addWidget(viewPtr.release());
108  setLayout(layout.release());
109  }
110 
111  QPointF
113  {
114  return nibble->pos();
115  }
116 
117  double
119  {
120  //if the nibble is in the middle return the angle 0.
121  //otherwise use polar coordinates (up is 0, down pi, Quadrant I & IV are positive)
122  auto pos = getPosition();
123  auto length = std::hypot(pos.x(), pos.y());
124  auto normalized = pos / length;
125 
126  if (length == 0)
127  {
128  return 0;
129  }
130  else
131  {
132  if (normalized.x() < 0)
133  {
134  return -std::acos(-normalized.y());
135  }
136  else
137  {
138  return std::acos(-normalized.y());
139  }
140  }
141  }
142 
143  void
144  JoystickControlWidget::mouseReleased()
145  {
146  setNibble({0, 0});
147  emit released();
148  }
149 
150  void
152  {
153  if (onlyQuadrant2and1 && (pos.y() > 0))
154  {
155  //project position to quadrant II & I
156  pos.setY(0);
157  }
158 
159  auto length = std::hypot(pos.x(), pos.y());
160  auto normalized = pos / length;
161 
162  if (length != 0)
163  {
164 
165  if (steps == 0)
166  {
167  //dont snap
168  pos = (length > 1) ? normalized : pos;
169  }
170  else
171  {
172  //snapp to step
173  double stepSize = 1.0 / steps;
174  //length/(1.0/steps) => length*steps
175  // +0.3*stepSize => if the border of the step is more forgiving
176  double newLength =
177  static_cast<unsigned int>(length * steps + 0.3 * stepSize) * stepSize;
178  pos = std::fmin(1, newLength) * normalized;
179  }
180  }
181 
182 
183  //set position
184  nibble->setPos(pos);
185 
186  //flip y (from downwards to upwards)
187  pos.setY(-pos.y());
188 
189  //emit signals
190  emit positionChanged(pos);
191 
193 
194  emit changed(pos, getRotation());
195  }
196 
197  void
199  {
200  int width;
201  int height;
202 
203  //calculate size
204  if (onlyQuadrant2and1)
205  {
206  height = std::min(contentsRect().width() / 2, contentsRect().height());
207  width = height * 2;
208  }
209  else
210  {
211  width = std::min(contentsRect().width(), contentsRect().height());
212  height = width;
213  }
214 
215  //if minsz=maxsz you block resizing
216  view->setMinimumSize(0.9 * width, 0.9 * height);
217  view->setMaximumSize(width, height);
218  auto viewScaleFactor = 0.49 * width;
219  view->setTransform(QTransform::fromScale(viewScaleFactor, viewScaleFactor));
220  }
221 
222  void
224  {
225  steps = (stepCount < 0) ? 0 : stepCount;
226  }
227 
228  int
230  {
231  return steps;
232  }
233 } // namespace armarx
armarx::JoystickControlWidgetQGraphicsView::~JoystickControlWidgetQGraphicsView
~JoystickControlWidgetQGraphicsView() override
armarx::JoystickControlWidget::getRotation
double getRotation() const
f the control in polar coordinates (-pi,pi].
Definition: JoystickControlWidget.cpp:118
armarx::JoystickControlWidgetQGraphicsView::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *event) override
Passes the mapped mouse coordinates of the event through the signal positionChanged.
Definition: JoystickControlWidget.cpp:59
armarx::JoystickControlWidget::getSteps
int getSteps()
Returns the steps of the control.
Definition: JoystickControlWidget.cpp:229
armarx::JoystickControlWidgetQGraphicsView::released
void released()
Emitted when the mouse was released.
armarx::JoystickControlWidgetQGraphicsView::JoystickControlWidgetQGraphicsView
JoystickControlWidgetQGraphicsView(QGraphicsScene *scene, QWidget *parent=nullptr)
Definition: JoystickControlWidget.cpp:43
armarx::JoystickControlWidgetQGraphicsView::pressed
void pressed()
Emitted when the mouse was pressed.
armarx::JoystickControlWidget::released
void released()
Emitted when the nibble was released.
armarx::JoystickControlWidget::setNibble
void setNibble(QPointF pos)
Sets the nibble to pos.
Definition: JoystickControlWidget.cpp:151
armarx::JoystickControlWidget::changed
void changed(QPointF, double)
Passes the position and angle of the control in polar coordinates (-pi,pi].
armarx::JoystickControlWidget::JoystickControlWidget
JoystickControlWidget(bool useQuadrant3and4=true, QWidget *parent=0)
Definition: JoystickControlWidget.cpp:71
armarx::JoystickControlWidget::getPosition
QPointF getPosition() const
Returns the position of the nibble.
Definition: JoystickControlWidget.cpp:112
armarx::JoystickControlWidget::rotationChanged
void rotationChanged(double)
Passes the angle of the control in polar coordinates (-pi,pi].
armarx::JoystickControlWidget::setSteps
void setSteps(int stepCount)
Sets the steps of the control.
Definition: JoystickControlWidget.cpp:223
JoystickControlWidget.h
armarx::JoystickControlWidget::resizeEvent
void resizeEvent(QResizeEvent *event) override
Definition: JoystickControlWidget.cpp:198
armarx::JoystickControlWidgetQGraphicsView::mouseReleaseEvent
void mouseReleaseEvent(QMouseEvent *) override
Passes (0;0) through the signal positionChanged.
Definition: JoystickControlWidget.cpp:65
armarx::JoystickControlWidget::positionChanged
void positionChanged(QPointF)
Passes the position of the control.
min
T min(T t1, T t2)
Definition: gdiam.h:44
armarx::JoystickControlWidgetQGraphicsView::mousePressEvent
void mousePressEvent(QMouseEvent *event) override
Passes the mapped mouse coordinates of the event through the signal positionChanged.
Definition: JoystickControlWidget.cpp:52
armarx::JoystickControlWidgetQGraphicsView::positionChanged
void positionChanged(QPointF)
Sends the mouse position on press or move in the scene coordinates.
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27