LookAtClickWidgetController.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 VisionX::gui-plugins::LookAtClickWidgetController
17 * \author [Author Name] ( [Author Email] )
18 * \date 2020
19 * \copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
24
25#include <algorithm>
26#include <iostream>
27#include <string>
28
29#include <QImage>
30
32
33#include <RobotAPI/interface/core/RobotState.h>
34
36
37namespace armarx
38{
40 {
41 widget.setupUi(getWidget());
42
43 _turnOnClick = new LookAtClick;
44 widget.verticalLayoutImage->addWidget(_turnOnClick);
45 // _turnOnClick->drawBackground();
46 connect(
47 _turnOnClick, SIGNAL(clickedAt(const QPoint&)), this, SLOT(clickedAt(const QPoint&)));
48 startTimer(10);
49 }
50
54
55 QPointer<QDialog>
57 {
58 if (!_dialog)
59 {
60 _dialog = new SimpleConfigDialog(parent);
61 _dialog->addProxyFinder<visionx::ImageProviderInterfacePrx>(
62 "ImageProvider", "ImageProvider", "Image*|*Provider");
63 _dialog->addProxyFinder<RobotStateComponentInterfacePrx>(
64 "rsc", "Robot State Component", "*Component");
65 _dialog->addProxyFinder<KinematicUnitInterfacePrx>(
66 "KinematicUnitInterface", "Kinematic Unit Interface", "*KinematicUnit");
67 _dialog->addLineEdit("pitch", "Pitch Joint (empty = autodetect)", "");
68 _dialog->addLineEdit("yaw", "Yaw Joint (empty = autodetect)", "");
69 }
70 return qobject_cast<SimpleConfigDialog*>(_dialog);
71 }
72
73 void
75 {
76 _imageProviderName = settings->value("_imageProviderName").toString().toStdString();
77 _robotStateUnitComponentName = settings->value("rsc").toString().toStdString();
78 _kinematicUnitInterfaceName =
79 settings->value("KinematicUnitInterface").toString().toStdString();
80 _pitchJointName = settings->value("pitch").toString().toStdString();
81 _yawJointName = settings->value("yaw").toString().toStdString();
82 _inverseYaw = settings->value("inverseYaw").toFloat();
83
84 widget.doubleSpinBoxFactorPitch->setValue(settings->value("pitchFactor").toDouble());
85 widget.doubleSpinBoxFactorYaw->setValue(settings->value("yawFactor").toDouble());
86 }
87
88 void
90 {
91 settings->setValue("_imageProviderName", QString::fromStdString(_imageProviderName));
92 settings->setValue(
93 "rsc",
94 QString::fromStdString(getRobotStateComponentPlugin().getRobotStateComponentName()));
95 settings->setValue("KinematicUnitInterface",
96 QString::fromStdString(_kinematicUnitInterfaceName));
97 settings->setValue("pitch", QString::fromStdString(_pitchJointName));
98 settings->setValue("yaw", QString::fromStdString(_yawJointName));
99 settings->setValue("inverseYaw", _inverseYaw);
100
101 settings->setValue("pitchFactor", widget.doubleSpinBoxFactorPitch->value());
102 settings->setValue("yawFactor", widget.doubleSpinBoxFactorPitch->value());
103 }
104
105 void
107 {
108 usingImageProvider(_imageProviderName);
109 usingProxy(_kinematicUnitInterfaceName);
110 }
111
112 void
113 LookAtClickWidgetController::autoDetectRobotSpecificVariables()
114 {
115 synchronizeLocalClone(_robot);
116 if (_yawJointName == "")
117 {
118 if (_robot->getName() == "Armar6")
119 {
120 _inverseYaw = -1;
121 _yawJointName = "Neck_1_Yaw";
122 }
123 else if (_robot->getName() == "Armar3")
124 {
125 _inverseYaw = 1;
126 _yawJointName = "Neck_3_Yaw";
127 }
128 else
129 {
130 throw std::invalid_argument("Could not autodetect yaw!");
131 }
132 }
133 if (_pitchJointName == "")
134 {
135 if (_robot->getName() == "Armar6")
136 {
137 _pitchJointName = "Neck_2_Pitch";
138 }
139 else if (_robot->getName() == "Armar3")
140 {
141 _pitchJointName = "Neck_1_Pitch";
142 }
143 else
144 {
145 throw std::invalid_argument("Could not autodetect pitch!");
146 }
147 }
148 }
149
150 void
152 {
153 _robot = addRobot("state robot", VirtualRobot::RobotIO::eStructure);
154 try
155 {
156 autoDetectRobotSpecificVariables();
157 }
158 catch (...)
159 {
160 ARMARX_ERROR << "Could not autodetect joints!";
161 }
162 getProxy(kinematicUnitInterfacePrx, _kinematicUnitInterfaceName);
163 //image provider
164 {
165 _imageProviderInfo = getImageProvider(_imageProviderName, true);
166 _imageProvider = _imageProviderInfo.proxy;
167 ARMARX_CHECK_GREATER(_imageProviderInfo.numberImages, 0);
168 ARMARX_CHECK_EQUAL(_imageProviderInfo.imageFormat.type, visionx::ImageType::eRgb);
169 //reserve buffers
170 _providerImagesOwner.reserve(_imageProviderInfo.numberImages);
171 _providerImages.reserve(_imageProviderInfo.numberImages);
172 for (int i = 0; i < _imageProviderInfo.numberImages; ++i)
173 {
174 _providerImagesOwner.emplace_back(
175 visionx::tools::createByteImage(_imageProviderInfo));
176 _providerImages.emplace_back(
177 static_cast<void*>(_providerImagesOwner.back()->pixels));
178 }
179 _numberOfImages = _imageProviderInfo.numberImages;
180 }
181 }
182
183 void
185 {
186 if (!waitForImages(_imageProviderName, 1000))
187 {
188 return;
189 }
190 getImages(_providerImages.data());
191 const CByteImage& img = *(_providerImagesOwner.at(_imageIndex));
192 {
193 std::lock_guard<std::mutex> guard{_currentImageMutex};
194 _currentImage = QImage(img.width, img.height, QImage::Format_RGB888);
195 ARMARX_CHECK_NOT_NULL(_currentImage.bits());
196 ARMARX_CHECK_NOT_NULL(img.pixels);
197 std::memcpy(_currentImage.bits(), img.pixels, 3 * img.width * img.height);
198 _currentImageDirty = true;
199 }
200 }
201
202 void
204 {
205 _imageProviderName = _dialog->getProxyName("ImageProvider");
206 _pitchJointName = _dialog->getLineEditText("pitch");
207 _yawJointName = _dialog->getLineEditText("yaw");
208 _kinematicUnitInterfaceName = _dialog->getProxyName("KinematicUnitInterface");
209 }
210
211 void
212 LookAtClickWidgetController::refreshWidgetData(float* factorPitch, float* factorYaw)
213 {
214 *factorPitch = widget.doubleSpinBoxFactorPitch->value();
215 *factorYaw = widget.doubleSpinBoxFactorYaw->value();
216 }
217
218 void
219 LookAtClickWidgetController::determineNewAngles(const QPoint& offset,
220 NameValueMap& jointAngles,
221 NameControlModeMap& jointModes,
222 float factorPitch,
223 float factorYaw)
224 {
225 jointModes[_pitchJointName] = ePositionControl;
226 jointModes[_yawJointName] = ePositionControl;
227 ARMARX_INFO << _robot->getRobotNode(_pitchJointName)->getJointValue();
228 ARMARX_INFO << _robot->getRobotNode(_yawJointName)->getJointValue();
229 auto pitch = _robot->getRobotNode(_pitchJointName);
230 auto yaw = _robot->getRobotNode(_yawJointName);
231 const float pitchValue = offset.y() * factorPitch + pitch->getJointValue();
232 const float yawValue = _inverseYaw * offset.x() * factorYaw + yaw->getJointValue();
233 jointAngles[_pitchJointName] =
234 std::clamp(pitchValue, pitch->getJointLimitLo(), pitch->getJointLimitHi());
235 jointAngles[_yawJointName] =
236 std::clamp(yawValue, yaw->getJointLimitLo(), yaw->getJointLimitHi());
237 ARMARX_INFO << "pitch value: " << jointAngles[_pitchJointName]
238 << "yaw value: " << jointAngles[_yawJointName];
239 }
240
241 void
243 {
244 ARMARX_INFO << "ClickedAt called!";
245 float factorPitch, factorYaw;
246 NameValueMap jointAngles;
247 NameControlModeMap jointModes;
248
249 refreshWidgetData(&factorPitch, &factorYaw);
250 synchronizeLocalClone(_robot);
251 determineNewAngles(offset, jointAngles, jointModes, factorPitch, factorYaw);
252 try
253 {
254 kinematicUnitInterfacePrx->switchControlMode(jointModes);
255 kinematicUnitInterfacePrx->setJointAngles(jointAngles);
256 }
257 catch (...)
258 {
259 ARMARX_ERROR << "Error occurred in clickedAt";
260 }
261 ARMARX_INFO << "after setjointangles";
262 }
263
264 void
266 {
267 if (!_currentImageDirty)
268 {
269 return;
270 }
271 {
272 std::lock_guard<std::mutex> guard{_currentImageMutex};
273 _turnOnClick->drawBackground(_currentImage);
274 _currentImageDirty = false;
275 }
276 }
277} // namespace armarx
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
void process()
Process the vision component.
void loadSettings(QSettings *settings) override
void saveSettings(QSettings *settings) override
virtual ~LookAtClickWidgetController()
Controller destructor.
void configured() override
This function must be implemented by the user, if he supplies a config dialog.
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.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
bool synchronizeLocalClone(const VirtualRobot::RobotPtr &robot) const
const RobotStateComponentPlugin & getRobotStateComponentPlugin() const
VirtualRobot::RobotPtr addRobot(const std::string &id, const VirtualRobot::RobotPtr &robot, const VirtualRobot::RobotNodeSetPtr &rns={}, const VirtualRobot::RobotNodePtr &node={})
A config-dialog containing one (or multiple) proxy finders.
void usingImageProvider(std::string name)
Registers a delayed topic subscription and a delayed provider proxy retrieval which all will be avail...
bool waitForImages(int milliseconds=1000)
Wait for new images.
ImageProviderInfo getImageProvider(std::string name, ImageType destinationImageType=eRgb, bool waitForProxy=false)
Select an ImageProvider.
int getImages(CByteImage **ppImages)
Poll images from provider.
#define ARMARX_CHECK_GREATER(lhs, rhs)
This macro evaluates whether lhs is greater (>) than rhs and if it turns out to be false it will thro...
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
This file offers overloads of toIce() and fromIce() functions for STL container types.
::IceInternal::ProxyHandle<::IceProxy::armarx::RobotStateComponentInterface > RobotStateComponentInterfacePrx
CByteImage * createByteImage(const ImageFormatInfo &imageFormat, const ImageType imageType)
Creates a ByteImage for the destination type specified in the given imageProviderInfo.