ImageProviderDynamicSimulation.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2013-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 Nikolaus Vahrenkamp
20 * @date 2014
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
25#include <exception>
26
27#include <Ice/Properties.h>
28
33
34// VisionXCore
37
38// VisionXTools
42
44#include <Calibration/Calibration.h>
45#include <Inventor/SoInteraction.h>
46#include <Inventor/SoOffscreenRenderer.h>
47#include <Inventor/nodes/SoDirectionalLight.h>
48#include <Inventor/nodes/SoUnits.h>
49#include <Math/Math3d.h>
50
51namespace armarx
52{
53 void
55 {
56 // init SoDB / Coin3D
57 //SoDB::init();
58
59 ARMARX_INFO << "1";
60
61 VirtualRobot::init(this->getName());
62
63 // needed for SoSelection
64 SoInteraction::init();
65
66 // image format
67 setImageSyncMode(visionx::eFpsSynchronization);
68 frameRate = getProperty<float>("FrameRate").getValue();
69
70 std::string calibrationFileName = getProperty<std::string>("CalibrationFile").getValue();
71 ARMARX_VERBOSE << "Camera calibration file: " << calibrationFileName;
72
73 if (!calibrationFileName.empty())
74 {
75 std::string fullCalibrationFileName;
76
77 if (!ArmarXDataPath::getAbsolutePath(calibrationFileName, fullCalibrationFileName))
78 {
79 ARMARX_ERROR << "Could not find camera calibration file in ArmarXDataPath: "
80 << calibrationFileName;
81 }
82
83 setlocale(LC_NUMERIC, "C");
84
85 CStereoCalibration ivtStereoCalibration;
86
87 if (!ivtStereoCalibration.LoadCameraParameters(fullCalibrationFileName.c_str(), true))
88 {
89 ARMARX_ERROR << "Error loading camera calibration file: "
90 << fullCalibrationFileName;
91 }
92 stereoCalibration = visionx::tools::convert(ivtStereoCalibration);
93
94 renderImg_width = stereoCalibration->calibrationLeft.cameraParam.width;
95 renderImg_height = stereoCalibration->calibrationLeft.cameraParam.height;
96
97 ARMARX_CHECK_EQUAL(stereoCalibration->calibrationLeft.cameraParam.height,
99 ARMARX_CHECK_EQUAL(stereoCalibration->calibrationRight.cameraParam.height,
101 ARMARX_CHECK_EQUAL(stereoCalibration->calibrationLeft.cameraParam.width,
103 ARMARX_CHECK_EQUAL(stereoCalibration->calibrationRight.cameraParam.width,
105 }
106 else
107 {
108 const visionx::ImageDimension dimensions =
109 getProperty<visionx::ImageDimension>("ImageSize").getValue();
110
111 renderImg_width = dimensions.width;
112 renderImg_height = dimensions.height;
113 }
114
115 setImageFormat(visionx::ImageDimension{renderImg_width, renderImg_height}, visionx::eRgb);
116
117 renderImg_bpp = 3;
118
119
121 images = new CByteImage*[getNumberImages()];
122
123 for (int i = 0; i < getNumberImages(); i++)
124 {
125 images[i] = new CByteImage(renderImg_width, renderImg_height, CByteImage::eRGB24);
126 }
127
128 resizedImages = new CByteImage*[getNumberImages()];
129
130 for (int i = 0; i < getNumberImages(); i++)
131 {
132 resizedImages[i] =
134 }
135
136
137 std::stringstream svName;
138 svName << getName() << "_PhysicsWorldVisualization";
139 simVisu =
141 getArmarXManager()->addObject(simVisu);
142 }
143
144 void
146 {
147 if (images != NULL)
148 {
149 for (int i = 0; i < getNumberImages(); i++)
150 {
151 delete images[i];
152 delete resizedImages[i];
153 }
154
155 delete[] images;
156 delete[] resizedImages;
157
158 images = NULL;
159 }
160
161 rendererLeft.reset();
162 rendererRight.reset();
163
164 if (simVisu)
165 {
166 simVisu->releaseResources();
167 getArmarXManager()->removeObjectBlocking(simVisu);
168 }
169
170 simVisu = NULL;
171
172 SoDB::finish();
173 }
174
175 void
177 {
178 ARMARX_VERBOSE << "start capture";
179
180 // check nodes
181 robotName = getProperty<std::string>("RobotName").getValue();
182 leftNodeName = getProperty<std::string>("RobotNodeLeftCamera").getValue();
183 rightNodeName = getProperty<std::string>("RobotNodeRightCamera").getValue();
184 focalLength = getProperty<float>("focalLength").getValue();
185
186 // ensure that all data is loaded
187 if (simVisu)
188 {
189 simVisu->synchronizeVisualizationData();
190 }
191 while (!simVisu->getRobot(robotName))
192 {
193 usleep(100000);
194 simVisu->synchronizeVisualizationData();
195 ARMARX_INFO << deactivateSpam(3) << "Waiting for visu";
196 }
198 }
199
200 bool
202 const std::string& cameraSensorNameLeft,
203 const std::string& cameraSensorNameRight)
204 {
205 std::unique_lock lock(captureMutex);
206 auto l = simVisu->getScopedLock();
207
208 rendererLeft.reset(VirtualRobot::CoinVisualizationFactory::createOffscreenRenderer(
210 rendererRight.reset(VirtualRobot::CoinVisualizationFactory::createOffscreenRenderer(
212
213 // some checks...
214 if (!simVisu || !simVisu->getVisualization())
215 {
216 ARMARX_ERROR << "No physics visualization scene";
217 return false;
218 }
219
220 return true;
221 }
222
223 static void
224 copyRenderBufferToByteImage(CByteImage* image, std::uint8_t* renderBuffer)
225 {
226 int height = image->height;
227 int width = image->width;
228 std::uint8_t* pixelsRow = image->pixels;
229 std::uint8_t* renderBufferEndOfRow = renderBuffer + 3 * (width - 1);
230 for (int y = 0; y < height; y++)
231 {
232 for (int x = 0; x < width; x++)
233 {
234 pixelsRow[x * 3 + 0] = renderBufferEndOfRow[-x * 3 + 0];
235 pixelsRow[x * 3 + 1] = renderBufferEndOfRow[-x * 3 + 1];
236 pixelsRow[x * 3 + 2] = renderBufferEndOfRow[-x * 3 + 2];
237 }
238 pixelsRow += width * 3;
239 renderBufferEndOfRow += width * 3;
240 }
241 }
242
243 bool
245 {
246 auto l = simVisu->getScopedLock();
247
248 if (!simVisu || !simVisu->getRobot(robotName))
249 {
250 ARMARX_WARNING << deactivateSpam() << " no visu or no robot";
251 usleep(100000);
252 return false;
253 }
254
255 unsigned char* renderBuffer = NULL;
256 bool renderOK = false;
257
258
259 cameraNodeL = simVisu->getRobot(robotName)->getRobotNode(leftNodeName);
260 cameraNodeR = simVisu->getRobot(robotName)->getRobotNode(rightNodeName);
261
262 if (!rendererLeft || !cameraNodeL)
263 {
264 ARMARX_ERROR << deactivateSpam() << "No renderer Left, node:" << leftNodeName;
265 return false;
266 }
267
268 if (!rendererRight || !cameraNodeR)
269 {
270 ARMARX_ERROR << deactivateSpam() << "No renderer Right, node: " << rightNodeName;
271 return false;
272 }
273
274
275 if (not stereoCalibration.has_value())
276 {
278 }
279
280 float fovLeft =
281 2.0 * std::atan(renderImg_height /
282 (2.0 * stereoCalibration->calibrationLeft.cameraParam.focalLength[1]));
283 float fovRight =
284 2.0 * std::atan(renderImg_height /
285 (2.0 * stereoCalibration->calibrationRight.cameraParam.focalLength[1]));
286 // ARMARX_LOG << "fov left: " << (fovLeft / M_PI * 180.0) << " fov right: " << (fovRight / M_PI * 180.0);
287
288
289 // render Left Camera
290#if 1
291 renderOK =
292 VirtualRobot::CoinVisualizationFactory::renderOffscreen(rendererLeft.get(),
294 simVisu->getVisualization(),
295 &renderBuffer,
296 100.0f,
297 100000.0f,
298 fovLeft);
299#else
300 //////////////// optional: we render by our own
301 SoPerspectiveCamera* cam = new SoPerspectiveCamera();
302 cam->ref();
303 // set camera position and orientation
304 Eigen::Matrix4f camPose = cameraNodeL->getGlobalPose();
305 Eigen::Vector3f camPos = MathTools::getTranslation(camPose);
306 float sc = 0.001f; // to m
307 cam->position.setValue(camPos[0] * sc, camPos[1] * sc, camPos[2] * sc);
308
309 SbRotation align(
310 SbVec3f(1, 0, 0),
311 (float)(M_PI)); // first align from default direction -z to +z by rotating with 180 degree around x axis
312 SbRotation align2(
313 SbVec3f(0, 0, 1),
314 (float)(-M_PI / 2.0)); // align up vector by rotating with -90 degree around z axis
315 SbRotation trans(
316 CoinVisualizationFactory::getSbMatrix(camPose)); // get rotation from global pose
317 cam->orientation.setValue(align2 * align * trans); // perform total transformation
318
319 // 10cm to 100m
320 cam->nearDistance.setValue(0.01f);
321 cam->farDistance.setValue(10000.0f);
322
323 // add all to a inventor scene graph
324 SoSeparator* root = new SoSeparator();
325 root->ref();
326 SoDirectionalLight* light = new SoDirectionalLight;
327 root->addChild(light);
328
329 // easy light model, no shadows or something
330 //SoLightModel *lightModel = new SoLightModel();
331 //lightModel->model = SoLightModel::BASE_COLOR;
332 //root->addChild(lightModel);
333
334 root->addChild(cam);
335 root->addChild(simVisu->getVisualization());
336
337 renderOK = rendererLeft.get()->render(root) == TRUE ? true : false;
338 root->unref();
339
340 // get render buffer pointer
341 renderBuffer = rendererLeft.get()->getBuffer();
342 cam->unref();
343
344#endif
345
346
347 if (renderOK && renderBuffer != NULL)
348 {
349 copyRenderBufferToByteImage(images[0], renderBuffer);
350 }
351
352
353 // render Right Camera
354 renderOK =
355 VirtualRobot::CoinVisualizationFactory::renderOffscreen(rendererRight.get(),
357 simVisu->getVisualization(),
358 &renderBuffer,
359 100.0f,
360 100000.0f,
361 fovRight);
362
363 if (renderOK && renderBuffer != NULL)
364 {
365 copyRenderBufferToByteImage(images[1], renderBuffer);
366 }
367
368 return true;
369 }
370
371 void
376
377 bool
379 {
380 bool succeeded = true;
381
382 try
383 {
384 simVisu->synchronizeVisualizationData();
385
386 {
387 std::unique_lock lock(captureMutex);
388 succeeded = updateCameraRendering();
389 }
390 }
391 catch (...)
392 {
394 }
395
396 if (succeeded)
397 {
398 try
399 {
401 {
402 ARMARX_WARNING << "Shared memory provider is null (possibly shutting down)";
403 return false;
404 }
406
407 for (int i = 0; i < getNumberImages(); i++)
408 {
409 ::ImageProcessor::Resize(images[i], resizedImages[i]);
410
411 memcpy(ppImageBuffers[i],
412 resizedImages[i]->pixels,
413 getImageFormat().dimension.width * getImageFormat().dimension.height *
414 getImageFormat().bytesPerPixel);
415 }
416 }
417 catch (...)
418 {
420 }
421 }
422
423
424 return succeeded;
425 }
426
427 void
429 {
430
431
432 CCalibration leftCalibration;
433 leftCalibration.SetCameraParameters(focalLength,
435 renderImg_width / 2,
437 0,
438 0,
439 0,
440 0,
441 Math3d::unit_mat,
442 Math3d::zero_vec,
445
447 while (!simVisu->getRobot(robotName))
448 {
449 usleep(100000);
450 simVisu->synchronizeVisualizationData();
451 ARMARX_INFO << deactivateSpam(3) << "Waiting for visu";
452 }
453
454 ARMARX_CHECK(simVisu->synchronizeVisualizationData());
455 auto robot = simVisu->getRobot(robotName);
457
458 cameraNodeL = robot->getRobotNode(leftNodeName);
459 cameraNodeR = robot->getRobotNode(rightNodeName);
460
463
464 const Eigen::Vector3f left_P_right = cameraNodeR->getPositionInFrame(cameraNodeL);
465 ARMARX_IMPORTANT << VAROUT(left_P_right);
466
467 CCalibration rightCalibration;
468 Vec3d transRight{-left_P_right.x(), 0, 0};
469 rightCalibration.SetCameraParameters(focalLength,
471 renderImg_width / 2,
473 0,
474 0,
475 0,
476 0,
477 Math3d::unit_mat,
478 transRight,
481
482 CStereoCalibration ivtStereoCalibration;
483 ivtStereoCalibration.SetSingleCalibrations(leftCalibration, rightCalibration);
484 stereoCalibration = visionx::tools::convert(ivtStereoCalibration);
485 }
486
487 visionx::StereoCalibration
489 {
490 if (not stereoCalibration.has_value())
491 {
493 }
494
495 return stereoCalibration.value();
496 }
497
498 bool
500 {
501 return true;
502 }
503
504 std::string
506 {
507 return getProperty<std::string>("ReferenceFrame").getValue();
508 }
509
510 std::string
512 {
513 return "ImageProviderDynamicSimulation";
514 }
515
517
518} // namespace armarx
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
Definition Decoupled.h:29
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)
constexpr T c
static bool getAbsolutePath(const std::string &relativeFilename, std::string &storeAbsoluteFilename, const std::vector< std::string > &additionalSearchPaths={}, bool verbose=true)
static TPtr create(Ice::PropertiesPtr properties=Ice::createProperties(), const std::string &configName="", const std::string &configDomain="ArmarX")
Factory method for a component.
Definition Component.h:116
Property< PropertyType > getProperty(const std::string &name)
Image provider captures images from the simulator and broadcasts notifications at a specified frame r...
visionx::StereoCalibration getStereoCalibration(const Ice::Current &c=Ice::emptyCurrent) override
Returns the StereoCalibration as provided in configuration.
bool setupCameraRendering(const std::string &robotName, const std::string &cameraSensorNameLeft, const std::string &cameraSensorNameRight)
std::optional< visionx::StereoCalibration > stereoCalibration
std::shared_ptr< SoOffscreenRenderer > rendererRight
bool getImagesAreUndistorted(const Ice::Current &c=Ice::emptyCurrent) override
Returns whether images are undistorted.
std::string getReferenceFrame(const ::Ice::Current &=Ice::emptyCurrent) override
std::shared_ptr< SoOffscreenRenderer > rendererLeft
std::string getName() const
Retrieve name of object.
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
Ice::PropertiesPtr getIceProperties() const
Returns the set of Ice properties.
void setImageSyncMode(ImageSyncMode imageSyncMode)
Sets the image synchronization mode.
armarx::SharedMemoryScopedWriteLockPtr getScopedWriteLock()
Retrieve scoped lock for writing to the memory.
armarx::IceSharedMemoryProvider< unsignedchar >::pointer_type sharedMemoryProvider
shared memory provider
ImageFormatInfo getImageFormat(const Ice::Current &c=Ice::emptyCurrent) override
Returns the entire image format info struct via Ice.
void setImageFormat(ImageDimension imageDimension, ImageType imageType, BayerPatternType bayerPatternType=visionx::eBayerPatternRg)
Sets the image basic format data.
int getNumberImages(const Ice::Current &c=Ice::emptyCurrent) override
Retrieve number of images handled by this provider.
void setNumberImages(int numberImages)
Sets the number of images on each capture.
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#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_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#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.
std::shared_ptr< SharedMemoryScopedWriteLock > SharedMemoryScopedWriteLockPtr
void handleExceptions()
void * align(size_t alignment, size_t bytes, void *&bufferPlace, size_t &bufferSpace) noexcept
CByteImage * createByteImage(const ImageFormatInfo &imageFormat, const ImageType imageType)
Creates a ByteImage for the destination type specified in the given imageProviderInfo.
CByteImage::ImageType convert(const ImageType visionxImageType)
Converts a VisionX image type into an image type of IVT's ByteImage.