ArMarkerLocalizer.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 David Schiebener (schiebener at kit dot edu)
20 * @date 2015
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
25#include "ArMarkerLocalizer.h"
26
27#include <opencv2/calib3d.hpp>
28
29// RobotState
31
32// MemoryX
35
36// IVT
37#include <math.h>
38
40
41#include <Calibration/Calibration.h>
42#include <Image/IplImageAdaptor.h>
43
44using namespace armarx;
45using namespace ::visionx;
46using namespace memoryx;
47using namespace memoryx::EntityWrappers;
48
51{
52 defineOptionalProperty<float>("MarkerSize", 40.0, "The side length of the marker(s)");
54 "ReferenceFrameName", "DepthCamera", "Name of the ReferenceFrameName");
55 defineOptionalProperty<std::string>("AgentName", "Armar6", "name of the agent");
57 "ImageProviderName", "ImageProvider", "name of the image provider to use");
58}
59
62{
65
66 defs->optional(visuEnabled, "visu.enabled", "If true, visualize marker position.");
67
68 return defs;
69}
70
71std::string
73{
74 return "ArMarkerLocalizer";
75}
76
77void
79{
80 imageProviderName = getProperty<std::string>("ImageProviderName").getValue();
81}
82
83void
85{
86 markerSize = getProperty<float>("MarkerSize").getValue();
87 ARMARX_VERBOSE << "markerSize: " << markerSize;
88
89 visionx::ImageProviderInfo imageProviderInfo = getImageProvider(imageProviderName);
90 StereoCalibrationInterfacePrx calibrationProvider =
91 StereoCalibrationInterfacePrx::checkedCast(imageProviderInfo.proxy);
92
93 std::unique_ptr<CStereoCalibration> stereoCalibration(
94 visionx::tools::convert(calibrationProvider->getStereoCalibration()));
95 CCalibration::CCameraParameters ivtCameraParameters =
96 stereoCalibration->GetLeftCalibration()->GetCameraParameters();
97 cv::Mat cameraMatrix(3, 3, cv::DataType<float>::type);
98 cameraMatrix.at<float>(0, 0) = ivtCameraParameters.focalLength.x;
99 cameraMatrix.at<float>(0, 1) = 0;
100 cameraMatrix.at<float>(0, 2) = ivtCameraParameters.principalPoint.x;
101 cameraMatrix.at<float>(1, 0) = 0;
102 cameraMatrix.at<float>(1, 1) = ivtCameraParameters.focalLength.y;
103 cameraMatrix.at<float>(1, 2) = ivtCameraParameters.principalPoint.y;
104 cameraMatrix.at<float>(2, 0) = 0;
105 cameraMatrix.at<float>(2, 1) = 0;
106 cameraMatrix.at<float>(2, 2) = 1;
107 ARMARX_VERBOSE << "cameraMatrix: " << cameraMatrix;
108 cv::Mat distortionParameters(4, 1, cv::DataType<float>::type);
109
110 if (!calibrationProvider->getImagesAreUndistorted())
111 {
112 distortionParameters.at<float>(0, 0) = ivtCameraParameters.distortion[0];
113 distortionParameters.at<float>(1, 0) = ivtCameraParameters.distortion[1];
114 distortionParameters.at<float>(2, 0) = ivtCameraParameters.distortion[2];
115 distortionParameters.at<float>(3, 0) = ivtCameraParameters.distortion[3];
116 }
117 else
118 {
119 distortionParameters.at<float>(0, 0) = distortionParameters.at<float>(1, 0) =
120 distortionParameters.at<float>(2, 0) = distortionParameters.at<float>(3, 0) = 0;
121 }
122
123 cv::Size imageSize;
124 imageSize.width = ivtCameraParameters.width;
125 imageSize.height = ivtCameraParameters.height;
126 arucoCameraParameters.setParams(cameraMatrix, distortionParameters, imageSize);
127 //markerDetector.setCornerRefinementMethod(aruco::MarkerDetector::CornerRefinementMethod::NONE);
128
129 startingTime = IceUtil::Time::now();
130
131 cameraImages = new CByteImage*[2];
132
133 cameraImages[0] = tools::createByteImage(imageProviderInfo);
134 cameraImages[1] = tools::createByteImage(imageProviderInfo);
135
138}
139
140void
142{
143 if (!waitForImages(500))
144 {
145 ARMARX_WARNING << "Timeout or error in wait for images";
146 return;
147 }
148 getImages(cameraImages);
149
150 ArMarkerLocalizationResultList result = localizeAllMarkersInternal();
151 {
152 std::unique_lock lock(resultMutex);
153 lastLocalizationResult = result;
154 }
155 if (visuEnabled)
156 {
157 viz::Layer layer = arviz.layer("Marker Poses");
158
159 for (const auto& r : result)
160 {
161 layer.add(viz::Pose(std::to_string(r.id))
162 .pose(FramedPosePtr::dynamicCast(r.pose)->toEigen()));
163 }
164
165 arviz.commit(layer);
166 }
167}
168
169ArMarkerLocalizationResultList
170ArMarkerLocalizer::localizeAllMarkersInternal()
171{
172 IplImage* imageIpl = IplImageAdaptor::Adapt(cameraImages[0]);
173 cv::Mat imageOpenCV = cv::cvarrToMat(imageIpl);
174
175 ARMARX_VERBOSE << "Calling marker detector";
176 std::vector<aruco::Marker> markers;
177 markerDetector.detect(imageOpenCV, markers, arucoCameraParameters, markerSize);
178
179 ARMARX_INFO << deactivateSpam() << "Localized " << markers.size()
180 << " markers: " << ARMARX_STREAM_PRINTER
181 {
182 for (const auto& m : markers)
183 {
184 out << m.id << " ";
185 }
186 };
187
188
189 std::string refFrame = getProperty<std::string>("ReferenceFrameName").getValue();
190 const auto agentName = getProperty<std::string>("AgentName").getValue();
191
192 visionx::ArMarkerLocalizationResultList resultList;
193
194 for (aruco::Marker marker : markers)
195 {
196 // assemble result
197 visionx::ArMarkerLocalizationResult result;
198
199 // position and orientation
200 marker.calculateExtrinsics(
201 markerSize, arucoCameraParameters.CameraMatrix, arucoCameraParameters.Distorsion);
202 Eigen::Vector3f position(
203 marker.Tvec.at<float>(0, 0), marker.Tvec.at<float>(1, 0), marker.Tvec.at<float>(2, 0));
204 Eigen::Matrix3f orientation;
205
206
207 cv::Matx33f cvOrientation;
208
209 cv::Rodrigues(marker.Rvec, cvOrientation);
210
211 // putting z column first, fixes wrong orientation.
212 orientation << cvOrientation(0, 2), cvOrientation(0, 0), cvOrientation(0, 1),
213 cvOrientation(1, 2), cvOrientation(1, 0), cvOrientation(1, 1), cvOrientation(2, 2),
214 cvOrientation(2, 0), cvOrientation(2, 1);
215
216
217 //result.position = new armarx::FramedPosition(position, refFrame, agentName);
218 //result.orientation = new armarx::FramedOrientation(orientation, refFrame, agentName);
219 result.pose = new armarx::FramedPose(orientation, position, refFrame, agentName);
220 result.id = marker.id;
221
222 /*Eigen::Vector3f mean;
223 mean << 0, 0, 0;
224 Eigen::Matrix3f vars;
225 vars << 0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1;
226 result.positionNoise = memoryx::MultivariateNormalDistributionPtr(new memoryx::MultivariateNormalDistribution(mean, vars));
227
228 // calculate recognition certainty
229 result.recognitionCertainty = 1.0;
230 result.objectClassName = "Marker_" + std::to_string(marker.id);*/
231
232 resultList.push_back(result);
233 }
234
235 return resultList;
236}
237
238visionx::ArMarkerLocalizationResultList
240{
241 if (!waitForImages(500))
242 {
243 ARMARX_WARNING << "No new Images available!";
244 return visionx::ArMarkerLocalizationResultList();
245 }
246 getImages(cameraImages);
247 return localizeAllMarkersInternal();
248}
249
250ArMarkerLocalizationResultList
252{
253 std::unique_lock lock(resultMutex);
254 return lastLocalizationResult;
255}
256
257namespace visionx
258{
259
260 void
262 {
263 using namespace armarx::RemoteGui::Client;
264
265 GridLayout grid;
266 int row = 0;
267
268 tab.markerSize.setRange(1.0, 1000.0);
269 tab.markerSize.setSteps(1000);
270 tab.markerSize.setDecimals(1);
271 tab.markerSize.setValue(this->markerSize);
272
273 grid.add(Label("Marker size:"), {row, 0}).add(tab.markerSize, {row, 1});
274 row++;
275
276 VBoxLayout root = {grid, VSpacer()};
277 RemoteGui_createTab(getName(), root, &tab);
278 }
279
280 void
282 {
283 if (tab.markerSize.hasValueChanged())
284 {
285 this->markerSize = tab.markerSize.getValue();
286 }
287 }
288
289} // namespace visionx
int Label(int n[], int size, int *curLabel, MiscLib::Vector< std::pair< int, size_t > > *labels)
Definition Bitmap.cpp:801
#define ARMARX_STREAM_PRINTER
use this macro to write output code that is executed when printed and thus not executed if the debug ...
Definition Logging.h:310
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition Component.cpp:90
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
std::string getName() const
Retrieve name of object.
std::string prefix
Prefix of the properties such as namespace, domain, component name, etc.
PropertyDefinition< PropertyType > & defineOptionalProperty(const std::string &name, PropertyType defaultValue, const std::string &description="", PropertyDefinitionBase::PropertyConstness constness=PropertyDefinitionBase::eConstant)
DerivedT & pose(Eigen::Matrix4f const &pose)
Definition ElementOps.h:176
void onConnectImageProcessor() override
Implement this method in the ImageProcessor in order execute parts when the component is fully initia...
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
void process() override
Process the vision component.
void onInitImageProcessor() override
Setup the vision component.
visionx::ArMarkerLocalizationResultList LocalizeAllMarkersNow(const Ice::Current &) override
visionx::ArMarkerLocalizationResultList GetLatestLocalizationResult(const Ice::Current &) override
std::string getDefaultName() const override
ImageProcessorPropertyDefinitions(std::string prefix)
bool waitForImages(int milliseconds=1000)
Wait for new images.
ImageProviderInfo getImageProvider(std::string name, ImageType destinationImageType=eRgb, bool waitForProxy=false)
Select an ImageProvider.
int getImages(CByteImage **ppImages)
Poll images from provider.
ImageProviderInterfacePrx proxy
proxy to image provider
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#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.
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
VirtualRobot headers.
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.
ArmarX headers.
void RemoteGui_createTab(std::string const &name, RemoteGui::Client::Widget const &rootWidget, RemoteGui::Client::Tab *tab)
GridLayout & add(Widget const &child, Pos pos, Span span=Span{1, 1})
Definition Widgets.cpp:438
void add(ElementT const &element)
Definition Layer.h:31