44 pcl::PointCloud<PointT>::ConstPtr cloud_,
45 pcl::PointCloud<PointN>::ConstPtr normals_,
46 pcl::PointCloud<PointL>::ConstPtr labels_,
const double grid_size) ->
void {
48 using RTCVertex =
struct RTCVertex {
52 using RTCNormal =
struct RTCNormal {
56 using RTCData =
struct RTCData {
60 spdlog::trace(
"calling compute_room_probabilities");
62 assert(cloud_->size() == labels_->size() &&
63 "Point cloud and label cloud must have the same size");
64 assert(cloud_->size() == normals_->size() &&
65 "Point cloud and normal cloud must have the same size");
67 const double radius_ = grid_size * M_SQRT2;
70 "Using ray tracing for {} points with grid size {:.3} and radius {:.3}",
71 cloud_->size(), grid_size, radius_);
74 "c:room_probabilities")
78 std::vector<unsigned int> labels;
79 labels.reserve(labels_->points.size());
81 for (
const auto &p : labels_->points)
82 if (p.label !=
static_cast<unsigned int>(-1))
83 labels.push_back(p.label);
85 std::sort(labels.begin(), labels.end());
86 labels.erase(std::unique(labels.begin(), labels.end()), labels.end());
87 spdlog::debug(
"Room labels: {}", fmt::join(labels,
", "));
90 c_rp[*cit] = std::vector<double>(labels.size() + 1, 0.0);
92 spdlog::debug(
"Number of rooms (labels): {}", labels.size());
94 unsigned int old_mxcsr = _mm_getcsr();
95 _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
96 _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
98 spdlog::trace(
"Creating device and scene for ray tracing");
99 RTCDevice device_ = rtcNewDevice(
"verbose=0");
100 RTCScene scene_ = rtcNewScene(device_);
101 rtcSetSceneFlags(scene_, RTC_SCENE_FLAG_ROBUST);
102 rtcSetSceneBuildQuality(scene_, RTC_BUILD_QUALITY_HIGH);
103 assert(device_ !=
nullptr &&
"Error creating Embree device");
104 assert(scene_ !=
nullptr &&
"Error creating Embree scene");
105 rtcSetDeviceErrorFunction(
107 [](
void *, RTCError err,
const char *str) {
108 spdlog::error(
"Embree error {}:", str);
112 case RTC_ERROR_UNKNOWN:
113 throw std::runtime_error(
"Embree: An unknown error has occurred.");
115 case RTC_ERROR_INVALID_ARGUMENT:
116 throw std::runtime_error(
117 "Embree: An invalid argument was specified.");
119 case RTC_ERROR_INVALID_OPERATION:
120 throw std::runtime_error(
121 "Embree: The operation is not allowed for the specified object.");
123 case RTC_ERROR_OUT_OF_MEMORY:
124 throw std::runtime_error(
"Embree: There is not enough memory left to "
125 "complete the operation.");
127 case RTC_ERROR_UNSUPPORTED_CPU:
128 throw std::runtime_error(
129 "Embree: The CPU is not supported as it does not support SSE2.");
131 case RTC_ERROR_CANCELLED:
132 throw std::runtime_error(
133 "Embree: The operation got cancelled by an Memory Monitor "
134 "Callback or Progress Monitor Callback function.");
137 throw std::runtime_error(
"Embree: An invalid error has occurred.");
144 spdlog::trace(
"Creating scene geometry for ray tracing");
146 pcl::UniformSampling<PointT> us;
147 us.setInputCloud(cloud_);
148 us.setRadiusSearch(grid_size);
150 using RTCDataPtr = std::shared_ptr<RTCData>;
151 std::vector<RTCDataPtr> rtc_data_vec{};
152 for (
size_t i = 0; i < labels.size(); ++i) {
154 pcl::IndicesPtr indices(
new pcl::Indices);
155 for (
size_t j = 0; j < cloud_->size(); ++j)
156 if (labels_->points[j].label == labels[i])
157 indices->push_back(
static_cast<int>(j));
159 spdlog::trace(
"Room label {}: {} points", labels[i], indices->size());
162 us.setIndices(indices);
168 RTCGeometry geometry_ =
169 rtcNewGeometry(device_, RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT);
171 RTCVertex *vb = (RTCVertex *)rtcSetNewGeometryBuffer(
172 geometry_, RTC_BUFFER_TYPE_VERTEX, 0, RTC_FORMAT_FLOAT4,
173 sizeof(RTCVertex), indices->size());
175 RTCNormal *nb = (RTCNormal *)rtcSetNewGeometryBuffer(
176 geometry_, RTC_BUFFER_TYPE_NORMAL, 0, RTC_FORMAT_FLOAT3,
177 sizeof(RTCNormal), indices->size());
179 for (
size_t i = 0; i < indices->size(); ++i) {
180 const auto &p = cloud_->points[indices->at(i)];
181 const auto &n = normals_->points[indices->at(i)];
183 vb[i].x =
static_cast<float>(p.x);
184 vb[i].y =
static_cast<float>(p.y);
185 vb[i].z =
static_cast<float>(p.z);
186 vb[i].r =
static_cast<float>(radius_) * 1.05f;
188 nb[i].x =
static_cast<float>(n.normal_x);
189 nb[i].y =
static_cast<float>(n.normal_y);
190 nb[i].z =
static_cast<float>(n.normal_z);
193 rtc_data_vec.emplace_back(
new RTCData{i});
194 rtcSetGeometryUserData(geometry_, rtc_data_vec.back().get());
196 rtcCommitGeometry(geometry_);
197 rtcAttachGeometry(scene_, geometry_);
198 rtcReleaseGeometry(geometry_);
201 spdlog::trace(
"Committing scene");
202 rtcCommitScene(scene_);
207 auto logger = spdmon::LoggerProgress(
"Computing room probabilities",
210#pragma omp parallel for schedule(dynamic)
211 for (
size_t cell_idx = 0; cell_idx < this->
num_cells(); ++cell_idx) {
213 std::advance(cit, cell_idx);
218 std::vector<double> local_accum(c_rp[*cit].size(), 0.0);
219 double *accum_ptr = local_accum.data();
220 const int N =
static_cast<int>(c_rp[*cit].size());
222#pragma omp parallel for reduction(+ : accum_ptr[ : N])
223 for (
size_t i = 0; i < dirs.size(); ++i) {
224 const auto dir = dirs[i];
225 auto c = (*this)[*cit].pos;
228 rayhit.ray.org_x =
static_cast<float>(c.x());
229 rayhit.ray.org_y =
static_cast<float>(c.y());
230 rayhit.ray.org_z =
static_cast<float>(c.z());
231 rayhit.ray.dir_x =
static_cast<float>(dir.x());
232 rayhit.ray.dir_y =
static_cast<float>(dir.y());
233 rayhit.ray.dir_z =
static_cast<float>(dir.z());
235 rayhit.ray.tnear = 0.001f;
236 rayhit.ray.tfar = std::numeric_limits<float>::infinity();
237 rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
239 rayhit.ray.mask = -1;
240 rayhit.ray.flags = 0;
241 rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
243 rtcIntersect1(scene_, &rayhit);
245 if (rayhit.hit.geomID == RTC_INVALID_GEOMETRY_ID) {
253 Eigen::Vector3f(rayhit.hit.Ng_x, rayhit.hit.Ng_y, rayhit.hit.Ng_z)
255 const Eigen::Vector3f dir_vec(dir.x(), dir.y(), dir.z());
256 if (normal.dot(dir_vec) > 0) {
265 auto geometry = rtcGetGeometry(scene_, rayhit.hit.geomID);
267 RTCData *data = (RTCData *)rtcGetGeometryUserData(
geometry);
274 accum_ptr[data->label_index + 1] += 1;
285 for (
auto &p : local_accum)
287 c_rp[*cit] = std::move(local_accum);
292 rtcReleaseScene(scene_);
293 rtcReleaseDevice(device_);
295 _mm_setcsr(old_mxcsr);
298 auto sum_results = std::vector<double>(labels.size() + 1, 0.0);
300 for (
size_t i = 0; i < c_rp[*cit].size(); ++i)
301 sum_results[i] += c_rp[*cit][i];
302 spdlog::trace(
"Sum probabilities => [{:.3f}]", fmt::join(sum_results,
", "));