ArmarXSimulatorWindow.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 * @package
19 * @author
20 * @date
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
25
26// ArmarX
30
31
32// Qt
33#include <stdlib.h>
34
35#include <filesystem>
36
37#include <QFile>
38#include <QFileDialog>
39#include <QGLWidget>
40#include <QImage>
41#include <QInputDialog>
42#include <QLabel>
43#include <QListView>
44#include <QMessageBox>
45#include <QPushButton>
46#include <QTimer>
47#include <QToolButton>
48#include <QtCore/QDirIterator>
49
50#include <VirtualRobot/MathTools.h>
51#include <VirtualRobot/Visualization/CoinVisualization/CoinVisualization.h>
52#include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h>
53#include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationNode.h>
54
55#include <Inventor/actions/SoBoxHighlightRenderAction.h>
56#include <Inventor/nodes/SoCamera.h>
57#include <Inventor/nodes/SoUnits.h>
58#include <SimDynamics/DynamicsEngine/DynamicsRobot.h>
59
60#define ARMARX_GUI_APPLICATION_NAME "ArmarXSimulator"
61
62
63#define TIMER_MS 30.0f
64
65using namespace armarx;
66using namespace VirtualRobot;
67using namespace SimDynamics;
68
70 QMainWindow(NULL), viewer(nullptr), sceneSep(nullptr)
71{
72}
73
74void
77{
78 drawTimeMS = 0;
79 guiWindowBaseName = ARMARX_GUI_APPLICATION_NAME;
80 setWindowTitle(guiWindowBaseName);
81 setTag(ARMARX_GUI_APPLICATION_NAME);
82 ARMARX_INFO << " ************** ArmarXSimulatorWindow INIT ************** " << armarx::flush;
83
84 setAttribute(Qt::WA_QuitOnClose);
85
86 this->physicsVisu = physicsVisu;
87 this->debugDrawer = debugDrawer;
88
89 sceneSep = new SoSeparator;
90 sceneSep->ref();
91
92 if (physicsVisu && physicsVisu->getVisualization())
93 {
94 sceneSep->addChild(physicsVisu->getVisualization());
95 }
96
97 if (debugDrawer && debugDrawer->getVisualization())
98 {
99 sceneSep->addChild(debugDrawer->getVisualization());
100 }
101
102 setupUI();
103}
104
105void
109
110void
112{
113 float x = getProperty<float>("Camera.x").getValue();
114 float y = getProperty<float>("Camera.y").getValue();
115 float z = getProperty<float>("Camera.z").getValue();
116 float ro = getProperty<float>("Camera.roll").getValue();
117 float pi = getProperty<float>("Camera.pitch").getValue();
118 float ya = getProperty<float>("Camera.yaw").getValue();
119 setCamPose(x, y, z, ro, pi, ya);
120}
121
122void
124{
126
127 bool showBase = getProperty<bool>("ShowBaseCoordSystem").getValue();
128 showBaseCoordSystem(showBase);
129
130 int alias = getProperty<int>("AntiAliasingRenderPasses").getValue();
131 setAntiAliasing(alias);
132
133 saveVideo = getProperty<bool>("SaveVideo").getValue();
134 tmpDir = getProperty<std::string>("TempDir").getValue();
135}
136
137void
141
142void
146
147void
149{
150 ui.setupUi(this);
151
152 viewer = new CoinViewer(ui.frameViewer,
153 "ArmarXSimulator",
154 TRUE,
155 SoQtExaminerViewer::BUILD_POPUP,
156 SoQtExaminerViewer::BROWSER);
157 viewer->setMutex(mutex);
158
159 // setup
160 viewer->setBackgroundColor(SbColor{getProperty<float>("Background.r").getValue(),
161 getProperty<float>("Background.g").getValue(),
162 getProperty<float>("Background.b").getValue()});
163
164 int numPasses = getProperty<int>("AntiAliasingRenderPasses").getValue();
165 viewer->setAccumulationBuffer(numPasses > 0);
166 //viewer->setAntialiasing(false, 1);
167
168 viewer->setGLRenderAction(new SoBoxHighlightRenderAction);
169 viewer->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_BLEND);
170 viewer->setFeedbackVisibility(true);
171 viewer->setSceneGraph(sceneSep);
172 viewer->viewAll();
173 // really needed?
174 //viewer->setAccumulationBuffer(numPasses > 0);
175
176 SoSensorManager* sensor_mgr = SoDB::getSensorManager();
177 SoTimerSensor* timer = new SoTimerSensor(timerCB, this);
178 timer->setInterval(SbTime(TIMER_MS / 1000.0f));
179 sensor_mgr->insertTimerSensor(timer);
180}
181
183{
184 if (sceneSep)
185 {
186 sceneSep->unref();
187 }
188 delete viewer;
189 ARMARX_INFO << "~ArmarXSimulatorWindow() ";
190}
191
192void
194{
195 emit closeRequest();
196 event->accept();
197}
198
199void
200ArmarXSimulatorWindow::timerCB(void* data, SoSensor* /*sensor*/)
201{
202 ArmarXSimulatorWindow* simWindow = static_cast<ArmarXSimulatorWindow*>(data);
203
204 //simWindow->redraw();
205 simWindow->saveScreenshot();
206}
207
208void
210{
211 if (!saveVideo)
212 {
213 return;
214 }
215
216 static long counter = 0;
217 clock_t start = clock();
218
219 //framefile.sprintf("renderFrame_%06d.png", counter);
220 std::stringstream ss;
221 ss << tmpDir << "/armarx-render-frame-" << counter << ".bmp";
222 std::string fn = ss.str();
223 counter++;
224 //redraw();
225
226 viewer->getSceneManager()->render();
227 //viewer->getSceneManager()->scheduleRedraw();
228
229 QGLWidget* w = (QGLWidget*)viewer->getGLWidget();
230
231 QImage i = w->grabFrameBuffer();
232 QString fnQ(fn.c_str());
233 bool res = i.save(fnQ, "BMP");
234 if (!res)
235 {
236 ARMARX_WARNING << deactivateSpam(5) << "Could not write screenshot to file " << fn;
237 }
238 else
239 {
240 clock_t end = clock();
241 float timeMS = (float)(end - start) / (float)CLOCKS_PER_SEC * 1000.0f;
242 ARMARX_INFO << deactivateSpam(5) << "Wrote image " << fn << " in " << timeMS << " ms";
243 }
244}
245
246void
248{
249 auto l = getScopedLock();
250
251 if (viewer)
252 {
253 viewer->setAccumulationBuffer(numPasses > 0);
254 viewer->setAntialiasing((numPasses > 0), numPasses);
255 }
256}
257
258void
260{
261 if (physicsVisu)
262 {
263 physicsVisu->showBaseCoord(show, scale);
264 }
265}
266
267void
269{
270 auto l = getScopedLock();
271
272 if (show && sceneSep && debugDrawer && debugDrawer->getVisualization() &&
273 sceneSep->findChild(debugDrawer->getVisualization()) < 0)
274 {
275 sceneSep->addChild(debugDrawer->getVisualization());
276 }
277
278 if (!show && sceneSep && debugDrawer && debugDrawer->getVisualization() &&
279 sceneSep->findChild(debugDrawer->getVisualization()) >= 0)
280 {
281 sceneSep->removeChild(debugDrawer->getVisualization());
282 }
283}
284
285void
287{
288 auto l = getScopedLock();
289 ARMARX_DEBUG << "viewall" << flush;
290
291 if (!viewer || !physicsVisu)
292 {
293 return;
294 }
295
296 SoCamera* cam = viewer->getCamera();
297 SoSeparator* sceneViewableSep = physicsVisu->getViewableScene();
298
299 if (cam && sceneViewableSep)
300 {
301 cam->viewAll(sceneViewableSep, viewer->getViewportRegion());
302 }
303}
304
305Eigen::Matrix4f
307{
308 auto l = getScopedLock();
309 Eigen::Matrix4f camPose = Eigen::Matrix4f::Identity();
310
311 if (viewer && viewer->getCamera())
312 {
313 SbVec3f position = viewer->getCamera()->position.getValue();
314 SbRotation orientation = viewer->getCamera()->orientation.getValue();
315 SbVec3f rotAxis;
316 float angle;
317 orientation.getValue(rotAxis, angle);
318 Eigen::Vector3f axE;
319 axE(0) = rotAxis[0];
320 axE(1) = rotAxis[1];
321 axE(2) = rotAxis[2];
322 camPose = MathTools::axisangle2eigen4f(axE, angle);
323 camPose(0, 3) = position[0];
324 camPose(1, 3) = position[1];
325 camPose(2, 3) = position[2];
326 }
327
328 return camPose;
329}
330
331void
332ArmarXSimulatorWindow::setCamPose(float x, float y, float z, float roll, float pitch, float yaw)
333{
334 ARMARX_VERBOSE << "setting cam pose " << VAROUT(x) << VAROUT(y) << VAROUT(z) << VAROUT(roll)
335 << VAROUT(pitch) << VAROUT(yaw);
336 auto l = getScopedLock();
337
338 if (viewer && viewer->getCamera())
339 {
340 SbVec3f position(x * 0.001f, y * 0.001f, z * 0.001f);
341 SbRotation orientation;
342 Eigen::Matrix4f m;
343 MathTools::rpy2eigen4f(roll, pitch, yaw, m);
344 float ang;
345 Eigen::Vector3f ax;
346 MathTools::eigen4f2axisangle(m, ax, ang);
347 SbVec3f ax2(ax(0), ax(1), ax(2));
348 orientation.setValue(ax2, ang);
349 viewer->getCamera()->position.setValue(position);
350 viewer->getCamera()->orientation.setValue(orientation);
351 }
352}
353
359
360SoNode*
365
366void
368{
369 mutex = m;
370
371 if (viewer)
372 {
373 viewer->setMutex(m);
374 }
375}
376
383
384void
385ArmarXSimulatorWindow::enableSimulatorWindow(bool show, const Ice::Current& c)
386{
387 {
388 auto l = getScopedLock();
389 info.windowEnabled = show;
390 }
391
392 if (show)
393 {
394 ARMARX_INFO << "Showing simulator window";
395 QMetaObject::invokeMethod(
396 this,
397 "show"); //, Q_ARG(float, currentPlatformPositionX), Q_ARG(float, currentPlatformPositionY), Q_ARG(float, currentPlatformRotation));
398
399 //simWindow->show();
400 }
401 else
402 {
403 ARMARX_INFO << "Hiding simulator window";
404 QMetaObject::invokeMethod(this, "hide");
405 //simWindow->hide();
406 }
407}
408
409void
410ArmarXSimulatorWindow::showBaseCoordSystem(bool show, float scale, const Ice::Current& c)
411{
412 QMetaObject::invokeMethod(
413 this, "slotShowBaseCoord", Qt::QueuedConnection, Q_ARG(bool, show), Q_ARG(float, scale));
414}
415
416/*
417void ArmarXSimulatorWindow::showContacts(bool show, const Ice::Current &c)
418{
419 QMetaObject::invokeMethod(this, "slotShowContacts", Qt::QueuedConnection, Q_ARG(bool, show));
420}*/
421
422armarx::SimulatorViewerInformation
424{
425 auto l = getScopedLock();
426
427 // update data
428 if (physicsVisu)
429 {
430 info.comTimeMS = physicsVisu->getSyncVisuTime();
431 }
432 else
433 {
434 info.comTimeMS = 0;
435 }
436
437 info.drawTimeMS = drawTimeMS;
438
439 return info;
440}
441
442void
447
448void
449ArmarXSimulatorWindow::setAntiAliasing(int steps, const Ice::Current& c)
450{
451 if (steps < 0)
452 {
453 steps = 0;
454 }
455
456
457 if (!QMetaObject::invokeMethod(
458 this, "setupAntiAliasing", Qt::QueuedConnection, Q_ARG(int, steps)))
459 {
460 ARMARX_VERBOSE << "Failed to invoke method";
461 }
462}
463
464PoseBasePtr
466{
467 // maybe we should invoke a qt-thread safe method, but a lock (used in getCamPose) seems to be fine for now...
468 Eigen::Matrix4f camPose = getCamPose();
469 PosePtr p(new Pose(camPose));
470 return p;
471}
472
473void
474ArmarXSimulatorWindow::showDebugDrawLayer(bool show, const Ice::Current& c)
475{
476 if (!QMetaObject::invokeMethod(
477 this, "slotEnableDebugDrawLayer", Qt::QueuedConnection, Q_ARG(bool, show)))
478 {
479 ARMARX_VERBOSE << "Failed to invoke method";
480 }
481}
482
483void
485{
486 ARMARX_VERBOSE << "Clearing debug layer...";
487
488 if (debugDrawer)
489 {
490 debugDrawer->clearLayer("debug");
491 }
492}
493
494void
496{
497 if (!QMetaObject::invokeMethod(this, "slotClearDebugDrawLayer", Qt::QueuedConnection))
498 {
499 ARMARX_VERBOSE << "Failed to invoke method";
500 }
501}
502
503void
504ArmarXSimulatorWindow::clearLayer(const std::string& layerName, const ::Ice::Current&)
505{
506 QString s(layerName.c_str());
507
508 if (!QMetaObject::invokeMethod(this, "slotClearLayer", Qt::QueuedConnection, Q_ARG(QString, s)))
509 {
510 ARMARX_VERBOSE << "Failed to invoke method";
511 }
512}
513
514void
515ArmarXSimulatorWindow::removeLayer(const std::string& layerName, const ::Ice::Current&)
516{
517 QString s(layerName.c_str());
518
519 if (!QMetaObject::invokeMethod(
520 this, "slotRemoveLayer", Qt::QueuedConnection, Q_ARG(QString, s)))
521 {
522 ARMARX_VERBOSE << "Failed to invoke method";
523 }
524}
525
526void
527ArmarXSimulatorWindow::enableLayerVisu(const std::string& layerName,
528 bool visible,
529 const ::Ice::Current&)
530{
531 QString s(layerName.c_str());
532
533 if (!QMetaObject::invokeMethod(this,
534 "slotEnableLayerVisu",
535 Qt::QueuedConnection,
536 Q_ARG(QString, s),
537 Q_ARG(bool, visible)))
538 {
539 ARMARX_VERBOSE << "Failed to invoke method";
540 }
541}
542
543void
545{
546 if (debugDrawer)
547 {
548 debugDrawer->clearLayer(layerName.toStdString());
549 }
550}
551
552void
554{
555 if (debugDrawer)
556 {
557 debugDrawer->removeLayer(layerName.toStdString());
558 }
559}
560
561void
562ArmarXSimulatorWindow::slotEnableLayerVisu(const QString layerName, bool visible)
563{
564 if (debugDrawer)
565 {
566 debugDrawer->enableLayerVisu(layerName.toStdString(), visible);
567 }
568}
569
570::armarx::LayerInformationSequence
572{
573 if (debugDrawer)
574 {
575 return debugDrawer->layerInformation();
576 }
577
578 return ::armarx::LayerInformationSequence{};
579}
580
581void
582ArmarXSimulatorWindow::setTempPath(const std::string& p, const Ice::Current&)
583{
584 tmpDir = p;
585}
586
587void
588ArmarXSimulatorWindow::saveScreenshots(bool enable, const Ice::Current&)
589{
590 saveVideo = enable;
591}
592
593void
594ArmarXSimulatorWindow::selectVisuType(bool fullModel, const Ice::Current& c)
595{
596 if (!QMetaObject::invokeMethod(
597 this, "slotSelectVisuType", Qt::QueuedConnection, Q_ARG(bool, fullModel)))
598 {
599 ARMARX_VERBOSE << "Failed to invoke method";
600 }
601}
602
603void
605{
606 if (physicsVisu)
607 {
608 physicsVisu->enableVisuType(fullModel);
609 }
610}
#define float
Definition 16_Level.h:22
#define pi
#define TIMER_MS
#define VAROUT(x)
constexpr T c
void onInitComponent() override
Pure virtual hook for the subclass.
void showDebugDrawLayer(bool show, const Ice::Current &c=Ice::emptyCurrent) override
PoseBasePtr getCameraPose(const Ice::Current &c=Ice::emptyCurrent) override
void setAntiAliasing(int steps, const Ice::Current &c=Ice::emptyCurrent) override
void slotShowBaseCoord(bool show, float scale)
void saveScreenshots(bool enable, const ::Ice::Current &=Ice::emptyCurrent) override
void enableLayerVisu(const std::string &layerName, bool visible, const ::Ice::Current &=Ice::emptyCurrent) override
void initialize(ArmarXPhysicsWorldVisualizationPtr physicsVisu, DebugDrawerComponentPtr debugDrawer)
armarx::SimulatorViewerInformation info
void onDisconnectComponent() override
Hook for subclass.
void setMutex(CoinViewer::RecursiveMutexPtr const &m)
::armarx::LayerInformationSequence layerInformation(const ::Ice::Current &=Ice::emptyCurrent) override
DebugDrawerComponentPtr debugDrawer
void closeRequest()
emitted, when the main window should be closed
void closeEvent(QCloseEvent *event) override
emits the closeRequest signal
void slotClearLayer(const QString layerName)
void setCamPose(float x, float y, float z, float roll, float pitch, float yaw)
CoinViewer::RecursiveMutexLockPtr getScopedLock()
Protect access with this lock.
void onConnectComponent() override
Pure virtual hook for the subclass.
CoinViewer::RecursiveMutexPtr mutex
void selectVisuType(bool fullModel, const Ice::Current &c=Ice::emptyCurrent) override
Switch between full/collision model.
void clearDebugDrawLayer(const Ice::Current &c=Ice::emptyCurrent) override
void slotRemoveLayer(const QString layerName)
void clearLayer(const std::string &layerName, const ::Ice::Current &=Ice::emptyCurrent) override
void setTempPath(const std::string &p, const ::Ice::Current &=Ice::emptyCurrent) override
void slotEnableLayerVisu(const QString layerName, bool visible)
void enableSimulatorWindow(bool show, const Ice::Current &c=Ice::emptyCurrent) override
void onExitComponent() override
Hook for subclass.
void removeLayer(const std::string &layerName, const ::Ice::Current &=Ice::emptyCurrent) override
Ui::MainWindowArmarXSimulator ui
void showBaseCoordSystem(bool show, float scale=1.0, const Ice::Current &c=Ice::emptyCurrent) override
SimulatorViewerInformation getSimulatorInformation(const Ice::Current &c=Ice::emptyCurrent) override
ArmarXPhysicsWorldVisualizationPtr physicsVisu
static void timerCB(void *data, SoSensor *sensor)
std::shared_ptr< RecursiveMutexLock > RecursiveMutexLockPtr
Definition CoinViewer.h:53
std::shared_ptr< RecursiveMutex > RecursiveMutexPtr
Definition CoinViewer.h:51
std::unique_lock< RecursiveMutex > RecursiveMutexLock
Definition CoinViewer.h:52
Property< PropertyType > getProperty(const std::string &name)
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
Definition Logging.cpp:99
void setTag(const LogTag &tag)
Definition Logging.cpp:54
The Pose class.
Definition Pose.h:243
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< Pose > PosePtr
Definition Pose.h:306
IceInternal::Handle< DebugDrawerComponent > DebugDrawerComponentPtr
IceInternal::Handle< ArmarXPhysicsWorldVisualization > ArmarXPhysicsWorldVisualizationPtr
const LogSender::manipulator flush
Definition LogSender.h:251
double angle(const Point &a, const Point &b, const Point &c)
Definition point.hpp:109