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
32
33// VisionXCore
36
37// VisionXTools
41
43#include <Calibration/Calibration.h>
44#include <Inventor/SoInteraction.h>
45#include <Inventor/SoOffscreenRenderer.h>
46#include <Inventor/nodes/SoDirectionalLight.h>
47#include <Inventor/nodes/SoUnits.h>
48#include <Math/Math3d.h>
49
50namespace armarx
51{
52 void
54 {
55 // init SoDB / Coin3D
56 //SoDB::init();
57
58 ARMARX_INFO << "1";
59
60 VirtualRobot::init(this->getName());
61
62 // needed for SoSelection
63 SoInteraction::init();
64
65 // image format
66 setImageSyncMode(visionx::eFpsSynchronization);
67 frameRate = getProperty<float>("FrameRate").getValue();
68
69 std::string calibrationFileName = getProperty<std::string>("CalibrationFile").getValue();
70 ARMARX_VERBOSE << "Camera calibration file: " << calibrationFileName;
71
72 if (!calibrationFileName.empty())
73 {
74 std::string fullCalibrationFileName;
75
76 if (!ArmarXDataPath::getAbsolutePath(calibrationFileName, fullCalibrationFileName))
77 {
78 ARMARX_ERROR << "Could not find camera calibration file in ArmarXDataPath: "
79 << calibrationFileName;
80 }
81
82 setlocale(LC_NUMERIC, "C");
83
84 CStereoCalibration ivtStereoCalibration;
85
86 if (!ivtStereoCalibration.LoadCameraParameters(fullCalibrationFileName.c_str(), true))
87 {
88 ARMARX_ERROR << "Error loading camera calibration file: "
89 << fullCalibrationFileName;
90 }
91 stereoCalibration = visionx::tools::convert(ivtStereoCalibration);
92
93 renderImg_width = stereoCalibration->calibrationLeft.cameraParam.width;
94 renderImg_height = stereoCalibration->calibrationLeft.cameraParam.height;
95
96 ARMARX_CHECK_EQUAL(stereoCalibration->calibrationLeft.cameraParam.height,
98 ARMARX_CHECK_EQUAL(stereoCalibration->calibrationRight.cameraParam.height,
100 ARMARX_CHECK_EQUAL(stereoCalibration->calibrationLeft.cameraParam.width,
102 ARMARX_CHECK_EQUAL(stereoCalibration->calibrationRight.cameraParam.width,
104 }
105 else
106 {
107 const visionx::ImageDimension dimensions =
108 getProperty<visionx::ImageDimension>("ImageSize").getValue();
109
110 renderImg_width = dimensions.width;
111 renderImg_height = dimensions.height;
112 }
113
114 setImageFormat(visionx::ImageDimension{renderImg_width, renderImg_height}, visionx::eRgb);
115
116 renderImg_bpp = 3;
117
118
120 images = new CByteImage*[getNumberImages()];
121
122 for (int i = 0; i < getNumberImages(); i++)
123 {
124 images[i] = new CByteImage(renderImg_width, renderImg_height, CByteImage::eRGB24);
125 }
126
127 resizedImages = new CByteImage*[getNumberImages()];
128
129 for (int i = 0; i < getNumberImages(); i++)
130 {
131 resizedImages[i] =
133 }
134
135
136 std::stringstream svName;
137 svName << getName() << "_PhysicsWorldVisualization";
138 simVisu =
140 getArmarXManager()->addObject(simVisu);
141 }
142
143 void
145 {
146 if (images != NULL)
147 {
148 for (int i = 0; i < getNumberImages(); i++)
149 {
150 delete images[i];
151 delete resizedImages[i];
152 }
153
154 delete[] images;
155 delete[] resizedImages;
156
157 images = NULL;
158 }
159
160 rendererLeft.reset();
161 rendererRight.reset();
162
163 if (simVisu)
164 {
165 simVisu->releaseResources();
166 getArmarXManager()->removeObjectBlocking(simVisu);
167 }
168
169 simVisu = NULL;
170
171 SoDB::finish();
172 }
173
174 void
176 {
177 ARMARX_VERBOSE << "start capture";
178
179 // check nodes
180 robotName = getProperty<std::string>("RobotName").getValue();
181 leftNodeName = getProperty<std::string>("RobotNodeLeftCamera").getValue();
182 rightNodeName = getProperty<std::string>("RobotNodeRightCamera").getValue();
183 focalLength = getProperty<float>("focalLength").getValue();
184
185 // ensure that all data is loaded
186 if (simVisu)
187 {
188 simVisu->synchronizeVisualizationData();
189 }
190 while (!simVisu->getRobot(robotName))
191 {
192 usleep(100000);
193 simVisu->synchronizeVisualizationData();
194 ARMARX_INFO << deactivateSpam(3) << "Waiting for visu";
195 }
197 }
198
199 bool
201 const std::string& cameraSensorNameLeft,
202 const std::string& cameraSensorNameRight)
203 {
204 std::unique_lock lock(captureMutex);
205 auto l = simVisu->getScopedLock();
206
207 rendererLeft.reset(VirtualRobot::CoinVisualizationFactory::createOffscreenRenderer(
209 rendererRight.reset(VirtualRobot::CoinVisualizationFactory::createOffscreenRenderer(
211
212 // some checks...
213 if (!simVisu || !simVisu->getVisualization())
214 {
215 ARMARX_ERROR << "No physics visualization scene";
216 return false;
217 }
218
219 return true;
220 }
221
222 static void
223 copyRenderBufferToByteImage(CByteImage* image, std::uint8_t* renderBuffer)
224 {
225 int height = image->height;
226 int width = image->width;
227 std::uint8_t* pixelsRow = image->pixels;
228 std::uint8_t* renderBufferEndOfRow = renderBuffer + 3 * (width - 1);
229 for (int y = 0; y < height; y++)
230 {
231 for (int x = 0; x < width; x++)
232 {
233 pixelsRow[x * 3 + 0] = renderBufferEndOfRow[-x * 3 + 0];
234 pixelsRow[x * 3 + 1] = renderBufferEndOfRow[-x * 3 + 1];
235 pixelsRow[x * 3 + 2] = renderBufferEndOfRow[-x * 3 + 2];
236 }
237 pixelsRow += width * 3;
238 renderBufferEndOfRow += width * 3;
239 }
240 }
241
242 bool
244 {
245 auto l = simVisu->getScopedLock();
246
247 if (!simVisu || !simVisu->getRobot(robotName))
248 {
249 ARMARX_WARNING << deactivateSpam() << " no visu or no robot";
250 usleep(100000);
251 return false;
252 }
253
254 unsigned char* renderBuffer = NULL;
255 bool renderOK = false;
256
257
258 cameraNodeL = simVisu->getRobot(robotName)->getRobotNode(leftNodeName);
259 cameraNodeR = simVisu->getRobot(robotName)->getRobotNode(rightNodeName);
260
261 if (!rendererLeft || !cameraNodeL)
262 {
263 ARMARX_ERROR << deactivateSpam() << "No renderer Left, node:" << leftNodeName;
264 return false;
265 }
266
267 if (!rendererRight || !cameraNodeR)
268 {
269 ARMARX_ERROR << deactivateSpam() << "No renderer Right, node: " << rightNodeName;
270 return false;
271 }
272
273
274 if (not stereoCalibration.has_value())
275 {
277 }
278
279 float fovLeft =
280 2.0 * std::atan(renderImg_height /
281 (2.0 * stereoCalibration->calibrationLeft.cameraParam.focalLength[1]));
282 float fovRight =
283 2.0 * std::atan(renderImg_height /
284 (2.0 * stereoCalibration->calibrationRight.cameraParam.focalLength[1]));
285 // ARMARX_LOG << "fov left: " << (fovLeft / M_PI * 180.0) << " fov right: " << (fovRight / M_PI * 180.0);
286
287
288 // render Left Camera
289#if 1
290 renderOK =
291 VirtualRobot::CoinVisualizationFactory::renderOffscreen(rendererLeft.get(),
293 simVisu->getVisualization(),
294 &renderBuffer,
295 100.0f,
296 100000.0f,
297 fovLeft);
298#else
299 //////////////// optional: we render by our own
300 SoPerspectiveCamera* cam = new SoPerspectiveCamera();
301 cam->ref();
302 // set camera position and orientation
303 Eigen::Matrix4f camPose = cameraNodeL->getGlobalPose();
304 Eigen::Vector3f camPos = MathTools::getTranslation(camPose);
305 float sc = 0.001f; // to m
306 cam->position.setValue(camPos[0] * sc, camPos[1] * sc, camPos[2] * sc);
307
308 SbRotation align(
309 SbVec3f(1, 0, 0),
310 (float)(M_PI)); // first align from default direction -z to +z by rotating with 180 degree around x axis
311 SbRotation align2(
312 SbVec3f(0, 0, 1),
313 (float)(-M_PI / 2.0)); // align up vector by rotating with -90 degree around z axis
314 SbRotation trans(
315 CoinVisualizationFactory::getSbMatrix(camPose)); // get rotation from global pose
316 cam->orientation.setValue(align2 * align * trans); // perform total transformation
317
318 // 10cm to 100m
319 cam->nearDistance.setValue(0.01f);
320 cam->farDistance.setValue(10000.0f);
321
322 // add all to a inventor scene graph
323 SoSeparator* root = new SoSeparator();
324 root->ref();
325 SoDirectionalLight* light = new SoDirectionalLight;
326 root->addChild(light);
327
328 // easy light model, no shadows or something
329 //SoLightModel *lightModel = new SoLightModel();
330 //lightModel->model = SoLightModel::BASE_COLOR;
331 //root->addChild(lightModel);
332
333 root->addChild(cam);
334 root->addChild(simVisu->getVisualization());
335
336 renderOK = rendererLeft.get()->render(root) == TRUE ? true : false;
337 root->unref();
338
339 // get render buffer pointer
340 renderBuffer = rendererLeft.get()->getBuffer();
341 cam->unref();
342
343#endif
344
345
346 if (renderOK && renderBuffer != NULL)
347 {
348 copyRenderBufferToByteImage(images[0], renderBuffer);
349 }
350
351
352 // render Right Camera
353 renderOK =
354 VirtualRobot::CoinVisualizationFactory::renderOffscreen(rendererRight.get(),
356 simVisu->getVisualization(),
357 &renderBuffer,
358 100.0f,
359 100000.0f,
360 fovRight);
361
362 if (renderOK && renderBuffer != NULL)
363 {
364 copyRenderBufferToByteImage(images[1], renderBuffer);
365 }
366
367 return true;
368 }
369
370 void
375
376 bool
378 {
379 bool succeeded = true;
380
381 try
382 {
383 simVisu->synchronizeVisualizationData();
384
385 {
386 std::unique_lock lock(captureMutex);
387 succeeded = updateCameraRendering();
388 }
389 }
390 catch (...)
391 {
393 }
394
395 if (succeeded)
396 {
397 try
398 {
400 {
401 ARMARX_WARNING << "Shared memory provider is null (possibly shutting down)";
402 return false;
403 }
405
406 for (int i = 0; i < getNumberImages(); i++)
407 {
408 ::ImageProcessor::Resize(images[i], resizedImages[i]);
409
410 memcpy(ppImageBuffers[i],
411 resizedImages[i]->pixels,
412 getImageFormat().dimension.width * getImageFormat().dimension.height *
413 getImageFormat().bytesPerPixel);
414 }
415 }
416 catch (...)
417 {
419 }
420 }
421
422
423 return succeeded;
424 }
425
426 void
428 {
429
430
431 CCalibration leftCalibration;
432 leftCalibration.SetCameraParameters(focalLength,
434 renderImg_width / 2,
436 0,
437 0,
438 0,
439 0,
440 Math3d::unit_mat,
441 Math3d::zero_vec,
444
446 while (!simVisu->getRobot(robotName))
447 {
448 usleep(100000);
449 simVisu->synchronizeVisualizationData();
450 ARMARX_INFO << deactivateSpam(3) << "Waiting for visu";
451 }
452
453 ARMARX_CHECK(simVisu->synchronizeVisualizationData());
454 auto robot = simVisu->getRobot(robotName);
456
457 cameraNodeL = robot->getRobotNode(leftNodeName);
458 cameraNodeR = robot->getRobotNode(rightNodeName);
459
462
463 const Eigen::Vector3f left_P_right = cameraNodeR->getPositionInFrame(cameraNodeL);
464 ARMARX_IMPORTANT << VAROUT(left_P_right);
465
466 CCalibration rightCalibration;
467 Vec3d transRight{-left_P_right.x(), 0, 0};
468 rightCalibration.SetCameraParameters(focalLength,
470 renderImg_width / 2,
472 0,
473 0,
474 0,
475 0,
476 Math3d::unit_mat,
477 transRight,
480
481 CStereoCalibration ivtStereoCalibration;
482 ivtStereoCalibration.SetSingleCalibrations(leftCalibration, rightCalibration);
483 stereoCalibration = visionx::tools::convert(ivtStereoCalibration);
484 }
485
486 visionx::StereoCalibration
488 {
489 if (not stereoCalibration.has_value())
490 {
492 }
493
494 return stereoCalibration.value();
495 }
496
497 bool
499 {
500 return true;
501 }
502
503 std::string
505 {
506 return getProperty<std::string>("ReferenceFrame").getValue();
507 }
508
509} // 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)
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)
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.