ADTF Device Toolbox SDK
Loading...
Searching...
No Matches
pointcloud_data.h
Go to the documentation of this file.
1
16
17#pragma once
18
19#include <adtfmediadescription/adtf_mediadescription.h>
20
21#include <map>
22#include <memory>
23#include <optional>
24#include <string>
25#include <unordered_map>
26#include <variant>
27
29#include "pointcloud_access.h"
30
34namespace adtf
35{
39namespace devicetb
40{
44namespace sdk
45{
49namespace pointcloud
50{
54namespace navigation
55{
56
58{
59public:
61 {
62 public:
63 cDynamicSampleHeader& EnableSensorTransformation()
64 {
65 m_bTransformation = true;
66 return *this;
67 }
68
69 cDynamicSampleHeader& EnableSize()
70 {
71 m_bSize = true;
72 return *this;
73 }
74
75 cDynamicSampleHeader& AddAttribute(std::string_view strName)
76 {
77 m_oAttributes.emplace_back(strName);
78 return *this;
79 }
80
81 ddl::DDStructure GetDefinition()
82 {
83 auto oPointCloudDescription = ddl::DDStructure("point_cloud_sample_header");
84
85 if (m_bTransformation)
86 {
87 static const auto oTransformationDescription =
88 ddl::DDStructureGenerator<tSensorTransformation>("sensor_transformation")
89 .addElement("x", &tSensorTransformation::x)
90 .addElement("y", &tSensorTransformation::y)
91 .addElement("z", &tSensorTransformation::z)
92 .addElement("roll", &tSensorTransformation::roll)
93 .addElement("pitch", &tSensorTransformation::pitch)
94 .addElement("yaw", &tSensorTransformation::yaw);
95
96 oPointCloudDescription.addElement(stream_meta_type_pointcloud_properties::Transformation,
97 oTransformationDescription);
98 }
99
100 // Deploy dynamic attributes
101 if (!m_oAttributes.empty())
102 {
103 static const auto oDataTypeEnum = ddl::DDEnumGenerator<tAttribute::tDataType>(
104 "data_type", {{"dt_boolean", tAttribute::tDataType::dt_boolean},
105 {"dt_uint_8", tAttribute::tDataType::dt_uint8},
106 {"dt_int_8", tAttribute::tDataType::dt_int8},
107 {"dt_uint_16", tAttribute::tDataType::dt_uint16},
108 {"dt_int_16", tAttribute::tDataType::dt_int16},
109 {"dt_float16", tAttribute::tDataType::dt_float16},
110 {"dt_uint_32", tAttribute::tDataType::dt_uint32},
111 {"dt_int_32", tAttribute::tDataType::dt_int32},
112 {"dt_float32", tAttribute::tDataType::dt_float32},
113 {"dt_uint_64", tAttribute::tDataType::dt_uint64},
114 {"dt_int_64", tAttribute::tDataType::dt_int64},
115 {"dt_float64", tAttribute::tDataType::dt_float64},
116 {"dt_computed_from_index", tAttribute::tDataType::dt_computed_from_index}});
117
118 static const auto oEndianEnum = ddl::DDEnumGenerator<tAttribute::tInMemory::eEndianess>(
119 "endianess", {{"endian_big", tAttribute::tInMemory::eEndianess::endian_big},
120 {"endian_little", tAttribute::tInMemory::eEndianess::endian_little}});
121
122 static const auto oInMemoryDescription =
123 ddl::DDStructureGenerator<tAttribute::tInMemory>("in_memory")
124 .addElement("endianess", &tAttribute::tInMemory::endianess, oEndianEnum)
125 .addElement("offset", &tAttribute::tInMemory::offset)
126 .addElement("stride", &tAttribute::tInMemory::stride);
127
128 static const auto oComputedFromIndexDescription =
129 ddl::DDStructureGenerator<tAttribute::tComputedFromIndex>("computed_from_index")
130 .addElement("stride_to_increment", &tAttribute::tComputedFromIndex::stride_to_increment)
131 .addElement("stride_to_reset", &tAttribute::tComputedFromIndex::stride_to_reset)
132 .addElement("increment", &tAttribute::tComputedFromIndex::increment)
133 .addElement("offset", &tAttribute::tComputedFromIndex::offset);
134
135 static const auto oAttributeDescription =
136 ddl::DDStructureGenerator<tAttribute>("attribute")
137 .addElement("type", &tAttribute::type, oDataTypeEnum)
138 .addElement("in_memory", &tAttribute::sInMemory, oInMemoryDescription)
139 .addElement("computed", &tAttribute::sComputed, oComputedFromIndexDescription);
140
141 auto oAttributesDescription = ddl::DDStructure(stream_meta_type_pointcloud_properties::Attributes);
142 for (const auto& oUserAttr : m_oAttributes)
143 {
144 oAttributesDescription.addElement(oUserAttr, oAttributeDescription);
145 }
146
147 oPointCloudDescription.addElement(stream_meta_type_pointcloud_properties::Attributes,
148 oAttributesDescription);
149 }
150
151 if (m_bSize)
152 {
153 oPointCloudDescription.addElement<size_t>(stream_meta_type_pointcloud_properties::Count);
154 }
155
156 return oPointCloudDescription;
157 }
158
159 private:
160 bool m_bTransformation = false;
161 std::vector<std::string> m_oAttributes;
162 bool m_bSize = false;
163 };
164
170 cPointCloudTypeHelper(const adtf::ucom::iobject_ptr<const adtf::streaming::IStreamType>& pType):
172 {
173 try
174 {
175 const auto [strName, strDDL, eRepresentation] =
176 adtf::mediadescription::get_media_description_from_stream_type(*pType.Get());
177 SetDynamicSampleHeader(ddl::DDStructure(strName, strDDL), eRepresentation);
178 }
179 catch (...)
180 {
181 }
182
183 adtf::ucom::object_ptr<const adtf::base::IProperties> pProperties;
184 THROW_IF_FAILED(pType->GetConfig(pProperties));
185
186 // Static: Read transformation from StreamType properties
187 if (pProperties->Exists(stream_meta_type_pointcloud_properties::Transformation))
188 {
189 tSensorTransformation oTransformation;
190 oTransformation.x = adtf::base::get_property_by_path<float>(
191 *pProperties, stream_meta_type_pointcloud_properties::TransformationX);
192 oTransformation.y = adtf::base::get_property_by_path<float>(
193 *pProperties, stream_meta_type_pointcloud_properties::TransformationY);
194 oTransformation.z = adtf::base::get_property_by_path<float>(
195 *pProperties, stream_meta_type_pointcloud_properties::TransformationZ);
196 oTransformation.roll = adtf::base::get_property_by_path<float>(
197 *pProperties, stream_meta_type_pointcloud_properties::TransformationRoll);
198 oTransformation.pitch = adtf::base::get_property_by_path<float>(
199 *pProperties, stream_meta_type_pointcloud_properties::TransformationPitch);
200 oTransformation.yaw = adtf::base::get_property_by_path<float>(
201 *pProperties, stream_meta_type_pointcloud_properties::TransformationYaw);
202
203 m_oTransformation = oTransformation;
204 }
205
206 if (!IsDynamic())
207 {
208 // Static: Read attributes from StreamType properties
209 std::map<std::string, std::pair<std::string, tAttribute>, std::less<>> oFoundAttributes;
210 adtf::base::visit_sub_properties(
211 *pProperties, stream_meta_type_pointcloud_properties::Attributes,
212 [&](const adtf::base::IProperty& oProperty)
213 {
214 std::string strOrder;
215 THROW_IF_FAILED(oProperty.GetName(adtf_string_intf(strOrder)));
216
217 adtf::ucom::object_ptr<const adtf::base::IProperties> pSubProperties;
218 THROW_IF_FAILED(oProperty.GetProperties(pSubProperties));
219
220 const auto strAttributeName = adtf::base::get_property_by_path<std::string>(
221 *pSubProperties, stream_meta_type_pointcloud_properties::AttributeName);
222
223 tAttribute oAttribute;
224
225 const auto strDataType = adtf::base::get_property_by_path<std::string>(
226 *pSubProperties, stream_meta_type_pointcloud_properties::AttributeDataType);
227
228 static const std::unordered_map<std::string, tAttribute::tDataType> oDataTypeNames{
229 {"bool", tAttribute::tDataType::dt_boolean},
230 {"uint8", tAttribute::tDataType::dt_uint8},
231 {"int8", tAttribute::tDataType::dt_int8},
232 {"uint16", tAttribute::tDataType::dt_uint16},
233 {"int16", tAttribute::tDataType::dt_int16},
234 {"float16", tAttribute::tDataType::dt_float16},
235 {"uint32", tAttribute::tDataType::dt_uint32},
236 {"int32", tAttribute::tDataType::dt_int32},
237 {"float32", tAttribute::tDataType::dt_float32},
238 {"uint64", tAttribute::tDataType::dt_uint64},
239 {"int64", tAttribute::tDataType::dt_int64},
240 {"float64", tAttribute::tDataType::dt_float64},
241 {"computed", tAttribute::tDataType::dt_computed_from_index}};
242
243 const auto it = oDataTypeNames.find(strDataType);
244 if (it == oDataTypeNames.end())
245 {
246 THROW_ERROR_DESC(ERR_INVALID_TYPE, "Invalid datatype.");
247 }
248 oAttribute.type = it->second;
249
250 if (oAttribute.type == tAttribute::tDataType::dt_computed_from_index)
251 {
252 oAttribute.sComputed.stride_to_increment = adtf::base::get_property_by_path<uint64_t>(
253 *pSubProperties,
254 stream_meta_type_pointcloud_properties::AttributeComputedStrideToIncrement);
255 oAttribute.sComputed.stride_to_reset = adtf::base::get_property_by_path<uint64_t>(
256 *pSubProperties,
257 stream_meta_type_pointcloud_properties::AttributeComputedStrideToReset);
258 oAttribute.sComputed.increment = adtf::base::get_property_by_path<double>(
259 *pSubProperties, stream_meta_type_pointcloud_properties::AttributeComputedIncrement);
260 oAttribute.sComputed.offset = adtf::base::get_property_by_path<double>(
261 *pSubProperties, stream_meta_type_pointcloud_properties::AttributeComputedOffset);
262 }
263 else // In Memory
264 {
265 static const std::unordered_map<std::string, tAttribute::tInMemory::eEndianess>
266 oEndianessNames{{"be", tAttribute::tInMemory::eEndianess::endian_big},
267 {"le", tAttribute::tInMemory::eEndianess::endian_little}};
268
269 oAttribute.sInMemory.endianess =
270 oEndianessNames.at(adtf::base::get_property_by_path<std::string>(
271 *pSubProperties,
272 stream_meta_type_pointcloud_properties::AttributeInMemoryEndianess));
273 oAttribute.sInMemory.offset = adtf::base::get_property_by_path<uint64_t>(
274 *pSubProperties, stream_meta_type_pointcloud_properties::AttributeInMemoryOffset);
275 oAttribute.sInMemory.stride = adtf::base::get_property_by_path<uint64_t>(
276 *pSubProperties, stream_meta_type_pointcloud_properties::AttributeInMemoryStride);
277 }
278
279 oFoundAttributes.emplace(strOrder, std::make_pair(strAttributeName, oAttribute));
280 });
281
282 for (const auto& oOrderedAttributePair : oFoundAttributes)
283 {
284 m_oStaticAttributes.add(oOrderedAttributePair.second.first, oOrderedAttributePair.second.second);
285 }
286 }
287
288 // Static: Read count from StreamType properties
289 if (pProperties->Exists(stream_meta_type_pointcloud_properties::Count))
290 {
291 m_oCount = adtf::base::get_property_by_path<size_t>(
292 *pProperties, stream_meta_type_pointcloud_properties::Count);
293 }
294
295 CheckCompatibility();
296 }
297
301 cPointCloudTypeHelper(): m_nHeaderSize(0), m_eRepresentation(ddl::DataRepresentation::deserialized)
302 {
303 // Attributes not present, they need to be constructed
304 }
305
310 adtf::ucom::object_ptr<adtf::streaming::IStreamType> GetStreamType() const
311 {
312 CheckCompatibility();
313
314 auto pType = adtf::ucom::make_object_ptr<adtf::streaming::cStreamType>(stream_meta_type_pointcloud());
315 adtf::ucom::object_ptr<adtf::base::IProperties> pPropertiesType;
316 THROW_IF_FAILED(pType->GetConfig(pPropertiesType));
317
318 if (!IsDynamic())
319 {
320 // Deploy transformation, if present
321 if (m_oTransformation)
322 {
323 THROW_IF_FAILED(CreateAndSetProperty(
324 *pPropertiesType, stream_meta_type_pointcloud_properties::TransformationX, m_oTransformation->x));
325 THROW_IF_FAILED(CreateAndSetProperty(
326 *pPropertiesType, stream_meta_type_pointcloud_properties::TransformationY, m_oTransformation->y));
327 THROW_IF_FAILED(CreateAndSetProperty(
328 *pPropertiesType, stream_meta_type_pointcloud_properties::TransformationZ, m_oTransformation->z));
329 THROW_IF_FAILED(CreateAndSetProperty(*pPropertiesType,
330 stream_meta_type_pointcloud_properties::TransformationRoll,
331 m_oTransformation->roll));
332 THROW_IF_FAILED(CreateAndSetProperty(*pPropertiesType,
333 stream_meta_type_pointcloud_properties::TransformationPitch,
334 m_oTransformation->pitch));
335 THROW_IF_FAILED(CreateAndSetProperty(*pPropertiesType,
336 stream_meta_type_pointcloud_properties::TransformationYaw,
337 m_oTransformation->yaw));
338 }
339
340 // Deploy static attributes, if present
341 size_t nIndex = 0;
342 for (const auto& oStaticAttrTuple : m_oStaticAttributes)
343 {
344 const auto& strAttributeName = std::get<std::string>(oStaticAttrTuple);
345 const auto& oAttribute = std::get<tAttribute>(oStaticAttrTuple);
346
347 const auto strPropertyPath = std::string(stream_meta_type_pointcloud_properties::Attributes) + "/" +
348 std::to_string(nIndex) + "/";
349 THROW_IF_FAILED(adtf::base::create_property_tree(*pPropertiesType, strPropertyPath.c_str()));
350
351 THROW_IF_FAILED(CreateAndSetProperty(
352 *pPropertiesType, strPropertyPath + stream_meta_type_pointcloud_properties::AttributeName,
353 strAttributeName));
354
355 static const std::unordered_map<tAttribute::tDataType, std::string> oDataTypeStrings{
356 {tAttribute::tDataType::dt_boolean, "bool"}, {tAttribute::tDataType::dt_uint8, "uint8"},
357 {tAttribute::tDataType::dt_int8, "int8"}, {tAttribute::tDataType::dt_uint16, "uint16"},
358 {tAttribute::tDataType::dt_int16, "int16"}, {tAttribute::tDataType::dt_float16, "float16"},
359 {tAttribute::tDataType::dt_uint32, "uint32"}, {tAttribute::tDataType::dt_int32, "int32"},
360 {tAttribute::tDataType::dt_float32, "float32"}, {tAttribute::tDataType::dt_uint64, "uint64"},
361 {tAttribute::tDataType::dt_int64, "int64"}, {tAttribute::tDataType::dt_float64, "float64"},
362 {tAttribute::tDataType::dt_computed_from_index, "computed"}};
363 THROW_IF_FAILED(CreateAndSetProperty(
364 *pPropertiesType, strPropertyPath + stream_meta_type_pointcloud_properties::AttributeDataType,
365 oDataTypeStrings.at(oAttribute.type)));
366
367 if (oAttribute.type == tAttribute::tDataType::dt_computed_from_index)
368 {
369 THROW_IF_FAILED(CreateAndSetProperty(
370 *pPropertiesType,
371 strPropertyPath + stream_meta_type_pointcloud_properties::AttributeComputedStrideToIncrement,
372 oAttribute.sComputed.stride_to_increment));
373 THROW_IF_FAILED(CreateAndSetProperty(
374 *pPropertiesType,
375 strPropertyPath + stream_meta_type_pointcloud_properties::AttributeComputedStrideToReset,
376 oAttribute.sComputed.stride_to_reset));
377 THROW_IF_FAILED(CreateAndSetProperty(
378 *pPropertiesType,
379 strPropertyPath + stream_meta_type_pointcloud_properties::AttributeComputedIncrement,
380 oAttribute.sComputed.increment));
381 THROW_IF_FAILED(CreateAndSetProperty(
382 *pPropertiesType,
383 strPropertyPath + stream_meta_type_pointcloud_properties::AttributeComputedOffset,
384 oAttribute.sComputed.offset));
385 }
386 else
387 {
388 static const std::map<tAttribute::tInMemory::eEndianess, std::string> oEndianessStrings = {
389 {tAttribute::tInMemory::eEndianess::endian_big, "be"},
390 {tAttribute::tInMemory::eEndianess::endian_little, "le"}};
391
392 THROW_IF_FAILED(CreateAndSetProperty(
393 *pPropertiesType,
394 strPropertyPath + stream_meta_type_pointcloud_properties::AttributeInMemoryEndianess,
395 oEndianessStrings.at(oAttribute.sInMemory.endianess)));
396 THROW_IF_FAILED(CreateAndSetProperty(
397 *pPropertiesType,
398 strPropertyPath + stream_meta_type_pointcloud_properties::AttributeInMemoryOffset,
399 oAttribute.sInMemory.offset));
400 THROW_IF_FAILED(CreateAndSetProperty(
401 *pPropertiesType,
402 strPropertyPath + stream_meta_type_pointcloud_properties::AttributeInMemoryStride,
403 oAttribute.sInMemory.stride));
404 }
405 ++nIndex;
406 }
407
408 // Deploy count, if present
409 if (m_oCount)
410 {
411 THROW_IF_FAILED(CreateAndSetProperty(*pPropertiesType,
412 stream_meta_type_pointcloud_properties::Count, *m_oCount));
413 }
414 }
415 else
416 {
417 assert(m_oDynamicSampleHeader);
418 THROW_IF_FAILED(adtf::mediadescription::set_media_description_properties(
419 *pPropertiesType, *m_oDynamicSampleHeader, m_eRepresentation));
420 }
421
422 return pType;
423 }
424
430 {
431 if (m_oTransformationAccess)
432 {
433 THROW_ERROR_DESC(ERR_ACCESS_DENIED, "Sensor transformation is already defined.");
434 }
435
436 m_oTransformation = oTransformation;
437 }
438
444 void AddStaticAttribute(const std::string& strName, const tAttribute& oAttribute)
445 {
446 if (IsDynamic())
447 {
448 THROW_ERROR_DESC(ERR_INVALID_ARG, "Can't add static attribute to dynamic layout.");
449 }
450 if (m_oStaticAttributes.exists(strName))
451 {
452 THROW_ERROR_DESC(ERR_INVALID_ARG, "Static attribute '%s' already exists.", strName.c_str());
453 }
454
455 m_oStaticAttributes.add(strName, oAttribute);
456 }
457
462 void SetStaticCount(const size_t nCount)
463 {
464 if (m_oCountAccess)
465 {
466 THROW_ERROR_DESC(ERR_INVALID_ARG,
467 "Can't add static count to type with dynamic layout which also contains a count element.");
468 }
469
470 m_oCount = nCount;
471 }
472
473 void SetDynamicSampleHeader(ddl::DDStructure oHeader, ddl::DataRepresentation eRepresentation)
474 {
475 m_oTransformationAccess = std::nullopt;
476 m_oDynamicAttributes.clear();
477 m_oCountAccess = std::nullopt;
478
479 ddl::codec::CodecFactory oCodecFactory(oHeader);
480
481 try
482 {
483 const auto oTransformationElement =
484 oCodecFactory.getElement(stream_meta_type_pointcloud_properties::Transformation);
485 m_oTransformationAccess.emplace(oTransformationElement, eRepresentation);
486 }
487 catch (const std::runtime_error&)
488 {
489 }
490
491 const auto oAttributesElement = [&]() -> std::optional<ddl::codec::CodecFactory::Element>
492 {
493 try
494 {
495 return oCodecFactory.getElement(stream_meta_type_pointcloud_properties::Attributes);
496 }
497 catch (const std::runtime_error&)
498 {
499 return std::nullopt;
500 }
501 }();
502
503 if (oAttributesElement)
504 {
505 for (const auto& oAttribute : oAttributesElement->getChildElements())
506 {
507 m_oDynamicAttributes.add(oAttribute.getName(), tAttributeAccess(oAttribute, eRepresentation));
508 }
509 }
510
511 try
512 {
513 const auto oCountElement = oCodecFactory.getElement(stream_meta_type_pointcloud_properties::Count);
514 m_oCountAccess.emplace(oCountElement, eRepresentation);
515 }
516 catch (const std::runtime_error&)
517 {
518 }
519
520 m_nHeaderSize = oCodecFactory.getStaticBufferSize(eRepresentation);
521 m_oDynamicSampleHeader = std::move(oHeader);
522 m_eRepresentation = eRepresentation;
523 }
524
528 size_t GetHeaderSize() const
529 {
530 return m_nHeaderSize;
531 }
532
538 static size_t GetPayloadSize(size_t nPointCount, const tAttributes& oAttributes) noexcept
539 {
540 size_t nMax = 0;
541 for (const auto& oTuple : oAttributes)
542 {
543 const auto& oAttribute = std::get<tAttribute>(oTuple);
544 nMax = std::max(nMax, oAttribute.sInMemory.offset + nPointCount * oAttribute.sInMemory.stride +
545 oAttribute.Size());
546 }
547 return nMax;
548 }
549
555 const tAttributes& GetStaticAttributes() const
556 {
557 return m_oStaticAttributes;
558 }
559
563 const std::vector<std::string> GetDynamicAttributes() const
564 {
565 std::vector<std::string> oResult;
566 for (const auto& oAttributeTuple : m_oDynamicAttributes)
567 {
568 oResult.emplace_back(std::get<std::string>(oAttributeTuple));
569 }
570
571 return oResult;
572 }
573
577 const std::vector<std::string> GetAttributes() const
578 {
579 std::vector<std::string> oResult = GetDynamicAttributes();
580
581 for (const auto& oAttributeTuple : m_oStaticAttributes)
582 {
583 oResult.emplace_back(std::get<std::string>(oAttributeTuple));
584 }
585
586 return oResult;
587 }
588
593 const std::optional<tSensorTransformation>& GetTransformation() const
594 {
595 if (m_oTransformationAccess)
596 {
597 THROW_ERROR_DESC(ERR_NOT_SUPPORTED, "Can't predict sensor transformation for an external source.");
598 }
599
600 return m_oTransformation;
601 }
602
607 const std::optional<size_t> GetCount() const
608 {
609 if (m_oCountAccess)
610 {
611 THROW_ERROR_DESC(ERR_NOT_SUPPORTED, "Can't predict amount of points in pointcloud for an external source.");
612 }
613
614 return m_oCount;
615 }
616
620 bool IsDynamic() const
621 {
622 return m_oDynamicSampleHeader.has_value();
623 }
624
625public:
626 struct tPointCloudAccess
627 {
628 tPointCloudAccess() = delete;
629 tPointCloudAccess(const tPointCloudAccess&) = delete;
630
638 tPointCloudAccess(const cPointCloudTypeHelper& oLayout, const void* pData, size_t nDataSize):
639 m_oLayout(oLayout),
640 m_oHeader(detail::tConstBuffer(pData, m_oLayout.GetHeaderSize())),
641 m_oData(detail::tConstBuffer(static_cast<const std::byte*>(pData) + m_oLayout.GetHeaderSize(),
642 nDataSize - m_oLayout.GetHeaderSize()))
643 {
644 Construct(nDataSize);
645 }
646
654 tPointCloudAccess(const cPointCloudTypeHelper& oLayout, void* pData, size_t nDataSize):
655 m_oLayout(oLayout),
656 m_oHeader(detail::tBuffer(pData, m_oLayout.GetHeaderSize())),
657 m_oData(detail::tBuffer(static_cast<std::byte*>(pData) + m_oLayout.GetHeaderSize(),
658 nDataSize - m_oLayout.GetHeaderSize()))
659 {
660 Construct(nDataSize);
661 }
662
669 tPointCloudAccess(const cPointCloudTypeHelper& oLayout, const adtf::streaming::ISampleBuffer& oData):
670 m_oLayout(oLayout),
671 m_oHeader(detail::tConstBuffer(oData.GetPtr(), m_oLayout.GetHeaderSize())),
672 m_oData(detail::tConstBuffer(static_cast<const std::byte*>(oData.GetPtr()) + m_oLayout.GetHeaderSize(),
673 oData.GetSize() - m_oLayout.GetHeaderSize()))
674 {
675 Construct(oData.GetSize());
676 }
677
684 tPointCloudAccess(const cPointCloudTypeHelper& oLayout, adtf::streaming::ISampleBuffer& oData):
685 m_oLayout(oLayout),
686 m_oHeader(detail::tBuffer(oData.GetPtr(), m_oLayout.GetHeaderSize())),
687 m_oData(detail::tBuffer(static_cast<std::byte*>(oData.GetPtr()) + m_oLayout.GetHeaderSize(),
688 oData.GetSize() - m_oLayout.GetHeaderSize()))
689 {
690 Construct(oData.GetSize());
691 }
692
693 constexpr const cPointCloudTypeHelper& GetLayout() const
694 {
695 return m_oLayout;
696 }
697
698 const void* GetData() const
699 {
700 return std::visit([this](auto&& oData) -> const void* { return oData.pData; }, m_oData);
701 }
702
703 void* GetMutableData()
704 {
705 return std::visit(
706 [this](auto&& oData) -> void*
707 {
708 if constexpr (std::is_same_v<decltype(oData.pData), const void* const>)
709 {
710 THROW_ERROR_DESC(ERR_INVALID_ARG,
711 "Can't obtain a mutable buffer reference from non-const buffer.");
712 }
713 else
714 {
715 return oData.pData;
716 }
717 },
718 m_oData);
719 }
720
721 size_t GetBufferSize() const
722 {
723 return std::visit([this](auto&& oData) -> size_t { return oData.nSize; }, m_oData);
724 }
725
726 const tAttributes& GetAttributes() const
727 {
728 if (m_oResolvedAttributes)
729 {
730 return *m_oResolvedAttributes;
731 }
732
733 return m_oLayout.GetStaticAttributes();
734 }
735
736 const std::optional<tSensorTransformation>& GetTransformation() const
737 {
738 if (m_oLayout.IsDynamic())
739 {
740 return m_oResolvedSensorTransformation;
741 }
742
743 return m_oLayout.GetTransformation();
744 }
745
746 std::optional<size_t> GetCount() const
747 {
748 if (m_oResolvedCount)
749 {
750 return m_oResolvedCount;
751 }
752
753 return m_oLayout.GetCount();
754 }
755
756 template <typename Callable, typename Signature = adtf::ucom::nitro::detail::signature_t<Callable>>
757 void IteratePoints(Callable&& fnCallback) const
758 {
759 IteratePointsImplementation(std::function<Signature>(fnCallback), make_tuple_sequence<adtf::ucom::nitro::detail::function_traits<std::remove_reference_t<Callable>>::argument_count, size_t>());
760 }
761
762 template <typename Callable, typename ...Indices, typename Signature = adtf::ucom::nitro::detail::signature_t<Callable>>
763 void IteratePoints(Callable&& fnCallback, Indices... indices) const
764 {
765 static_assert(adtf::ucom::nitro::detail::function_traits<std::remove_reference_t<Callable>>::argument_count == sizeof...(Indices));
766 IteratePointsImplementation(std::function<Signature>(fnCallback), std::forward_as_tuple(indices...));
767 }
768
769 private:
770 template<typename T, T ...I>
771 static auto make_tuple_sequence_helper(std::integer_sequence<T, I...>)
772 {
773 return std::make_tuple(I...);
774 }
775
776 template<std::size_t I, typename T>
777 static auto make_tuple_sequence()
778 {
779 return make_tuple_sequence_helper(std::make_integer_sequence<T, I>());
780 }
781
782 template <typename ...Indices, std::size_t... Is>
783 auto GetAttributesByIndex(const std::tuple<Indices...>& indices,
784 std::index_sequence<Is...>) const
785 {
786 return std::forward_as_tuple(static_cast<const tAttribute&>(GetAttributes().at(std::get<Is>(indices)))...);
787 }
788
789 template <typename ...Indices>
790 auto GetAttributesByIndex(const std::tuple<Indices...>& indices) const
791 {
792 return GetAttributesByIndex(indices, std::index_sequence_for<Indices...>{});
793 }
794
795 template <typename ...Attributes, typename ...Indices>
796 void IteratePointsImplementation(const std::function<void(Attributes...)>& fnCallback, const std::tuple<Indices...>& indices) const
797 {
798 const auto oAttributes = GetAttributesByIndex(indices);
799 for (size_t nIndex = 0; nIndex < GetCount(); ++nIndex)
800 {
801 CallWithAttribute<sizeof...(Attributes)>(fnCallback, oAttributes, nIndex);
802 }
803 }
804
805 template <size_t nAttributeIndex, typename ...CallbackAttributes, typename AttributeReferences, typename ...Attributes>
806 void CallWithAttribute(const std::function<void(CallbackAttributes...)>& fnCallback,
807 [[maybe_unused]] const AttributeReferences& oAttributes,
808 [[maybe_unused]] size_t nIndex,
809 Attributes&&... args) const
810 {
811 if constexpr (nAttributeIndex == 0)
812 {
813 fnCallback(detail::to_type<CallbackAttributes>(std::forward<Attributes>(args))...);
814 }
815 else
816 {
817 CallWithAttribute<nAttributeIndex - 1>(fnCallback,
818 oAttributes,
819 nIndex,
820 get_attribute_value(std::get<nAttributeIndex - 1>(oAttributes), detail::tConstBuffer(GetData(), GetBufferSize()), nIndex), std::forward<Attributes>(args)...);
821 }
822 }
823
824 void Construct(const size_t nDataSize)
825 {
826 if (!m_oLayout.IsDynamic())
827 {
828 if (m_oLayout.GetHeaderSize() != 0)
829 {
830 THROW_ERROR_DESC(ERR_INVALID_ARG, "Static layout must not define a header.");
831 }
832
833 if (!m_oLayout.GetCount())
834 {
835 // Try to calculate count
836 // Get size of of 1 point from attributes
837 size_t nPointSizeBytes = 0;
838 for (const auto& oAttributeTuple : m_oLayout.m_oStaticAttributes)
839 {
840 const auto& oAttribute = std::get<tAttribute>(oAttributeTuple);
841 nPointSizeBytes += oAttribute.Size(oAttribute.type);
842 }
843 // Calculate amount of points
844 if (nPointSizeBytes != 0)
845 {
846 m_oResolvedCount = nDataSize / nPointSizeBytes;
847 }
848 }
849 }
850 else // Dynamic layout
851 {
852 if (m_oLayout.GetHeaderSize() == 0)
853 {
854 THROW_ERROR_DESC(ERR_INVALID_ARG, "Can't target dynamic layout without a header.");
855 }
856 if (nDataSize < m_oLayout.GetHeaderSize())
857 {
858 THROW_ERROR_DESC(ERR_INVALID_ARG, "Passed buffer can't even hold valid header.");
859 }
860
861 ResolveHeader();
862 }
863 }
864
865 template<typename T, typename Access>
866 T Resolve(const Access& oHeaderAccess) const
867 {
868 return std::visit(
869 [&oHeaderAccess](auto&& oHeader) -> T
870 {
871 if constexpr (!std::is_same_v<std::monostate, std::decay_t<decltype(oHeader)>>)
872 {
873 return oHeaderAccess.getMember(oHeader.pData, oHeader.nSize);
874 }
875 else
876 {
877 return T{};
878 }
879 },
880 m_oHeader);
881 }
882
883 tAttributes ResolveAttributes() const
884 {
885 tAttributes oResult;
886 for (const auto& oAttribute : m_oLayout.m_oDynamicAttributes)
887 {
888 oResult.add(std::get<0>(oAttribute), Resolve<tAttribute>(std::get<1>(oAttribute)));
889 }
890 return oResult;
891 }
892
893 void ResolveHeader()
894 {
895 if (m_oLayout.m_oTransformationAccess)
896 {
897 m_oResolvedSensorTransformation = Resolve<tSensorTransformation>(*m_oLayout.m_oTransformationAccess);
898 }
899 m_oResolvedAttributes = ResolveAttributes();
900
901 if (m_oLayout.m_oCountAccess)
902 {
903 m_oResolvedCount = Resolve<size_t>(*m_oLayout.m_oCountAccess);
904 }
905
906 // If not present, derive count from attributes and buffer size
907 if (!m_oResolvedCount && m_oResolvedAttributes)
908 {
909 // Get size of of 1 point from attributes
910 size_t nPointSizeBytes = 0;
911 for (const auto& oAttributeTuple : *m_oResolvedAttributes)
912 {
913 const auto& oAttribute = std::get<tAttribute>(oAttributeTuple);
914 nPointSizeBytes += oAttribute.Size(oAttribute.type);
915 }
916 // Calculate amount of points
917 if (nPointSizeBytes != 0)
918 {
919 m_oResolvedCount = GetBufferSize() / nPointSizeBytes;
920 }
921 }
922 }
923
924 private:
925 const cPointCloudTypeHelper& m_oLayout;
926
927 const std::variant<std::monostate, detail::tBuffer, detail::tConstBuffer> m_oHeader;
928 std::optional<tAttributes> m_oResolvedAttributes;
929
930 std::optional<tSensorTransformation> m_oResolvedSensorTransformation;
931 std::optional<size_t> m_oResolvedCount;
932
933 const std::variant<detail::tBuffer, detail::tConstBuffer> m_oData;
934 };
935
936private:
937 struct tSensorTransformationAccess
938 {
939 tSensorTransformationAccess() = delete;
940 tSensorTransformationAccess(const ddl::codec::CodecFactory::Element& oElement,
941 ddl::DataRepresentation eRepresentation)
942 {
943 m_oX = adtf::mediadescription::tLeafCodecIndex(oElement.getChildElement("x").getIndex(), eRepresentation)
944 .getLayout();
945 m_oY = adtf::mediadescription::tLeafCodecIndex(oElement.getChildElement("y").getIndex(), eRepresentation)
946 .getLayout();
947 m_oZ = adtf::mediadescription::tLeafCodecIndex(oElement.getChildElement("z").getIndex(), eRepresentation)
948 .getLayout();
949 m_oRoll =
950 adtf::mediadescription::tLeafCodecIndex(oElement.getChildElement("roll").getIndex(), eRepresentation)
951 .getLayout();
952 m_oPitch =
953 adtf::mediadescription::tLeafCodecIndex(oElement.getChildElement("pitch").getIndex(), eRepresentation)
954 .getLayout();
955 m_oYaw =
956 adtf::mediadescription::tLeafCodecIndex(oElement.getChildElement("yaw").getIndex(), eRepresentation)
957 .getLayout();
958 }
959
960 tSensorTransformation getMember(const void* pHeader, const size_t nHeaderSize) const
961 {
962 tSensorTransformation oResult{ddl::codec::LeafValueGetter<float>::getValue(pHeader, nHeaderSize, m_oX),
963 ddl::codec::LeafValueGetter<float>::getValue(pHeader, nHeaderSize, m_oY),
964 ddl::codec::LeafValueGetter<float>::getValue(pHeader, nHeaderSize, m_oZ),
965 ddl::codec::LeafValueGetter<float>::getValue(pHeader, nHeaderSize, m_oRoll),
966 ddl::codec::LeafValueGetter<float>::getValue(pHeader, nHeaderSize, m_oPitch),
967 ddl::codec::LeafValueGetter<float>::getValue(pHeader, nHeaderSize, m_oYaw)};
968
969 return oResult;
970 }
971
972 private:
973 ddl::codec::LeafLayout m_oX;
974 ddl::codec::LeafLayout m_oY;
975 ddl::codec::LeafLayout m_oZ;
976 ddl::codec::LeafLayout m_oRoll;
977 ddl::codec::LeafLayout m_oPitch;
978 ddl::codec::LeafLayout m_oYaw;
979 };
980
981 struct tAttributeAccess
982 {
983 tAttributeAccess() = delete;
984
985 tAttributeAccess(const ddl::codec::CodecFactory::Element& oElement, ddl::DataRepresentation eRepresentation)
986 {
987 m_oType =
988 adtf::mediadescription::tLeafCodecIndex(oElement.getChildElement("type").getIndex(), eRepresentation)
989 .getLayout();
990 m_oEndianess = adtf::mediadescription::tLeafCodecIndex(
991 oElement.getChildElement("in_memory.endianess").getIndex(), eRepresentation)
992 .getLayout();
993 m_oOffsetMemory = adtf::mediadescription::tLeafCodecIndex(
994 oElement.getChildElement("in_memory.offset").getIndex(), eRepresentation)
995 .getLayout();
996 m_oStride = adtf::mediadescription::tLeafCodecIndex(oElement.getChildElement("in_memory.stride").getIndex(),
997 eRepresentation)
998 .getLayout();
999 m_oStrideToInc = adtf::mediadescription::tLeafCodecIndex(
1000 oElement.getChildElement("computed.stride_to_increment").getIndex(), eRepresentation)
1001 .getLayout();
1002 m_oStrideToReset = adtf::mediadescription::tLeafCodecIndex(
1003 oElement.getChildElement("computed.stride_to_reset").getIndex(), eRepresentation)
1004 .getLayout();
1005 m_oIncrement = adtf::mediadescription::tLeafCodecIndex(
1006 oElement.getChildElement("computed.increment").getIndex(), eRepresentation)
1007 .getLayout();
1008 m_oOffsetComputed = adtf::mediadescription::tLeafCodecIndex(
1009 oElement.getChildElement("computed.offset").getIndex(), eRepresentation)
1010 .getLayout();
1011 }
1012
1013 tAttribute getMember(const void* pHeader, const size_t nHeaderSize) const
1014 {
1015 tAttribute oResult;
1016 oResult.type = ddl::codec::LeafValueGetter<tAttribute::tDataType>::getValue(pHeader, nHeaderSize, m_oType);
1017 if (oResult.type != tAttribute::tDataType::dt_computed_from_index)
1018 {
1019 oResult.sInMemory.endianess = ddl::codec::LeafValueGetter<tAttribute::tInMemory::eEndianess>::getValue(
1020 pHeader, nHeaderSize, m_oEndianess);
1021 oResult.sInMemory.offset =
1022 ddl::codec::LeafValueGetter<size_t>::getValue(pHeader, nHeaderSize, m_oOffsetMemory);
1023 oResult.sInMemory.stride =
1024 ddl::codec::LeafValueGetter<size_t>::getValue(pHeader, nHeaderSize, m_oStride);
1025 }
1026 else
1027 {
1028 oResult.sComputed.stride_to_increment =
1029 ddl::codec::LeafValueGetter<size_t>::getValue(pHeader, nHeaderSize, m_oStrideToInc);
1030 oResult.sComputed.stride_to_reset =
1031 ddl::codec::LeafValueGetter<size_t>::getValue(pHeader, nHeaderSize, m_oStrideToReset);
1032 oResult.sComputed.increment =
1033 ddl::codec::LeafValueGetter<double>::getValue(pHeader, nHeaderSize, m_oIncrement);
1034 oResult.sComputed.offset =
1035 ddl::codec::LeafValueGetter<double>::getValue(pHeader, nHeaderSize, m_oOffsetComputed);
1036 }
1037
1038 return oResult;
1039 }
1040
1041 private:
1042 ddl::codec::LeafLayout m_oType;
1043 // in_memory
1044 ddl::codec::LeafLayout m_oEndianess;
1045 ddl::codec::LeafLayout m_oOffsetMemory;
1046 ddl::codec::LeafLayout m_oStride;
1047 // computed
1048 ddl::codec::LeafLayout m_oStrideToInc;
1049 ddl::codec::LeafLayout m_oStrideToReset;
1050 ddl::codec::LeafLayout m_oIncrement;
1051 ddl::codec::LeafLayout m_oOffsetComputed;
1052 };
1053
1054 struct tCountAccess
1055 {
1056 tCountAccess() = delete;
1057
1058 tCountAccess(const ddl::codec::CodecFactory::Element& oElement, ddl::DataRepresentation eRepresentation)
1059 {
1060 m_oCount = adtf::mediadescription::tLeafCodecIndex(oElement.getIndex(), eRepresentation).getLayout();
1061 }
1062
1063 size_t getMember(const void* pHeader, const size_t nHeaderSize) const
1064 {
1065 return ddl::codec::LeafValueGetter<size_t>::getValue(pHeader, nHeaderSize, m_oCount);
1066 }
1067
1068 private:
1069 ddl::codec::LeafLayout m_oCount;
1070 };
1071
1072 void CheckCompatibility() const
1073 {
1074 using namespace std::literals;
1075 // Check mutually exclusiveness
1076 if (!m_oStaticAttributes.empty() && !m_oDynamicAttributes.empty())
1077 {
1078 THROW_ERROR_DESC(ERR_NOT_SUPPORTED, "The defines both static and dynamic attributes, which is not allowed.");
1079 }
1080
1081 static const std::array<std::string, 6> oReservedAttributes{"x"s, "y"s, "z"s, "distance"s, "yaw"s, "pitch"s};
1082 size_t nMandatoryCount = 0;
1083 for (const auto& strAttribute : oReservedAttributes)
1084 {
1085 if (m_oStaticAttributes.exists(strAttribute))
1086 {
1087 nMandatoryCount++;
1088 }
1089 else if (m_oDynamicAttributes.exists(strAttribute))
1090 {
1091 nMandatoryCount++;
1092 }
1093 }
1094
1095 if (nMandatoryCount < 3)
1096 {
1097 THROW_ERROR_DESC(ERR_INVALID_TYPE, "The StreamType is missing mandatory attributes.");
1098 }
1099 }
1100
1101 template<typename T>
1102 static tResult
1103 CreateAndSetProperty(adtf::base::IProperties& oProperties, const std::string& strPath, const T& oValue)
1104 {
1105 RETURN_IF_FAILED(adtf::base::create_property_tree(oProperties, strPath.c_str()));
1106 RETURN_IF_FAILED(adtf::base::set_property_by_path(oProperties, strPath.c_str(), oValue));
1107 RETURN_NOERROR;
1108 }
1109
1110private:
1111 std::optional<tCountAccess> m_oCountAccess;
1112 std::optional<tSensorTransformationAccess> m_oTransformationAccess;
1113 indexed_vector<tAttributeAccess> m_oDynamicAttributes;
1114
1115 tAttributes m_oStaticAttributes;
1116 std::optional<tSensorTransformation> m_oTransformation;
1117 std::optional<size_t> m_oCount;
1118 size_t m_nHeaderSize = 0;
1119 std::optional<ddl::DDStructure> m_oDynamicSampleHeader;
1120 ddl::DataRepresentation m_eRepresentation;
1121};
1122
1123} // namespace navigation
1124
1125using cPointCloudTypeHelper = navigation::cPointCloudTypeHelper;
1126
1127} // namespace pointcloud
1128} // namespace sdk
1129} // namespace devicetb
1130} // namespace adtf
adtf::ucom::object_ptr< adtf::streaming::IStreamType > GetStreamType() const
Definition pointcloud_data.h:310
const tAttributes & GetStaticAttributes() const
Definition pointcloud_data.h:555
bool IsDynamic() const
Definition pointcloud_data.h:620
void AddStaticAttribute(const std::string &strName, const tAttribute &oAttribute)
Definition pointcloud_data.h:444
void SetStaticTransformation(const tSensorTransformation &oTransformation)
Definition pointcloud_data.h:429
const std::optional< size_t > GetCount() const
Definition pointcloud_data.h:607
void SetStaticCount(const size_t nCount)
Definition pointcloud_data.h:462
const std::optional< tSensorTransformation > & GetTransformation() const
Definition pointcloud_data.h:593
static size_t GetPayloadSize(size_t nPointCount, const tAttributes &oAttributes) noexcept
Estimate the size required to hold a pointcloud with a given number of points.
Definition pointcloud_data.h:538
const std::vector< std::string > GetDynamicAttributes() const
Definition pointcloud_data.h:563
const std::vector< std::string > GetAttributes() const
Definition pointcloud_data.h:577
size_t GetHeaderSize() const
Definition pointcloud_data.h:528
cPointCloudTypeHelper(const adtf::ucom::iobject_ptr< const adtf::streaming::IStreamType > &pType)
Definition pointcloud_data.h:170
Namespace for functionality provided by 3.13.0.
Definition pointcloud_access.h:52
Namespace for pointcloud in ADTF-Devicetoolbox.
Definition pointcloud_access.h:49
Namespace for SDK of ADTF-Devicetoolbox.
Definition bus_database_intf.h:42
Devicetoolbox - Namespace.
Definition bus_database_intf.h:36
ADTF - Namespace.
Definition bus_database_intf.h:30
tPointCloudAccess(const cPointCloudTypeHelper &oLayout, void *pData, size_t nDataSize)
Definition pointcloud_data.h:654
tPointCloudAccess(const cPointCloudTypeHelper &oLayout, adtf::streaming::ISampleBuffer &oData)
Definition pointcloud_data.h:684
tPointCloudAccess(const cPointCloudTypeHelper &oLayout, const adtf::streaming::ISampleBuffer &oData)
Definition pointcloud_data.h:669
tPointCloudAccess(const cPointCloudTypeHelper &oLayout, const void *pData, size_t nDataSize)
Definition pointcloud_data.h:638