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 <QVBoxLayout>
30 #include <QPen>
31 #include <QBrush>
32 #include <QColor>
33 #include <QSizePolicy>
34 
35 //std
36 #include <memory>
37 #include <cmath>
38 
39 #include <iostream>
40 
41 namespace armarx
42 {
43 
45  QGraphicsView {scene, parent}
46  {
47  }
48 
50  = default;
51 
53  {
54  emit positionChanged(mapToScene(event->pos()));
55  emit pressed();
56  }
57 
59  {
60  emit positionChanged(mapToScene(event->pos()));
61  }
63  {
64  emit positionChanged({0, 0});
65  emit released();
66  }
67 
68  JoystickControlWidget::JoystickControlWidget(bool useQuadrant3and4, QWidget* parent) :
69  QWidget {parent},
70  onlyQuadrant2and1 {!useQuadrant3and4},
71  nibble {},
72  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>
91  viewPtr{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 
113  {
114  return nibble->pos();
115  }
116 
118  {
119  //if the nibble is in the middle return the angle 0.
120  //otherwise use polar coordinates (up is 0, down pi, Quadrant I & IV are positive)
121  auto pos = getPosition();
122  auto length = std::hypot(pos.x(), pos.y());
123  auto normalized = pos / length;
124 
125  if (length == 0)
126  {
127  return 0;
128  }
129  else
130  {
131  if (normalized.x() < 0)
132  {
133  return -std::acos(-normalized.y());
134  }
135  else
136  {
137  return std::acos(-normalized.y());
138  }
139  }
140  }
141 
142  void JoystickControlWidget::mouseReleased()
143  {
144  setNibble({0, 0});
145  emit released();
146  }
147 
149  {
150  if (onlyQuadrant2and1 && (pos.y() > 0))
151  {
152  //project position to quadrant II & I
153  pos.setY(0);
154  }
155 
156  auto length = std::hypot(pos.x(), pos.y());
157  auto normalized = pos / length;
158 
159  if (length != 0)
160  {
161 
162  if (steps == 0)
163  {
164  //dont snap
165  pos = (length > 1) ? normalized : pos;
166  }
167  else
168  {
169  //snapp to step
170  double stepSize = 1.0 / steps;
171  //length/(1.0/steps) => length*steps
172  // +0.3*stepSize => if the border of the step is more forgiving
173  double newLength = static_cast<unsigned int>(length * steps + 0.3 * stepSize) * stepSize;
174  pos = std::fmin(1, newLength) * normalized;
175  }
176  }
177 
178 
179 
180  //set position
181  nibble->setPos(pos);
182 
183  //flip y (from downwards to upwards)
184  pos.setY(-pos.y());
185 
186  //emit signals
187  emit positionChanged(pos);
188 
190 
191  emit changed(pos, getRotation());
192  }
193 
195  {
196  int width;
197  int height;
198 
199  //calculate size
200  if (onlyQuadrant2and1)
201  {
202  height = std::min(contentsRect().width() / 2, contentsRect().height());
203  width = height * 2;
204  }
205  else
206  {
207  width = std::min(contentsRect().width(), contentsRect().height());
208  height = width;
209  }
210 
211  //if minsz=maxsz you block resizing
212  view->setMinimumSize(0.9 * width, 0.9 * height);
213  view->setMaximumSize(width, height);
214  auto viewScaleFactor = 0.49 * width;
215  view->setTransform(QTransform::fromScale(viewScaleFactor, viewScaleFactor));
216  }
217 
218 
220  {
221  steps = (stepCount < 0) ? 0 : stepCount;
222  }
223 
225  {
226  return steps;
227  }
228 }// namespace armarx
armarx::JoystickControlWidgetQGraphicsView::~JoystickControlWidgetQGraphicsView
~JoystickControlWidgetQGraphicsView() override
armarx::JoystickControlWidget::getRotation
double getRotation() const
f the control in polar coordinates (-pi,pi].
Definition: JoystickControlWidget.cpp:117
armarx::JoystickControlWidgetQGraphicsView::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *event) override
Passes the mapped mouse coordinates of the event through the signal positionChanged.
Definition: JoystickControlWidget.cpp:58
armarx::JoystickControlWidget::getSteps
int getSteps()
Returns the steps of the control.
Definition: JoystickControlWidget.cpp:224
armarx::JoystickControlWidgetQGraphicsView::released
void released()
Emitted when the mouse was released.
armarx::JoystickControlWidgetQGraphicsView::JoystickControlWidgetQGraphicsView
JoystickControlWidgetQGraphicsView(QGraphicsScene *scene, QWidget *parent=nullptr)
Definition: JoystickControlWidget.cpp:44
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:148
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:68
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:219
JoystickControlWidget.h
armarx::JoystickControlWidget::resizeEvent
void resizeEvent(QResizeEvent *event) override
Definition: JoystickControlWidget.cpp:194
armarx::JoystickControlWidgetQGraphicsView::mouseReleaseEvent
void mouseReleaseEvent(QMouseEvent *) override
Passes (0;0) through the signal positionChanged.
Definition: JoystickControlWidget.cpp:62
armarx::JoystickControlWidget::positionChanged
void positionChanged(QPointF)
Passes the position of the control.
min
T min(T t1, T t2)
Definition: gdiam.h:42
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:28