LaserScannerPluginWidgetController.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * \package RobotAPI::gui-plugins::LaserScannerPluginWidgetController
17 * \author Fabian Paus ( fabian dot paus at kit dot edu )
18 * \date 2017
19 * \copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
24
25#include <string>
26
27#include <QGraphicsLineItem>
28#include <QGraphicsView>
29
30using namespace armarx;
31
36
40
41void
45
46void
50
51void
53{
54 usingProxy(laserScannerUnitName);
55
56 connect(this,
58 this,
60 Qt::QueuedConnection);
61 connect(
62 widget.deviceComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onDeviceSelected(int)));
63}
64
65void
67{
68 laserScannerUnit = getProxy<LaserScannerUnitInterfacePrx>(laserScannerUnitName);
69 std::string topicName = laserScannerUnit->getReportTopicName();
70 usingTopic(topicName);
71
72 laserScanners = laserScannerUnit->getConnectedDevices();
73}
74
75QPointer<QDialog>
77{
78 if (!dialog)
79 {
80 dialog = new SimpleConfigDialog(parent);
81 dialog->addProxyFinder<LaserScannerUnitInterfacePrx>({"LaserScannerUnit", "", "*"});
82 }
83 return qobject_cast<SimpleConfigDialog*>(dialog);
84}
85
86void
88{
89 if (dialog)
90 {
91 laserScannerUnitName = dialog->getProxyName("LaserScannerUnit");
92 }
93}
94
95void
97 const std::string& name,
98 const LaserScan& newScan,
99 const TimestampBasePtr& timestamp,
100 const Ice::Current& c)
101{
102 {
103 std::unique_lock lock(scanMutex);
104
105 LaserScan& scan = scans[device];
106 // TODO: Do some filtering? aggregation?
107 scan = newScan;
108 }
109
111}
112
113void
115{
116 QComboBox* deviceBox = widget.deviceComboBox;
117
118 std::unique_lock lock(scanMutex);
119 for (auto& pair : scans)
120 {
121 QString deviceName(QString::fromStdString(pair.first.c_str()));
122 if (deviceBox->findText(deviceName) < 0)
123 {
124 deviceBox->addItem(deviceName);
125 }
126 }
127
128 std::string deviceName(deviceBox->currentText().toUtf8().data());
129 float stepSize = 0.25f;
130 for (LaserScannerInfo const& scanner : laserScanners)
131 {
132 if (scanner.device == deviceName)
133 {
134 stepSize = scanner.stepSize;
135 }
136 }
137
138 QGraphicsView* view = widget.graphicsView;
139
140 scene.reset(new QGraphicsScene());
141 widget.graphicsView->setScene(scene.get());
142 int outerR = std::min(view->width() / 2, view->height() / 2);
143 scene->addEllipse(-outerR, -outerR, 2 * outerR, 2 * outerR, QPen(QColor(255, 255, 255)));
144 int r = outerR - 10;
145 //scene.addEllipse(-r, -r, 2 * r, 2 * r, QPen(QColor(200, 200, 200)));
146 QColor stepColor(QColor::fromRgb(100, 100, 255));
147 QPen stepPen(stepColor);
148 QBrush stepBrush(stepColor);
149 auto line = [&](float angle, float d)
150 {
151 float di = d * r;
152 QGraphicsEllipseItem* item =
153 scene->addEllipse(-di, -di, 2 * di, 2 * di, stepPen, stepBrush);
154 // Angles for Qt ellipse are in 16th of degree (who thought that would be a great idea?)
155 item->setStartAngle(std::round(16.0f * angle * 180.0 / M_PI) + 90 * 16);
156 item->setSpanAngle(std::round(stepSize * 16.0f * 180.0 / M_PI));
157 };
158
159 LaserScan& scan = scans[deviceName];
160 float maxDistance = 1000.0f;
161 for (LaserScanStep& step : scan)
162 {
163 if (step.distance > maxDistance)
164 {
165 maxDistance = step.distance;
166 }
167 }
168 float ringDistance = 1000.0f;
169 int numberOfRings = (std::size_t)std::ceil(maxDistance / ringDistance);
170 std::deque<int>& history = numberOfRingsHistory[deviceName];
171 history.push_back(numberOfRings);
172 if (history.size() > 256)
173 {
174 history.pop_front();
175 }
176 int maxNumberOfRings = *std::max_element(history.begin(), history.end());
177 float outerRadius = maxNumberOfRings * ringDistance;
178
179 for (LaserScanStep& step : scan)
180 {
181 line(step.angle, step.distance / outerRadius);
182 }
183
184 for (int ringIndex = 1; ringIndex <= maxNumberOfRings; ++ringIndex)
185 {
186 float ri = 1.0f * ringIndex / maxNumberOfRings * r;
187 scene->addEllipse(-ri, -ri, 2 * ri, 2 * ri, QPen(QColor(200, 200, 200)));
188 }
189
190 view->fitInView(scene->itemsBoundingRect(), Qt::KeepAspectRatio);
191}
192
193void
195{
196 if (index < 0 && index >= widget.deviceComboBox->count())
197 {
198 return;
199 }
200 std::string deviceName = widget.deviceComboBox->itemText(index).toStdString();
201 for (LaserScannerInfo const& scanner : laserScanners)
202 {
203 if (scanner.device == deviceName)
204 {
205 widget.frameLabel->setText(QString::fromStdString(scanner.frame));
206 widget.minAngleLabel->setText(QString::number(scanner.minAngle));
207 widget.maxAngleLabel->setText(QString::number(scanner.minAngle));
208 widget.stepSizeLabel->setText(QString::number(scanner.stepSize));
209 }
210 }
211}
std::string timestamp()
uint8_t index
#define M_PI
Definition MathTools.h:17
constexpr T c
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
void configured() override
This function must be implemented by the user, if he supplies a config dialog.
void reportSensorValues(const std::string &device, const std::string &name, const LaserScan &scan, const TimestampBasePtr &timestamp, const Ice::Current &c) override
QPointer< QDialog > getConfigDialog(QWidget *parent) override
getConfigDialog returns a pointer to the a configuration widget of this controller.
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
A config-dialog containing one (or multiple) proxy finders.
This file offers overloads of toIce() and fromIce() functions for STL container types.
double angle(const Point &a, const Point &b, const Point &c)
Definition point.hpp:109