CartesianNaturalPositionControllerWidgetController.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::CartesianNaturalPositionControllerWidgetController
17 * \author armar-user ( armar-user at kit dot edu )
18 * \date 2020
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 <VirtualRobot/math/Helpers.h>
28
30
31namespace armarx
32{
35 {
36 std::lock_guard g{_allMutex};
37 _ui.setupUi(getWidget());
38
39 connect(this,
41 this,
43 Qt::QueuedConnection);
44 connect(this,
46 this,
47 SLOT(onDisconnectComponentQt()),
48 Qt::QueuedConnection);
49
50
51 //connect(_ui.pushButtonStop, SIGNAL(clicked()), this, SLOT(on_pushButtonStop_clicked()));
52 //connect(_ui.pushButtonExecute, SIGNAL(clicked()), this, SLOT(on_pushButtonExecute_clicked()));
53 //connect(_ui.pushButtonZeroFT, SIGNAL(clicked()), this, SLOT(on_pushButtonZeroFT_clicked()));
54 //connect(_ui.pushButtonSendSettings, SIGNAL(clicked()), this, SLOT(on_pushButtonSendSettings_clicked()));
55 connect(_ui.pushButtonCreateController,
56 SIGNAL(clicked()),
57 this,
59 connect(
60 _ui.sliderKpElbow, SIGNAL(valueChanged(int)), this, SLOT(on_sliders_valueChanged(int)));
61 connect(
62 _ui.sliderKpJla, SIGNAL(valueChanged(int)), this, SLOT(on_sliders_valueChanged(int)));
63 connect(_ui.checkBoxAutoKp,
64 SIGNAL(stateChanged(int)),
65 this,
67 connect(_ui.checkBoxSetOri,
68 SIGNAL(stateChanged(int)),
69 this,
71 connect(_ui.sliderPosVel,
72 SIGNAL(valueChanged(int)),
73 this,
75
76 auto addBtn =
77 [&](QPushButton* btn, float px, float py, float pz, float rx, float ry, float rz)
78 {
79 _deltaMapPos[btn] = {px, py, pz};
80 _deltaMapOri[btn] = {rx, ry, rz};
81 //ARMARX_IMPORTANT << "connect";
82 //ARMARX_IMPORTANT << btn->text().toStdString();
83 connect(btn, SIGNAL(clicked()), this, SLOT(on_anyDeltaPushButton_clicked()));
84 };
85 addBtn(_ui.pushButtonPxp, +1, 0, 0, 0, 0, 0);
86 addBtn(_ui.pushButtonPxn, -1, 0, 0, 0, 0, 0);
87 addBtn(_ui.pushButtonPyp, 0, +1, 0, 0, 0, 0);
88 addBtn(_ui.pushButtonPyn, 0, -1, 0, 0, 0, 0);
89 addBtn(_ui.pushButtonPzp, 0, 0, +1, 0, 0, 0);
90 addBtn(_ui.pushButtonPzn, 0, 0, -1, 0, 0, 0);
91
92 addBtn(_ui.pushButtonRxp, 0, 0, 0, +1, 0, 0);
93 addBtn(_ui.pushButtonRxn, 0, 0, 0, -1, 0, 0);
94 addBtn(_ui.pushButtonRyp, 0, 0, 0, 0, +1, 0);
95 addBtn(_ui.pushButtonRyn, 0, 0, 0, 0, -1, 0);
96 addBtn(_ui.pushButtonRzp, 0, 0, 0, 0, 0, +1);
97 addBtn(_ui.pushButtonRzn, 0, 0, 0, 0, 0, -1);
98
99 //_ui.widgetSpacer->setVisible(false);
100 _timer = startTimer(100);
101 }
102
108
109 void
111 {
112 std::lock_guard g{_allMutex};
113 _robotStateComponentName =
114 settings->value("rsc", "Armar6StateComponent").toString().toStdString();
115 _robotUnitName = settings->value("ru", "Armar6Unit").toString().toStdString();
116 }
117
118 void
120 {
121 std::lock_guard g{_allMutex};
122 settings->setValue("rsc", QString::fromStdString(_robotStateComponentName));
123 settings->setValue("ru", QString::fromStdString(_robotUnitName));
124 }
125
126 void
128 {
129 std::lock_guard g{_allMutex};
130 usingProxy(_robotStateComponentName);
131 usingProxy(_robotUnitName);
132 }
133
134 void
136 {
137 std::lock_guard g{_allMutex};
138 //proxies
139 {
140 _robotStateComponent =
141 getProxy<RobotStateComponentInterfacePrx>(_robotStateComponentName);
142 _robotUnit = getProxy<RobotUnitInterfacePrx>(_robotUnitName);
143 }
144 //robot
145 {
146 _robot = RemoteRobot::createLocalCloneFromFile(_robotStateComponent,
147 VirtualRobot::RobotIO::eStructure);
148 }
149
150 _controller.reset();
152 }
153
154 void
156 {
157 _ui.comboBoxSide->addItem("Right");
158 _ui.comboBoxSide->addItem("Left");
159 _ui.comboBoxSide->setCurrentIndex(0);
160 }
161
162 void
164 {
165 std::lock_guard g{_allMutex};
166 deleteOldController();
167 _robotStateComponent = nullptr;
168 }
169
170 void
172 {
173 std::lock_guard g{_allMutex};
174 deleteOldController();
175
176 std::string side = _ui.comboBoxSide->currentText().toStdString();
177
178 VirtualRobot::RobotNodeSetPtr rns = _robot->getRobotNodeSet(side + "Arm");
179
180 _ui.gridLayoutNullspaceTargets->removeWidget(_ui.checkBoxExampleJoint1);
181 _ui.gridLayoutNullspaceTargets->removeWidget(_ui.labelExampleJoint1);
182 _ui.gridLayoutNullspaceTargets->removeWidget(_ui.horizontalSliderExampleJoint1);
183
184 for (size_t i = 0; i < rns->getSize(); i++)
185 {
186 QCheckBox* checkBox = new QCheckBox(QString::fromStdString(rns->getNode(i)->getName()));
187 QSlider* slider = new QSlider(Qt::Orientation::Horizontal);
188 slider->setMinimum(rns->getNode(i)->getJointLimitLo() / M_PI * 180);
189 slider->setMaximum(rns->getNode(i)->getJointLimitHi() / M_PI * 180);
190 slider->setValue(rns->getNode(i)->getJointValue() / M_PI * 180);
191 QLabel* label = new QLabel(QString::number(slider->value()));
192 _ui.gridLayoutNullspaceTargets->addWidget(checkBox, i, 0);
193 _ui.gridLayoutNullspaceTargets->addWidget(slider, i, 1);
194 _ui.gridLayoutNullspaceTargets->addWidget(label, i, 2);
195 connect(checkBox,
196 SIGNAL(stateChanged(int)),
197 this,
199 connect(slider,
200 SIGNAL(valueChanged(int)),
201 this,
204 nt.checkBox = checkBox;
205 nt.slider = slider;
206 nt.label = label;
207 nt.i = i;
208 _nullspaceTargets.emplace_back(nt);
209 }
210
211
212 VirtualRobot::RobotNodePtr cla = rns->getNode(0);
213 VirtualRobot::RobotNodePtr sho1 = rns->getNode(1);
214 ARMARX_IMPORTANT << VAROUT(cla->getJointValue());
215 cla->setJointValue(0);
216 Eigen::Vector3f shoulder = sho1->getPositionInRootFrame();
217 VirtualRobot::RobotNodePtr elb = rns->getNode(4);
218 VirtualRobot::RobotNodePtr wri1 = rns->getNode(6);
219 VirtualRobot::RobotNodePtr tcp = rns->getTCP();
221
222 arm.rns = rns;
223 arm.shoulder = sho1;
224 arm.elbow = elb;
225 arm.tcp = tcp;
226
227 std::vector<float> jointCosts = std::vector<float>(rns->getSize(), 1);
228 jointCosts.at(0) = 4;
229
230
231 armarx::RemoteRobot::synchronizeLocalClone(_robot, _robotStateComponent);
232 _tcpTarget = rns->getTCP()->getPoseInRootFrame();
233
234 NaturalIK ik(side, shoulder, 1.3f);
235 float upper_arm_length =
236 (sho1->getPositionInRootFrame() - elb->getPositionInRootFrame()).norm();
237 float lower_arm_length =
238 (elb->getPositionInRootFrame() - wri1->getPositionInRootFrame()).norm() +
239 (wri1->getPositionInRootFrame() - tcp->getPositionInRootFrame()).norm();
240 ik.setUpperArmLength(upper_arm_length);
241 ik.setLowerArmLength(lower_arm_length);
242 NJointCartesianNaturalPositionControllerConfigPtr config =
243 CartesianNaturalPositionControllerProxy::MakeConfig(rns->getName(), elb->getName());
244 config->runCfg.jointCosts = jointCosts;
245 CartesianNaturalPositionControllerConfig runCfg = config->runCfg;
246 updateKpSliders(runCfg);
247 //config->runCfg = runCfg;
248 _controller.reset(new CartesianNaturalPositionControllerProxy(
249 ik, arm, _robotUnit, side + "NaturalPosition", config));
250 _controller->init();
251 }
252
253 void
255 {
256 Eigen::Matrix4f newTarget = _tcpTarget;
257 ARMARX_IMPORTANT << "on_anyDeltaPushButton_clicked";
258 std::lock_guard g{_allMutex};
259 Eigen::Vector3f deltaPos = _deltaMapPos.at(QObject::sender());
260 Eigen::Vector3f deltaOri = _deltaMapOri.at(QObject::sender());
261 newTarget = math::Helpers::TranslatePose(newTarget, deltaPos * _ui.spinBoxDpos->value());
262 if (deltaOri.norm() > 0)
263 {
264 deltaOri = deltaOri * _ui.spinBoxDori->value() / 180 * M_PI;
265 Eigen::AngleAxisf aa(deltaOri.norm(), deltaOri.normalized());
266 math::Helpers::Orientation(newTarget) =
267 aa.toRotationMatrix() * math::Helpers::Orientation(newTarget);
268 }
269 updateTarget(newTarget);
270 }
271
272 void
273 CartesianNaturalPositionControllerWidgetController::updateTarget(
274 const Eigen::Matrix4f& newTarget)
275 {
276 if (!_controller->setTarget(
278 {
279 return;
280 }
281 _tcpTarget = newTarget;
282 if (_controller->getDynamicKp().enabled)
283 {
284 updateKpSliders(_controller->getRuntimeConfig());
285 }
286 }
287
288 void
289 CartesianNaturalPositionControllerWidgetController::readRunCfgFromUi(
290 CartesianNaturalPositionControllerConfig& runCfg)
291 {
292 runCfg.elbowKp = _ui.sliderKpElbow->value() * 0.01f;
293 runCfg.jointLimitAvoidanceKp = _ui.sliderKpJla->value() * 0.01f;
294 }
295
296 void
297 CartesianNaturalPositionControllerWidgetController::updateKpSliderLabels(
298 const CartesianNaturalPositionControllerConfig& runCfg)
299 {
300 _ui.labelKpElbow->setText(QString::number(runCfg.elbowKp, 'f', 2));
301 _ui.labelKpJla->setText(QString::number(runCfg.jointLimitAvoidanceKp, 'f', 2));
302 }
303
304 void
305 CartesianNaturalPositionControllerWidgetController::updateKpSliders(
306 const CartesianNaturalPositionControllerConfig& runCfg)
307 {
308 const QSignalBlocker blockKpElb(_ui.sliderKpElbow);
309 const QSignalBlocker blockKpJla(_ui.sliderKpJla);
310 _ui.sliderKpElbow->setValue(runCfg.elbowKp * 100);
311 _ui.sliderKpJla->setValue(runCfg.jointLimitAvoidanceKp * 100);
312 updateKpSliderLabels(runCfg);
313 ARMARX_IMPORTANT << VAROUT(runCfg.elbowKp) << VAROUT(runCfg.jointLimitAvoidanceKp);
314 }
315
316 void
318 {
319 CartesianNaturalPositionControllerConfig runCfg = _controller->getRuntimeConfig();
320 //ARMARX_IMPORTANT << VAROUT(_runCfg.elbowKp) << VAROUT(_runCfg.jointLimitAvoidanceKp);
321 readRunCfgFromUi(runCfg);
322 updateKpSliderLabels(runCfg);
323 _controller->setRuntimeConfig(runCfg);
324 _controller->updateBaseKpValues(runCfg);
325 }
326
327 void
329 {
331 dynamicKp.enabled = _ui.checkBoxAutoKp->isChecked();
332 _controller->setDynamicKp(dynamicKp);
333 if (_controller->getDynamicKp().enabled)
334 {
335 updateKpSliders(_controller->getRuntimeConfig());
336 }
337 }
338
339 void
341 {
342 _setOri = _ui.checkBoxSetOri->isChecked();
343 updateTarget(_tcpTarget);
344 }
345
346 void
347 CartesianNaturalPositionControllerWidgetController::updateNullspaceTargets()
348 {
349 std::vector<float> nsTargets;
350 for (const NullspaceTarget& nt : _nullspaceTargets)
351 {
352 nsTargets.push_back(nt.checkBox->isChecked() ? nt.slider->value() * M_PI / 180
353 : std::nanf(""));
354 nt.label->setText(QString::number(nt.slider->value()));
355 }
356 _controller->setNullspaceTarget(nsTargets);
357 }
358
359 void
364
365 void
370
371 void
373 {
374 _ui.labelPosVel->setText(QString::number(_ui.sliderPosVel->value()));
375 float posVel = _ui.sliderPosVel->value();
376 _controller->setMaxVelocities(posVel);
377 //_runCfg = _controller->getRuntimeConfig();
378 }
379
380 //void CartesianNaturalPositionControllerWidgetController::on_pushButtonSendSettings_clicked()
381 //{
382 // std::lock_guard g{_allMutex};
383 // if (_controller)
384 // {
385 // ARMARX_IMPORTANT << "sending new config to " << _controllerName;
386 // _controller->setConfig(readRunCfg());
387 // }
388 //}
389
390
391 QPointer<QDialog>
393 {
394 std::lock_guard g{_allMutex};
395 if (!_dialog)
396 {
397 _dialog = new SimpleConfigDialog(parent);
398 _dialog->addProxyFinder<RobotUnitInterfacePrx>({"ru", "Robot Unit", "*Unit"});
399 _dialog->addProxyFinder<RobotStateComponentInterfacePrx>(
400 {"rsc", "Robot State Component", "*Component"});
401 }
402 return qobject_cast<SimpleConfigDialog*>(_dialog);
403 }
404
405 void
407 {
408 std::lock_guard g{_allMutex};
409 _robotStateComponentName = _dialog->getProxyName("rsc");
410 _robotUnitName = _dialog->getProxyName("ru");
411 }
412
413 /*NJointCartesianWaypointControllerRuntimeConfig CartesianWaypointControlGuiWidgetController::readRunCfg() const
414 {
415 std::lock_guard g{_allMutex};
416 NJointCartesianWaypointControllerRuntimeConfig cfg;
417
418 cfg.wpCfg.maxPositionAcceleration = static_cast<float>(_ui.doubleSpinBoxMaxAccPos->value());
419 cfg.wpCfg.maxOrientationAcceleration = static_cast<float>(_ui.doubleSpinBoxMaxAccOri->value());
420 cfg.wpCfg.maxNullspaceAcceleration = static_cast<float>(_ui.doubleSpinBoxMaxAccNull->value());
421
422 cfg.wpCfg.kpJointLimitAvoidance = static_cast<float>(_ui.doubleSpinBoxLimitAvoidKP->value());
423 cfg.wpCfg.jointLimitAvoidanceScale = static_cast<float>(_ui.doubleSpinBoxLimitAvoidScale->value());
424
425 cfg.wpCfg.thresholdOrientationNear = static_cast<float>(_ui.doubleSpinBoxOriNear->value());
426 cfg.wpCfg.thresholdOrientationReached = static_cast<float>(_ui.doubleSpinBoxOriReached->value());
427 cfg.wpCfg.thresholdPositionNear = static_cast<float>(_ui.doubleSpinBoxPosNear->value());
428 cfg.wpCfg.thresholdPositionReached = static_cast<float>(_ui.doubleSpinBoxPosReached->value());
429
430 cfg.wpCfg.maxOriVel = static_cast<float>(_ui.doubleSpinBoxOriMaxVel->value());
431 cfg.wpCfg.maxPosVel = static_cast<float>(_ui.doubleSpinBoxPosMaxVel->value());
432 cfg.wpCfg.kpOri = static_cast<float>(_ui.doubleSpinBoxOriKP->value());
433 cfg.wpCfg.kpPos = static_cast<float>(_ui.doubleSpinBoxPosKP->value());
434
435 cfg.forceThreshold = static_cast<float>(_ui.doubleSpinBoxFTLimit->value());
436 cfg.optimizeNullspaceIfTargetWasReached = _ui.checkBoxKeepOptimizing->isChecked();
437 cfg.forceThresholdInRobotRootZ = _ui.checkBoxLimitinZ->isChecked();
438
439 return cfg;
440 }*/
441
442 void
443 CartesianNaturalPositionControllerWidgetController::deleteOldController()
444 {
445 std::lock_guard g{_allMutex};
446 if (_controller)
447 {
448 _controller->cleanup();
449 }
450 }
451
452 void
453 CartesianNaturalPositionControllerWidgetController::timerEvent(QTimerEvent*)
454 {
455 std::lock_guard g{_allMutex};
456 if (!_robot || !_robotStateComponent)
457 {
458 return;
459 }
460 RemoteRobot::synchronizeLocalClone(_robot, _robotStateComponent);
461 if (_controller)
462 {
463 ARMARX_INFO << deactivateSpam() << "setting visu gp to:\n" << _robot->getGlobalPose();
464 _controller->getInternalController()->setVisualizationRobotGlobalPose(
465 _robot->getGlobalPose());
466 }
467 }
468
469
470} // namespace armarx
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
#define M_PI
Definition MathTools.h:17
#define VAROUT(x)
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
static NJointCartesianNaturalPositionControllerConfigPtr MakeConfig(const std::string &rns, const std::string &elbowNode)
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)
The NaturalIK class.
Definition NaturalIK.h:53
void setUpperArmLength(float value)
void setLowerArmLength(float value)
static VirtualRobot::RobotPtr createLocalCloneFromFile(RobotStateComponentInterfacePrx robotStatePrx, VirtualRobot::RobotIO::RobotDescription loadMode=VirtualRobot::RobotIO::eFull)
This is a convenience function for createLocalClone, which automatically gets the filename from the R...
static bool synchronizeLocalClone(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx)
A config-dialog containing one (or multiple) proxy finders.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
This file offers overloads of toIce() and fromIce() functions for STL container types.
::IceInternal::ProxyHandle<::IceProxy::armarx::RobotUnitInterface > RobotUnitInterfacePrx
::IceInternal::ProxyHandle<::IceProxy::armarx::RobotStateComponentInterface > RobotStateComponentInterfacePrx
VirtualRobot::RobotNodePtr elbow
Definition NaturalIK.h:68
VirtualRobot::RobotNodePtr shoulder
Definition NaturalIK.h:69
VirtualRobot::RobotNodeSetPtr rns
Definition NaturalIK.h:67
VirtualRobot::RobotNodePtr tcp
Definition NaturalIK.h:70