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 /**
107 * @see armarx::ManagedIceObject::getDefaultName()
108 */
109 std::string getDefaultName() const override;
110
111 protected:
112 /**
113 * @see PropertyUser::createPropertyDefinitions()
114 */
116
117 // ManagedIceObject interface
118 protected:
119 void onInitComponent() override;
120 void onConnectComponent() override;
121 void onDisconnectComponent() override;
122
123 void onExitComponent() override;
124
125 // StereoCalibrationInterface interface
126 public:
127 visionx::StereoCalibration getStereoCalibration(const Ice::Current& c) override;
128 bool getImagesAreUndistorted(const ::Ice::Current& c) override;
129
130 std::string getReferenceFrame(const Ice::Current& c) override;
131
132 std::vector<imrec::ChannelPreferences>
133 getImageRecordingChannelPreferences(const Ice::Current&) override;
134
135 // AzureKinectBodyTrackingInterface interface
136 public:
137 void enableHumanPoseEstimation(const armarx::EnableHumanPoseEstimationInput& input,
138 const Ice::Current& = Ice::emptyCurrent) override;
139
140 void setMaxDepthBodyTracking(int maxDepthInMM,
141 const Ice::Current& = Ice::emptyCurrent) override;
142
143 void setWidthBodyTracking(int minXinPixel,
144 int maxXinPixel,
145 const Ice::Current& = Ice::emptyCurrent) override;
146
147 protected:
148 void onStartCapture(float frames_per_second) override;
149 void onStopCapture() override;
150 void onInitImageProvider() override;
151 void onConnectImageProvider() override;
152 void onDisconnectImageProvider() override;
153
154 void
156 {
157 }
158
159 void onInitCapturingPointCloudProvider() override;
160 void onExitCapturingPointCloudProvider() override;
161 bool doCapture() override;
162
163 bool
164 hasSharedMemorySupport(const Ice::Current& c) override
165 {
166 return true;
167 }
168
169 MetaPointCloudFormatPtr
171 {
172 MetaPointCloudFormatPtr info = new MetaPointCloudFormat();
173 //info->frameId = getProperty<std::string>("frameId").getValue();
174 info->type = PointContentType::eColoredPoints;
175
176 ARMARX_CHECK_EXPRESSION(resultColorImage);
177
178 ARMARX_INFO << "default pointcloud format: " << resultColorImage->width << ", "
179 << resultColorImage->height;
180
181 info->capacity =
182 resultColorImage->width * resultColorImage->height * sizeof(ColoredPoint3D);
183 info->size = info->capacity;
184 return info;
185 }
186
188
189 /*!
190 * @brief Returns the dimension of the color images that will be produced for a certain resolution.
191 * @param resolution The resolution that should be used for the color image.
192 * @return Pair of width and height that color images will have.
193 */
194 static inline std::pair<int, int>
195 GetColorDimensions(const k4a_color_resolution_t resolution)
196 {
197 switch (resolution)
198 {
199 case K4A_COLOR_RESOLUTION_720P:
200 return {1280, 720};
201 case K4A_COLOR_RESOLUTION_2160P:
202 return {3840, 2160};
203 case K4A_COLOR_RESOLUTION_1440P:
204 return {2560, 1440};
205 case K4A_COLOR_RESOLUTION_1080P:
206 return {1920, 1080};
207 case K4A_COLOR_RESOLUTION_3072P:
208 return {4096, 3072};
209 case K4A_COLOR_RESOLUTION_1536P:
210 return {2048, 1536};
211
212 default:
213 throw std::logic_error("Invalid color dimensions value!");
214 }
215 }
216
217 /*!
218 * @brief Returns the dimension of the depth images that will be produced for a certain resolution.
219 * @param resolution The resolution that should be used for the depth image.
220 * @return Pair of width and height that depth images will have.
221 */
222 static inline std::pair<int, int>
223 GetDepthDimensions(const k4a_depth_mode_t depth_mode)
224 {
225 switch (depth_mode)
226 {
227 case K4A_DEPTH_MODE_NFOV_2X2BINNED:
228 return {320, 288};
229 case K4A_DEPTH_MODE_NFOV_UNBINNED:
230 return {640, 576};
231 case K4A_DEPTH_MODE_WFOV_2X2BINNED:
232 return {512, 512};
233 case K4A_DEPTH_MODE_WFOV_UNBINNED:
234 return {1024, 1024};
235 case K4A_DEPTH_MODE_PASSIVE_IR:
236 return {1024, 1024};
237
238 default:
239 throw std::logic_error("Invalid depth dimensions value!");
240 }
241 }
242
243 /*!
244 * @brief Creates a string from a k4a_version_t.
245 * @param version The verstion that should be transformed into a string.
246 * @return The string representing the version.
247 */
248 static std::string
249 VersionToString(const k4a_version_t& version)
250 {
251 std::stringstream s;
252 s << version.major << "." << version.minor << "." << version.iteration;
253 return s.str();
254 }
255
256 std::function<void(armarx::Duration)> createSwCallback(const std::string& description);
257
258 void updateTimestampOffset(const std::chrono::microseconds& k4a_device_timestamp_us,
259 const std::chrono::nanoseconds& k4a_system_timestamp_ns);
260
261 void initializeTimestampOffset(const std::chrono::microseconds& k4a_device_timestamp_us);
262
263
264 armarx::DateTime timestampToArmarX(const std::chrono::microseconds& k4a_timestamp_us);
265
266 private:
267 // Time the last image was recorded.
268 IceUtil::Time imagesTime;
269
270 // Mutex to protect the point cloud provider.
271 std::mutex pointcloudProcMutex;
272 std::condition_variable pointcloudProcSignal;
273
274 bool depthImageReady;
275 bool depthImageProcessed;
276
277 // Task for the point cloud provider.
279
280 // IVT result images scaled to the size of the color image.
281 visionx::CByteImageUPtr resultDepthImage, resultColorImage;
282
283 // Result point cloud.
284 pcl::PointCloud<CloudPointType>::Ptr pointcloud;
285 MetaPointCloudFormatPtr cloudFormat;
286
287 // Stereo calibration used.
288 visionx::StereoCalibration calibration;
289
290 // Undistort the color image with all coefficients.
291 bool enableColorUndistortion = false;
292
293 //
294 bool enableHeartbeat = true;
295
296 // Path to a external calibration file.
297 std::string externalCalibrationFilePath;
298
299 // Camera parameters and distortion information.
300 cv::Mat cameraMatrix;
301 cv::Mat distCoeffs;
302
303 cv::Mat colorDistortionMap;
304
305 // K4A handles.
306 k4a::device device;
307 k4a_device_configuration_t config;
308 k4a::calibration k4aCalibration;
309
310 k4a::transformation transformation;
311
312 k4a::image alignedDepthImage, xyzImage;
313
314#ifdef INCLUDE_BODY_TRACKING
315 k4abt::tracker bodyTracker;
316 // armarx::armem::human::HumanMemoryServerInterfacePrx humanMemoryServer;
317
319
321
322 void runPublishBodyTrackingResults();
323#endif
324
325 int mDeviceId = K4A_DEVICE_DEFAULT;
326
327 struct diagnostics
328 {
329 unsigned int num_crashes = 0;
330 };
331
332 diagnostics mDiagnostics;
333
334 bool bodyTrackingEnabled = false; // Initialize Body Tracking
335 bool bodyTrackingRunAtStart = false;
336 std::atomic<bool> bodyTrackingIsRunning = false;
337 std::string bodyTrackingModelFilename = "${K4A_BODY_TRACKING_DNN_MODEL_FILEPATH}";
338 std::int32_t bodyTrackingGPUDeviceID = 0;
339 std::mutex bodyTrackingParameterMutex;
340 float bodyTrackingTemporalSmoothingFactor = 0.0f;
341 int bodyTrackingDepthMaskMinX = -1;
342 int bodyTrackingDepthMaskMaxX = -1;
343 int bodyTrackingDepthMaskMaxZ = -1;
344 bool startIMU = false;
345 bool useCPU = false;
346
347 std::string bodyCameraFrameName = "AzureKinectDepthCamera";
348 std::string robotName = "Armar6";
349
350 struct Framerate
351 {
352 int value = 30;
353
355 {
356 std::string name;
357 float value = 30;
358 unsigned int skipFrames = 0;
359 unsigned int skipFramesCount = 0;
360
361 void update(int higherFramerate);
362 bool skip();
363 };
364
365 Subordinate bodyTracking{.name = "Body Tracking"};
366 Subordinate pointCloud{.name = "Point Cloud"};
367 } framerate;
368
369 std::mutex deviceToRealtimeOffsetMtx;
370 std::chrono::nanoseconds device_to_realtime_offset_{0};
371
372 std::mutex debugObserverMtx;
373 std::mutex metaInfoMtx;
374
375 armarx::plugins::HeartbeatComponentPlugin* heartbeatPlugin = nullptr;
376 };
377} // 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