CVB++ 14.0
Cvb/CppPointCloudAcquisition
1// ----------------------------------------------------------------------------
6// ----------------------------------------------------------------------------
7
8#include <iostream>
9#include <fstream>
10#include <string>
11#include <vector>
12
13#include <cvb/device_factory.hpp>
14#include <cvb/driver/driver.hpp>
15#include <cvb/image.hpp>
16#include <cvb/utilities/utilities.hpp>
17#include <cvb/composite.hpp>
18#include <cvb/driver/multi_part_image.hpp>
19#include <cvb/plane_enumerator.hpp>
20#include <cvb/point_cloud.hpp>
21
22
23
24int main()
25{
26 try
27 {
28 const constexpr auto numElemsToAcquire = 10;
29
30 auto infoList = Cvb::DeviceFactory::Discover(Cvb::DiscoverFlags::IgnoreVins);
31 if (infoList.empty())
32 {
33 std::cout << "Discovered" << std::endl;
34 throw std::runtime_error("There is no available device for this demonstration.");
35 }
36
37 // Attention: even if you have connected such a device it is not necessarily found first.
38 // You may want to filter here.
39 auto device = Cvb::DeviceFactory::Open<Cvb::GenICamDevice>(infoList[0].AccessToken(), Cvb::AcquisitionStack::GenTL);
40
41 // Maybe adjust some values
42 //auto nodeMap = device->NodeMap(CVB_LIT("Device"));
43 //auto settingNodes = nodeMap->Node<Cvb::FloatNode>(CVB_LIT("Aperture"));
44 //settingNodes->SetValue(5.66f);
45 //auto exposureTime = nodeMap->Node<Cvb::IntegerNode>(CVB_LIT("Cust::ExposureTime"));
46 //exposureTime->SetValue(40000);
47
48 const auto numStreams = device->StreamCount();
49 // We know the device is streaming point clouds including neighborhood information.
50 // So we can directly acquire dense point clouds.
51 auto stream = device->Stream<Cvb::PointCloudStream>(0);
52
53 stream->Start();
54
55 for (auto i = 0; i < numElemsToAcquire; i++)
56 {
57 Cvb::DensePointCloudPtr pointCloud;
58 Cvb::WaitStatus waitStatus;
59 Cvb::NodeMapEnumerator enumerator;
60 std::tie(pointCloud, waitStatus, enumerator) = stream->Wait<Cvb::DensePointCloud>();
61 if (waitStatus != Cvb::WaitStatus::Ok)
62 {
63 std::cout << "wait status not ok: " << static_cast<int>(waitStatus) << std::endl;
64 break;
65 }
66
67 // Here we've got the point cloud (xyz), but there is more in the buffer as
68 // a multi part buffer is a composition of different parts.
69 // You can access these parts through a composite, which is basically just another view on the point cloud.
70 auto composite = Cvb::Composite::FromObject(pointCloud);
71 if (composite->Purpose() == Cvb::CompositePurpose::PointCloud)
72 {
73 const auto numberOfElements = composite->ItemCount();
74 std::cout << "Found " << numberOfElements << " point cloud parts" << std::endl;
75
76 // check if the format is as expected.
77 auto xyz = Cvb::get<Cvb::PlaneEnumeratorPtr>(composite->ItemAt(0));
78 if (!xyz)
79 {
80 std::cout << "Composite xyz is not a plane enumerator" << std::endl;
81 break;
82 }
83
84 if (!Cvb::holds_alternative<Cvb::PlanePtr>(composite->ItemAt(1)))
85 {
86 std::cout << "Composite confidence is not a plane" << std::endl;
87 break;
88 }
89
90 if (!Cvb::holds_alternative<Cvb::ImagePtr>(composite->ItemAt(2)))
91 {
92 std::cout << "Composite image is not an image" << std::endl;
93 break;
94 }
95
96 // Note: that items in composite are not automatically associated with each other.
97 // E.g. the image inside a composite could refer to a totally different sensor.
98 // As there is no standard way to communicate the relation between individual parts,
99 // you have to create this association with your a priori knowledge.
100 // This can be done by adding planes with specific roles to the composite/point cloud.
101 // Be aware that no data is copied.
102
103 // Get the RGB planes from the image.
104 // This is necessary because an image plane supports more memory layouts than a plane.
105 // For modern acquisition devices they are usually compatible.
106 auto rgbImage = Cvb::get<Cvb::ImagePtr>(composite->ItemAt(2));
107 auto rPlane = Cvb::Plane::FromImagePlane(rgbImage->Plane(0), Cvb::PlaneRole::PixRGB_R);
108 auto gPlane = Cvb::Plane::FromImagePlane(rgbImage->Plane(1), Cvb::PlaneRole::PixRGB_G);
109 auto bPlane = Cvb::Plane::FromImagePlane(rgbImage->Plane(2), Cvb::PlaneRole::PixRGB_B);
110
111 // Add them at the end
112 composite->InsertItemAt(composite->ItemCount(), rPlane);
113 composite->InsertItemAt(composite->ItemCount(), gPlane);
114 composite->InsertItemAt(composite->ItemCount(), bPlane);
115
116 // remember the point cloud and the composite are the same thing
117 pointCloud->Save("xyzrgb.pcd");
118
119 // Note: when you load it again the image is gone, but XYZ and RGB planes can be restored!
120 }
121 else
122 {
123 std::cout << "The composite contains something unexpected" << std::endl;
124 break;
125 }
126 }
127 stream->Stop();
128 }
129 catch (const std::exception& e)
130 {
131 std::cout << e.what() << std::endl;
132 }
133 return 0;
134}
static CompositePtr FromObject(std::shared_ptr< T > object)
Returns a composite object from the given composite compatible object.
A dense Cartesian 3D point cloud object.
Definition: decl_dense_point_cloud.hpp:31
static std::vector< DiscoveryInformation > Discover()
Discovers available devices (not vins) with a default time span of 300ms.
Definition: decl_device_factory.hpp:216
void Start() override
Starts the acquisition.
Definition: decl_composite_stream_base.hpp:349
Streams point clouds.
Definition: point_cloud_stream.hpp:20
Lazy enumeration of node maps.
Definition: node_map_enumerator.hpp:31
static PlanePtr FromImagePlane(const ImagePlane &imagePlane, PlaneRole role=PlaneRole::Undefined)
Creates a plane from an image plane.
Definition: decl_plane.hpp:60
WaitStatus
Status after waiting for an image to be returned.
Definition: global.hpp:351
@ Ok
Everything is fine, a new image arrived.
@ PixRGB_R
Red channel value.
@ PixRGB_B
Blue channel value.
@ PixRGB_G
Green channel value.