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 <RobotAPI/gui-plugins/LaserScannerPlugin/ui_LaserScannerPluginWidget.h>
26
27#include <string>
28
29#include <QGraphicsLineItem>
30#include <QGraphicsView>
31
32using namespace armarx;
33
35{
36 widget = std::make_unique<Ui::LaserScannerPluginWidget>();
37 widget->setupUi(getWidget());
38}
39
43
44void
48
49void
53
54void
56{
57 usingProxy(laserScannerUnitName);
58
59 connect(this,
61 this,
63 Qt::QueuedConnection);
64 connect(
65 widget->deviceComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onDeviceSelected(int)));
66}
67
68void
70{
71 laserScannerUnit = getProxy<LaserScannerUnitInterfacePrx>(laserScannerUnitName);
72 std::string topicName = laserScannerUnit->getReportTopicName();
73 usingTopic(topicName);
74
75 laserScanners = laserScannerUnit->getConnectedDevices();
76}
77
78QPointer<QDialog>
80{
81 if (!dialog)
82 {
83 dialog = new SimpleConfigDialog(parent);
84 dialog->addProxyFinder<LaserScannerUnitInterfacePrx>({"LaserScannerUnit", "", "*"});
85 }
86 return qobject_cast<SimpleConfigDialog*>(dialog);
87}
88
89void
91{
92 if (dialog)
93 {
94 laserScannerUnitName = dialog->getProxyName("LaserScannerUnit");
95 }
96}
97
98void
100 const std::string& name,
101 const LaserScan& newScan,
102 const TimestampBasePtr& timestamp,
103 const Ice::Current& c)
104{
105 {
106 std::unique_lock lock(scanMutex);
107
108 LaserScan& scan = scans[device];
109 // TODO: Do some filtering? aggregation?
110 scan = newScan;
111 }
112
114}
115
116void
118{
119 QComboBox* deviceBox = widget->deviceComboBox;
120
121 std::unique_lock lock(scanMutex);
122 for (auto& pair : scans)
123 {
124 QString deviceName(QString::fromStdString(pair.first.c_str()));
125 if (deviceBox->findText(deviceName) < 0)
126 {
127 deviceBox->addItem(deviceName);
128 }
129 }
130
131 std::string deviceName(deviceBox->currentText().toUtf8().data());
132 float stepSize = 0.25f;
133 for (LaserScannerInfo const& scanner : laserScanners)
134 {
135 if (scanner.device == deviceName)
136 {
137 stepSize = scanner.stepSize;
138 }
139 }
140
141 QGraphicsView* view = widget->graphicsView;
142
143 scene.reset(new QGraphicsScene());
144 widget->graphicsView->setScene(scene.get());
145 int outerR = std::min(view->width() / 2, view->height() / 2);
146 scene->addEllipse(-outerR, -outerR, 2 * outerR, 2 * outerR, QPen(QColor(255, 255, 255)));
147 int r = outerR - 10;
148 //scene.addEllipse(-r, -r, 2 * r, 2 * r, QPen(QColor(200, 200, 200)));
149 QColor stepColor(QColor::fromRgb(100, 100, 255));
150 QPen stepPen(stepColor);
151 QBrush stepBrush(stepColor);
152 auto line = [&](float angle, float d)
153 {
154 float di = d * r;
155 QGraphicsEllipseItem* item =
156 scene->addEllipse(-di, -di, 2 * di, 2 * di, stepPen, stepBrush);
157 // Angles for Qt ellipse are in 16th of degree (who thought that would be a great idea?)
158 item->setStartAngle(std::round(16.0f * angle * 180.0 / M_PI) + 90 * 16);
159 item->setSpanAngle(std::round(stepSize * 16.0f * 180.0 / M_PI));
160 };
161
162 LaserScan& scan = scans[deviceName];
163 float maxDistance = 1000.0f;
164 for (LaserScanStep& step : scan)
165 {
166 if (step.distance > maxDistance)
167 {
168 maxDistance = step.distance;
169 }
170 }
171 float ringDistance = 1000.0f;
172 int numberOfRings = (std::size_t)std::ceil(maxDistance / ringDistance);
173 std::deque<int>& history = numberOfRingsHistory[deviceName];
174 history.push_back(numberOfRings);
175 if (history.size() > 256)
176 {
177 history.pop_front();
178 }
179 int maxNumberOfRings = *std::max_element(history.begin(), history.end());
180 float outerRadius = maxNumberOfRings * ringDistance;
181
182 for (LaserScanStep& step : scan)
183 {
184 line(step.angle, step.distance / outerRadius);
185 }
186
187 for (int ringIndex = 1; ringIndex <= maxNumberOfRings; ++ringIndex)
188 {
189 float ri = 1.0f * ringIndex / maxNumberOfRings * r;
190 scene->addEllipse(-ri, -ri, 2 * ri, 2 * ri, QPen(QColor(200, 200, 200)));
191 }
192
193 view->fitInView(scene->itemsBoundingRect(), Qt::KeepAspectRatio);
194}
195
196void
198{
199 if (index < 0 && index >= widget->deviceComboBox->count())
200 {
201 return;
202 }
203 std::string deviceName = widget->deviceComboBox->itemText(index).toStdString();
204 for (LaserScannerInfo const& scanner : laserScanners)
205 {
206 if (scanner.device == deviceName)
207 {
208 widget->frameLabel->setText(QString::fromStdString(scanner.frame));
209 widget->minAngleLabel->setText(QString::number(scanner.minAngle));
210 widget->maxAngleLabel->setText(QString::number(scanner.minAngle));
211 widget->stepSizeLabel->setText(QString::number(scanner.stepSize));
212 }
213 }
214}
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