ObjectLocalizerProcessor.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 VisionX::Component
19 * @author Kai Welke (welke at kit dot edu)
20 * @date 2013
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
26
27// VisionXInterface
28#include <VisionX/interface/components/PointCloudAndImageAndCalibrationProviderInterface.h>
29#include <VisionX/interface/core/DataTypes.h>
30
31// VisionXTools
33
35
36// MemoryX
42
43// ArmarXCore
45
46// IVT
47#include "Calibration/Calibration.h"
48
49namespace visionx
50{
51
53 resultImagesEnabled(true), imagesAreUndistorted(false), numberOfResultImages(2), job(this)
54 {
57 }
58
59 void
61 {
62 ARMARX_VERBOSE << "Number of result images: " << numberOfResultImages;
63 resultImagesData.clear();
65 // HACK: boost::ptr_vector::c_array() is broken if the value type is nullable (check in new boost version)
66 void* firstEntry = &resultImagesData.begin().base()[0];
67 resultImages = static_cast<CByteImage**>(firstEntry);
68
69 // get properties
70 priorKnowledgeProxyName = getProperty<std::string>("PriorKnowledgeProxyName").getValue();
71 imageProviderName = getProperty<std::string>("ImageProviderName").getValue();
72
73 resultImagesEnabled = getProperty<bool>("EnableResultImages").getValue();
74
75 useResultImageMask = getProperty<bool>("useResultImageMask").getValue();
76 colorMask = getProperty<Eigen::Vector3i>("colorMask").getValue();
77
78 // setup proxy
81 usingTopic(getProperty<std::string>("CalibrationUpdateTopicName").getValue());
82
83 // setup noise
84 imageNoiseLeft(0) = imageNoiseLeft(1) =
85 getProperty<float>("2DLocalizationNoise").getValue();
86 imageNoiseRight(0) = imageNoiseRight(1) =
87 getProperty<float>("2DLocalizationNoise").getValue();
88
89 // subclass initialization
91 }
92
93 void
95 {
96 // retrieve proxies and required parameters
97 ImageProviderInfo imageProviderInfo = getImageProvider(imageProviderName, visionx::eRgb);
98 imageFormat = imageProviderInfo.imageFormat;
99
101
102 // retrieve stereo information
103
104 StereoCalibrationInterfacePrx calibrationProvider =
105 StereoCalibrationInterfacePrx::checkedCast(imageProviderPrx);
106
107 if (calibrationProvider)
108 {
109 stereoCalibration.reset(
110 visionx::tools::convert(calibrationProvider->getStereoCalibration()));
111 imagesAreUndistorted = calibrationProvider->getImagesAreUndistorted();
112 referenceFrameName = calibrationProvider->getReferenceFrame();
113 }
114
115 else
116 {
117 ARMARX_ERROR << "Unable to get calibration data. The image provider is not a "
118 "StereoCalibrationProvider";
119 }
120
121
122 if (resultImagesEnabled)
123 {
124 ARMARX_INFO << "Enabeling Visualization with " << numberOfResultImages << " images."
125 << std::endl;
128 ImageDimension(imageFormat.dimension.width, imageFormat.dimension.height),
129 visionx::eRgb);
130 }
131 job.reset();
132 setupImages(imageFormat.dimension.width, imageFormat.dimension.height);
133
135 }
136
137 void
138 ObjectLocalizerProcessor::initObjectClasses()
139 {
140 ARMARX_VERBOSE_S << "Initializing object classes";
141
142 // init proxies
144 classesSegmentPrx = priorKnowledgePrx->getObjectClassesSegment();
145 databasePrx = priorKnowledgePrx->getCommonStorage();
146
147 fileManager.reset(new memoryx::GridFileManager(databasePrx));
148
149 // retrieve object classes suitable for this recognizer type
150 memoryx::CollectionInterfacePrx coll = databasePrx->requestCollection(
151 getProperty<std::string>("DataBaseObjectCollectionName").getValue());
152 classesSegmentPrx->addReadCollection(coll);
153 // classesSegmentPrx->setWriteCollection(coll);
154
155 memoryx::EntityIdList idList = classesSegmentPrx->getAllEntityIds();
156
157 ARMARX_INFO << "Found " << idList.size() << " object classes in the class segments: "
158 << classesSegmentPrx->getReadCollectionsNS();
159
160 int classesUsed = 0;
161
162 for (memoryx::EntityIdList::iterator iter = idList.begin(); iter != idList.end(); iter++)
163 {
164 memoryx::EntityPtr entity =
165 memoryx::EntityPtr::dynamicCast(classesSegmentPrx->getEntityById(*iter));
166
167 if (!entity)
168 {
169 ARMARX_IMPORTANT << "RECEIVED NULL Entity";
170 continue;
171 }
172
175
176 if (recognitionWrapper->getRecognitionMethod() == getName())
177 {
178 if (addObjectClass(entity, fileManager))
179 {
180 std::string className = entity->getName();
181 ARMARX_INFO << "Adding class " << className << " to " << getDefaultName();
182 classesUsed++;
183 }
184 }
185 }
186
187 ARMARX_INFO << getDefaultName() << " is available using " << classesUsed
188 << " object classes";
189 }
190
191 memoryx::ObjectLocalizationResultList
193 const memoryx::ObjectClassNameList& objectClassNames,
194 const Ice::Current& c)
195 {
196 // assure processor thread is started and ManagedIceObject is fully connected
197 // getObjectScheduler()->waitForObjectState(eManagedIceObjectStarted);
198 memoryx::ObjectLocalizationResultList result;
199
200 // start localization job in a separate thread
201 try
202 {
203 job.start(objectClassNames);
204 result = job.waitForResult();
205 }
206 catch (std::exception& e)
207 {
209 }
210
211 return result;
212 }
213
214 void
216 {
217 job.process();
218 }
219
222 {
223 // initialize noise
225
226 Eigen::MatrixXd combinedNoise(4, 4);
227 combinedNoise.setZero();
228 combinedNoise(0, 0) = imageNoiseLeft(0);
229 combinedNoise(1, 1) = imageNoiseLeft(1);
230 combinedNoise(2, 2) = imageNoiseRight(0);
231 combinedNoise(3, 3) = imageNoiseRight(1);
232
233 Eigen::VectorXd mean(4);
234 mean << left_point.x, left_point.y, right_point.x, right_point.y;
235
236 Gaussian imageSpaceNoise(4);
237 imageSpaceNoise.setCovariance(combinedNoise);
238 imageSpaceNoise.setMean(mean);
239
240 // calculate sigma points
241 Eigen::MatrixXd sigmapoints = ut.getSigmaPoints(imageSpaceNoise);
242
243 // pass sigma points through system
244 Vec2d l, r;
245 Vec3d w;
246 Eigen::VectorXd base(4);
247 Eigen::VectorXd world(4);
248
249 Eigen::MatrixXd processedpoints(3, sigmapoints.cols());
250
251 for (int n = 0; n < sigmapoints.cols(); n++)
252 {
253
254 Math2d::SetVec(l, sigmapoints(0, n), sigmapoints(1, n));
255 Math2d::SetVec(r, sigmapoints(2, n), sigmapoints(3, n));
256
257 // calc 3d point (2D points are rectified but not distorted)
258 stereoCalibration->Calculate3DPoint(l, r, w, true, true);
259 world << w.x, w.y, w.z, 1.0f;
260
261 processedpoints(0, n) = world(0);
262 processedpoints(1, n) = world(1);
263 processedpoints(2, n) = world(2);
264 }
265
266 // recover covariance
267 Gaussian worldSpaceNoise = ut.extractGaussian(processedpoints);
268
269 // manual hack: avoid underestimation of noise
270 worldSpaceNoise.setCovariance(4.0f * worldSpaceNoise.getCovariance());
271
273 }
274
277 {
278 // calculate 2d points for localization uncerainty
279 Vec2d left2d, right2d;
280 Vec3d pos;
281 Math3d::SetVec(pos, position(0), position(1), position(2));
282
283 getStereoCalibration()->GetLeftCalibration()->WorldToImageCoordinates(pos, left2d);
284 getStereoCalibration()->GetRightCalibration()->WorldToImageCoordinates(pos, right2d);
285
286 // transform to rectified coordinates
287 Mat3d inverseHLeft, inverseHRight;
288 Math3d::Invert(getStereoCalibration()->rectificationHomographyLeft, inverseHLeft);
289 Math3d::Invert(getStereoCalibration()->rectificationHomographyRight, inverseHRight);
290 Math2d::ApplyHomography(inverseHLeft, left2d, left2d);
291 Math2d::ApplyHomography(inverseHRight, right2d, right2d);
292
293 return calculateLocalizationUncertainty(left2d, right2d);
294 }
295
296 void
297 ObjectLocalizerProcessor::setupImages(int width, int height)
298 {
299 ARMARX_IMPORTANT << "Setting up images";
300
301 for (CByteImage& cameraImage : cameraImagesData)
302 {
303 cameraImage.Set(width, height, CByteImage::eRGB24);
304 }
305
306 for (int i = 0; i < numberOfResultImages; i++)
307 {
308 resultImagesData.replace(i, new CByteImage(width, height, CByteImage::eRGB24));
309 }
310 }
311} // namespace visionx
constexpr T c
const covariance_type & getCovariance() const
Definition Gaussian.h:82
void setCovariance(const covariance_type &cov)
Definition Gaussian.cpp:272
void setMean(const value_type &mean)
Definition Gaussian.cpp:255
Gaussian extractGaussian(Eigen::MatrixXd processedSigmaPoints)
Eigen::MatrixXd getSigmaPoints(const Gaussian &gaussian)
Property< PropertyType > getProperty(const std::string &name)
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
virtual std::string getDefaultName() const =0
Retrieve default name of component.
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
std::string getName() const
Retrieve name of object.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
GridFileManager provides utility functions for working with files in Mongo GridFS and links to them s...
void enableResultImages(int numberImages, ImageDimension imageDimension, ImageType imageType, const std::string &name="")
Enables visualization.
void usingImageProvider(std::string name)
Registers a delayed topic subscription and a delayed provider proxy retrieval which all will be avail...
ImageProviderInfo getImageProvider(std::string name, ImageType destinationImageType=eRgb, bool waitForProxy=false)
Select an ImageProvider.
ImageFormatInfo imageFormat
Image format struct that contains all necessary image information.
void onConnectImageProcessor() override
Called from framework.
virtual void onConnectObjectLocalizerProcessor()
ObjectLocalizerProcessor interface: subclass hook.
void process() override
The process method is inherited from ImageProcessor.
memoryx::ObjectLocalizationResultList localizeObjectClasses(const memoryx::ObjectClassNameList &objectClassNames, const Ice::Current &c=Ice::emptyCurrent) override
The process method is inherited from the ObjectLocalizationProcessorInterface and is called by the Wo...
void onInitImageProcessor() override
Called from framework.
boost::ptr_vector< boost::nullable< CByteImage > > resultImagesData
virtual void onInitObjectLocalizerProcessor()
ObjectLocalizerProcessor interface: subclass hook.
virtual bool addObjectClass(const memoryx::EntityPtr &objectClassEntity, const memoryx::GridFileManagerPtr &fileManager)=0
ObjectLocalizerProcessor interface: The addObjectClass method needs to be implemented by any ObjectLo...
memoryx::MultivariateNormalDistributionPtr calculateLocalizationUncertainty(Vec2d left_point, Vec2d right_point)
Calculate 3D uncertainty from two 2d points in left and right camera.
CStereoCalibration * getStereoCalibration() const
Retrieve stereo calibration corresponding to image provider.
#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_VERBOSE_S
Definition Logging.h:207
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
void handleExceptions()
MultivariateNormalDistributionPtr convertToMemoryX_MULTI(const Gaussian &gaussian)
IceInternal::Handle< ObjectRecognitionWrapper > ObjectRecognitionWrapperPtr
IceInternal::Handle< MultivariateNormalDistribution > MultivariateNormalDistributionPtr
IceInternal::Handle< Entity > EntityPtr
Typedef of EntityPtr as IceInternal::Handle<Entity> for convenience.
Definition Entity.h:45
CByteImage::ImageType convert(const ImageType visionxImageType)
Converts a VisionX image type into an image type of IVT's ByteImage.
ArmarX headers.