CVB++ 15.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 auto [pointCloud, waitStatus, enumerator] = stream->Wait<Cvb::DensePointCloud>();
58 if (waitStatus != Cvb::WaitStatus::Ok)
59 {
60 std::cout << "wait status not ok: " << static_cast<int>(waitStatus) << std::endl;
61 break;
62 }
63
64 // Here we've got the point cloud (xyz), but there is more in the buffer as
65 // a multi part buffer is a composition of different parts.
66 // You can access these parts through a composite, which is basically just another view on the point cloud.
67 auto composite = Cvb::Composite::FromObject(pointCloud);
68 if (composite->Purpose() == Cvb::CompositePurpose::PointCloud)
69 {
70 const auto numberOfElements = composite->ItemCount();
71 std::cout << "Found " << numberOfElements << " point cloud parts" << std::endl;
72
73 // check if the format is as expected.
74 auto xyz = Cvb::get<Cvb::PlaneEnumeratorPtr>(composite->ItemAt(0));
75 if (!xyz)
76 {
77 std::cout << "Composite xyz is not a plane enumerator" << std::endl;
78 break;
79 }
80
81 if (!Cvb::holds_alternative<Cvb::PlanePtr>(composite->ItemAt(1)))
82 {
83 std::cout << "Composite confidence is not a plane" << std::endl;
84 break;
85 }
86
87 if (!Cvb::holds_alternative<Cvb::ImagePtr>(composite->ItemAt(2)))
88 {
89 std::cout << "Composite image is not an image" << std::endl;
90 break;
91 }
92
93 // Note: that items in composite are not automatically associated with each other.
94 // E.g. the image inside a composite could refer to a totally different sensor.
95 // As there is no standard way to communicate the relation between individual parts,
96 // you have to create this association with your a priori knowledge.
97 // This can be done by adding planes with specific roles to the composite/point cloud.
98 // Be aware that no data is copied.
99
100 // Get the RGB planes from the image.
101 // This is necessary because an image plane supports more memory layouts than a plane.
102 // For modern acquisition devices they are usually compatible.
103 auto rgbImage = Cvb::get<Cvb::ImagePtr>(composite->ItemAt(2));
104 auto rPlane = Cvb::Plane::FromImagePlane(rgbImage->Plane(0), Cvb::PlaneRole::PixRGB_R);
105 auto gPlane = Cvb::Plane::FromImagePlane(rgbImage->Plane(1), Cvb::PlaneRole::PixRGB_G);
106 auto bPlane = Cvb::Plane::FromImagePlane(rgbImage->Plane(2), Cvb::PlaneRole::PixRGB_B);
107
108 // Add them at the end
109 composite->InsertItemAt(composite->ItemCount(), rPlane);
110 composite->InsertItemAt(composite->ItemCount(), gPlane);
111 composite->InsertItemAt(composite->ItemCount(), bPlane);
112
113 // remember the point cloud and the composite are the same thing
114 pointCloud->Save("xyzrgb.pcd");
115
116 // Note: when you load it again the image is gone, but XYZ and RGB planes can be restored!
117 }
118 else
119 {
120 std::cout << "The composite contains something unexpected" << std::endl;
121 break;
122 }
123 }
124 stream->Stop();
125 }
126 catch (const std::exception& e)
127 {
128 std::cout << e.what() << std::endl;
129 }
130 return 0;
131}
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:221
void Start() override
Starts the acquisition.
Definition: decl_composite_stream_base.hpp:349
Streams point clouds.
Definition: point_cloud_stream.hpp:20
static PlanePtr FromImagePlane(const ImagePlane &imagePlane, PlaneRole role=PlaneRole::Undefined)
Creates a plane from an image plane.
Definition: decl_plane.hpp:69
@ Ok
Everything is fine, a new image arrived.
@ PixRGB_R
Red channel value.
@ PixRGB_B
Blue channel value.
@ PixRGB_G
Green channel value.