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 // Both flags must be initialized: the point cloud thread reads `depthImageReady`
274 // immediately after it is started, i.e. before `doCapture()` ever writes it. An
275 // indeterminate value there makes the thread process a frame that does not exist yet,
276 // using a `transformation` that has not been created yet (see `onStartCapture()`).
277 bool depthImageReady = false;
278 bool depthImageProcessed = false;
279
280 // Task for the point cloud provider.
282
283 // IVT result images scaled to the size of the color image.
284 visionx::CByteImageUPtr resultDepthImage, resultColorImage;
285
286 // Result point cloud.
287 pcl::PointCloud<CloudPointType>::Ptr pointcloud;
288 MetaPointCloudFormatPtr cloudFormat;
289
290 // Stereo calibration used.
291 visionx::StereoCalibration calibration;
292
293 // Undistort the color image with all coefficients.
294 bool enableColorUndistortion = false;
295
296 //
297 bool enableHeartbeat = true;
298
299 // Path to a external calibration file.
300 std::string externalCalibrationFilePath;
301
302 // Camera parameters and distortion information.
303 cv::Mat cameraMatrix;
304 cv::Mat distCoeffs;
305
306 cv::Mat colorDistortionMap;
307
308 // K4A handles.
309 k4a::device device;
310 k4a_device_configuration_t config;
311 k4a::calibration k4aCalibration;
312
313 k4a::transformation transformation;
314
315 k4a::image alignedDepthImage, xyzImage;
316
317#ifdef INCLUDE_BODY_TRACKING
318 k4abt::tracker bodyTracker;
319 // armarx::armem::human::HumanMemoryServerInterfacePrx humanMemoryServer;
320
322
324
325 void runPublishBodyTrackingResults();
326#endif
327
328 int mDeviceId = K4A_DEVICE_DEFAULT;
329
330 struct diagnostics
331 {
332 unsigned int num_crashes = 0;
333 };
334
335 diagnostics mDiagnostics;
336
337 bool bodyTrackingEnabled = false; // Initialize Body Tracking
338 bool bodyTrackingRunAtStart = false;
339 std::atomic<bool> bodyTrackingIsRunning = false;
340 std::string bodyTrackingModelFilename = "${K4A_BODY_TRACKING_DNN_MODEL_FILEPATH}";
341 std::int32_t bodyTrackingGPUDeviceID = 0;
342 std::mutex bodyTrackingParameterMutex;
343 float bodyTrackingTemporalSmoothingFactor = 0.0f;
344 int bodyTrackingDepthMaskMinX = -1;
345 int bodyTrackingDepthMaskMaxX = -1;
346 int bodyTrackingDepthMaskMaxZ = -1;
347 bool startIMU = false;
348 bool useCPU = false;
349
350 std::string bodyCameraFrameName = "AzureKinectDepthCamera";
351 std::string robotName = "Armar6";
352
353 struct Framerate
354 {
355 int value = 30;
356
358 {
359 std::string name;
360 float value = 30;
361 unsigned int skipFrames = 0;
362 unsigned int skipFramesCount = 0;
363
364 void update(int higherFramerate);
365 bool skip();
366 };
367
368 Subordinate bodyTracking{.name = "Body Tracking"};
369 Subordinate pointCloud{.name = "Point Cloud"};
370 } framerate;
371
372 std::mutex deviceToRealtimeOffsetMtx;
373 std::chrono::nanoseconds device_to_realtime_offset_{0};
374
375 std::mutex debugObserverMtx;
376 std::mutex metaInfoMtx;
377
378 armarx::plugins::HeartbeatComponentPlugin* heartbeatPlugin = nullptr;
379 };
380} // 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:179
client::plugins::PluginUser ClientPluginUser
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
ArmarX headers.
std::unique_ptr< CByteImage > CByteImageUPtr