AzureKinectPointCloudProvider.h
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package VisionX::ArmarXObjects::AzureKinectPointCloudProvider
17 * @author Mirko Wächter
18 * @author Christian R. G. Dreher <c.dreher@kit.edu>
19 * @date 2019
20 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
21 * GNU General Public License
22 */
23
24
25#pragma once
26
27// STD
28#include <chrono>
29#include <condition_variable>
30#include <mutex>
31
32// Eigen3
33#include <Eigen/Core>
34
35// OpenCV
36#include <opencv2/opencv.hpp>
37
38// ArmarXCore
43#include <ArmarXCore/interface/observers/ObserverInterface.h>
45
46// RobotAPI
48#include <RobotAPI/interface/visualization/DebugDrawerInterface.h>
49
50// VisionX
54//#include <VisionX/interface/components/RGBDImageProvider.h>
55#include <VisionX/interface/components/AzureKinectPointCloudProviderInterface.h>
56#include <VisionX/libraries/armem_human/server/HumanMemoryServerInterface.h>
57
58// K4A
59#include <k4a/k4a.h>
60#include <k4a/k4a.hpp>
61
62#ifdef INCLUDE_BODY_TRACKING
64
66
67#include <k4abt.hpp>
68#endif
69
70namespace visionx
71{
72 /// @class AzureKinectPointCloudProviderPropertyDefinitions
79
80
81 // TODO: Update the comments for this component.
82 /**
83 * @defgroup Component-AzureKinectPointCloudProvider AzureKinectPointCloudProvider
84 * @ingroup VisionX-Components
85 * Provides support for the Azure Kinect cameras for ArmarX.
86 *
87 * @class AzureKinectPointCloudProvider
88 * @ingroup Component-AzureKinectPointCloudProvider
89 * @brief Brief description of class AzureKinectPointCloudProvider.
90 */
92 // virtual public visionx::RGBDPointCloudProviderInterface,
93 virtual public armarx::AzureKinectPointCloudProviderInterface,
95 virtual public visionx::ImageProvider,
97#ifdef INCLUDE_BODY_TRACKING
98 ,
100#endif
101 {
102 public:
104
105 using CloudPointType = pcl::PointXYZRGBA;
106 /// @see armarx::ManagedIceObject::getDefaultName()
107 std::string getDefaultName() const override;
108 static std::string GetDefaultName();
109
110 protected:
111 /**
112 * @see PropertyUser::createPropertyDefinitions()
113 */
115
116 // ManagedIceObject interface
117 protected:
118 void onInitComponent() override;
119 void onConnectComponent() override;
120 void onDisconnectComponent() override;
121
122 void onExitComponent() override;
123
124 // StereoCalibrationInterface interface
125 public:
126 visionx::StereoCalibration getStereoCalibration(const Ice::Current& c) override;
127 bool getImagesAreUndistorted(const ::Ice::Current& c) override;
128
129 std::string getReferenceFrame(const Ice::Current& c) override;
130
131 std::vector<imrec::ChannelPreferences>
132 getImageRecordingChannelPreferences(const Ice::Current&) override;
133
134 // AzureKinectBodyTrackingInterface interface
135 public:
136 void enableHumanPoseEstimation(const armarx::EnableHumanPoseEstimationInput& input,
137 const Ice::Current& = Ice::emptyCurrent) override;
138
139 void setMaxDepthBodyTracking(int maxDepthInMM,
140 const Ice::Current& = Ice::emptyCurrent) override;
141
142 void setWidthBodyTracking(int minXinPixel,
143 int maxXinPixel,
144 const Ice::Current& = Ice::emptyCurrent) override;
145
146 protected:
147 void onStartCapture(float frames_per_second) override;
148 void onStopCapture() override;
149 void onInitImageProvider() override;
150 void onConnectImageProvider() override;
151 void onDisconnectImageProvider() override;
152
153 void
155 {
156 }
157
158 void onInitCapturingPointCloudProvider() override;
159 void onExitCapturingPointCloudProvider() override;
160 bool doCapture() override;
161
162 bool
163 hasSharedMemorySupport(const Ice::Current& c) override
164 {
165 return true;
166 }
167
168 MetaPointCloudFormatPtr
170 {
171 MetaPointCloudFormatPtr info = new MetaPointCloudFormat();
172 //info->frameId = getProperty<std::string>("frameId").getValue();
173 info->type = PointContentType::eColoredPoints;
174
175 ARMARX_CHECK_EXPRESSION(resultColorImage);
176
177 ARMARX_INFO << "default pointcloud format: " << resultColorImage->width << ", "
178 << resultColorImage->height;
179
180 info->capacity =
181 resultColorImage->width * resultColorImage->height * sizeof(ColoredPoint3D);
182 info->size = info->capacity;
183 return info;
184 }
185
187
188 /*!
189 * @brief Returns the dimension of the color images that will be produced for a certain resolution.
190 * @param resolution The resolution that should be used for the color image.
191 * @return Pair of width and height that color images will have.
192 */
193 static inline std::pair<int, int>
194 GetColorDimensions(const k4a_color_resolution_t resolution)
195 {
196 switch (resolution)
197 {
198 case K4A_COLOR_RESOLUTION_720P:
199 return {1280, 720};
200 case K4A_COLOR_RESOLUTION_2160P:
201 return {3840, 2160};
202 case K4A_COLOR_RESOLUTION_1440P:
203 return {2560, 1440};
204 case K4A_COLOR_RESOLUTION_1080P:
205 return {1920, 1080};
206 case K4A_COLOR_RESOLUTION_3072P:
207 return {4096, 3072};
208 case K4A_COLOR_RESOLUTION_1536P:
209 return {2048, 1536};
210
211 default:
212 throw std::logic_error("Invalid color dimensions value!");
213 }
214 }
215
216 /*!
217 * @brief Returns the dimension of the depth images that will be produced for a certain resolution.
218 * @param resolution The resolution that should be used for the depth image.
219 * @return Pair of width and height that depth images will have.
220 */
221 static inline std::pair<int, int>
222 GetDepthDimensions(const k4a_depth_mode_t depth_mode)
223 {
224 switch (depth_mode)
225 {
226 case K4A_DEPTH_MODE_NFOV_2X2BINNED:
227 return {320, 288};
228 case K4A_DEPTH_MODE_NFOV_UNBINNED:
229 return {640, 576};
230 case K4A_DEPTH_MODE_WFOV_2X2BINNED:
231 return {512, 512};
232 case K4A_DEPTH_MODE_WFOV_UNBINNED:
233 return {1024, 1024};
234 case K4A_DEPTH_MODE_PASSIVE_IR:
235 return {1024, 1024};
236
237 default:
238 throw std::logic_error("Invalid depth dimensions value!");
239 }
240 }
241
242 /*!
243 * @brief Creates a string from a k4a_version_t.
244 * @param version The verstion that should be transformed into a string.
245 * @return The string representing the version.
246 */
247 static std::string
248 VersionToString(const k4a_version_t& version)
249 {
250 std::stringstream s;
251 s << version.major << "." << version.minor << "." << version.iteration;
252 return s.str();
253 }
254
255 std::function<void(armarx::Duration)> createSwCallback(const std::string& description);
256
257 void updateTimestampOffset(const std::chrono::microseconds& k4a_device_timestamp_us,
258 const std::chrono::nanoseconds& k4a_system_timestamp_ns);
259
260 void initializeTimestampOffset(const std::chrono::microseconds& k4a_device_timestamp_us);
261
262
263 armarx::DateTime timestampToArmarX(const std::chrono::microseconds& k4a_timestamp_us);
264
265 private:
266 // Time the last image was recorded.
267 IceUtil::Time imagesTime;
268
269 // Mutex to protect the point cloud provider.
270 std::mutex pointcloudProcMutex;
271 std::condition_variable pointcloudProcSignal;
272
273 bool depthImageReady;
274 bool depthImageProcessed;
275
276 // Task for the point cloud provider.
278
279 // IVT result images scaled to the size of the color image.
280 visionx::CByteImageUPtr resultDepthImage, resultColorImage;
281
282 // Result point cloud.
283 pcl::PointCloud<CloudPointType>::Ptr pointcloud;
284 MetaPointCloudFormatPtr cloudFormat;
285
286 // Stereo calibration used.
287 visionx::StereoCalibration calibration;
288
289 // Undistort the color image with all coefficients.
290 bool enableColorUndistortion = false;
291
292 //
293 bool enableHeartbeat = true;
294
295 // Path to a external calibration file.
296 std::string externalCalibrationFilePath;
297
298 // Camera parameters and distortion information.
299 cv::Mat cameraMatrix;
300 cv::Mat distCoeffs;
301
302 cv::Mat colorDistortionMap;
303
304 // K4A handles.
305 k4a::device device;
306 k4a_device_configuration_t config;
307 k4a::calibration k4aCalibration;
308
309 k4a::transformation transformation;
310
311 k4a::image alignedDepthImage, xyzImage;
312
313#ifdef INCLUDE_BODY_TRACKING
314 k4abt::tracker bodyTracker;
315 // armarx::armem::human::HumanMemoryServerInterfacePrx humanMemoryServer;
316
318
320
321 void runPublishBodyTrackingResults();
322#endif
323
324 int mDeviceId = K4A_DEVICE_DEFAULT;
325
326 struct diagnostics
327 {
328 unsigned int num_crashes = 0;
329 };
330
331 diagnostics mDiagnostics;
332
333 bool bodyTrackingEnabled = false; // Initialize Body Tracking
334 bool bodyTrackingRunAtStart = false;
335 std::atomic<bool> bodyTrackingIsRunning = false;
336 std::string bodyTrackingModelFilename = "${K4A_BODY_TRACKING_DNN_MODEL_FILEPATH}";
337 std::int32_t bodyTrackingGPUDeviceID = 0;
338 std::mutex bodyTrackingParameterMutex;
339 float bodyTrackingTemporalSmoothingFactor = 0.0f;
340 int bodyTrackingDepthMaskMinX = -1;
341 int bodyTrackingDepthMaskMaxX = -1;
342 int bodyTrackingDepthMaskMaxZ = -1;
343 bool startIMU = false;
344 bool useCPU = false;
345
346 std::string bodyCameraFrameName = "AzureKinectDepthCamera";
347 std::string robotName = "Armar6";
348
349 struct Framerate
350 {
351 int value = 30;
352
354 {
355 std::string name;
356 float value = 30;
357 unsigned int skipFrames = 0;
358 unsigned int skipFramesCount = 0;
359
360 void update(int higherFramerate);
361 bool skip();
362 };
363
364 Subordinate bodyTracking{.name = "Body Tracking"};
365 Subordinate pointCloud{.name = "Point Cloud"};
366 } framerate;
367
368 std::mutex deviceToRealtimeOffsetMtx;
369 std::chrono::nanoseconds device_to_realtime_offset_{0};
370
371 std::mutex debugObserverMtx;
372 std::mutex metaInfoMtx;
373
374 armarx::plugins::HeartbeatComponentPlugin* heartbeatPlugin = nullptr;
375 };
376} // namespace visionx
constexpr T c
std::string prefix
Prefix of the properties such as namespace, domain, component name, etc.
IceUtil::Handle< RunningTask< T > > pointer_type
Shared pointer type for convenience.
Represents a point in time.
Definition DateTime.h:25
Represents a duration.
Definition Duration.h:17
void onInitComponent() override
Pure virtual hook for the subclass.
void setMaxDepthBodyTracking(int maxDepthInMM, const Ice::Current &=Ice::emptyCurrent) override
armarx::DateTime timestampToArmarX(const std::chrono::microseconds &k4a_timestamp_us)
bool doCapture() override
Main capturing function.
void enableHumanPoseEstimation(const armarx::EnableHumanPoseEstimationInput &input, const Ice::Current &=Ice::emptyCurrent) override
void onExitCapturingPointCloudProvider() override
This is called when the Component::onExitComponent() setup is called.
void onDisconnectComponent() override
Hook for subclass.
static std::pair< int, int > GetDepthDimensions(const k4a_depth_mode_t depth_mode)
Returns the dimension of the depth images that will be produced for a certain resolution.
void onStartCapture(float frames_per_second) override
This is called when the point cloud provider capturing has been started.
static std::pair< int, int > GetColorDimensions(const k4a_color_resolution_t resolution)
Returns the dimension of the color images that will be produced for a certain resolution.
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
void onConnectImageProvider() override
This is called when the Component::onConnectComponent() setup is called.
visionx::StereoCalibration getStereoCalibration(const Ice::Current &c) override
std::string getReferenceFrame(const Ice::Current &c) override
static std::string VersionToString(const k4a_version_t &version)
Creates a string from a k4a_version_t.
std::function< void(armarx::Duration)> createSwCallback(const std::string &description)
void onInitCapturingPointCloudProvider() override
This is called when the Component::onInitComponent() is called.
MetaPointCloudFormatPtr getDefaultPointCloudFormat() override
default point cloud format used to initialize shared memory
void onConnectComponent() override
Pure virtual hook for the subclass.
void onStopCapture() override
This is called when the point cloud provider capturing has been stopped.
bool getImagesAreUndistorted(const ::Ice::Current &c) override
std::vector< imrec::ChannelPreferences > getImageRecordingChannelPreferences(const Ice::Current &) override
void onInitImageProvider() override
This is called when the Component::onInitComponent() is called.
void setWidthBodyTracking(int minXinPixel, int maxXinPixel, const Ice::Current &=Ice::emptyCurrent) override
void onExitImageProvider() override
This is called when the Component::onExitComponent() setup is called.
void initializeTimestampOffset(const std::chrono::microseconds &k4a_device_timestamp_us)
bool hasSharedMemorySupport(const Ice::Current &c) override
void updateTimestampOffset(const std::chrono::microseconds &k4a_device_timestamp_us, const std::chrono::nanoseconds &k4a_system_timestamp_ns)
The CapturingPointCloudProvider provides a callback function to trigger the capturing of point clouds...
ImageProvider abstract class defines a component which provide images via ice or shared memory.
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
client::plugins::PluginUser ClientPluginUser
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
ArmarX headers.
std::unique_ptr< CByteImage > CByteImageUPtr